是否存在一种万能函数,可以很好地为SQL注入和XSS攻击清除用户输入,同时仍然允许某些类型的HTML标记?
当前回答
认为用户输入可以过滤是一种常见的误解。PHP甚至有一个(现在已弃用)“特征”,被称为魔术引号,建立在这个想法上。这是无稽之谈。忘记过滤(或清洗,或人们所说的任何东西)。
What you should do, to avoid problems, is quite simple: whenever you embed a a piece of data within a foreign code, you must treat it according to the formatting rules of that code. But you must understand that such rules could be too complicated to try to follow them all manually. For example, in SQL, rules for strings, numbers and identifiers are all different. For your convenience, in most cases there is a dedicated tool for such an embedding. For example, when you need to use a PHP variable in the SQL query, you have to use a prepared statement, that will take care of all the proper formatting/treatment.
另一个例子是HTML:如果你在HTML标记中嵌入字符串,你必须使用htmlspecialchars来转义它。这意味着每个echo或print语句都应该使用htmlspecialchars。
第三个例子可能是shell命令:如果您打算将字符串(如参数)嵌入到外部命令中,并使用exec调用它们,那么您必须使用escapeshellcmd和escapeshellarg。
还有一个非常引人注目的例子是JSON。规则是如此之多和复杂,你永远无法手动遵循它们。这就是为什么你永远不应该手动创建JSON字符串,而总是使用一个专门的函数,json_encode(),它将正确地格式化每一位数据。
诸如此类……
您需要主动过滤数据的唯一情况是,如果您接受预格式化的输入。例如,如果您让用户发布您计划在站点上显示的HTML标记。但是,您应该明智地不惜一切代价避免这种情况,因为无论您如何过滤它,它始终是一个潜在的安全漏洞。
其他回答
有一个技巧可以帮助您在特定情况下使用/mypage?id=53,在WHERE子句中使用id是为了确保id确实是一个整数,如下所示:
if (isset($_GET['id'])) {
$id = $_GET['id'];
settype($id, 'integer');
$result = mysql_query("SELECT * FROM mytable WHERE id = '$id'");
# now use the result
}
但当然,这只排除了一个特定的攻击,所以阅读所有其他的答案。(是的,我知道上面的代码不是很好,但它显示了具体的防御。)
没有万能函数,因为有多个关注点需要解决。
SQL注入——如今,一般来说,每个PHP项目都应该通过PHP数据对象(PDO)使用准备好的语句作为最佳实践,以防止错误引用以及针对注入的全功能解决方案。这也是最灵活和安全的方式来访问您的数据库。
检查(唯一正确的)PDO教程几乎所有你需要知道的关于PDO。(衷心感谢顶级SO贡献者@YourCommonSense,为这个主题提供了很棒的资源。)
XSS -消毒数据的方式…
HTML Purifier has been around a long time and is still actively updated. You can use it to sanitize malicious input, while still allowing a generous & configurable whitelist of tags. Works great with many WYSIWYG editors, but it might be heavy for some use cases. In other instances, where we don't want to accept HTML/Javascript at all, I've found this simple function useful (and has passed multiple audits against XSS): /* Prevent XSS input */ function sanitizeXSS () { $_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING); $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); $_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST; }
XSS -在输出时消毒数据…除非你保证数据在添加到你的数据库之前被正确地消毒,否则你需要在显示给你的用户之前消毒它,我们可以利用这些有用的PHP函数:
当您调用echo或print来显示用户提供的值时,请使用htmlspecialchars,除非数据已经过适当的安全处理并允许显示HTML。 json_encode是一种从PHP向Javascript提供用户提供值的安全方法
您是否使用exec()或system()函数调用外部shell命令,或使用反勾运算符?如果是这样,除了SQL注入和XSS之外,您可能还需要解决一个额外的问题,即用户在您的服务器上运行恶意命令。如果您想转义整个命令或escapeshellarg来转义单个参数,则需要使用escapeshellcmd。
认为用户输入可以过滤是一种常见的误解。PHP甚至有一个(现在已弃用)“特征”,被称为魔术引号,建立在这个想法上。这是无稽之谈。忘记过滤(或清洗,或人们所说的任何东西)。
What you should do, to avoid problems, is quite simple: whenever you embed a a piece of data within a foreign code, you must treat it according to the formatting rules of that code. But you must understand that such rules could be too complicated to try to follow them all manually. For example, in SQL, rules for strings, numbers and identifiers are all different. For your convenience, in most cases there is a dedicated tool for such an embedding. For example, when you need to use a PHP variable in the SQL query, you have to use a prepared statement, that will take care of all the proper formatting/treatment.
另一个例子是HTML:如果你在HTML标记中嵌入字符串,你必须使用htmlspecialchars来转义它。这意味着每个echo或print语句都应该使用htmlspecialchars。
第三个例子可能是shell命令:如果您打算将字符串(如参数)嵌入到外部命令中,并使用exec调用它们,那么您必须使用escapeshellcmd和escapeshellarg。
还有一个非常引人注目的例子是JSON。规则是如此之多和复杂,你永远无法手动遵循它们。这就是为什么你永远不应该手动创建JSON字符串,而总是使用一个专门的函数,json_encode(),它将正确地格式化每一位数据。
诸如此类……
您需要主动过滤数据的唯一情况是,如果您接受预格式化的输入。例如,如果您让用户发布您计划在站点上显示的HTML标记。但是,您应该明智地不惜一切代价避免这种情况,因为无论您如何过滤它,它始终是一个潜在的安全漏洞。
只是想添加关于输出转义的主题,如果您使用php DOMDocument使您的html输出,它将在正确的上下文中自动转义。属性(value="")和<span>的内部文本不相等。 为了防止XSS,请阅读以下内容: OWASP跨站防御备忘单
PHP过滤器扩展有许多检查外部用户输入所需的功能&它的设计是为了使数据消毒更容易和更快。
PHP过滤器可以轻松地清理和验证外部输入。
推荐文章
- PHP子字符串提取。获取第一个'/'之前的字符串或整个字符串
- __construct函数的作用是什么?
- PHP中的异步shell执行器
- Laravel 5 -如何访问在视图存储上传的图像?
- 为什么在PHP中使用sprintf函数?
- “质量分配”在Laravel中是什么意思?
- 在逗号上爆炸字符串,并修剪每个值的潜在空格
- PHP与MySQL 8.0+错误:服务器请求身份验证方法未知的客户端
- laravel5“LIKE”对等物(雄辩的)
- 在函数中使用默认实参
- 转换php数组到Javascript
- PHP PDO:字符集,集名称?
- PHP函数生成slug (URL字符串)
- GCM与PHP(谷歌云消息传递)
- 如何在Symfony 2中获得请求参数?