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.
永远不要相信用户输入的内容,哈哈哈。