单引号是不是在 PHP 中自动转义?那么清洁的必要性是啥?

Posted

技术标签:

【中文标题】单引号是不是在 PHP 中自动转义?那么清洁的必要性是啥?【英文标题】:Are single quotes escaped automatically in PHP? Then what's the need for cleaning?单引号是否在 PHP 中自动转义?那么清洁的必要性是什么? 【发布时间】:2011-09-15 13:00:00 【问题描述】:

我正在阅读有关网络安全的内容,其中一个显而易见的主题是SQL injections。我正在尝试设置一个基本的 php 页面,我可以在其中执行 SQL 注入(它是本地服务器)。但是,似乎我的代码(或服务器)会自动转义单引号。这是一个新标准,还是在我的服务器上激活了我不知道的设置?还需要清理输入吗?

这是我的服务器端代码示例:

$foo = $_POST['foo'];
$sql = "SELECT * FROM bar WHERE foo='" . $foo . "'";

connectoTo("database");
query($sql);

其中 connectTo() 连接到数据库服务器并选择数据库,而 query() 是执行查询时使用的常用过程。从来没有清洁过。但是,当我发送时

$_POST['foo'] = "' OR 1=1 #" 

PHP 页面接收到这个

$_POST['foo'] = "\' OR 1=1 #"

那么 foo 已经逃脱了吗?这与 $_GET 相同。

有什么想法吗?我们不再需要清理用户输入了吗?

【问题讨论】:

我认为你做错了!转义用户输入不仅是一种好习惯,而且还可以验证他们正在输入的输入。例如,如果您有一个名字字段,您应该验证名字。也许只允许 A-Za-z -。或者该字段可能只是数字,因此 0-9 将是验证 我同意你 100% 我只是为了学习目的而探索 sql 注入的概念,似乎只要启用了 magic_quote 就不需要清理数据......仍然执行启用了magic_quote 的sql 注入似乎是我真正的问题。 即使禁用了magic_quote,它仍然会执行: $_POST['foo'] = "\' OR 1=1 " 因为您没有验证数据。没有设置禁用以防止注入! 启用魔术引号 $_POST['foo'] = " OR 1=1 " 只会将查询设置为 "SELECT * FROM bar WHERE foo=' OR 1=1'" 这实际上是'根本没有对查询做太多。 错字,抱歉已修复。第二个例子你正在转义单引号,所以它应该执行 【参考方案1】:

PHP 中有一个死的“功能”会自动转义 POST/GET 数据,称为Magic Quotes。其想法是防止常见类型的 SQL 注入发生。

实际上,您会得到混乱的数据,并且 SQL 注入仍然很有可能,具体取决于实现。 PHP 的开发人员很快就意识到了这一点,并弃用了该功能,并且不鼓励使用它。

在正确的 PHP 安装中,绝对应该禁用它!如果您无权访问 PHP.ini 来设置 magic_quotes_gpc off,那么您可以将其放在代码的顶部:

if (get_magic_quotes_gpc()) 
    $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
    while (list($key, $val) = each($process)) 
        foreach ($val as $k => $v) 
            unset($process[$key][$k]);
            if (is_array($v)) 
                $process[$key][stripslashes($k)] = $v;
                $process[] = &$process[$key][stripslashes($k)];
             else 
                $process[$key][stripslashes($k)] = stripslashes($v);
            
        
    
    unset($process);

取自:http://www.php.net/manual/en/security.magicquotes.disabling.php

现在,谈谈您的 SQL 注入问题。你看,除了报价之外,还有更多的事情需要担心。您没有指定您正在使用哪个数据库,但这并不重要。避免注入问题的最佳方法是使用准备好的/参数化查询。

准备好的查询是带参数发送到服务器的查询,其值稍后发送。

INSERT INTO someTable (field1, field2) VALUES (:field1, :field2);

注意:field1:field2,因为它们是参数。当我执行此语句时,它们将被替换为正确的值。由于服务器正在执行此操作,因此无需转义(和/或它发生在您的后台,具体取决于您使用的 DB 层)。

在 PHP 中实现这一点的最简单方法是利用 PDO。 PDO的使用方法这个框太长了,我给大家指个教程的方向:

http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/

【讨论】:

我完全同意你的观点,准备好的查询绝对是要走的路!但是,在启用了魔术引号的输入上,哪种类型的 sql 注入仍然有效? ***.com/questions/1086918/… ***.com/questions/110575/… 为什么投反对票?谁在不解释的情况下投反对票?即使你不同意我的观点,如果你能解释一下,那肯定对 Erik 有利。 嗯,我仍然无法让任何 sql 注入工作。我知道魔术引号存在根本缺陷,但我希望看到一个真实世界的 sql 注入示例,它将绕过魔术引号安全性。到目前为止,魔术引号似乎确实可以防止任何 sql 注入...【参考方案2】:

在 php.ini 中禁用 magic_quote 并使用 PDO

【讨论】:

那么是否还可以执行sql注入? @Erik,绝对的。看我的帖子。

以上是关于单引号是不是在 PHP 中自动转义?那么清洁的必要性是啥?的主要内容,如果未能解决你的问题,请参考以下文章

PHP教程:PHP中单引号与双引号的区别分析

(实用篇)PHP中单引号与双引号的区别分析

我应该对单引号使用 php 引号转义还是在数组中使用双引号?

php中单引号和双引号的区别,哪个速度更快?为啥?

PHP中单引号与双引号的区别分析

php性能优化三(PHP语言本身)