40'OR'1'='1这很容易被sql注入?

时间:2010-12-23 10:39:56

标签: php sql mysql sql-injection

我开发了一个简单的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/>";
}

?>

5 个答案:

答案 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,所有行都返回。