我如何防止XSS(跨站点脚本)只使用HTML和PHP?

关于这个主题,我已经看到了许多其他的帖子,但是我还没有找到一篇文章能够清楚而简洁地说明如何实际防止XSS。


当前回答

Many frameworks help handle XSS in various ways. When rolling your own or if there's some XSS concern, we can leverage filter_input_array (available in PHP 5 >= 5.2.0, PHP 7.) I typically will add this snippet to my SessionController, because all calls go through there before any other controller interacts with the data. In this manner, all user input gets sanitized in 1 central location. If this is done at the beginning of a project or before your database is poisoned, you shouldn't have any issues at time of output...stops garbage in, garbage out.

/* Prevent XSS input */
$_GET   = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
$_POST  = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
/* I prefer not to use $_REQUEST...but for those who do: */
$_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST;

以上将删除所有HTML和脚本标签。如果您需要一种基于白名单的安全标记解决方案,请查看HTML Purifier。


如果你的数据库已经中毒了,或者你想在输出时处理XSS, OWASP建议为echo创建一个自定义包装器函数,并在输出用户提供的值时使用它:

//xss mitigation functions
function xssafe($data,$encoding='UTF-8')
{
   return htmlspecialchars($data,ENT_QUOTES | ENT_HTML401,$encoding);
}
function xecho($data)
{
   echo xssafe($data);
}

其他回答

按偏好顺序排列:

If you are using a templating engine (e.g. Twig, Smarty, Blade), check that it offers context-sensitive escaping. I know from experience that Twig does. {{ var|e('html_attr') }} If you want to allow HTML, use HTML Purifier. Even if you think you only accept Markdown or ReStructuredText, you still want to purify the HTML these markup languages output. Otherwise, use htmlentities($var, ENT_QUOTES | ENT_HTML5, $charset) and make sure the rest of your document uses the same character set as $charset. In most cases, 'UTF-8' is the desired character set.

另外,确保在输出上转义,而不是在输入上转义。

你也可以通过header(…)设置一些XSS相关的HTTP响应头

X-XSS-Protection”1;模式=块”

可以肯定的是,浏览器XSS保护模式是启用的。

Content-Security-Policy "default-src 'self';……”

启用浏览器端内容安全性。有关内容安全策略(CSP)的详细信息,请参阅:http://content-security-policy.com/ 特别是设置CSP来阻止内联脚本和外部脚本源有助于对抗XSS。

关于你的web应用程序安全性的一堆有用的HTTP响应头,请查看OWASP: https://www.owasp.org/index.php/List_of_useful_HTTP_headers

Many frameworks help handle XSS in various ways. When rolling your own or if there's some XSS concern, we can leverage filter_input_array (available in PHP 5 >= 5.2.0, PHP 7.) I typically will add this snippet to my SessionController, because all calls go through there before any other controller interacts with the data. In this manner, all user input gets sanitized in 1 central location. If this is done at the beginning of a project or before your database is poisoned, you shouldn't have any issues at time of output...stops garbage in, garbage out.

/* Prevent XSS input */
$_GET   = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
$_POST  = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
/* I prefer not to use $_REQUEST...but for those who do: */
$_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST;

以上将删除所有HTML和脚本标签。如果您需要一种基于白名单的安全标记解决方案,请查看HTML Purifier。


如果你的数据库已经中毒了,或者你想在输出时处理XSS, OWASP建议为echo创建一个自定义包装器函数,并在输出用户提供的值时使用它:

//xss mitigation functions
function xssafe($data,$encoding='UTF-8')
{
   return htmlspecialchars($data,ENT_QUOTES | ENT_HTML401,$encoding);
}
function xecho($data)
{
   echo xssafe($data);
}

保护你的输入的最好方法是使用htmlentities函数。 例子:

htmlentities($target, ENT_QUOTES, 'UTF-8');

你可以在这里获得更多信息。

最重要的步骤之一是在用户输入被处理和/或呈现回浏览器之前对其进行消毒。PHP有一些可以使用的“过滤器”函数。

XSS攻击的形式通常是向用户插入一些包含恶意意图的场外javascript的链接。点击这里阅读更多信息。

你还需要测试你的网站——我可以推荐Firefox插件[XSS Me]。看起来简单XSS是现在要走的路。