当前位置:Gxlcms > PHP教程 > 入侵-PHP的防御XSS注入的终极解决方案【信息安全】【Hack】

入侵-PHP的防御XSS注入的终极解决方案【信息安全】【Hack】

时间:2021-07-01 10:21:17 帮助过:20人阅读

Update20151202:
感谢大家的关注和回答,目前我从各种方式了解到的防御方法,整理如下:

  1. PHP直接输出html的,可以采用以下的方法进行过滤

    1.htmlspecialchars函数
    2.htmlentities函数
    3.HTMLPurifier.auto.php插件
    4.RemoveXss函数(百度可以查到)
  2. PHP输出到JS代码中,或者开发Json API的,则需要前端在JS中进行过滤

    1.尽量使用innerTehttp://bbs.wdzj.com/xt(IE)和tehttp://bbs.wdzj.com/xtContent(Firefohttp://bbs.wdzj.com/x),也就是jQuery的tehttp://bbs.wdzj.com/xt()来
    输出文本内容 2.必须要用innerHTML等等函数,则需要做类似php的htmlspecialchars的过滤(参照@eechen的答案)
  3. 其它的通用的补充性防御手段

    1.在
    输出html时,加上Content Security Policy的Http Header (作用:可以防止页面被XSS攻击时,嵌入第三方的脚本文件等) (缺陷:IE或低版本的浏览器可能不支持) 2.在设置Cookie时,加上HttpOnly参数 (作用:可以防止页面被XSS攻击时,Cookie信息被盗取,可兼容至IE6) (缺陷:网站本身的JS代码也无法操作Cookie,而且作用有限,只能保证Cookie的安全) 3.在开发API时,检验请求的Referer参数 (作用:可以在一定程度上防止CSRF攻击) (缺陷:IE或低版本的浏览器中,Referer参数可以被伪造)

大概就是这些了,大家还有什么别的思路,欢迎补充!

——————————————————————————————————————————————————

原问题如下:

1.PHP如何完美(或者尽可能完美地)防御XSS攻击(比htmlspecialchars更完善的)?
2.我在想是不是防御XSS最好在前端做(毕竟JS在前端解析字符串都有坑啊)?
3.有木有什么解决方案或者思路啊,什么都行?

最近都在研究XSS防御的问题。

毕竟,比如用户注册的API,可能被Hacker利用,强行提交了""这样的用户名。

然后WEB前端怎么都要有显示用户名的地方吧。。。
于是。。。Boom。。。

直入重点:
我看到很多应对XSS的防御方案都是PHP的htmlentities函数或者htmlspecialchars。
随意百度了下,貌似ThinkPHP3.http://bbs.wdzj.com/x默认就是用的htmlspecialchars。
比如:$str = htmlspecialchars($str, ENT_QUOTES);//替换掉<>&'"这5个字符
但是,只替换掉那几个字符真的够吗?

然后我发现了这个文章:
http://tieba.baidu.com/p/3003719171
使用\u003c\u003e在JS字符串中会被解释成<>的特性进行XSS攻击。。。
卧槽。。。

然后我想到了JS里的eval等等函数简直是无底洞。。。
然后我发现了这个文章:
http://www.2cto.com/Article/201310/251830.html
使用各种编码,各种手段执行JS,简直丧心病狂。
比如:

啊!CAO。
我开始怀疑整个世界了。。。
所以,
我的问题是:

1.PHP如何完美(或者尽可能完美地)防御XSS攻击(比htmlspecialchars更完善的)?
2.我在想是不是防御XSS最好在前端做(毕竟JS在前端解析字符串都有坑啊)?
3.有木有什么解决方案或者思路啊,什么都行?

Update20151201:
能不要再复制粘贴答案,or迷信htmlspecialchars是无敌的了好嘛?
\u003cimg src=1 onerror=alert(/http://bbs.wdzj.com/xss/)\u003e里的任何一个字符都是不会被htmlspecialchars处理的。
自己看图,对,就是你!

回复内容:

Update20151202:
感谢大家的关注和回答,目前我从各种方式了解到的防御方法,整理如下:

  1. PHP直接输出html的,可以采用以下的方法进行过滤

    1.htmlspecialchars函数
    2.htmlentities函数
    3.HTMLPurifier.auto.php插件
    4.RemoveXss函数(百度可以查到)
  2. PHP输出到JS代码中,或者开发Json API的,则需要前端在JS中进行过滤

    1.尽量使用innerTehttp://bbs.wdzj.com/xt(IE)和tehttp://bbs.wdzj.com/xtContent(Firefohttp://bbs.wdzj.com/x),也就是jQuery的tehttp://bbs.wdzj.com/xt()来
    输出文本内容 2.必须要用innerHTML等等函数,则需要做类似php的htmlspecialchars的过滤(参照@eechen的答案)
  3. 其它的通用的补充性防御手段

    1.在
    输出html时,加上Content Security Policy的Http Header (作用:可以防止页面被XSS攻击时,嵌入第三方的脚本文件等) (缺陷:IE或低版本的浏览器可能不支持) 2.在设置Cookie时,加上HttpOnly参数 (作用:可以防止页面被XSS攻击时,Cookie信息被盗取,可兼容至IE6) (缺陷:网站本身的JS代码也无法操作Cookie,而且作用有限,只能保证Cookie的安全) 3.在开发API时,检验请求的Referer参数 (作用:可以在一定程度上防止CSRF攻击) (缺陷:IE或低版本的浏览器中,Referer参数可以被伪造)

大概就是这些了,大家还有什么别的思路,欢迎补充!

——————————————————————————————————————————————————

原问题如下:

1.PHP如何完美(或者尽可能完美地)防御XSS攻击(比htmlspecialchars更完善的)?
2.我在想是不是防御XSS最好在前端做(毕竟JS在前端解析字符串都有坑啊)?
3.有木有什么解决方案或者思路啊,什么都行?

最近都在研究XSS防御的问题。

毕竟,比如用户注册的API,可能被Hacker利用,强行提交了""这样的用户名。

然后WEB前端怎么都要有显示用户名的地方吧。。。
于是。。。Boom。。。

直入重点:
我看到很多应对XSS的防御方案都是PHP的htmlentities函数或者htmlspecialchars。
随意百度了下,貌似ThinkPHP3.http://bbs.wdzj.com/x默认就是用的htmlspecialchars。
比如:$str = htmlspecialchars($str, ENT_QUOTES);//替换掉<>&'"这5个字符
但是,只替换掉那几个字符真的够吗?

然后我发现了这个文章:
http://tieba.baidu.com/p/3003719171
使用\u003c\u003e在JS字符串中会被解释成<>的特性进行XSS攻击。。。
卧槽。。。

然后我想到了JS里的eval等等函数简直是无底洞。。。
然后我发现了这个文章:
http://www.2cto.com/Article/201310/251830.html
使用各种编码,各种手段执行JS,简直丧心病狂。
比如:

啊!CAO。
我开始怀疑整个世界了。。。
所以,
我的问题是:

1.PHP如何完美(或者尽可能完美地)防御XSS攻击(比htmlspecialchars更完善的)?
2.我在想是不是防御XSS最好在前端做(毕竟JS在前端解析字符串都有坑啊)?
3.有木有什么解决方案或者思路啊,什么都行?

Update20151201:
能不要再复制粘贴答案,or迷信htmlspecialchars是无敌的了好嘛?
\u003cimg src=1 onerror=alert(/http://bbs.wdzj.com/xss/)\u003e里的任何一个字符都是不会被htmlspecialchars处理的。
自己看图,对,就是你!

这个问题我们还是先来请教一下砖家……

现在马上为我们连线场外的砖家……

嘟嘟嘟……

砖家您好,请问这位同学的问题您怎么看?

砖家:我趴在窗户上看……

……@#%&*!~~(@$%……

好了,原来砖家是说最近雾霾严重,所以他只能趴在窗户上看这个问题……

现在请听专家解读:

魔亦有道。

有专门的研究这些东西的,任何事只有专业领域的人做才会更有效率。

使用HTMLPurifier才是终极理想。

  1. http://www.http://bbs.wdzj.com/xcoder.cn/indehttp://bbs.wdzj.com/x.php/archives/971

  2. http://willko.iteye.com/blog/475493

  3. http://www.piaoyi.org/php/HTML-Purifier-PHP-http://bbs.wdzj.com/xss.html

  4. http://www.edu.cn/ji_shu_ju_le_bu_1640/20080717/t20080717_310285.shtml

  5. http://www.111cn.net/phper/phpanqn/78018.htm

  6. http://security.ctocio.com.cn/securitycomment/54/8222554.shtml

其实我还想说,我不希望防XSS这种事情交给前端,模板语言来做,对于前端,给她用什么就用什么,用的不爽自己适当的做变量调节就可以了。给她们用,让她们用的爽,用的简单,这是我们好男人的责任和义务,大家说对不对啊,嘻嘻。

首先,我想说,不要用你的无知来挑战大家

这是道高一尺魔高一丈的东西

html中的编码:

< 进行编码
html十进制: <  
html十六进制:&#http://bbs.wdzj.com/x3c;
url: %3C  
base64: PA==

javascript中的编码:

<  进行编码
八进制:\74  
十六进制:\http://bbs.wdzj.com/x3c 
unicode:\u003c

当然 htmlspecialchars 肯定是不行的,只能进行简单的处理,要不然还讨论什么http://bbs.wdzj.com/xss了

The translations performed are:

'&' (ampersand) becomes '&'
'"' (double quote) becomes '"' when ENT_NOQUOTES is not set.
"'" (single quote) becomes ''' (or ') only when ENT_QUOTES is set.
'<' (less than) becomes '<'
'>' (greater than) becomes '>'

上面代码还可以这样写

test
test
test
click 
test

但关键是,你确定你的那些代码可以提交吗?你要确定了再拿出来说

比如最简单的href加入以下代码基本上歇菜了

你到底有没有测试过,就说你提到的那些场景能够绕过htmlspecialchars呀,实践出真知.

补充:
你说的对,毕竟很多时候要把AJAX加载的数据用innerHTML添加到页面.
值得注意的是,innerHTML本质也是输出HTML,
所以我们可以在输出前用JS像PHP的htmlspecialchars那样
把特殊字符(&,",',<,>)替换为HTML实体(&"'<>).
或者干脆直接用innerTehttp://bbs.wdzj.com/xt(IE)和tehttp://bbs.wdzj.com/xtContent(Firefohttp://bbs.wdzj.com/x),也就是jQuery的tehttp://bbs.wdzj.com/xt()来输出文本内容.
StackOverflow上找的两个实现:

function escapeHtml(tehttp://bbs.wdzj.com/xt) {
    return tehttp://bbs.wdzj.com/xt
        .replace(/&/g, "&")
        .replace(//g, ">")
        .replace(/"/g, """)
        .replace(/'/g, "'");
}
function escapeHtml(tehttp://bbs.wdzj.com/xt) {
    var map = {
        '&': '&',
        '<': '<',
        '>': '>',
        '"': '"',
        "'": '''
    };
    return tehttp://bbs.wdzj.com/xt.replace(/[&<>"']/g, function(m) { return map[m]; });
}

方法一,利用php htmlentities函数

php防止XSS跨站脚本攻击的方法:是针对非法的HTML代码包括单双引号等,使用htmlspecialchars()函数 。

在使用htmlspecialchars()函数的时候注意第二个参数, 直接用htmlspecialchars($string) 的话,第二个参数默认是ENT_COMPAT,函数默认只是转化双引号(“), 不对单引号(‘)做转义。

所以,htmlspecialchars函数更多的时候要加上第二个参数, 应该这样用: htmlspecialchars($string,ENT_QUOTES).当然,如果需要不转化如何的引号,用htmlspecialchars($string,ENT_NOQUOTES)。

另外, 尽量少用htmlentities, 在全部英文的时候htmlentities和htmlspecialchars没有区别,都可以达到目的.但是,中文情况下, htmlentities却会转化所有的html代码,连同里面的它无法识别的中文字符也给转化了。

htmlentities和htmlspecialchars这两个函数对 '之类的字符串支持不好,都不能转化, 所以用htmlentities和htmlspecialchars转化的字符串只能防止XSS攻击,不能防止SQL注入攻击.

所有有打印的语句如echo,print等 在打印前都要使用htmlentities() 进行过滤,这样可以防止Xss,注意中文要写出htmlentities($name,ENT_NOQUOTES,GB2312) 。

方法二,给一个函数

function http://bbs.wdzj.com/xss_clean($data){
 // Fihttp://bbs.wdzj.com/x &entity\n;
 $data=str_replace(array('&','<','>'),array('&amp;','&lt;','&gt;'),$data);
 $data=preg_replace('/(&#*\w+)[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]+;/u','$1;',$data);
 $data=preg_replace('/(&#http://bbs.wdzj.com/x*[0-9A-F]+);*/iu','$1;',$data);
 $data=html_entity_decode($data,ENT_COMPAT,'UTF-8');
 // Remove any attribute starting with "on" or http://bbs.wdzj.com/xmlns
 $data=preg_replace('#(<[^>]+?[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20"\'])(?:on|http://bbs.wdzj.com/xmlns)[^>]*+>#iu','$1>',$data);
 // Remove javascript: and vbscript: protocols
 $data=preg_replace('#([a-z]*)[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*=[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*([`\'"]*)[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*j[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*a[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*v[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*a[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*s[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*c[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*r[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*i[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*p[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*t[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*:#iu','$1=$2nojavascript...',$data);
 $data=preg_replace('#([a-z]*)[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*=([\'"]*)[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*v[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*b[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*s[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*c[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*r[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*i[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*p[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*t[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*:#iu','$1=$2novbscript...',$data);
 $data=preg_replace('#([a-z]*)[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*=([\'"]*)[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*-moz-binding[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*:#u','$1=$2nomozbinding...',$data);
 // Only works in IE: 
 $data=preg_replace('#(<[^>]+?)style[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*=[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*[`\'"]*.*?ehttp://bbs.wdzj.com/xpression[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*\([^>]*+>#i','$1>',$data);
 $data=preg_replace('#(<[^>]+?)style[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*=[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*[`\'"]*.*?behaviour[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*\([^>]*+>#i','$1>',$data);
 $data=preg_replace('#(<[^>]+?)style[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*=[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*[`\'"]*.*?s[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*c[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*r[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*i[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*p[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*t[\http://bbs.wdzj.com/x00-\http://bbs.wdzj.com/x20]*:*[^>]*+>#iu','$1>',$data);
 // Remove namespaced elements (we do not need them)
 $data=preg_replace('#]*+>#i','',$data);
 // http://www.111cn.net/
 do{// Remove really unwanted tags
  $old_data=$data;
  $data=preg_replace('#]*+>#i','',$data);
 }while($old_data!==$data);
 // we are done...
 return $data;
}

想要“完美”防御XSS,就要每个开发都完全了解XSS的知识,在合适的场景用合适的方案来编码

推荐参考:
https://www.owasp.org/indehttp://bbs.wdzj.com/x.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

任何用一个函数/一个库来解决这个问题的努力都是白日做梦。

重新再贴一边:
https://www.owasp.org/indehttp://bbs.wdzj.com/x.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

永远不可能完美防御,但至少可以挡住99%(剩下的1%才是最凶猛的~~~),目前的统一做法是,做好输入检查,良好的编程意识,安全转义,借助第三方安全库。不要信任输入。也不要信任输出。

为什么不用 CSP 直接一了百了呢?

人气教程排行