2011-12-02 79 views
0

我们知道,在php脚本中执行mysql之前,所有的用户输入必须通过mysql_real_escape_string()函数转义。并且知道该功能在用户输入中的任何'"字符之前插入\。假设以下代码:mysql_real_escape_string()对十六进制编码数据不安全吗?

$_POST['username'] = 'aidan'; 
$_POST['password'] = "' OR ''='"; 

// Query database to check if there are any matching users 
$query = "SELECT * FROM users WHERE user='".mysql_real_escape_string($_POST['username']."' AND password='".mysql_real_escape_string($_POST['password']."'"; 

mysql_query($query); 

// This means the query sent to MySQL would be: 
echo $query; 

此代码是安全的。

但我发现如果用户以十六进制格式输入她的输入,那么mysql_real_escape_string()不能做任何事情,用户可以轻松地执行她的SQL注入。在波纹管27204f522027273d27是相同' OR ''='但在十六进制格式化,没有问题的SQL执行:

$_POST['username'] = 'aidan'; 
$_POST['password'] = "27204f522027273d27"; 

// Query database to check if there are any matching users 
$query = "SELECT * FROM users WHERE user='".mysql_real_escape_string($_POST['username']."' AND password='".mysql_real_escape_string($_POST['password']."'"; 

mysql_query($query); 

// This means the query sent to MySQL would be: 
echo $query; 

但是,这是否是真实的,如果答案是肯定的我们如何防止SQL注入这样?

+1

当处理诸如漏洞之类的问题时,最好提供一段代码样本(如果有必要,请简化说明问题)并输入引发您遇到的问题的代码。 –

+1

请演示攻击者如何通过使用十六进制符号来绕过“mysql_real_escape_string”。 – deceze

+0

@deceze:一个十六进制编码如何用来规避转义的例子[可以在Rook的答案中找到](http://stackoverflow.com/a/4262043/106769)。 –

回答

1

如果您使用的是mysql_real_escape_string(),那么使用准备好的语句可能会更好地服务您。

针对您的特殊情况下,试试这个代码:

/* 
Somewhere earlier in your application, you will have to set $dbh 
by connecting to your database using code like: 
$dbh = new PDO('mysql:host=localhost;dbname=test', $DBuser, $DBpass); 
*/ 

$_POST['username'] = 'aidan'; 
$_POST['password'] = "' OR ''='"; 

$user = $_POST['username']; 
$password = $_POST['password']; 

// Query database to check if there are any matching users 
$query = "SELECT * FROM users WHERE user=? AND password=?"; 

$stmt = $dbh->prepare($query); 
$stmt->bindParam(1, $user); 
$stmt->bindParam(2, $password); 
$stmt->execute(); 

这并不需要您使用PDO为你的数据库的交互,但是这是整体一件好事。 Here's a question discussing the differences between PDO and mysqli statements

另请参阅this StackOverflow question which is remarkably similar to yours和我接受的答案,我从中挖掘了一些答案。

+0

这并没有真正回答这个问题。是的,准备好的陈述*是可取的,但问题是不同的。另外,如果数据库不支持预准备语句,PDO将回退到类似于mysql_real_escape_string的行为,所以它仍然是一个问题。 – deceze

+0

@deceze:恐怕这是不准确的。正如我在聊天中详细描述的,这可以解决可能的攻击向量。而且,过去十年发布的任何MySQL版本都支持PDO。回落到'mysql_real_escape_string()'永远不会实际发生。我不认为以这种方式进行好斗对于提问者是有帮助的。 –

+0

而且我不认为避免*核心问题*也有帮助。 [聊天]中的详细信息(http://chat.stackoverflow.com/rooms/5521/discussion-between-conspicuous-compiler-and-deceze)。 :) – deceze