2010-07-22 60 views
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

您正在使用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

+0

+1实际上知道库(而不是谷歌参数绑定为它,就像我做了xD),并推荐一个更好的替代:) – Matchu 2010-07-22 22:01:40

+0

我从来没有碰过ADODB在我的生活中,我GOOGLE参数绑定方法为好。我实际上更喜欢你的解决方案,因为我并不真正需要做一个单独的准备。交叉+1。 ;) – Charles 2010-07-22 22:04:27

+1

我假设ADODB是自动转义的东西,无论用于构建语句的方法如何。这是*魔术!*(tm)。谢谢你让我平静下来;我正在使用绑定并将其切换到PDO。 – James 2010-07-23 14:59:47

1

我认为解决的办法是比较容易的方式:你直接将用户输入的,因此'打破你SQL查询。 (这已经是一个SQL注入!)所以你需要逃避这些。但我不知道ADOdb为此提供了哪种方法。它的mysql_real_escape_stringmysql_PDO::quotePDO

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

+0

我在这个例子中使用$ _REQUEST,因为它更容易测试。 :-) – James 2010-07-22 22:01:36

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'"); 

的语法是正确的,你避免错误和注射,这是好得多的工作,反正:)