Проведение SQL-инъекций в Zend Framework

в 19:24, , рубрики: Zend Framework, информационная безопасность, метки: ,

Возможно слегка громкое название статьи, но полностью отображает ее суть.

Момент первый

Если следовать всем правилам, т.е. использовать внутренние механизмы Zend, подготавливать параметры в методах — то на данный момент нет информации о возможности проведения sql-инъекции. Речь идет о подобных конструкциях:

$select->order($value);

Которые так или иначе встречаются на практике.

Момент второй

В чем же соль? В том, что даже при поступлении параметров в подобные методы без какой-либо подготовки внутренние механизмы все же их подготавливают. Только не все (а некоторые частично) — об этом и речь.

Хоть у нас и есть исходный код данной библиотеки, мы рассмотрим данную тему как «черный ящик», будет нагляднее и понятнее. Конкретнее — адаптер MySQL, класс Zend_Db_Select (тоже самое проверялось и на PgSQL)

Момент третий

Для того, чтобы провести инъекцию в Zend, нам нужно закрыть предыдущую обратную кавычку (к примеру в случае синтаксиса from = select * from `table`), или апостроф — (where id = '1'), так как Zend следует правилам и при указании параметра открывает нужное «обрамление». В первом случае, при передаче на вход tab`ble у нас на выходе должно быть ta``ble, во втором: на входе 1'2, на выходе 1''2.
Еще раз, мы ведем речь о «сырой» отправке данных методу.

У нас возможны три случая:

  1. FQ — все параметры подготавливаются (fully quoted)
  2. NQ — данные не подготавливаются, к БД все «уйдет», так, как и передали (no quoted)
  3. PQ — некоторые параметры проходят обработку, некоторые нет (partially quoted)

Пойдем по порядку, по порядку в синтаксисе SQL

1) ->from — FQ

Код:

$table = "wp_use`rs";
$select->from($table);

[queryString] => SELECT `wp_use``rs`.* FROM `wp_use``rs

2) ->join — PQ

$table1 = 'tab`le1';
$table2 = 'tab`le2';
$key = 'i`d';
$data = 'da`ta';
$select = $db->select()->from($table1)->join($table2, $table1.'.'.$key.' = '.$table2.'.'.$key, array($data));

[queryString] => SELECT `tab``le1`.*, `tab``le2`.`da``ta` FROM `tab``le1` INNER JOIN `tab``le2` ON tab`le1.i`d = tab`le2.i`d

3) ->joinUsing — PQ

$table1 = 'tab`le1';
$table2 = 'tab`le2';
$key = 'i`d';
$column = 'c`ol'u;m"n';

$select = $db->select()->from($table1)->joinUsing($table2, $column);

[queryString] => SELECT `tab``le1`.*, `tab``le2`.* FROM `tab``le1` INNER JOIN `tab``le2` ON `tab``le2`.c`ol'u;m"n = `tab``le1`.c`ol'u;m"n

4) ->where — NQ

$select->from($table);
$value = "1)2'3 --";
$select->where($value);

[queryString] => SELECT `wp_users`.* FROM `wp_users` WHERE (1)2'3 --)

5) ->group — FQ

$table = "wp_users";
$value = 'i`d';
$select = $db->select()->from($table)->group($value);

[queryString] => SELECT `wp_users`.* FROM `wp_users` GROUP BY `i``d`

6) ->having — NQ

$table = "wp_users";
$value = 'some_count > 0); hello habr -- 10';
$select = $db->select()->from($table)->having($value);

[queryString] => SELECT `wp_users`.* FROM `wp_users` HAVING (some_count > 0); hello habr -- 10)

7) ->order — FQ

$table = "wp_users";
$value = i`d';
$select = $db->select()->from($table)->having($value);

[queryString] => SELECT `wp_users`.* FROM `wp_users` ORDER BY `i``d` ASC

8) ->limit — FQ

Тут даже не FQ, а просто — приведение типов (к int)

$table = "wp_users";
$limit1 = '1; hello -- ';
$limit2 = '2; hello -- ';
$select = $db->select()->from($table)->limit($limit1, $limit2);

[queryString] => SELECT `wp_users`.* FROM `wp_users` LIMIT 1 OFFSET 2
Сюда же ->limitPage(), аналогичная работа

9) ->union — NQ

$db->select + string

$table = "wp_users";
$select = $db->select()->from($table);
$select2 = "select * from ta"b'le`2";
$select3 = $db->select()->union(array($select, $select2));
$db->query($select3);

[queryString] => SELECT `wp_users`.* FROM `wp_users` UNION select * from ta"b'le`2

Сводные данные

FQ: ->from, ->group, ->order, ->limit, ->limitPage
PQ: ->join, ->joinUsing
NQ: ->where, ->having, ->union

На практике не фильтруемые данные можно встретить к примеру в ajax-обработчиках.

Выводы

Я не возьмусь делать глобальных выводов, но то, что ваш инструмент может повести себя не так, как вы ожидаете — факт. Будьте бдительны ;]

P.S. Кроме всего прочего, возможно эти данные кто-нибудь возьмет к себе в CTF ;)

Автор: BeLove

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js