Подтвердить что ты не робот

Есть ли что-нибудь, что можно положить после предложения "ORDER BY", которое может представлять угрозу безопасности?

В принципе, я хочу сделать следующее:

mysql_query("SELECT ... FROM ... ORDER BY $_GET[order]")

Очевидно, что они могут легко создать ошибку SQL, помещая туда нечувствительность, но mysql_query позволяет выполнять только 1 запрос, поэтому они не могут помещать что-то вроде 1; DROP TABLE ....

Есть ли какой-либо вред, который может сделать злоумышленник, кроме создания синтаксической ошибки?

Если да, как я могу дезинфицировать запрос?

Там много логики, построенной на переменной $_GET['order'], находящейся в синтаксисе типа SQL, поэтому я действительно не хочу менять формат.


Чтобы уточнить, $_GET['order'] будет не просто отдельным полем/столбцом. Это может быть что-то вроде last_name DESC, first_name ASC.

4b9b3361

Ответ 1

Да, атаки SQL-инъекций могут использовать предложение unescaped ORDER BY в качестве вектора. Там объясняется, как это можно использовать и как избежать этой проблемы здесь:

http://josephkeeler.com/2009/05/php-security-sql-injection-in-order-by/

В этом сообщении в блоге рекомендуется использовать белый список для проверки параметра ORDER BY, что почти наверняка является самым безопасным подходом.


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

function validate_order_by($order_by_parameter) {
    $columns = array('first_name', 'last_name', 'zip', 'created_at');

    $parts = preg_split("/[\s,]+/", $order_by_parameter);

    foreach ($parts as $part) {
        $subparts = preg_split("/\s+/", $part);

        if (count($subparts) < 0 || count($subparts) > 2) {
           // Too many or too few parts.
           return false;
        }

        if (!in_array($subparts[0], $columns)) {
           // Column name is invalid.
           return false;
        }

        if (count($subparts) == 2 
            && !in_array(strtoupper($subparts[1]), array('ASC', 'DESC')) {
          // ASC or DESC is invalid
          return false;
        }
    }

    return true;
}

Даже если предложение ORDER BY является сложным, оно по-прежнему выполняется только из значений, которые вы предоставляете (при условии, что вы не позволяете пользователям редактировать его вручную). Вы все еще можете подтвердить использование белого списка.

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

Ответ 2

Не рассчитывайте на то, что SQL-инъекция в этой точке не вызовет проблемы; не допускайте ЛЮБОЙ инъекции SQL. Если ничего другого, злоумышленник может определить очень сложный порядок, который может вызвать серьезное замедление вашей БД.

Ответ 3

Я предпочитаю делать белый список и обрабатывать строку параметров http как отдельную от строки, которая получает интерполяцию в SQL-запрос.

В следующем примере PHP ключи массива будут значениями, переданными как параметры http, какой-то символической меткой для разных схем упорядочения, в соответствии с вашим веб-интерфейсом. Значения массива были бы тем, что мы хотим интерполировать в SQL для этих соответствующих схем упорядочения, например. имена столбцов или выражения.

<?php

$orderby_whitelist = array(
  "name"    => "last_name, first_name",
  "date"    => "date_created",
  "daterev" => "date_created DESC",
  "DEFAULT" => "id"
);

$order = isset($_GET["order"]) 
  ? $_GET["order"] 
  : "DEFAULT";
$order_expr = array_key_exists($order, $orderby_whitelist) 
  ? $orderby_whitelist[$order] 
  : $orderby_whitelist["DEFAULT"];

mysql_query("SELECT ... FROM ... ORDER BY $order_expr")

Это имеет преимущества:

  • Вы можете защитить от SQL-инъекции даже в тех случаях, когда вы не можете использовать параметры запроса. Если клиент передает нераспознанное значение, ваш код игнорирует его и использует порядок по умолчанию.

  • Вам не нужно ничего дезинфицировать, потому что ключи и значения в массиве написаны вами, программистом. Клиентский вход может выбрать только один из вариантов, которые вы разрешаете.

  • В вашем веб-интерфейсе не отображается структура вашей базы данных.

  • Вы можете создавать собственные заказы, соответствующие выражениям SQL или альтернативным ASC/DESC, как я показал выше.

  • Вы можете изменить структуру базы данных, не изменяя свой веб-интерфейс, или наоборот.

Я рассматриваю это решение в своей презентации SQL Injection Myths and Fallacies, а также в моей книге SQL Antipatterns: устранение ошибок программирования баз данных.

Ответ 4

Логика, построенная вокруг переменной $_GET['order'], должна быть такой же допустимой при использовании переменной $order_sanitized. Почему бы просто не санировать вход в первую очередь, а затем выполнить свою логику, чтобы она вписывалась в инструкцию SELECT?

Ответ 5

Это все еще точка потенциальной инъекции SQL. Вы зависите от внутренней реализации mysql_query. Что делать, если в более поздней версии они меняют его, чтобы использовать несколько запросов?

Вы можете использовать mysql_real_escape_string.