为什么mysql_real_escape_string()没有阻止hack?

时间:2013-12-27 19:28:32

标签: php mysql code-injection mysql-real-escape-string

我的网站今天被黑了。服务器日志返回类似黑客的尝试:

  

www.site.com/notifications.php?PID=7&id=999999.9%20union%20all%20select%20%28select%20distinct%20concat%280x7e%2C0x27%2Cunhex%28Hex%28cast%28schema_name%20as%20char %29%29%29%2C0x27%2C0x7e%29%20起%20%60information_schema%60.schemata%20limit%201%2C1%29%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536--

但我在代码中使用了 mysql_real_escape_string()

if (isset($_GET['id']) && $_GET['id'] != '') {
   $id = mysql_real_escape_string($_GET['id']); 
} else {
   $id = '';
}

if ($id == '') {
   $stmt = "SELECT * FROM tbln13 ORDER BY id DESC"; 
} else {
   $stmt = "SELECT * FROM tbln13 WHERE id = $id";
}

$NewsResult = mysql_query($stmt) or die (mysql_error());

为什么我的网站无法阻止此攻击?

5 个答案:

答案 0 :(得分:9)

因为escape_string会为引号添加斜杠等。您的查询或他们提交的字符串中没有任何引号。

您的查询中没有STRING,它似乎期望一个int。如果您期望一个整数,那么在查询中使用它之前,您应该已经验证它是一个int,或者强制它为int。将值作为字符串转义,然后将其用作int,将无效。

切换到MySQLi或PDO中的预准备语句。

答案 1 :(得分:2)

sql注入的查询看起来像这样

SELECT * FROM tbln13 WHERE id = 999999.9 
union all select 
 (select distinct concat(0x7e,0x27,unhex(Hex(cast(schema_name as char))),0x27,0x7e) 
  from `information_schema`.schemata 
  limit 1,1), 
 0x31303235343830303536, 0x31303235343830303536, 0x31303235343830303536--

如你所见,你被注入了,因为你刚刚允许这个

您希望数字,但您没有检查!所以你得到了数字等等。

您应该检查$id变量的预期值,即数字。这就是我要用的:

if (!preg_match('/^\d+$/', $id))
    die("ERROR: invalid id"); // error, don't continue

答案 2 :(得分:1)

使用准备好的陈述,在大多数情况下会阻止SQL injections

本网站提供了一份简单易懂的准备语句指南:

Bobby Tables

你应该停止使用MYSQL,它已经过时,将来会被删除。请改用MySQLiPDO

答案 3 :(得分:1)

因为您的转义变量不是字符串,因此它不在您的查询中的引号内。如果您想快速修复,可以将查询更改为:

$stmt = "SELECT * FROM tbln13 WHERE id = '$id'";

它不是数字比较的标准用途,但应该有用。

答案 4 :(得分:0)

正如其他人所提到的,你应该放弃已弃用的mysql_*函数,而是通过mysqliPDO使用预准备语句。

即使这样,您也应该验证输入,因为仅使用预准备语句无法帮助您确定是否有有效的输入值。理想情况下,即使尝试准备好的语句,也要确保所有输入都有效。在这种情况下,此验证可能就像这样简单:

$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if (false === $id) {
   // you do not have a valid integer value passed. Do something.
} else {
   // continue with your prepared statement
}