我开发了一个简单的sql注入研究应用程序,我在其中搜索速率< 40并检索所有速率低于40的名称但当我通过搜索时 40'OR'1'='1 所以它从数据库表中检索所有记录 我知道如何解决这个问题,但我不知道 40'OR'1'='1 当我通过 40'OR'1'='1 任何人都可以简单地告诉我当我在搜索框中传递 40'OR'1'='1 时会发生什么?
希望得到快速和积极的回应...
<?php
include("conn.php");
$get_rate = $_GET['rate'];
$query = "select * from `sqlinjection`.`products` WHERE `products`.`rate` < '".$get_rate."'";
$result=mysql_query($query);
if($result == false)
{
die(mysql_error());
}
while($row=mysql_fetch_array($result))
{
echo "Name".$row['srno']."<br/>";
echo "Name".$row['name']."<br/>";
echo "Rate".$row['rate']."<br/>";
}
?>
答案 0 :(得分:5)
SQL注入的工作方式
想象一下对数据库的查询。通常它会是这样的:
select *
from products
where productID = '[some parameter]'
但是在你的情况下,因为参数来自用户,并且该用户输入了40'OR'1'='1你还剩下:
select *
from products
where productID = '40' OR '1'='1'
1 = 1它将选择所有内容
防止这种情况的最佳方法是使用参数化查询。 Excellent article.
答案 1 :(得分:3)
根据生成的SQL查询的外观来考虑它:
SELECT * FROM my_table WHERE rate<'40' OR '1'='1';
'1'
确实等于'1'
,因此rate<'40' OR '1'='1'
将始终为真,并且每条记录都会返回。你之前见过这个:http://xkcd.com/327/?
答案 2 :(得分:2)
尝试通过添加一些调试信息来修改脚本:
$get_rate = $_GET['rate'];
$query = "select * from sqlinjection.products WHERE products.rate < '".$get_rate."'";
echo $query;
您应该看到生成的SQL是:
select * from sqlinjection.products WHERE products.rate < '20' OR '1'='1' ^^^^^^^^^^^^^
$get_rate
值内的引号终止字符串'20'
,因此以下OR '1'='1'
被解释为SQL。由于'1' = '1'
始终为true,因此此查询将返回所有行。
答案 3 :(得分:1)
您似乎有一个最终尝试此操作的应用程序:
SELECT somefield FROM sometable WHERE rate < '$yourRate'
通常会(例如将40
作为输入)扩展为
SELECT somefield FROM sometable WHERE rate < '40'
但是,如果您没有清理SQL输入,并且恶意用户输入40' OR '1'='1
,则查询将变为
SELECT somefield FROM sometable WHERE rate < '40' OR '1'='1'
因为''1'='1'始终为真,所以相当于
SELECT somefield FROM sometable
现在,该怎么办?如果应用程序仍然很小,我建议切换到mysqli - 它允许您使用预备语句,这对此更有弹性。如果没有,至少要消毒你的参数。这意味着,如果应该有一个整数作为参数,则将输入转换为整数;如果一个字符串,使用语言的转义函数 - 在PHP中,这将是mysql_real_escape_string。 PHP中的示例:
$get_count = $_GET['count']; // an example of integer
$get_rate = $_GET['rate']; // an example of float
$comment = $_GET['comment']; // an example of string
$sanitized_count = (int) $get_count; // now we're *sure* it's an int, and nothing else
$sanitized_rate = (float) $get_rate; // ditto
$sql_sanitized_comment = mysql_real_escape_string($comment); // you need to have the mySQL connection open to use this function (for charset purposes)
$query = "select * from sqlinjection.products
WHERE
products.rate < ".$sanitized_rate."
OR products.comment = '" . $sql_sanitized_comment . "'
LIMIT " . $sanitized_count;
这样,参数可以安全地从SQL注入。
答案 4 :(得分:1)
基本上发生的是声明
SELECT * FROM blah WHERE rate > 'param'
传递40'或'1'='1变为
SELECT * FROM blah WHERE rate > '40' OR '1'='1
由于1 = 1,所有行都返回。