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

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

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 отправляется на стороне клиента.

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

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

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

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

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

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

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

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

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

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

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

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