在SQL注入中利用MySQL隐形的类型转换绕过WAF检测

  web应用一般采用基于表单的身份验证方式(页面雏形如下图所示),处理逻辑就是将表单中提交的用户名和密
码传递到后台数据库去查询,并根据查询结果判断是否通过身份验证。对于LAMP架构的web应用而言,处理逻辑采用PHP,后台数据库采用MySQL。而 在这一处理过程,由于种种处理不善,会导致不少严重的漏洞,除去弱口令与暴力破解,最常见的就是SQL注入。SQL注入可以在SQLNuke——mysql 注入load_file Fuzz工具看到如何利用,而本篇博客的重点是利用MySQL隐形的类型转换绕过WAF的检测。

下面使用实例来展示这一过程。
实例包括2个脚本login.html与login.php,1张存放用户名与密码的member.user表

(1)表单login.html

    <html>
    
    <body>
    
    <form
     
    id
    =
    "form1"
     
    name
    =
    "form1"
     
    method
    =
    "post"
     
    action
    =
    "login.php"
    >
    
    <label>
    UserName
    <input
     
    name
    =
    "user"
     
    type
    =
    "text"
     
    id
    =
    "user"
    />
    
    </label>
    
    <br/>
    
    <label>
    Password
    <input
     
    name
    =
    "password"
     
    type
    =
    "text"
     
    id
    =
    "password"
    />
    
    </label>
    
    <br/>
    
    <label>
    
    <input
     
    name
    =
    "login"
     
    type
    =
    "submit"
     
    id
    =
    "login"
     
    value
    =
    "Login"
    />
    
    </label>
    
    </body>
    
    </html>
  

(2)认证处理login.php

    <?
    php
    if
    (
    isset
    (
    $_POST
    [
    "login"
    ]))
    
    {
    $link 
    =
     mysql_connect
    (
    "localhost"
    ,
    "root"
    ,
    "toor"
    )
     
    or
     
    die
     
    (
    "cannot connect database"
    .
    mysql_error
    ());
    mysql_select_db
    (
    "member"
    )
     
    or
     
    die
     
    (
    "cannot select the db"
    );
    $query 
    =
     
    "select * from user where user='"
    .
    $_POST
    [
    "user"
    ].
    "'and password='"
    .
    md5
    (
    $_POST
    [
    "password"
    ]).
    "'"
    ;
    echo $query
    .
    "<br/>"
    ;
    $result 
    =
     mysql_query
    (
    $query
    )
     
    or
     
    die
     
    (
    "the query failed:"
    .
    mysql_error
    ());
    echo 
    "<br/>"
    ;
    $match_count 
    =
     mysql_num_rows
    (
    $result
    );
    
    if
    (
    $match_count
    ){
    
    while
    (
    $row 
    =
     mysql_fetch_assoc
    (
    $result
    )){
    echo 
    "<strong>User: </strong>"
    .
    $row
    [
    "user"
    ].
    "<br/>"
    ;
    echo 
    "<strong>Password: </strong>"
    .
    $row
    [
    "password"
    ].
    "<br/>"
    ;
    echo 
    "<br/>"
    ;
    
    }
    
    }
    
    else
     
    {
    echo 
    "Wrong User or password <br/>"
    ;
    echo 
    '<a href="http://10.1.36.34/login.html">Back</a><br/>'
    ;
    
    }
    mysql_free_result
    (
    $result
    );
    mysql_close
    (
    $link
    );
    
    }
  

注意红色字体部分,为用户输入的用户名和密码,没有进行任何过滤就传入到数据库中去进行查询. 该脚本将查询字符串及查询结果展示在页面中以供直观的演示SQL查询结果。

(3)member.user

大家看一张常见的用户表user表,由两个字段构成user用户名和password字段。

表中包含8行数据

很明显这是一段有SQL注入的程序,接下来我们来看看下面这些有趣的查询结果
(1) 输入用户名a’+'b#

查询结果如下图所示

(2)输入用户名45a’+'b’#

 产生以上结果的原因是算术操作符+的出现将字符型的user转换为了数值性的user
    dani,tanjiti,dani123,0dani 对应的数值为0
123dani,123tanjiti对应的数值为123
45dani,045tanjiti对应的数值为45
'a'+'b'对应数值为0+0=0,会把类型转换后为0的用户名搜索出来
'45a'+'b'对应数值为45+0=45,会把类型转换后为45的用户名搜索出来
  
除了+号,其他算术操作符号也会发生类型的类型转换,例如MOD,DIV,*,/,%,-,

 (3)输入用户名a’MOD’1′#

 ’a'MOD’1′对应的数值为0 MOD 1 =0,会把user对应数值为0的搜索出来

(4)输入用户名‘-”#

 ”-”对应的数值为0 -0 =0,会把user对应数值为0的搜索出来

bit操作符&,|,^,<< ,>>也有同样的效果

(5)输入用户名‘/’1′#

”/’1′对应的数值为0 /1 =0,会把user对应数值为0的搜索出来

bit操作符&,|,^,<< ,>>也有同样的效果

(6)输入用户名a’&’b'#

 ’a'&’b'对应的数值为0&0 =0,会把user对应数值为0的搜索出来

对应WAF防火墙而言,当输入’ or 1=’1 时,ModSecurity防火墙会报错(我没有试验过ModSecurity,博客中有介绍)

而上面的实例则可以绕过防火墙.
总的来说,利用MySQL隐性的类型转换来绕过WAF对SQL注入的检测是蛮有想法的。