什么是最好的PHPinput消毒function?

我对PHP /编程非常陌生,考虑到这一点,我试图想出一个函数,可以将所有string传递给sanatize。 因此,从它出来的string将是安全的数据库插入。 但是,有太多的过滤function,我不知道哪些我应该使用/需要。 请帮我填补空白:

function filterThis($string) { $string = mysql_real_escape_string($string); $string = htmlentities($string); etc... return $string; } 

停止!

你在这里犯了一个错误。 哦,不,你已经select了正确的PHP函数来使你的数据更安全一些。 没关系。 你的错误是按照操作顺序 ,以及如何和在哪里使用这些function。

了解在清理和validation用户数据,转义数据存储以及转义数据进行演示之间的区别很重要。

消毒和validation用户数据

当用户提交数据时,您需要确保他们提供了您期望的内容。

消毒和过滤

例如,如果你期望一个数字, 确保提交的数据是一个数字 。 您也可以将用户数据转换为其他types。 所有提交的内容最初都被视为一个string,因此将已知数字数据强制为一个整数或浮点数使得消毒快速而轻松。

那么自由forms的文本字段和textareas呢? 你需要确保在这些领域没有任何意外。 主要是,你需要确保不应该有任何HTML内容的字段不包含HTML。 有两种方法可以解决这个问题。

首先,您可以尝试使用htmlspecialchars 转义 HTMLinput。 您不应该使用htmlentities来中和HTML,因为它也会执行它认为也需要编码的重音字符和其他字符的编码。

其次,您可以尝试删除任何可能的HTML。 strip_tags既快速又简单,而且马虎。 HTML Purifier做了更彻底的工作,既去除了所有的HTML,也允许通过标签和属性的select性白名单。

现代的PHP版本提供了filter扩展 ,它提供了一个全面的方法来清理用户input。

validation

确保提交的数据没有意外的内容只是一半的工作。 您还需要尝试确保提交的数据包含实际可以使用的值。

如果您期待1至10之间的数字,则需要检查该值。 如果您正在使用微调器和步骤使用这些新颖的HTML5时代数字input之一,请确保提交的数据与步骤一致。

如果这些数据来自于下拉菜单,请确保提交的值是出现在菜单中的值。

那些满足其他需求的文本input呢? 例如,dateinput应该通过strtotime或DateTime类来validation。 给定的date应该在你期望的范围之间。 那么电子邮件地址呢? 前面提到的filter扩展可以检查一个地址格式正确,虽然我是is_email库的粉丝。

所有其他表单控件也是如此。 有单选button? 根据列表进行validation。 有checkbox? 根据列表进行validation。 有file upload? 确保文件是预期的types,并将文件名视为未过滤的用户数据。

每个现代的浏览器都带有一套完整的开发工具,这使得任何人操纵你的表单变得微不足道。 你的代码应该假定用户已经完全删除了表单内容的所有客户端限制

转义数据存储

既然您已经确定您的数据是预期的格式,并且只包含期望的值,那么您需要担心将数据保存到存储中。

每一个数据存储机制都有一个确保数据正确转义和编码的具体方法。 如果您正在构buildSQL,那么在查询中传递数据的可接受方式是通过带有占位符的准备语句 。

在PHP中使用大多数SQL数据库的更好方法之一是PDO扩展 。 它遵循准备语句 , 将variables绑定到语句 ,然后将语句和variables发送到服务器的通用模式。 如果你还没有使用PDO,那么这里有一个非常好的面向MySQL的教程 。

一些SQL数据库在PHP中有自己的专业扩展,包括SQL Server , PostgreSQL和SQLite 3 。 每个扩展都准备了语句支持,这些语句支持与PDO以相同的准备绑定执行方式运行。 有时您可能需要使用这些扩展来代替PDO来支持非标准function或行为。

MySQL也有它自己的PHP扩展。 事实上其中两个。 你只想使用一个叫mysqli的 。 旧的“mysql”扩展名已被弃用 ,在现代时代并不安全或没有用。

我个人不是mysqli的粉丝。 在准备好的语句上执行variables绑定的方式是不灵活的,可能是一个痛苦的使用。 如有疑问,请使用PDO。

如果您不使用SQL数据库来存储数据,请检查您正在使用的数据库接口的文档,以确定如何安全地通过数据库传递数据。

如果可能,请确保您的数据库以适当的格式存储您的数据。 将数字存储在数字字段中。 将date存储在date字段中。 将货币存储在小数域中,而不是浮点域。 查看数据库提供的文档,了解如何正确存储不同的数据types。

转义数据进行演示

每次向用户显示数据时,都必须确保数据安全地转义,除非您知道不应该转义数据。

发布HTML时,几乎总是应该传递任何通过htmlspecialchars提供的数据。 事实上,你唯一不应该这样做的时候,就是你知道用户提供了HTML,而且你知道已经用白名单对它进行了清理。

有时你需要使用PHP来生成一些Javascript。 Javascript没有像HTML一样的转义规则! 通过PHP为用户提供的值提供给Javascript的安全方法是通过json_encode

和更多

数据validation还有很多细微之处。

例如, 字符集编码可能是一个巨大的陷阱 。 您的应用程序应遵循“ UTF-8一路贯穿 ”中所述的做法 。 当您将string数据视为错误的字符集时,会出现假想的攻击。

早些时候我提到了浏览器debugging工具。 这些工具也可以用来操纵cookie数据。 Cookie应该被视为不可信的用户input

数据validation和转义只是Web应用程序安全性的一个方面。 您应该让自己意识到Web应用程序攻击方法,以便您可以构build针对它们的防御措施。

防止SQL注入的最有效的清理是使用PDO参数化。 使用参数化查询,查询与数据分离,从而消除了一阶SQL注入的威胁。

就删除HTML而言, strip_tags可能是删除HTML的最好方法,因为它只会删除所有内容。 htmlentities做它听起来像,所以也工作。 如果你需要parsing哪个HTML允许(即你想允许一些标签),你应该使用一个成熟的现有parsing器,比如HTML Purifier

数据库input – 如何防止SQL注入

  1. 例如,通过确保整型数据是一个整数来检查数据是否有效
    • 在非string的情况下,您需要确保数据实际上是正确的types
    • 在string的情况下,你需要确保string被查询中的引号包围(显然,否则它甚至不能工作)
  2. input值到数据库,同时避免SQL注入(mysql_real_escape_string或参数化查询)
  3. 当从数据库检索值时,确保避免跨站点脚本攻击,方法是确保HTML无法注入页面(htmlspecialchars)

在插入或更新到数据库之前,您需要转义用户input。 这是一个较老的方法来做到这一点。 你现在想要使用参数化查询(可能来自PDO类)。

 $mysql['username'] = mysql_real_escape_string($clean['username']); $sql = "SELECT * FROM userlist WHERE username = '{$mysql['username']}'"; $result = mysql_query($sql); 

数据库输出 – 如何防止XSS(跨站点脚本)

仅当从数据库输出数据时才使用htmlspecialchars() 。 HTML Purifier同样适用。 例:

 $html['username'] = htmlspecialchars($clean['username']) 
  • 如果可以,请购买本书: 基本的PHP安全性
  • 另请阅读这篇文章: 为什么mysql_real_escape_string是重要的和一些陷阱

最后…你要求什么

我必须指出,如果你使用带参数化查询的PDO对象(正确的方法),那么实现这一点很简单。 但是,如果你使用旧的'mysql'的方式,那么这是你所需要的。

 function filterThis($string) { return mysql_real_escape_string($string); } 

我的5美分。

这里没有人理解mysql_real_escape_string工作方式。 此function不会过滤或“消毒”任何东西。
所以,你不能使用这个function作为一些通用的filter,这将避免注入。
只有当你明白在工作中如何适用时,你才能使用它。

我已经回答了我写的非常类似的问题: 在向数据库提交string时,我应该使用htmlspecialchars()来处理非法字符,还是使用正则expression式?
请点击查看完整的数据库端安全说明。

关于这个问题 – 查尔斯正确地告诉你要分开这些function。
试想一下,你将插入一个由admin生成的数据,允许他发布HTML。 你的function会破坏它。

虽然我会build议反对的。 这个function很久以前就被废弃了。 如果您只是为了HTML安全性而只replace<>"字符 – 请使用为此目的而有意开发的函数 – htmlspecialchars()

这取决于你正在使用的数据的种类。 一般来说,最好使用的是mysql_real_escape_string但是,例如,您知道不会有HTML内容,使用strip_tags将会增加额外的安全性。

你也可以删除你认为不应该被允许的字符。

对于数据库插入,您只需要mysql_real_escape_string (或使用参数化查询)。 您通常不希望在保存之前更改数据,如果使用了htmlentities会发生什么情况。 这会导致一个乱七八糟的混乱,当你再次通过htmlentities来显示它在网页上的某个地方。

在某个网页上显示数据时使用htmlentities

有一点相关,如果你是通过电子邮件的方式发送提交的数据,比如使用联系表单,那么一定要从头文件中使用的任何数据中去掉换行符(比如发件人:姓名和电子邮件地址,子邮件等等)

 $input = preg_replace('/\s+/', ' ', $input); 

如果你不这样做,垃圾邮件机器人发现你的表单和滥用它只是时间问题,我已经学会了很难。

1)根据http://www.php.net/manual/en/filter.filters.sanitize.php ,我testing了不同的filter:


https://github.com/tazotodua/sanitize-filter-php-variable/blob/master/sanitize-filters-php获取代码,并testing你的variables。; 另外,你也可以使用更多的参数和文件

您可以使用这些filter的任何variables,即$ _POST$ _GET ..

我总是build议使用像GUMP这样的小型validation软件包: https : //github.com/Wixel/GUMP

像这样build立一个图书馆的基本function,几乎不可能忘记卫生。 “mysql_real_escape_string”不是最好的select(如“你的常识”解释) – 如果你忘记只使用一次,整个系统将通过注射和其他讨厌的攻击攻击。

在类似于下面的代码中使用mysql_real_escape_string() 。

 $query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'", mysql_real_escape_string($user), mysql_real_escape_string($password) ); 

正如文档所述,它的目的是在作为parameter passing的string中转义特殊字符,同时考虑连接的当前字符集,以便将它放在mysql_query()中是安全的。 文档还增加了:

如果要插入二进制数据,则必须使用此函数。

在HTML内容中输出string时, htmlentities()用于转换实体中的某些字符。