40' OR '1'='1是否容易受到SQL注入攻击?

3
我开发了一个简单的应用程序,用于研究SQL注入,其中我搜索速率 < 40 并检索所有速率小于40的名称,但是当我将搜索传递为 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/>";
}

?>

1
你可以使用 010110 工具栏按钮格式化源代码。这一次我已经为你完成了。 - Álvaro González
@Alvaro - 我本来想编辑那个,但我的声望已经减少50分 :-( - m.edmondson
@Alvaro 我在发布源代码时总是遇到问题。在哪里可以找到 010110 的选项?如何格式化源代码? - Vishwanath Dalvi
@mr_eclair:最近更改了图片,现在看起来像这样:{} - Piskvor left the building
@Piskvor 非常感谢..现在我知道如何格式化源代码了..谢谢大家..分享你们的精彩知识..并为我的疑问提供最佳解决方案。 - Vishwanath Dalvi
显示剩余2条评论
5个回答

5

这就是SQL注入的工作原理

想象一下对数据库的查询。通常会像这样:

select *
from products
where productID = '[some parameter]'

但在你的情况下,由于参数来自用户,并且该用户输入了40' OR '1'='1,你只剩下:

select *
from products
where productID = '40' OR '1'='1'

当1 = 1时,将选择所有内容。

最好的方法是使用参数化查询来防止这种情况。 这篇文章非常优秀。


是的,我正在学习如何保护Web应用程序免受SQL注入攻击,但我对这个查询如何工作还有疑问。 - Vishwanath Dalvi
通常情况下,您会有这个productID = '[一些参数]'。如果我将'[一些参数]'替换为40' OR '1'='1,那么最终的productID将变为'40' OR '1'='1'。 - m.edmondson
你确定你完全理解了“参数查询,例如存储过程”这样的说法吗? - Your Common Sense
抱歉,我的意思是使用参数化查询,忘了存储过程的部分。我想我的头脑在跳跃我正在打字的内容之前。 - m.edmondson

3

从最终的SQL查询语句出发考虑:

SELECT * FROM my_table WHERE rate<'40' OR '1'='1';

'1'确实等于'1',所以rate<'40' OR '1'='1'将始终为真,并且每个记录都将被返回。您看过这个吗:http://xkcd.com/327/

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'总是成立,所以这个查询返回所有行。

@Marks +1,这样更好...通过查询实际传递SQL注入作弊代码来学习它的工作原理。 - Vishwanath Dalvi

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 注入的攻击。


1

基本上发生的是这个语句

SELECT * FROM blah WHERE rate > 'param'

传递了40' OR '1'='1,这就变成了

SELECT * FROM blah WHERE rate > '40' OR '1'='1

由于1 = 1对于所有行都成立,因此返回所有行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接