
Выполнение команд с правами root через UDP Broadcast в infosvr маршрутизаторов ASUS
Ряд моделей роутеров ASUS включает службу infosvr, которая прослушивает UDP-широковещательный порт 9999 на интерфейсе LAN или WLAN. Она используется одним из инструментов ASUS для упрощения настройки роутеров путём автоматического обнаружения роутеров в локальной подсети. Эта служба работает с привилегиями root и содержит уязвимость выполнения команд без аутентификации. Исходный код этой службы, как и остальной части роутера, доступен на сайте поддержки ASUS.
Уязвимости присвоен идентификатор CVE-2014-9583 (увы, в итоге не CVE-2014-10000 :-/).
В настоящее время предполагается, что все известные версии прошивок для соответствующих роутеров (RT-AC66U, RT-N66U и т. д.) уязвимы. Тестирование проводилось на версии 3.0.0.376.2524-g0013f52.
Подтверждено, что следующие роутеры/версии прошивок уязвимы:
| Роутер | Версия прошивки | Кем подтверждено |
|---|---|---|
| RT-N66U | 3.0.0.4.376_1071-g8696125 | Friedrich Postelstorfer |
| RT-AC87U | 3.0.0.4.378_3754 | David Longenecker |
| RT-N56U | 3.0.0.4.374_5656 | @argilo |
| RT-AC68U | 3.0.0.4.376_3626-g9a8323e | @Arie |
| DSL-N55U | 3.0.0.4.374_4422-gc83c78f | @S2- |
| DSL-AC68U | 3.0.0.4.376_2158-g340202b | @magJ, @gitFurious |
| RT-AC66R | 3.0.0.4.376_2524-g0013f52 | @asgh |
| RT-AC66R | 3.0.0.4.376_3602 | @facerolling |
| RT-AC55U | 3.0.0.4.376_6587-gaa506e9 | @pellaeon |
| RT-N12HP_B1 | 3.0.0.4.374_1327 | @vittee |
| RT-N16 | 3.0.0.4.220 | @xorrbit |
Кроме того, роутеры с прошивками на основе поддерживаемого сообществом asuswrt-merlin уязвимы до версии 376.49_5.
Роутеры, использующие ревизии прошивок, выпущенные 12 января 2015 года или позже, не должны быть подвержены уязвимости. В следующей таблице приведены сообщения о не подверженных уязвимости роутерах/прошивках.
| Роутер | Версия прошивки | Кем подтверждено |
|---|---|---|
| RT-AC66R | 3.0.0.4.376_3754-g5ef7c1f | @asgh |
| RT-N12HP_B1 | 3.0.0.4.376_3754-g5ef7c1f | @vittee |
Рассмотрим следующий фрагмент из проекта ASUSWRT-Merlin, который является расширенным форком кода ASUS. Вы можете просмотреть файл целиком (рекомендуется для дополнительного веселья) здесь.
177 char *processPacket(int sockfd, char *pdubuf)
178 {
...
202 phdr = (IBOX_COMM_PKT_HDR *)pdubuf;
...
207 if (phdr->ServiceID==NET_SERVICE_ID_IBOX_INFO &&
208 phdr->PacketType==NET_PACKET_TYPE_CMD)
209 {
...
Функция processPacket вызывается после получения пакета размером INFO_PDU_LENGTH (512) байт. Конкретный уязвимый путь выполнения кода: main->processReq->processPacket. Затем служба приводит пакет к структуре и проверяет, что поля ServiceID и PacketType соответствуют ожидаемым значениям.
Следующий блок содержит то, что, как полагают, является корневой причиной этой уязвимости.
222 if (phdr->OpCode!=NET_CMD_ID_GETINFO && phdr->OpCode!=NET_CMD_ID_GETINFO_MANU)
223 {
224 phdr_ex = (IBOX_COMM_PKT_HDR_EX *)pdubuf;
225
226 // Check Mac Address
227 if (memcpy(phdr_ex->MacAddress, mac, 6)==0)
228 {
229 _dprintf("Mac Error %2x%2x%2x%2x%2x%2x\n",
230 (unsigned char)phdr_ex->MacAddress[0],
231 (unsigned char)phdr_ex->MacAddress[1],
232 (unsigned char)phdr_ex->MacAddress[2],
233 (unsigned char)phdr_ex->MacAddress[3],
234 (unsigned char)phdr_ex->MacAddress[4],
235 (unsigned char)phdr_ex->MacAddress[5]
236 );
237 return NULL;
238 }
239
240 // Check Password
241 //if (strcmp(phdr_ex->Password, "admin")!=0)
242 //{
243 // phdr_res->OpCode = phdr->OpCode | NET_RES_ERR_PASSWORD;
244 // _dprintf("Password Error %s\n", phdr_ex->Password);
245 // return NULL;
246 //}
247 phdr_res->Info = phdr_ex->Info;
248 memcpy(phdr_res->MacAddress, phdr_ex->MacAddress, 6);
249 }
Блок начинается с исключения пары значений OpCode, которые, предположительно, по замыслу не требуют аутентификации. Затем вызывается memcpy, и возвращаемое значение подозрительным образом сравнивается с нулём. Это явно указывает на то, что автор намеревался использовать memcmp. Тем не менее, даже если бы эта проверка была реализована правильно, знание MAC-адреса устройства вряд ли можно считать достаточной аутентификацией.
Следующий блок закомментирован, но показывает, что автор в какой-то момент экспериментировал с проверкой пароля. Правда, в этом случае пароль был жёстко прописан как «admin».
Далее следующий оператор switch распределяет обработку в зависимости от переданного OpCode.
251 switch(phdr->OpCode)
252 {
...
428 case NET_CMD_ID_MANU_CMD:
429 {
430 #define MAXSYSCMD 256
431 char cmdstr[MAXSYSCMD];
432 PKT_SYSCMD *syscmd;
...
440 syscmd = (PKT_SYSCMD *)(pdubuf+sizeof(IBOX_COMM_PKT_HDR_EX));
...
443 if (syscmd->len>=MAXSYSCMD) syscmd->len=MAXSYSCMD;
444 syscmd->cmd[syscmd->len]=0;
445 syscmd->len=strlen(syscmd->cmd);
446 fprintf(stderr,"system cmd: %d %s\n", syscmd->len, syscmd->cmd);
447 #if 0
...
512 #endif
513 {
514 sprintf(cmdstr, "%s > /tmp/syscmd.out", syscmd->cmd);
515 system(cmdstr);
Если злоумышленник указывает значение OpCode NET_CMD_ID_MANU_CMD, предыдущий блок обрабатывает пакет, приводя его к структуре PKT_SYSCMD. Таким образом, все члены syscmd полностью контролируются злоумышленником. Прежде чем позаботиться (подмигивание) о NUL-завершении строки команды, автор выполняет команду в строке 514. После выполнения команды вывод считывается из временного файла и отправляется обратно на адрес источника инициирующего пакета.
Конечные пользователи: обновите прошивку до ревизии 3.0.0.4.376.3754 или новее. Важно отметить, что функция роутера «Проверить обновление» может работать некорректно. Вручную проверьте версию установленной прошивки и, если она устарела, загрузите/установите новую прошивку.
ASUS/Merlin: удалите функциональность удалённого выполнения команд из этой службы. Даже если бы она была защищена надёжной аутентификацией, широковещательная передача пароля на всю локальную сеть — не то, что нужно. Если выполнение команд действительно необходимо, его следует предоставлять через SSH или аналогичный безопасный механизм.
Дэвид Лонгенекер (David Longenecker) рекомендует использовать скрипт (JFFS) в сочетании с настройкой nvram script_usbmount, чтобы завершать процесс infosvr при загрузке. Дополнительную информацию см. в его сообщении в блоге.