Предотвращение отклонения пользователем базы данных - PullRequest
0 голосов
/ 23 июля 2010

Я делаю простой интерфейс, который позволит пользователю изменять фрагменты 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>

Ответы [ 3 ]

4 голосов
/ 23 июля 2010

Вы используете 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 .

2 голосов
/ 23 июля 2010

Это не агрессивная фильтрация для предотвращения внедрения 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'");

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

1 голос
/ 23 июля 2010

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

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

...