SQL注入奇技淫巧

前言

有段时间没打ctf了,感觉有些生疏,知识点也不够全面,想着赶紧总结一下知识点把以前的东西捡回来。

时间盲注的几个姿势

时间盲注,顾名思义就是根据请求响应时间的不同来判断是否存在注入。

sleep被过滤

sleep()函数是时间盲注里面最重要的函数之一了,当sleep()被过滤时有三种绕过方式。
**get_lock()**
get_lock(key,time),该函数的意思是给一个key上锁,如果上锁失败就等待time秒,然后回滚事务。

利用方式:先使用get_lock(key,time)key上锁,然后再开一个进程使用get(key,time),这时候就会因为原来的key已经被上锁了而会等待time

这里我先将终端1的key(也就是1)上锁。

然后再打开终端2对同样的key进行上锁,time为3,很明显这里等待了3秒。

**benchmark()**
benchmark(count,expr),该函数会重复计算expr表达式count次从而消耗大量时间。

if((布尔盲注语句),BENCHMARK(10000000,md5(‘a’)),1)

笛卡尔积
这里的笛卡尔积和离散数学里的笛卡尔积的意思是一样的,因为mysql支持多表查询,笛卡尔积可以将多个表合并成一个表,但是如果多个表中的数据较多就会导致运算过程中耗费大量的时间。

if((布尔盲注语句),(select count(*) from information_schema.columns A,information_schema.columns B, information_schema.columns C),1)

RLIKE
语法规则:

  • A RLIKE B,表示B是否再A里面。
  • B中的表达式可以使用标准的正则语法。

利用方式:

if((布尔盲注语句),concat(rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’)) RLIKE ‘(a.)+(a.)+(a.)+(a.)+(a.)+(a.)+(a.*)+b’,1)

原理和之前差不多,都是多次计算消耗计算机资源产生的延时效果。

if()被过滤

if()sleep()可以说是时间盲注当中最重要的函数之二了,同样if()也要可以代替的函数。
case when

case when [condition1] then [result1],when [condition2] then [result2] ······ else [resultn] end

当满足条件一返回结果一,以此类推返回相应结果。

case when (布尔盲注语句) then sleep(n) else 1 end

报错注入的几个姿势

整型溢出

数据溢出的原理很简单,当需要进行运算的数字的结果超过mysql规定的范围后就会返回报错信息,而我们便可以利用这一信息去获取相应的数据。mysql的整型数据范围可以参考这篇文章:Integer Types (Exact Value)。还有一点我们需要注意的是只有在mysql>5.5之后整型溢出才会报错,并且mysql<5.5.53时不能返回查询结果。个人认为比较鸡肋。

**exp()**
首先当一个查询成功时,则返回0;如果失败则返回1。而我们对0取反时得到的数值为18446744073709551615,已经超过了exp()所能接受的范围。

注入姿势:

select exp(~(select * from (注入语句)x));

此外,报错信息是由长度限制的,所以要想得到后面的信息可以结合limit一起使用。除了exp()之外,能达到同样的效果的函数还有pow()cot()

xpath语法错误

该类报错注入中,经常使用的函数为updatexmlextractvalue

适用版本:5.1.5+

updatexml(XML_document,XPath_string,new_value);

extractvalue(XML_document, XPath_string);

这两个函数造成报错注入的原因都是一样的,都是因为参数XPath_string的格式不符合xpath语法并且将查询结果放在报错信息当中。所以我们可以在需要注入的地方前后拼接~即可造成报错。

updatexml(1,concat(‘‘,(注入语句),’‘),1);
extractvalue(1,concat(‘‘,(注入语句),’‘));

主键重复

无列名注入

information_schema 的绕过

在SQL注入当中要想知道数据库名和表名等,information_schema这个库是必不可少的,但如果这个库被过滤的时候必须找到另外一个备胎从而实现我们的目的。

由于performance_schema过于繁杂的特性,在mysql 5.7版本中新增了sys schema,其数据来自于performance_schemainformation_schema两个库,本身数据库不存储数据。

sys.schema_auto_increment_columns

在所有数据库中查找带有自增列的基表及其相关的信息,默认按照自增值使用率和自增列类型最大值进行降序排序。

人话就是查找自增主键的表的数据,但是这样就有另外一个问题就是无法得到不存在自增主键的表,所以其它寻找其他的视图来满足我们的需求。

sys.schema_table_statistics_with_buffer,sys.x$schema_table_statistics_with_buffer

查询表的统计信息,其中还包括InnoDB缓冲池统计信息,默认情况下按照增删改查操作的总表I/O延迟时间(执行时间,即也可以理解为是存在最多表I/O争用的表)降序排序,数据来源:performance_schema.table_io_waits_summary_by_table、sys.x$ps_schema_table_statistics_io、sys.x$innodb_buffer_stats_by_table

根据这两个视图的数据来源便可以得到我们想要的数据从而绕过information_schema。通过这三个视图的比较也可以发现,后两个视图可以获取的数据更多。

DNSlog外带数据

mysql8新特性注入

参考文章

Dnslog在SQL注入中的实战

浅谈利用mysql8新特性进行SQL注入

聊一聊bypass information_schema

SQL注入有趣姿势总结

对MYSQL注入相关内容及部分Trick的归类小结

在不知道 MySQL 列名的情况下泄露数据的 SQL 注入技巧

MYSQL报错注入的一点总结