记一次实战 Dom XSS 漏洞

国庆的前一天,突然有一个漏洞单接到我这里来,当时心里很着急,第一实习生小白,对于我们这种支付部门有漏洞不是很可怕,以前没见过,觉得有点吓人。第二,为什么是国庆的前一天呢,不能发版本。看了下,就是熟悉又不太熟悉的 Dom xss 漏洞。熟悉是因为以前书里经常见,不熟悉是因为以前没有实践过。


现象及解决办法

安全部门的同事说,它更改了 uin, 然后就可以输出 用户uin, 也就是俗称的 alert 出来。

大概是这样一个步骤

1
2
document.cookie = "uin=<img src=x onerror=alert('')>"
然后刷新了我的网页,由于我获取cookie的方法不严谨,这个时候就alert出来了。

解决方法当然是换掉我不严谨的获取cookie的方法,正确获取 cookie 的方法应该如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function getCookie(b) {

var filterXSS = function(e) {

if (!e) return e;

for (; e != unescape(e);) e = unescape(e);

for (var r = ["<", ">", "'", '"', "%3c", "%3e", "%27", "%22", "%253c", "%253e", "%2527", "%2522"], n = ["&#x3c;", "&#x3e;", "&#x27;", "&#x22;", "%26%23x3c%3B", "%26%23x3e%3B", "%26%23x27%3B", "%26%23x22%3B", "%2526%2523x3c%253B", "%2526%2523x3e%253B", "%2526%2523x27%253B", "%2526%2523x22%253B"], a = 0; a < r.length; a++) e = e.replace(new RegExp(r[a], "gi"), n[a]);

return e
};

var a;

return filterXSS((a=document.cookie.match(RegExp("(^|;\\s*)"+b+"=([^;]*)(;|$)")))?unescape(a[2]):null)
}


探究原因

那么我的 Cookie 是怎么获取的呢?

1
2
var ret = document.cookie.match(new RegExp("(?:^|;\\s)" + name + "=(.*?)(?:;\\s|$)"));
return ret ? ret[1] : "";

为啥我的就不严谨了呢?

日常我们的cookie 是这样一种格式:

1
ts_refer=ADTAGpay.index.header.paycenter; pgv_si=s3636090880; pgv_info=ssid=s9066946176; ts_last=pay.qq.com/; pgv_pvid=2986859684; ts_uid=8406093480

所以上面代码通过 = 和 ; 获得对应的 cookie , 似乎没有错,但是如果一遇到恶意攻击,没有对不合法字符进行任意转义就输出到页面上,就会造成 web 前端的安全大隐患。所以看到最上面我们的好方法里面,是有对不合法字符进行转义的。所以我们这样处理后,就会变成下面这样一个结果:

转义后


延伸

记得我刚来面试的时候,当时 qq 问了我获取 cookie 的方法,那时之前做项目写过获取 cookie 的方法,还是特别傻的方法,代码大概是这样的:

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
function getCookie(c_name)

{

if (document.cookie.length>0)

{

c_start=document.cookie.indexOf(c_name + "=")

if (c_start!=-1)

{

c_start=c_start + c_name.length+1

c_end=document.cookie.indexOf(";",c_start)

if (c_end==-1) c_end=document.cookie.length

return unescape(document.cookie.substring(c_start,c_end))

}

}

return ""

}

没错,就是正则也没用,直接去找 =;之间的串是否与要查找的相同。这个方法在 w3cShool 上作为了标准方法,现在看来是误导人了。 当时 qq 问我有没有更好的方法,我说正则,但是正则还不能很快的写出来。那么这种方法除了效率不那么高以外,有没有上面提到的安全隐患呢?**做个实验:

1
document.cookie = "a=123 b=other; b=678";

这个的意思是 cookie a 的值为 123 b=other, b的值为 678, 但是我们通过上面的 getCookie 方法 做实验时:

1
2
getCookie("b"); //输出 other
getCookie("a"); //输出 123 b=other

b的值很明显不正确了。这样就混淆了正确的 cookie。 所以这种方法也不是正确的方法,运用我们最上面提到的解决方法 可以很好的解决这个问题。


总结

还是实战出真知,继续前行!不怕犯错,积累经验。我当时跟师傅说我遇到了 dom xss 漏洞,师傅马上就让我去检查 cookie 获取的方法,连整个事情的经过就没问,就可以做出准确的判断,这就是老司机啊,向他学习。希望以后知道一些更多关于安全方面的实战。