0

我正在制作一个简单的界面,允许用户修改存储在 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>
4

3 回答 3

4

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

您的查询失败,因为事情没有被正确转义。使用占位符会自动添加转义。阅读Param 方法,它将为您正在使用的数据库插入正确类型的占位符。(看起来你正在使用 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

于 2010-07-22T21:55:26.710 回答
2

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

我以前没有使用过 ADOdb,但它看起来支持参数绑定,这将允许您形成看起来更漂亮的查询并让它们按预期工作(没有 SQL 注入的风险)。

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

如数据库所见,以上等价于以下内容:

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

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

于 2010-07-22T21:57:20.450 回答
1

我认为解决方案更简单:您直接插入用户输入,因此'中断您的 SQL 查询。(这已经是 SQL 注入了!)所以你需要逃避那些。但我不知道 ADOdb 为此提供了哪种方法。这是mysql_real_escape_string为了mysql_PDO::quote为了PDO

此外:不要使用$_REQUEST$_POST而是使用。更不要使用register_globals,它是不安全的!改为使用$_POST

于 2010-07-22T21:55:00.143 回答