我之前已经发布了这个,但从来没有这方面,所以请看看:
我被告知进行sql注射的一种方法是使用1 = 1,其中有人可以看到所有不属于他们的条目。
但是,让我说我构建我的查询,以便它也选择当前用户的user_id,这样可行:
$userid = Current users stored id in database;
$postid = mysql_real_escape_string($_GET['id']);
现在假设我输入:domain.com/page.php?id='' OR '1'='1'
Select article_name from table where user_id=$userid and post_id=$postid
由于我添加了User_id
屏障,查询是否仍会返回所有内容或不会返回?
答案 0 :(得分:4)
如果您使用PDO,则无需担心转义数据(在这种情况下):
$stmt = $pdo->prepare('SELECT article_name FROM table WHERE user_id = :userid AND post_id = :postid');
$stmt->execute(array(
':userid' => $userid,
':postid' => intval($_GET['id']) //Just to be safe
));
// You could also do this instead (thanks @Digital Precision)
//$stmt->bindValue(':postid', $_GET['id'], PDO::PARAM_INT);
//$stmt->execute(array(':userid' => $userid));
while($row = $stmt->fetch()) {
//Work with data
}
有关PDO的更多信息,请参阅PHP docs。
使用mysql_real_escape_string()
的问题在于它的名称表明它只会转义字符串。它会转义可用于终止字符串的字符,以便攻击者无法关闭字符串并输入恶意SQL。
如果你很顽固并拒绝使用PDO,你可以在任何未经过整理的整数上使用intval()
之类的函数来确保它们只包含数字。
$post_id = intval($_GET['id']); //Now $post_id can only be a number
答案 1 :(得分:3)
mysql_real_escape_string()
仅用于清理字符串。它不会保护SQL注入没有用引号括起来的整数,所以你的观察是正确的:尽管mysql_real_escape_string()
,上面所示的内容确实不安全。
您需要将值包装在引号中:
Select article_name from table where user_id='$userid' and post_id='$postid'
或在运行查询之前确保$userid
和$postid
是整数。
答案 2 :(得分:1)
不确定你是什么意思"我被告知进行sql注射的一种方法是使用1 = 1,其中有人可以看到所有不属于他们的条目"。
1 = 1始终评估为true。当应用程序生成的查询只有条件where子句没有root where子句时,我才见过这种情况。不确定它与保护您进行sql注射有什么关系。
答案 3 :(得分:1)
您的查询如下:
Select article_name from table where user_id=$userid and post_id=\'\' OR \'1\'=\'1\'
正如我在输入时提到的那样,最好引用你的值。所以你将拥有:
Select article_name from table where user_id=$userid and post_id='\'\' OR \'1\'=\'1\''
如果没有具有此类ID的帖子,则不返回任何内容。
因此,您的查询不会返回当前用户的每个帖子。但请记住引用你的价值观。