#php #javascript #mysql #security
#php #javascript #mysql #Безопасность
Вопрос:
У меня есть метод ajax, который, по сути, работает следующим образом
function getRow(tableName, idName, idValue, callback)
Очевидным преимуществом этого является то, что у меня есть одна функция, которая может извлекать данные из любой таблицы. Однако это просто кажется неправильным с точки зрения безопасности, является ли это риском для безопасности? Соответствующие PHP-файлы, которые фактически читают базу данных / управляют ею, защищены с помощью предварительного процесса аутентификации, поэтому теоретически видимость имен таблиц в вакууме не должна представлять риска (не говоря уже о том, что база данных принимает только подключения к localhost), но мне интересно, нет ли лучшего способа добиться этого.
Редактировать: просто чтобы прояснить процесс аутентификации, безопасность пользователя / роли запрещает доступ ко всем таблицам, кроме тех, которые явно разрешены пользователю.
Комментарии:
1. Что, если я вызову эту функцию с
syscolumns
в качестве параметра?
Ответ №1:
Если вы уверены, что у вас нет уязвимостей для SQL-инъекций и что у вас никогда не будет, все в порядке.
Если у вас действительно есть уязвимость SQL-инъекции, это несколько облегчит работу злоумышленника.
Само собой разумеется (я надеюсь), что серверный скрипт должен использовать белый список таблиц и столбцов, которые могут быть представлены с помощью этого метода.
Комментарии:
1. Мне это нравится, несколько проще, потому что если у вас есть уязвимость при внедрении SQL, то найти имена таблиц несложно.
2. @mcdonald: Если вы не можете получить какие-либо выходные данные из-за уязвимости, это немного упрощает задачу.
3. 1, я согласен с @SLaks. Однако (просто мысль), знание имен таблиц, я думаю, немного упрощает для них задачу. Что я обычно делаю, просто потому, что мне не нравится, когда люди что-то знают о том, что у меня есть в фоновом режиме (т. Е. Таблицы, базы данных, файлы и т.д.), я обычно использую XOR для имен моих таблиц и файлов. Это не предназначено для того, чтобы «остановить» или «Помешать» людям разобраться в этом, но это немного усложняет для обычного человека определение используемых имен. Но вы, вероятно, не хотите дополнительных накладных расходов, связанных с необходимостью XOR имен.
4. @JTS: Если вы делаете это, вы могли бы также использовать жестко запрограммированный поиск от имен таблиц до случайных строк на сервере, чтобы клиент никогда не видел никаких реальных имен.
Ответ №2:
Сами по себе имена таблиц не так уж плохи, однако API, который вы, похоже, создаете, может быть не лучшей идеей…
Тщательно подумайте, есть ли какие-то таблицы, к которым люди не должны иметь возможности запрашивать, потому что, судя по всему, я мог бы запросить любую таблицу в вашей базе данных со стороны клиента. Например:
getRow('users', 'id', '7', function(data){console.log(data)})
Что, если таблица users вернет их пароль? даже если это хэшировано, это нехорошо. Или их электронной почты? Что, если я хочу получить все электронные письма пользователей? Для этого я мог бы написать довольно простой скрипт.
Комментарии:
1. Я надеюсь , что это то, что он подразумевает под аутентификацией на стороне сервера.
2. Точно, надеюсь, аутентификация не остановится на «могу выполнить запрос!»
Ответ №3:
Это риск, потому что он предоставляет информацию злоумышленникам. Это то же самое, что предоставлять версию программного обеспечения, которое вы используете. Это не уязвимость как таковая, но это путь к уязвимостям.
Ответ №4:
Это действительно плохая идея.
Допустим, например, вы используете этот код:
$table_name=mysql_real_escape_string($_GET['table']);
$id_name=mysql_real_escape_string($_GET['idname']);
$id_value=mysql_real_escape_string($_GET['idvalue']);
mysql_query("select * from `$table_name` where `$id_name`='$id_value'");
Это можно использовать несколькими способами:
НЕ SQL-инъекция
Этот запрос вернет пользователя root в mysql.user
, и это
?table=mysql.useramp;idname=useramp;idvalue=root
Этот запрос создаст запрос:
select * from
mysql.user where
пользователь ='root'
Внедрение SQL:
Это работает, потому что mysql_real_escpae_string не экранирует обратные галочки:`
?table=`table where 1 union select * from mysql.user/*amp;idname=junkamp;idvalue=junk
Комментарии:
1. Да, но имя таблицы MySQL может содержать только
w
символы, если я не ошибаюсь. Но входные данные должны быть проверены.2. @webarto не раскрывать подобную функциональность просто глупо. Вы могли бы получить хэш пароля для другого пользователя в той же БД без необходимости ставить точку.
Ответ №5:
Вы можете показать, например, users
имя таблицы в JS, но на стороне сервера добавьте префикс like forum_users
, который будет фактическим именем таблицы в базе данных. Таким образом, если кто-то найдет точку внедрения, он попытается DROP TABLE users
и запрос завершится неудачей, если вам повезет 🙂
Также добавьте белый / черный список для таблиц и столбцов, добавьте ОГРАНИЧЕНИЕ 1 (не зацикливаться), не возвращайте несколько массивов, и вам следует выполнить очистку с помощью чего-то вроде этого.
$select = preg_replace("#[w]#", "", $_GET["select"]);
$from = preg_replace("#[w]#", "", $_GET["from"]);
$where = preg_replace("#[w]#", "", $_GET["where"]);
$equals = mysql_real_escape_string($_GET["equals"]);
$query = "SELECT $select FROM $from WHERE $where = '$equals' LIMIT 1";
Ответ №6:
Конечно, для особых случаев следует использовать прямой API базы данных на стороне клиента. Но вы можете легко защитить это с помощью белого списка. Например, в PHP:
if (in_array($tableName, array("users", "log", "messages", ...))) {
Так что я не думаю, что это такая уж большая проблема с точки зрения безопасности, пока у вас есть фиксированный список здесь.