我正在制作一个简单的界面,允许用户修改存储在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>
答案 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查询。 (这个mysql_real_escape_string
为mysql_
,PDO::quote
为PDO
。
此外:请不要使用$_REQUEST
,而是使用$_POST
。甚至 更多请 不要使用register_globals
,这是不安全的!请改用$_POST
。