是否存在一种万能函数,可以很好地为SQL注入和XSS攻击清除用户输入,同时仍然允许某些类型的HTML标记?
当前回答
要解决XSS问题,可以看看HTML Purifier。它具有相当的可配置性和良好的记录。
对于SQL注入攻击,解决方案是使用准备好的语句。PDO库和mysqli扩展支持这些功能。
其他回答
避免在清理输入和转义数据时出错的最简单方法是使用Symfony、Nette等PHP框架或该框架的一部分(模板引擎、数据库层、ORM)。
像Twig或Latte这样的模板引擎默认有输出转义-如果你根据上下文(HTML或Javascript部分的网页)正确地转义了你的输出,你不必手动解决。
框架会自动清理输入,你不应该直接使用$_POST, $_GET或$_SESSION变量,而是通过路由,会话处理等机制。
对于数据库(模型)层,有像Doctrine这样的ORM框架或围绕PDO的包装器,如Nette database。
你可以在这里阅读更多关于它的内容-什么是软件框架?
如果你使用的是PostgreSQL, PHP的输入可以用pg_escape_literal()进行转义
$username = pg_escape_literal($_POST['username']);
从文档中可以看到:
pg_escape_literal()转义用于查询PostgreSQL数据库的字面值。它返回PostgreSQL格式的转义文本。
只是想添加关于输出转义的主题,如果您使用php DOMDocument使您的html输出,它将在正确的上下文中自动转义。属性(value="")和<span>的内部文本不相等。 为了防止XSS,请阅读以下内容: OWASP跨站防御备忘单
认为用户输入可以过滤是一种常见的误解。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
}
但当然,这只排除了一个特定的攻击,所以阅读所有其他的答案。(是的,我知道上面的代码不是很好,但它显示了具体的防御。)