SQL injection - как санировать предложение sql, сгенерированное программой?
в стандартном Ajax,where
и order by
SQL предложения предоставляются программой (не пользователем), например
var url = ".select?dd=emp&where="+escape("emp_tp='abc' and hire_dt<current_date-'2 years' and super_emp_id is distinct from emp_id")
ответил на сервере
$where = (isset($_GET['where'])) ? pureClause($_GET['where']) : null;
$order = (isset($_GET['order'])) ? pureClause($_GET['order']) : null;
...
$query = $query.(($where)?" where $where":'').(($order)?" order by $order":'');
вопрос в том, что должна функция pureClause
выглядеть?
прямо сейчас pureClause
просто вызывает ошибку, если любой из следующих причин:
; select insert update delete drop create truncate
если другая инъекция вызывает сбой запроса, это нормально,пока данные не повреждены.
для меня это кажется адекватным, но в глубине души я знаю, что ошибаюсь.
пояснения:
- подготовленные операторы в Postgres, хотя и очень быстрые, являются болью для настройки и обслуживания - они в порядке для хорошо используемых запросов, но не пользовательских запросов.
- создание подготовленного оператора для каждой транзакции является огромный db hit. гораздо предпочтительнее, если безопасность может быть достигнута на уровне приложения.
наконец, рассмотрим, где пункт
emp_tp='abc' and hire_dt=current_dt-'2 years' and super_emp_id is distinct from emp_id
сколько здесь заполнителей? это нужно правильно проанализировать, прежде чем вводить в подготовленный оператор с заполнителями, верно? или я совсем упустил лодку?
первичные факты:
- не практические написания парсера выражение SQL для параметризованных подготовленные заявления
- не практические написать выражение SQL дезинфектор, что гарантии нет вред
устранение:
для выбора, где случайный SQL может быть проблемой: поскольку слишком сложно защитить базу данных, пусть база данных защищает себя! у разных пользователей разные роли / разрешения. для выбора используйте пользователя только для чтения. для обычного SQL это гарантирует отсутствие DML из этих операторов.
рекомендации: четыре пользователь обращений к БД
-
developer
, все сделаем (никогда использовать в качестве подключения в веб-приложение) -
dml
- можно выбрать / dml почти на все (необходимо использовать для dml) -
read
- можно выбрать (использовать для всех выбирает, будь то подготовленный или текст) -
login
- может выполнять только функции логина/пароля (используется в процессе входа в систему)
защита секретности пароля:
-
dml
иread
не может получить доступ к данным пароля, либо через select или dml -
login
должны получить доступ к данным пароль только через защищенные функции, например,
function login( username, password ) - returns user_id function set_password( usr_id, password ) - sets password
- только
login
наlogin()
иset_password()
функции - в зависимости от вашей базы данных,
login
мая нужен доступ sql к столбцам паролей - в зависимости от вашей базы данных,
password
столбец может быть защищен сам; если нет, то должен быть перемещен изuser
таблицы в собственная безопасная таблица
настройки в mysql
, используя инструмент администратора, заняло около 30 минут, включая время, чтобы написать функции входа и разделить столбец пароля.
4 ответов
то, что вы делаете, - это само определение SQL-инъекции и не может быть дезинфицировано. Вы не можете пройти в WHERE
предложение в безопасном режиме точка конец истории. Эту часть запроса необходимо построить на стороне сервера. Тот факт, что вы не узнали это означает, что вы должны подробнее о SQL-инъекции, явно спрашивая StackOverflow является небезопасным подходом к этой проблеме. Страх в том, что вы никогда не узнаете основы этого уязвимость.
$order
можно сделать безопасным способом с белым списком. Например:
if(in_array($_GET['order'],$list_of_rows)){
$order=$_GET['order'];
}
Если вы передаете имя таблицы или имя столбца, убедитесь, что вы проверяете его против белого списка, или это будет SQL-инъекция.
всегда использовать подготовленные операторы. Он будет обрабатывать экранирование ввода и избегать SQL-инъекции. Там не будет необходимости в хаки, как pureClause
.
Проверьте mysqli_stmt::prepare()
Как предложил @Stephen, укажите WHERE в качестве объекта, затем проанализируйте объект и создайте безопасный SQL var, где = { emp_tp: { условие: равный значение: 'АВС' } ВАР порядке = { emp_tp: 'ASC' }
отправить его как json:
var params = {
w: where,
o: order
}
$.post(url,params,function(result){...}, 'json');
и в PHP
$where = isset($_POST['w']) ? json_decode($_POST['w') : array();
if (!empty($where)) {
foreach ($where as $field => $data) {
// validate that field exists
// validate that operator is valid
$sql .= sprintf('%s %s "%s"', $field, $data->operator, mysql_escape_string($data->value));
}
}
понял! Маршрутизация всех этих запросов через пользователя базы данных (соединение), которому были предоставлены только права выбора в базе данных!
попытка DML задохнется. Это не предотвращает DoS-атаки (много способов сделать это!), но защищает данные. Ни для безопасного запросы, как войти. Но для клиента, созданного WHERE и ORDER, с целью предотвращения DML, это должно работать просто отлично.
десять/пятнадцать лет назад всегда настройте разных пользователей для разных ролей, но с app layer и т. д. и т. д. вышли из привычки. Это, вероятно, хорошая идея, чтобы повторно инвестировать в эти принципы.
Если hear по-другому не отметит это как правильный ответ - он удовлетворяет всем критериям, однако он уклоняется от теоретически невозможной задачи написания дезинфицирующего средства.