Есть ли способ продемонстрировать SQL-инъекцию с помощью mysqli? - PullRequest
0 голосов
/ 20 января 2019

Я хочу быстро и легко продемонстрировать, как работает SQL-инъекция. И я решил некоторые из моих проблем. У меня есть таблица со случайными именами пользователей, паролями и электронными письмами, и я могу «вставить» код SQL, чтобы просмотреть всех пользователей в поиске с помощью этой инъекции:

' OR '1'='1

Вот так выглядит мой PHP-код для поиска "членов":

if (isset($_POST['search'])) {
    $searchterm = $_POST['searchterm'];
    echo $searchterm . '<br>';

    /* SQL query for searching in database */
    $sql = "SELECT username, email FROM Members where username = '$searchterm'";
    if ($stmt = $conn->prepare($sql)) {
        /* Execute statement */
        $stmt->execute();

        /* Bind result variables */
        $stmt->bind_result($name, $email);

        /* Fetch values */
        while ($stmt->fetch()) {
            echo "Username: " . $name . " E-mail: " . $email . "<br>";
        }
    } 
    else {
        die($conn->error);
    }
}

Теперь я хочу продемонстрировать некоторые более фатальные проблемы, например, обрезание всей вашей таблицы. Поэтому я попробовал этот код в строке поиска:

'; TRUNCATE TABLE Members; -- 

Но я получаю это сообщение об ошибке:

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'TRUNCATE TABLE Members; -- '' at line 1

Похоже, я получил дополнительный ', но я не знаю, как от него избавиться, хотя -- это закомментирует. Сначала я подумал, что проблема в том, что у меня нет пробела за --, но добавление пробела не имеет никакого значения.

Я попытался переключиться на PDO, потому что я думал, что была проблема с mysqli, не принимающим множественные запросы, но потом я где-то читал, что PDO тоже не поддерживает это, но я не знаю.

Есть ли способ заставить его работать?

Позже я обнаружил, что PDO поддерживает многозапросы по умолчанию, но когда я попробовал, это не сработало. Возможно я неправильно связал параметры. Но я даже не мог сделать простой запрос select для работы.

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Вы пробовали что-то подобное?

'(here put something);

таким образом, вы собираетесь закрыть запрос с помощью 'и добавить к нему другие вещи, когда добавите;все остальное будет отброшено

0 голосов
/ 20 января 2019

mysqli_query () не поддерживает мультизапрос по умолчанию. Для этого есть отдельная функция: mysqli_multi_query () .

Внедрение SQL - это не только запуск нескольких операторов, несмотря на знаменитый мультфильм XKCD .

Ваш код имеет плохую уязвимость внедрения SQL. Считаете ли вы, что использование prepare() каким-то образом делает запрос безопасным, даже если вы интерполируете содержимое из ваших данных запроса $ _POST непосредственно в строку SQL?

Ваш код такой:

$searchterm = $_POST['searchterm'];

$sql = "SELECT username, email FROM Members where username = '$searchterm'";
if ($stmt = $conn->prepare($sql)) {
    /* execute statement */
    $stmt->execute();
    ...

Небезопасный ввод данных может легко привести к неправильному введению SQL. Это может быть даже невинно, но все равно приводит к проблемам. Предположим, например, что поиск: O'Reilly. Копирование этого значения непосредственно в ваш SQL приведет к следующему запросу:

SELECT username, email FROM Members where username = 'O'Reilly'

Видите несоответствующие ' цитаты? Это не принесет ничего плохого, но вызовет сбой запроса, потому что несбалансированные кавычки создают синтаксическую ошибку.

Использование prepare() не исправляет случайные синтаксические ошибки и не защищает от копирования вредоносного содержимого, которое изменяет синтаксис запроса.

Чтобы защитить как от случайного, так и от вредоносного внедрения SQL, вы должны использовать связанные параметры, такие как:

$searchterm = $_POST['searchterm'];

$sql = "SELECT username, email FROM Members where username = ?";
if ($stmt = $conn->prepare($sql)) {
    $stmt->bind_param('s', $searchterm);
    /* execute statement */
    $stmt->execute();
    ...

Связанные параметры не копируются в запрос SQL. Они отправляются на сервер базы данных отдельно и никогда не объединяются с запросом до тех пор, пока после *1029* не будет проанализирован, и поэтому не может вызвать проблемы с синтаксисом.

Что касается вашего вопроса о mysqli::query(), вы можете использовать его, если ваш запрос SQL не нуждается в связанных параметрах.


Ваш комментарий:

... уязвимы для инъекций, поэтому я могу показать студентам, какой вред может нанести злонамеренная атака.

Вот пример:

Несколько лет назад я был инструктором по SQL, и во время одного из моих тренингов в компании я говорил о внедрении SQL. Один из участников сказал: «Хорошо, покажи мне атаку SQL-инъекцией». Он вручил мне свой ноутбук. Браузер был открыт для экрана входа в систему для его сайта (это был только его тестовый сайт, а не настоящий рабочий сайт). Форма входа была простой, с полями для имени пользователя и пароля.

enter image description here

Я никогда не видел его код, который обрабатывает форму входа, но я предположил, что форма была обработана некоторым кодом, как большинство небезопасных веб-сайтов:

$user = $_POST['user'];
$password = $_POST['password'];

$sql = "SELECT * FROM accounts WHERE user = '$user' AND password = '$password'";
// execute this query.
// if it returns more than zero rows, then the user and password
// entered into the form match an account's credentials, and the
// client should be logged in.

(Это было мое образованное предположение о его коде, я еще не видел код.)

Мне потребовалось 5 секунд, чтобы подумать о логике, и я ввел логическое выражение в форму входа для имени пользователя, а для пароля я набрал случайные символы мусора.

Затем я вошел в его аккаунт - , не зная и даже не пытаясь угадать его пароль.

Я не буду давать точное логическое выражение, которое я использовал, но если вы понимаете базовый приоритет булевых операторов, описанный в любом классе Discrete Math, вы сможете понять его.

...