SQL注入攻击的产生
当应用程序使用输入内容来构造动态SQL语句以访问数据库时,会发生SQL注入攻击。 如果代码使用存储过程,而这些存储过程作为包含未筛选的用户输入的字符串来传递,也会发生SQL注入。
SQL注入可能导致攻击者使用应用程序登陆在数据库中执行命令。相关的SQL注入可以通过测试工具pangolin进行。如果应用程序使用特权过高的帐户连接到数据库,这种问题会变得很严重。在某些表单中,用户输入的内容直接用来构造动态SQL命令,或者作为存储过程的输入参数,这些表单特别容易受到SQL注入的攻击。而许多网站程序在编写时,没有对用户输入的合法性进行判断或者程序中本身的变量处理不当,使应用程序存在安全隐患。这样,用户就可以提交一段数据库查询的代码,根据程序返回的结果,获得一些敏感的信息或者控制整个服务器,于是SQL注入就发生了
在我们之前课程的审计中,我们已经知道在sys
文件夹下的lib.php
中存放着很多函数。
我们依次点击,来到其25~48行上下,内容如下:
function sqlwaf( $str ) {
$str = str_ireplace( "and", "sqlwaf", $str );
$str = str_ireplace( "or", "sqlwaf", $str );
$str = str_ireplace( "from", "sqlwaf", $str );
$str = str_ireplace( "execute", "sqlwaf", $str );
$str = str_ireplace( "update", "sqlwaf", $str );
$str = str_ireplace( "count", "sqlwaf", $str );
$str = str_ireplace( "chr", "sqlwaf", $str );
$str = str_ireplace( "mid", "sqlwaf", $str );
$str = str_ireplace( "char", "sqlwaf", $str );
$str = str_ireplace( "union", "sqlwaf", $str );
$str = str_ireplace( "select", "sqlwaf", $str );
$str = str_ireplace( "delete", "sqlwaf", $str );
$str = str_ireplace( "insert", "sqlwaf", $str );
$str = str_ireplace( "limit", "sqlwaf", $str );
$str = str_ireplace( "concat", "sqlwaf", $str );
$str = str_ireplace( "\\", "\\\\", $str );
$str = str_ireplace( "&&", "", $str );
$str = str_ireplace( "||", "", $str );
$str = str_ireplace( "'", "", $str );
$str = str_ireplace( "%", "\%", $str );
$str = str_ireplace( "_", "\_", $str );
return $str;
}
可以看到上述代码的作用为:过滤SQL注入语句的一些参数,比如它将and替换为sqlwaf,将or替换为sqlwaf,这样一来就破坏了SQL语句,导致注入语句不能成功执行。
但我们再次仔细查看,发现一处漏洞:代码将||
替换为空。
因此我们可以这样构造:
uni||on sele||ct 1,2,3,4 from admin
这里使用的是SQL语句的联合查询法,查询的时候,系统会匹配sqlwaf函数中黑名单的字符,因为我们加了||
,所以系统没有匹配到,但是在之后,系统将||
替换为空,这时,就又变回了之前的字符,这样就绕过了sqlwaf。
我们再查看user
下的messageDetail.php
,SQL查询语句就在这里执行,查看其5~7行:
if ( !empty( $_GET['id'] ) ) {
$id = sqlwaf( $_GET['id'] );
$query = "SELECT * FROM comment WHERE comment_id = $id";
他是通过GET方式接收前段传递的参数,使用sqlwaf函数进行了过滤,接下来就直接
执行了SQL查询语句。
下一步我们进行漏洞测试:
我们首先打开浏览器,输入网址127.0.0.1
,访问网址。
因为注入演示需要在网站的留言处进行验证,但此时还没有留言,因此我们点击上方的留言按钮,注册一个账号,并进行留言。
点击注册按钮
填入注册信息后点击注册
点击注册后来到此画面,这时候点击留言
点击留言后来到此页面,随意输入字符,点击留言
留言成功后,我们再次点击留言的内容:
我们发现,网站就会跳到messageDetail.php
,并且后面也有了参数。
这时,在参数后面构造SQL语句:
uni||on sele||ct 1,2,3,4 fr||om admin
因为本字段的名为admin_name,admin_pass,而_
在sqlwaf中是过滤的,我们使用*
号,对其绕过
在真实的场景中,字段的长度是需要去猜解的,因为本实验重在代码审计,这里就不在演示SQL注入攻击语句了,使用语句直接使其爆出密码。
uni||on sele||ct *,4 fr||om admin
可以看到,使用SQL注入语句,我们已经拿到了账号密码。
修复建议
将sys下lib.php文件中的sqlwaf
函数中,黑名单中的特殊符号,如||
,_
等,同样替换为sqlwaf
即可。
这样只要出现黑名单中的攻击语句,则会被系统自动替换。再利用文中方法,就无从谈起了。