2010-07-22 2 views
0

Я создаю простой интерфейс, который позволит пользователю изменять фрагменты CSS и HTML, которые хранятся в базе данных Microsoft SQL. Этот интерфейс использует 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 для фактического знания библиотеки (вместо привязки к параметру Googling для нее, как я сделал xD) и рекомендации лучшей альтернативы :) – Matchu

+0

Я никогда не касался ADODB в своей жизни, я искал Google для метода привязки параметров, Что ж. Я бы предпочел ваше решение, так как мне действительно не нужно делать отдельную подготовку. Крест + 1'd. ;) – Charles

+1

Я предположил, что ADODB автоматически исчезает, независимо от метода, используемого для построения инструкции. Это * магия! * (Tm). Спасибо, что поставил меня прямо; Теперь я использую привязку и переключение на PDO. – James

1

Я думаю, что решение способ проще: Вы вставляете ввод данных пользователем напрямую, поэтому ' разговляйся SQL-запрос. (Это is уже SQL-инъекция!) Таким образом, вам нужно избежать этих. Но я не знаю, какой метод ADOdb обеспечивает для этого. Это mysql_real_escape_string для mysql_ и PDO::quote для PDO.

Кроме того: не использовать $_REQUEST, вместо этого использовать $_POST. И даже больше пожалуйста не использовать register_globals, это небезопасно! Вместо этого используйте $_POST.

+0

Я использую $ _REQUEST в этом случае, потому что это легче проверить. :-) – James

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

Синтаксис является правильным, избежать ошибок и инъекции, и это гораздо лучше работать, в любом случае :)