防止数据库拒绝用户输入

时间:2010-07-22 21:48:56

标签: php escaping adodb

我正在制作一个简单的界面,允许用户修改存储在Microsoft SQL数据库中的CSS和HTML。此接口使用PHP5和ADOdb。

由于某种原因,此表单将拒绝包含一个或多个单引号的任何输入。例如,不允许使用此字符串:“background-image:url('paper.gif');”

我怀疑ADOdb可能会积极过滤单引号以防止SQL注入攻击。有没有办法在PHP中转义用户输入以允许存储单引号字符?

我考虑自动将所有单引号转换为双引号,但似乎有可能破坏用户的标记。

这可能不是很有帮助,但这是我正在使用的测试的一个例子:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Cp1252">
<title>Edit website</title>
</head>
<body>
<h1>CSS Test</h1>

<?php
    include_once ('database.php');
    $table = "[User Site]";

    if (!isset($_REQUEST['dbname'])) {
        return false;
    } else {
        $dbname = $_REQUEST['dbname'];
        $db = Database::singleton($dbname);

        //Push any new CSS to the database
        if (isset($_POST['css'])) {
            $css = $_POST['css'];
            $sql = "UPDATE " . $table . 
                    " SET html='" . $html . "', css='" . $css . "' " .
                    " WHERE dbnameId='" . $dbname . "'";
            $db->Execute($sql);
        }

        //Fetch any CSS from the database
        $sql = "SELECT * FROM " . $table . " WHERE dbnameId='" . $dbname . "'";
        $data = recordToArray($db->Execute($sql));
        echo "<p>";
        $css = $data[0]['css'];
    }

    $rows = 20;
    $cols = 80;
?>
<!-- Show the user a form -->
<form action="test.php" method="post">
    CSS:<br>  <textarea rows="<?php echo $rows ?>" cols="<?php echo $cols ?>" name="css"><?php echo $css ?></textarea><p>
    <input type="hidden" name="dbname" value="<?php echo $dbname ?>" />
    <input type="submit" value="Update CSS" />
</form>
</p>
</body></html>

3 个答案:

答案 0 :(得分:4)

您正在使用ADODB,但您并没有使用几乎所有曾经存在的数据库抽象库的主要功能:占位符/预处理语句。

您的查询失败,因为未正确转义内容。使用占位符会自动添加转义。阅读the Param method,它将为您正在使用的数据库插入正确类型的占位符。 (看起来你正在使用MSSQL,我不知道它是否使用?作为占位符。)

而不是

$sql = "SELECT * FROM " . $table . " WHERE dbnameId='" . $dbname . "'";
$sth = $db->Execute($sql);

你想要这样的东西:

$sql = "SELECT * FROM $table WHERE dbnameId = " . $db->Param('dbname');
$psh = $db->Prepare($sql);
$sth = $db->Execute($psh, array( $dbname ));

(这是未经测试的,可能会有些错误,请阅读链接的手册页以获取更多信息。我是否曾提到ADODB很糟糕?)

请记住ADODB 糟糕并且是在PHP4时代设计的。请考虑使用更现代的内容,例如PDO

答案 1 :(得分:2)

防止SQL注入不是积极的过滤;这就是没有任何SQL注入预防。 CSS中的单引号被解释为查询中的单引号,导致语法错误。

之前我没有使用过ADOdb,但它看起来像it supports parameter binding,它可以让你形成更漂亮的查询并让它们按预期工作(没有SQL注入的风险)。

$db->Execute('UPDATE foo SET bar = ?, baz = ?', array("it's", "working"));

当数据库看到它时,上述内容等同于以下内容:

$db->Execute("UPDATE foo SET bar = 'it\'s', baz = 'working'");

语法是正确的,你可以避免错误和注入,并且无论如何都可以使用它更好:)

答案 2 :(得分:1)

我认为解决方案更容易:您直接插入用户输入,因此'会破坏您的SQL查询。 (这个 已经是SQL注入了!)所以你需要逃避这些。但我不知道ADOdb为此提供了哪种方法。 mysql_real_escape_stringmysql_PDO::quotePDO

此外:不要使用$_REQUEST,而是使用$_POST。甚至 更多请 不要使用register_globals,这是不安全的!请改用$_POST