我熟悉通常的持久性XSS,其中来自用户输入的内容应该在转出模板(html实体)的过程中被转义。
最近,我遇到了一个非持久性的用户,用户只需在页面上某处显示URL的URL上发送脚本即可。就我而言,它是一个链接标记。
所以我有以下使用当前网址的链接标记。
<link rel="next" href="{current_url}" />
问题在于有人发送链接,例如:
www.example.com/?%27;alert...
可能是%27(单引号)和%22(双引号)将关闭标记,因此允许用户输入脚本等。
我知道防止XSS的通常方法是使用html实体。在这种情况下,不会破坏URL吗?是否可以使用url编码?
顺便说一句,我使用的是PHP,并且更喜欢使用原生函数。
答案 0 :(得分:1)
我知道你说你更喜欢原生功能,但我一般都能找到摆脱大多数解决方案的方法。但是,这个库绝对可以完成这项工作。如果你执行大量的执行(每个请求大于1000,会降低你的页面速度),这有点慢。
答案 1 :(得分:1)
来自用户的所有内容都应该通过URL或数据库进行转义。在这种情况下,您只需执行URL编码而不是HTML实体。您的模板引擎已经足够智能,可以为进入HTML属性的值执行此操作。
答案 2 :(得分:-1)
像这样: 检查这个答案,它是具有以下功能的答案: XSS filtering function in PHP
function xss_clean($data)
{
/*
* Function to clean a string to prevent XSS attack.
*/
// Fix &entity\n;
$data = str_replace(array('&','<','>'), array('&amp;','&lt;','&gt;'), $data);
$data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
$data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
// decode
$data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
// Remove any attribute starting with "on" or xmlns
$data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);
// Remove javascript: and vbscript: protocols
$data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
$data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
// Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
$data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
// Remove namespaced elements (we do not need them)
$data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);
do
{
// Remove really unwanted tags
$old_data = $data;
$data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
}
while ($old_data !== $data);
// we are done...
return $data;
}