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

Как предотвратить SQL-инъекцию с динамическими именами таблиц?

У меня было это обсуждение с высокой репутацией PHP guy:

PDO здесь бесполезно. а также mysql_real_escape_string. крайне низкое качество.

Это, конечно, классно, но я честно не знаю, что неправильно с предложением использовать mysql_real_escape_string или PDO для исправления этого кода:

<script type="text/javascript">
    var layer;

    window.location.href = "example3.php?layer="+ layer;

    <?php
        //Make a MySQL connection
        $query = "SELECT Category, COUNT(BUSNAME)
          FROM ".$_GET['layer']." GROUP BY Category";
        $result = mysql_query($query) or die(mysql_error());

В этот

$layer = mysql_real_escape_string($_GET['layer']);
$query = "SELECT Category, COUNT(BUSNAME)
FROM `".$layer."` GROUP BY Category";

учитывая, что код JavaScript получает клиентскую сторону.

4b9b3361

Ответ 1

Ваш совет действительно неверен.

mysql_real_escape_string() не будет работать для динамических имен таблиц; он предназначен для исключения строковых данных, ограниченных только кавычками. Он не ускользнет от обратного символа. Это небольшое, но важное различие.

Поэтому я мог бы вставить SQL-инъекцию в это, я просто должен был бы использовать закрывающий backtick.

PDO не обеспечивает санитарию для динамических имен таблиц, либо.

Вот почему хорошо не использовать динамические имена таблиц или, если нужно, сравнивать их со списком допустимых значений, например список таблиц из команды SHOW TABLES.

Я тоже не знал об этом и, вероятно, был виноват в повторении того же плохого совета, пока он не был указан мне здесь на SO, также полковником Шрапнелом.

Ответ 2

Для записи здесь приведен пример кода для фиксации этого отверстия.

$allowed_tables = array('table1', 'table2');
$clas = $_POST['clas'];
if (in_array($clas, $allowed_tables)) {
    $query = "SELECT * FROM `$clas`";
}

Ответ 3

Чтобы ответить, как действительно исправить код:

'...FROM `' . str_replace('`', '``', $tableName) . '`...'

Это дублирует все обратные ссылки в имени таблицы (это делается в MySQL).

Одна вещь, о которой я не уверен, является ли это "безопасным для кодирования" (как правильно это назвать?). Обычно для mysql_real_escape_string вместо addslashes рекомендуется использовать mysql_real_escape_string, потому что первый учитывает кодировку соединения MySQL. Возможно, эта проблема также применима и здесь.