是PHP';s addslashes易受sql注入攻击


Is PHP's addslashes vulnerable to sql injection attack?

可能重复:
mysql_real_eescape_string((做了什么,addslashes((做不到';t?

我一直在复习关于PHP的addslashes函数如何/为什么容易受到sql注入攻击的文章。我读到的所有内容都表明,特定的mysql编码类型(默认字符集=GBK(存在问题,或者如果启用了magic_quotes,就会出现问题。然而,在这种情况下,我无法突破addslashes((函数并进行恶意操作,例如以管理员身份登录。

    $user = addslashes($_POST['user']);
    $pass = sha1($_POST['pass']);
    $sql = "SELECT * FROM admins WHERE user = '".$user."' AND `pass` = '".$pass."'";
    $nums = mysql_num_rows(mysql_query($sql));
    if($nums==1){
    $_SESSION['admin_user'] = $user;
    $_SESSION['admin_pass'] = $pass;

这是对客户端的(次要(安全审计,我建议他们使用PDO,但我需要显示他们当前的漏洞。

参考文献:

  • http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string
  • http://hakipedia.com/index.php/SQL_Injection#addslashes.28.29_.26_magic_quotes_gpc
Shiflett在他的博客中展示了一个完整的工作漏洞。上面显示的代码似乎没有遵循该示例,因为它没有使用显示漏洞的字符集。尽管如此,这个洞确实存在。

即使在特定场景中它是安全的,使用addslashes()的做法仍然是危险的,Shiflett的文章应该给你足够的材料来争论,尽管这种利用所需的环境非常深奥,而且复制起来并不完全是琐碎的。

如果你的客户在没有看到特定系统上的实时漏洞的情况下不接受危险,那么他们就不值得进行安全审计。

对于您的特定情况,执行SQL注入似乎并不那么容易,但一个常见的尝试是,如果我输入unicode null变量?像'0?它会破坏脚本并返回所有内容吗?很可能不会。

所以问题是,您并不总是需要斜杠来执行SQL注入。有些SQL可能写得非常错误,下面是一个示例

"SELECT * FROM admins WHERE id = $id"

如果$id是一个数字,它是完全有效的SQL,并且您对$id执行addslashes,(谁会这么做?(。但对于这种特定的情况,SQL注入所需要的只是1 OR 1=1,使查询看起来像

"SELECT * FROM admins WHERE id = 1 OR 1=1"

addslashesmagic_quotes不可能保护你免受这种愚蠢的伤害。

回到手头的问题,为什么头脑正常的人会使用GBK而不是UTF-8UTF-16

PHP的addslashe易受sql注入攻击吗?

是的。根据你链接到的文章中提到的条件。

我需要显示他们当前的漏洞。

我怀疑你是否能显示这个,因为客户端的编码似乎不是著名的GBK。

尽管如此,很可能还存在其他可能的漏洞,只是因为人们倾向于滥用转义函数,认为它是错误的。

但我可以向你保证,只要你的客户端编码单字节一或UTF-8,只要这个函数使用得当(就像你发布的代码中一样(,就不可能进行注入。

我不知道你为什么要在mysql_real_eescape_string((上使用addslash,但我想这完全是你的选择。

addslashes((完全按照它说的做:引用带斜杠的字符串

Example #1 An addslashes() example
<?php
$str = "Is your name O'reilly?";
// Outputs: Is your name O''reilly?
echo addslashes($str);

但是有些SQL攻击可以在没有引号的情况下执行(某些shell注入和一些盲SQL注入(。

出于这个原因,在这种情况下,我个人会使用mysql_real_eescape_string((而不是addslashes((来保护您的数据。

还可以考虑对sql查询使用sprintf((,因为它会使其稍微更安全:

$query = sprintf("SELECT `username`,`password`
        FROM admins 
        WHERE user = '%s' 
        AND `pass` = '%s'", 
    $user, $pass);

它使它更加安全,因为它不允许使用除您提供的数据类型之外的任何其他数据类型。

%d=数字%s=字符串,等

我希望这能有所帮助。