Update20151202:
感谢大家的关注和回答,目前我从各种方式了解到的防御方法,整理如下:
PHP直接输出html的,可以采用以下的方法进行过滤:1.htmlspecialchars函数 2.htmlentities函数 3.HTMLPurifier.auto.php插件 4.RemoveXss函数(百度可以查到)
PHP输出到JS代码中,或者开发Json API的,则需要前端在JS中进行过滤:1.尽量使用innerText(IE)和textContent(Firefox),也就是jQuery的text()来输出文本内容 2.必须要用innerHTML等等函数,则需要做类似php的htmlspecialchars的过滤(参照@eechen的答案)
其它的通用的补充性防御手段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.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(/xss/)\u003e里的任何一个字符都是不会被htmlspecialchars处理的。
自己看图,对,就是你!

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
你到底有没有测试过,就说你提到的那些场景能够绕过htmlspecialchars呀,实践出真知.
补充:
你说的对,毕竟很多时候要把AJAX加载的数据用innerHTML添加到页面.
值得注意的是,innerHTML本质也是输出HTML,
所以我们可以在输出前用JS像PHP的htmlspecialchars那样
把特殊字符(&,",',<,>)替换为HTML实体(
&"'<>).或者干脆直接用innerText(IE)和textContent(Firefox),也就是jQuery的text()来输出文本内容.
StackOverflow上找的两个实现:
更正:
经过测试后发现,AJAX返回的数据用jQuery的html()函数插入
并不会因为Unicode字符u003c和u003e而发生XSS.
永远不可能完美防御,但至少可以挡住99%(剩下的1%才是最凶猛的~~~),目前的统一做法是,做好输入检查,良好的编程意识,安全转义,借助第三方安全库。不要信任输入。也不要信任输出。
Yii里面对xss做了很好的防范,如果需要,可以直接找Yii的过滤类,仿照浏览器对可执行代码的识别,如果遇到可执行代码,就过滤掉了
为什么不用 CSP 直接一了百了呢?
有没有完美的分隔符把数据与指定完美区分起来