JavaScript攻击属于Web前端安全,不存在黑盒测试的概念,直接可以对JS进行白盒代码审计。

DVWA中的JavaScript攻击的场景是基于token由前端JS生成而引起的一系列问题。

0x01 Low Level

页面如下,要求输入success来达到目的:

直接输入success提交,会显示invalid token:

查看页面源代码,看到是调用generate_token()函数,其中的token值是由md5(rot13(phrase))得到的,并且表单中存在一项隐藏的表项token:

可以看到,token是通过JS在客户端生成。而题目的意思应该就是让token的值和phrase经过某些加密操作后的值相等即可。

那就简单了,先在Console直接得到正确的token值:

在前端直接篡改token的值即可:

再输入success,OK:

最后,我们看下index.php源码,确认确实是通过比较加密phrase后的值与token的值是否相等来看是否JS攻击成功:

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
if ($phrase == "success") {
switch( $_COOKIE[ 'security' ] ) {
case 'low':
if ($token == md5(str_rot13("success"))) {
$message = "<p style='color:red'>Well done!</p>";
} else {
$message = "<p>Invalid token.</p>";
}
break;
case 'medium':
if ($token == strrev("XXsuccessXX")) {
$message = "<p style='color:red'>Well done!</p>";
} else {
$message = "<p>Invalid token.</p>";
}
break;
case 'high':
if ($token == hash("sha256", hash("sha256", "XX" . strrev("success")) . "ZZ")) {
$message = "<p style='color:red'>Well done!</p>";
} else {
$message = "<p>Invalid token.</p>";
}
break;
default:
$vulnerabilityFile = 'impossible.php';
break;
}
} else {
$message = "<p>You got the phrase wrong.</p>";
}

0x02 Medium Level

和前面类似,只是换了JS代码,在表单处单独调用JS文件:

访问该JS文件:

1
2
3
4
5
6
7
8
9
10
function do_something(e){
for(var t="",n=e.length-1;n>=0;n--)t+=e[n];
return t
}

setTimeout(function(){do_elsesomething("XX")},300);

function do_elsesomething(e){
document.getElementById("token").value=do_something(e+document.getElementById("phrase").value+"XX")
}

代码逻辑在调用setTimeout(),setTimeout()方法用于在指定的毫秒数后调用函数或计算表达式。这里调用do_elsesomething()函数,而do_elsesomething()函数中有生成token的代码,其中将传入参数e、前端表单输入的phrase值以及”XX”字符串进行拼接再调用do_something()函数进行字符串翻转处理。

那就这样吧:

改下JS即可:

0x03 High Level

再看下high的,调用了high.js:

查看high.js,发现不是人看的代码:

这是因为做了混淆,访问解码网站来转换成人民群众可看懂的形式,下面只列出关键的代码,前面省略的部分是算法部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
function do_something(e) {
for (var t = "", n = e.length - 1; n >= 0; n--) t += e[n];
return t
}
function token_part_3(t, y = "ZZ") {
document.getElementById("token").value = sha256(document.getElementById("token").value + y)
}
function token_part_2(e = "YY") {
document.getElementById("token").value = sha256(e + document.getElementById("token").value)
}
function token_part_1(a, b) {
document.getElementById("token").value = do_something(document.getElementById("phrase").value)
}
document.getElementById("phrase").value = "";
setTimeout(function() {
token_part_2("XX")
}, 300);
document.getElementById("send").addEventListener("click", token_part_3);
token_part_1("ABCD", 44);

几个函数调用顺序及生成token的步骤如下:

1、执行token_part_1(),取phrase值并进行字符串翻转处理;

2、延迟300ms后执行token_part_2(),传入参数字符串’XX’和token值拼接并调用sha256()加密;

3、点击按钮时执行token_part_3(),将token值和字符串’ZZ’拼接并调用sha256()加密,从而得到最终的token;

一波操作如下,先将转换过来的JS前一部分关于sha256算法定义代码输入实现初始化,方便后面直接调用sha256():

然后按照前面的分析得到token值:

最后修改token的值为ec7ef8687050b6fe803867ea696734c67b541dfafb286a0b1239f42ac5b0aa84即可。

0x04 Impossible Level

页面显示一句话:

You can never trust anything that comes from the user or prevent them from messing with it and so there is no impossible level.

永远不要相信用户输入的内容,哈哈哈。