什么是最好的 PHP 输入清理功能?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3126072/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are the best PHP input sanitizing functions?
提问by Lauren
I am trying to come up with a function that I can pass all my strings through to sanitize. So that the string that comes out of it will be safe for database insertion. But there are so many filtering functionsout there I am not sure which ones I should use/need.
我试图想出一个函数,我可以通过我的所有字符串进行消毒。这样从它出来的字符串对于数据库插入来说是安全的。但是有这么多过滤功能,我不确定我应该使用/需要哪些。
Please help me fill in the blanks:
请帮我填空:
function filterThis($string) {
$string = mysql_real_escape_string($string);
$string = htmlentities($string);
etc...
return $string;
}
回答by Charles
Stop!
停止!
You're making a mistake here. Oh, no, you've picked the right PHP functions to make your data a bit safer. That's fine. Your mistake is in the order of operations, and how and where to use these functions.
你在这里犯了一个错误。哦,不,您选择了正确的 PHP 函数来使您的数据更安全。没关系。您的错误在于操作顺序,以及如何以及在何处使用这些功能。
It's important to understand the difference between sanitizing and validating user data, escaping data for storage, and escaping data for presentation.
了解清理和验证用户数据、转义数据以进行存储和转义数据以进行展示之间的区别非常重要。
Sanitizing and Validating User Data
清理和验证用户数据
When users submit data, you need to make sure that they've provided something you expect.
当用户提交数据时,您需要确保他们提供了您期望的内容。
Sanitization and Filtering
消毒和过滤
For example, if you expect a number, make sure the submitted data is a number. You can also cast user datainto other types. Everything submitted is initially treated like a string, so forcing known-numeric data into being an integer or float makes sanitization fast and painless.
例如,如果您需要一个数字,请 确保提交的数据是一个数字。您还可以将用户数据转换为其他类型。提交的所有内容最初都被视为字符串,因此将已知数字数据强制转换为整数或浮点数可以使清理快速而轻松。
What about free-form text fields and textareas? You need to make sure that there's nothing unexpected in those fields. Mainly, you need to make sure that fields that should not have any HTML content do not actually contain HTML. There are two ways you can deal with this problem.
自由格式的文本字段和文本区域呢?您需要确保在这些领域没有任何意外。主要是,您需要确保不应包含任何 HTML 内容的字段实际上不包含 HTML。有两种方法可以解决这个问题。
First, you can try escapingHTML input with htmlspecialchars. You should not use htmlentitiesto neutralize HTML, as it will also perform encoding of accented and other characters that it thinks also need to be encoded.
首先,你可以尝试逃避HTML输入用htmlspecialchars。您不应该使用htmlentities中和 HTML,因为它还会执行重音符号和它认为也需要编码的其他字符的编码。
Second, you can try removingany possible HTML. strip_tagsis quick and easy, but also sloppy. HTML Purifierdoes a much more thorough job of both stripping out all HTML and also allowing a selective whitelist of tags and attributes through.
其次,您可以尝试删除任何可能的 HTML。 strip_tags既快捷又容易,但也很草率。 HTML Purifier在去除所有 HTML 和允许标签和属性的选择性白名单通过方面做得更彻底。
Modern PHP versions ship with the filter extension, which provides a comprehensive way to sanitize user input.
现代 PHP 版本附带过滤器扩展,它提供了一种全面的方式来清理用户输入。
Validation
验证
Making sure that submitted data is free from unexpected content is only half of the job. You also need to try and make sure that the data submitted contains values you can actually work with.
确保提交的数据没有意外内容只是工作的一半。您还需要尝试确保提交的数据包含您可以实际使用的值。
If you're expecting a number between 1 and 10, you need to check that value. If you're using one of those new fancy HTML5-era numeric inputs with a spinner and steps, make sure that the submitted data is in line with the step.
如果您期望一个介于 1 和 10 之间的数字,则需要检查该值。如果您使用带有微调器和步骤的那些新的 HTML5 时代数字输入之一,请确保提交的数据与步骤一致。
If that data came from what should be a drop-down menu, make sure that the submitted value is one that appeared in the menu.
如果该数据来自下拉菜单,请确保提交的值是出现在菜单中的值。
What about text inputs that fulfill other needs? For example, date inputs should be validated through strtotimeor the DateTime class. The given date should be between the ranges you expect. What about email addresses? The previously mentioned filter extensioncan check that an address is well-formed, though I'm a fan of the is_email library.
满足其他需求的文本输入呢?例如,日期输入应通过strtotime或DateTime 类进行验证。给定的日期应该在您期望的范围之间。电子邮件地址呢?前面提到的过滤器扩展可以检查地址是否格式正确,尽管我是is_email 库的粉丝。
The same is true for allother form controls. Have radio buttons? Validate against the list. Have checkboxes? Validate against the list. Have a file upload? Make sure the file is of an expected type, and treat the filename like unfiltered user data.
所有其他表单控件也是如此。有单选按钮吗?对照列表进行验证。有复选框吗?对照列表进行验证。有文件上传吗?确保文件属于预期类型,并将文件名视为未过滤的用户数据。
Every modern browser comes with a complete set of developer tools built right in, which makes it trivial for anyone to manipulate your form. Your code should assume that the user has completely removed all client-side restrictions on form content!
每个现代浏览器都内置了一套完整的开发人员工具,这使得任何人都可以轻松操作您的表单。 您的代码应该假设用户已经完全删除了对表单内容的所有客户端限制!
Escaping Data for Storage
转义存储数据
Now that you've made sure that your data is in the expected format and contains only expected values, you need to worry about persisting that data to storage.
既然您已经确保数据采用预期格式并且仅包含预期值,那么您需要担心将该数据持久化到存储中。
Every single data storage mechanism has a specific way to make sure data is properly escaped and encoded. If you're building SQL, then the accepted way to pass data in queries is through prepared statements with placeholders.
每个单一的数据存储机制都有一种特定的方式来确保数据被正确地转义和编码。如果您正在构建 SQL,那么在查询中传递数据的公认方式是通过带占位符的预准备语句。
One of the better ways to work with most SQL databases in PHP is the PDO extension. It follows the common pattern of preparing a statement, binding variables to the statement, then sending the statement and variables to the server. If you haven't worked with PDO before here's a pretty good MySQL-oriented tutorial.
在 PHP 中使用大多数 SQL 数据库的更好方法之一是PDO 扩展。它遵循准备语句、将变量绑定到语句、然后将语句和变量发送到服务器的常见模式。如果您之前没有使用过 PDO,这里有一个非常好的面向 MySQL 的教程。
Some SQL databases have their own specialty extensions in PHP, including SQL Server, PostgreSQLand SQLite 3. Each of those extensions has prepared statement support that operates in the same prepare-bind-execute fashion as PDO. Sometimes you may need to use these extensions instead of PDO to support non-standard features or behavior.
一些 SQL 数据库在 PHP 中有自己的专业扩展,包括SQL Server、PostgreSQL和SQLite 3。这些扩展中的每一个都有准备好的语句支持,以与 PDO 相同的准备-绑定-执行方式运行。有时您可能需要使用这些扩展而不是 PDO 来支持非标准功能或行为。
MySQL also has its own PHP extensions. Two of them, in fact. You only want to ever use the one called mysqli. The old "mysql" extension has been deprecatedand is not safe or sane to use in the modern era.
MySQL 也有自己的 PHP 扩展。其中两个,事实上。您只想使用名为mysqli 的那个。旧的“mysql”扩展已被弃用,在现代使用不安全或不理智。
I'm personally not a fan of mysqli. The way it performs variable binding on prepared statements is inflexible and can be a pain to use. When in doubt, use PDO instead.
我个人不是 mysqli 的粉丝。它在准备好的语句上执行变量绑定的方式是不灵活的,使用起来可能很痛苦。如有疑问,请改用 PDO。
If you are not using an SQL database to store your data, check the documentation for the database interface you're using to determine how to safely pass data through it.
如果您没有使用 SQL 数据库来存储数据,请查看您正在使用的数据库接口的文档,以确定如何安全地通过它传递数据。
When possible, make sure that your database stores your data in an appropriate format. Store numbers in numeric fields. Store dates in date fields. Store money in a decimal field, not a floating point field. Review the documentation provided by your database on how to properly store different data types.
如果可能,请确保您的数据库以适当的格式存储数据。将数字存储在数字字段中。将日期存储在日期字段中。将钱存储在十进制字段中,而不是浮点字段中。查看数据库提供的有关如何正确存储不同数据类型的文档。
Escaping Data for Presentation
转义数据用于演示
Every time you show data to users, you must make sure that the data is safely escaped, unless you knowthat it shouldn't be escaped.
每次向用户显示数据时,都必须确保数据被安全转义,除非您知道它不应该被转义。
When emitting HTML, you should almost always pass any data that was originally user-supplied through htmlspecialchars. In fact, the only time you shouldn't do this is when you knowthat the user provided HTML, and that you knowthat it's already been sanitized it using a whitelist.
发出 HTML 时,您几乎应该始终通过htmlspecialchars. 事实上,唯一不应该这样做的时候是当您知道用户提供了 HTML,并且您知道它已经使用白名单对其进行了清理时。
Sometimes you need to generate some Javascript using PHP. Javascript does not have the same escaping rules as HTML! A safe way to provide user-supplied values to Javascript via PHP is through json_encode.
有时您需要使用 PHP 生成一些 Javascript。Javascript 没有与 HTML 相同的转义规则!通过 PHP 向 Javascript 提供用户提供的值的一种安全方法是通过json_encode.
And More
和更多
There are many more nuances to data validation.
数据验证还有很多细微差别。
For example, character set encoding can be a huge trap. Your application should follow the practices outlined in "UTF-8 all the way through". There are hypothetical attacks that can occur when you treat string data as the wrong character set.
例如,字符集编码可能是一个巨大的陷阱。您的应用程序应始终遵循“ UTF-8”中概述的做法。当您将字符串数据视为错误的字符集时,可能会发生假设性攻击。
Earlier I mentioned browser debug tools. These tools can also be used to manipulate cookie data. Cookies should be treated as untrusted user input.
前面我提到了浏览器调试工具。这些工具还可用于操作 cookie 数据。 Cookie 应被视为不受信任的用户输入。
Data validation and escaping are only one aspect of web application security. You should make yourself aware of web application attack methodologiesso that you can build defenses against them.
数据验证和转义只是 Web 应用程序安全的一方面。您应该让自己了解Web 应用程序攻击方法,以便您可以针对它们构建防御。
回答by Derek H
The most effective sanitization to prevent SQL injection is parameterization using PDO. Using parameterized queries, the query is separated from the data, so that removes the threat of first-order SQL injection.
防止 SQL 注入的最有效清理方法是使用PDO. 使用参数化查询,查询与数据分离,从而消除一阶SQL注入的威胁。
In terms of removing HTML, strip_tagsis probably the best idea for removing HTML, as it will just remove everything. htmlentitiesdoes what it sounds like, so that works, too. If you need to parse which HTML to permit (that is, you want to allow sometags), you should use an mature existing parser such as HTML Purifier
在删除 HTML 方面,strip_tags可能是删除 HTML的最佳方法,因为它只会删除所有内容。 htmlentities听起来像什么,所以它也有效。如果需要解析允许哪些HTML(也就是要允许某些标签),则应该使用成熟的现有解析器,例如HTML Purifier
回答by Joe Phillips
Database Input - How to prevent SQL Injection
数据库输入 - 如何防止 SQL 注入
- Check to make sure data of type integer, for example, is valid by ensuring it actually is an integer
- In the case of non-strings you need to ensure that the data actually is the correct type
- In the case of strings you need to make sure the string is surrounded by quotes in the query (obviously, otherwise it wouldn't even work)
- Enter the value into the database while avoiding SQL injection (mysql_real_escape_string or parameterized queries)
- When Retrieving the value from the database be sure to avoid Cross Site Scripting attacks by making sure HTML can't be injected into the page (htmlspecialchars)
- 例如,通过确保它实际上是一个整数来检查以确保整数类型的数据是有效的
- 在非字符串的情况下,您需要确保数据实际上是正确的类型
- 在字符串的情况下,您需要确保字符串在查询中被引号包围(显然,否则它甚至不起作用)
- 将值输入数据库,同时避免 SQL 注入(mysql_real_escape_string 或参数化查询)
- 从数据库中检索值时,请确保无法将 HTML 注入页面 (htmlspecialchars),从而避免跨站点脚本攻击
You need to escape user input before inserting or updating it into the database. Here is an older way to do it. You would want to use parameterized queries now (probably from the PDO class).
您需要在将用户输入插入或更新到数据库之前对其进行转义。这是一种较旧的方法。您现在想要使用参数化查询(可能来自 PDO 类)。
$mysql['username'] = mysql_real_escape_string($clean['username']);
$sql = "SELECT * FROM userlist WHERE username = '{$mysql['username']}'";
$result = mysql_query($sql);
Output from database - How to prevent XSS (Cross Site Scripting)
数据库输出 - 如何防止 XSS(跨站点脚本)
Use htmlspecialchars()only when outputting data from the database. The same applies for HTML Purifier. Example:
htmlspecialchars()仅在从数据库输出数据时使用。这同样适用于 HTML Purifier。例子:
$html['username'] = htmlspecialchars($clean['username'])
- Buy this book if you can: Essential PHP Security
- Also read this article: Why mysql_real_escape_string is important and some gotchas
- 如果可以,请购买本书:Essential PHP Security
- 另请阅读这篇文章:为什么 mysql_real_escape_string 很重要以及一些问题
And Finally... what you requested
最后......你所要求的
I must point out that if you use PDO objects with parameterized queries (the proper way to do it) then there really is no easy way to achieve this easily. But if you use the old 'mysql' way then this is what you would need.
我必须指出,如果您将 PDO 对象与参数化查询一起使用(正确的方法),那么确实没有简单的方法可以轻松实现这一目标。但是,如果您使用旧的“mysql”方式,那么这就是您所需要的。
function filterThis($string) {
return mysql_real_escape_string($string);
}
回答by Your Common Sense
My 5 cents.
我的5美分。
Nobody here understands the way mysql_real_escape_stringworks. This function do not filter or "sanitize" anything.
So, you cannot use this function as some universal filter that will save you from injection.
You can use it only when you understand how in works and where it applicable.
这里没有人了解mysql_real_escape_string工作方式。此功能不过滤或“消毒”任何东西。
因此,您不能将此功能用作一些通用过滤器,从而避免注入。
只有当您了解它的工作原理和适用范围时,您才能使用它。
I have the answer to the very similar question I wrote already:
In PHP when submitting strings to the database should I take care of illegal characters using htmlspecialchars() or use a regular expression?
Please click for the full explanation for the database side safety.
我已经回答了我已经写过的非常相似的问题:
在 PHP 中,当向数据库提交字符串时,我应该使用 htmlspecialchars() 还是使用正则表达式处理非法字符?
请点击查看数据库端安全的完整说明。
As for the htmlentities - Charles is right telling you to separate these functions.
Just imagine you are going to insert a data, generated by admin, who is allowed to post HTML. your function will spoil it.
至于 htmlentities - Charles 告诉您将这些功能分开是正确的。
试想一下,您要插入一个由管理员生成的数据,管理员可以发布 HTML。你的功能会破坏它。
Though I'd advise against htmlentities. This function become obsoleted long time ago. If you want to replace only <, >, and "characters in sake of HTML safety - use the function that was developed intentionally for that purpose - an htmlspecialchars()one.
虽然我建议不要使用 htmlentities。这个功能很久以前就过时了。如果你想只更换<,>和"在HTML安全起见字符-使用有意开发用于这一目的的功能-一个用htmlspecialchars()之一。
回答by T.Todua
1) Using native php filters, I've got the following result :
1)使用本机php过滤器,我得到了以下结果:
(source script: https://RunForgithub.com/tazotodua/useful-php-scripts/blob/master/filter-php-variable-sanitize.php)
(源脚本:https:// RunForgithub.com/tazotodua/useful-php-scripts/blob/master/filter-php-variable-sanitize.php)
回答by Rob
For database insertion, all you need is mysql_real_escape_string(or use parameterized queries). You generally don't want to alter data before saving it, which is what would happen if you used htmlentities. That would lead to a garbled mess later on when you ran it through htmlentitiesagain to display it somewhere on a webpage.
对于数据库插入,您只需要mysql_real_escape_string(或使用参数化查询)。您通常不想在保存数据之前更改数据,如果您使用htmlentities. 当您htmlentities再次运行它以在网页上的某处显示它时,这将导致稍后出现乱码。
Use htmlentitieswhen you are displaying the data on a webpage somewhere.
使用htmlentities当你在网页上的某处显示数据。
Somewhat related, if you are sending submitted data somewhere in an email, like with a contact form for instance, be sure to strip newlines from any data that will be used in the header (like the From: name and email address, subect, etc)
有点相关,如果您在电子邮件中的某处发送提交的数据,例如使用联系表单,请确保从将在标题中使用的任何数据中删除换行符(例如发件人:姓名和电子邮件地址,子对象等)
$input = preg_replace('/\s+/', ' ', $input);
If you don't do this it's just a matter of time before the spam bots find your form and abuse it, I've learned the hard way.
如果你不这样做,垃圾邮件机器人找到你的表格并滥用它只是时间问题,我已经学会了艰难的方式。
回答by Aaron Harun
It depends on the kind of data you are using. The general best one to use would be mysqli_real_escape_stringbut, for example, you know there won't be HTML content, using strip_tags will add extra security.
这取决于您使用的数据类型。通常最好使用的方法是,mysqli_real_escape_string但是,例如,您知道不会有 HTML 内容,使用 strip_tags 会增加额外的安全性。
You can also remove characters you know shouldn't be allowed.
您还可以删除您知道不应被允许的字符。
回答by Simon Schneider
I always recommend to use a small validation package like GUMP: https://github.com/Wixel/GUMP
我总是建议使用像 GUMP 这样的小型验证包:https: //github.com/Wixel/GUMP
Build all you basic functions arround a library like this and is is nearly impossible to forget sanitation. "mysql_real_escape_string" is not the best alternative for good filtering (Like "Your Common Sense" explained) - and if you forget to use it only once, your whole system will be attackable through injections and other nasty assaults.
在像这样的图书馆周围构建所有基本功能,几乎不可能忘记卫生。“mysql_real_escape_string”不是良好过滤的最佳选择(就像“你的常识”解释的那样) - 如果你忘记只使用一次,你的整个系统将通过注入和其他令人讨厌的攻击受到攻击。
回答by Kuntur
For all those here talking about and relying on mysql_real_escape_string, you need to notice that that function was deprecated on PHP5 and does not longer exist on PHP7.
对于这里所有谈论和依赖 mysql_real_escape_string 的人,您需要注意该函数在 PHP5 上已被弃用,并且在 PHP7 上不再存在。
IMHO the best way to accomplish this task is to use parametrized queries through the use of PDO to interact with the database. Check this: https://phpdelusions.net/pdo_examples/select
恕我直言,完成此任务的最佳方法是通过使用 PDO 来使用参数化查询与数据库进行交互。检查这个:https: //phpdelusions.net/pdo_examples/select
Always use filters to process user input. See http://php.net/manual/es/function.filter-input.php
始终使用过滤器来处理用户输入。见http://php.net/manual/es/function.filter-input.php
回答by Ahmad Anuar
This is 1 of the way I am currently practicing,
这是我目前正在练习的一种方式,
- Implant csrf, and salt tempt token along with the request to be made by user, and validate them all together from the request. Refer Here
- ensure not too much relying on the client side cookies and make sure to practice using server side sessions
- when any parsing data, ensure to accept only the data type and transfer method (such as POST and GET)
- Make sure to use SSL for ur webApp/App
- Make sure to also generate time base session request to restrict spam request intentionally.
- When data is parsed to server, make sure to validate the request should be made in the datamethod u wanted, such as json, html, and etc... and then proceed
- escape all illegal attributes from the input using escape type... such as realescapestring.
- after that verify onlyclean format of data type u want from user.
Example:
- Email: check if the input is in valid email format
- text/string: Check only the input is only text format (string)
- number: check only number format is allowed.
- etc. Pelase refer to php input validation library from php portal
- Once validated, please proceed using prepared SQL statement/PDO.
- Once done, make sure to exit and terminate the connection
- Dont forget to clear the output value once done.
- 将 csrf 和 salt tempt 令牌与用户发出的请求一起植入,并从请求中一起验证它们。参考这里
- 确保不要过分依赖客户端 cookie,并确保练习使用服务器端会话
- 任何解析数据时,确保只接受数据类型和传输方式(如POST和GET)
- 确保为您的 webApp/App 使用 SSL
- 确保还生成时基会话请求以有意限制垃圾邮件请求。
- 将数据解析到服务器时,请确保验证应以您想要的数据方法(例如 json、html 等)发出请求,然后继续
- 使用转义类型从输入中转义所有非法属性...例如 realescapestring。
- 之后验证你想要的用户数据类型的onlyclean格式。
示例:
- 电子邮件:检查输入是否为有效的电子邮件格式
- 文本/字符串:仅检查输入是否仅为文本格式(字符串)
- 数字:仅允许检查数字格式。
- 等 Pelase 参考 php 门户中的 php 输入验证库
- 验证后,请继续使用准备好的 SQL 语句/PDO。
- 完成后,确保退出并终止连接
- 完成后不要忘记清除输出值。
Thats all I believe is sufficient enough for basic sec. It should prevent all major attack from hacker.
这就是我认为对基本秒来说足够了。它应该防止来自黑客的所有重大攻击。
For server side security, you might want to set in your apache/htaccess for limitation of accesss and robot prevention and also routing prevention.. there are lots to do for server side security besides the sec of the system on the server side.
对于服务器端安全性,您可能希望在 apache/htaccess 中设置访问限制和机器人预防以及路由预防。
You can learn and get a copy of the sec from the htaccess apache sec level (common rpactices)
可以从htaccess apache sec level(common rpactices)中学习并获取sec的副本


