jueves, enero 24, 2008

CVE-2008-0001 Privilege scalation exploit.

CVE-2008-0001 Linux Kernel VFS Unauthorized File Access Vulnerability.

Trond changed namei.c code, and implemented a vulnerability on 18 Oct 2005
Bill Roman detected it and solve the problem in the following patch:

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1576,7 +1576,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
if (S_ISLNK(inode->i_mode))
return -ELOOP;

- if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
+ if (S_ISDIR(inode->i_mode) && (acc_mode & MAY_WRITE))
return -EISDIR;

error = vfs_permission(nd, acc_mode);
return -EACCES;

flag &= ~O_TRUNC;
- } else if (IS_RDONLY(inode) && (flag & FMODE_WRITE))
+ } else if (IS_RDONLY(inode) && (acc_mode & MAY_WRITE))
return -EROFS;


Well, FMODE_WRITE=2 if we open with O_RDWR (=2) at don't writable file, we will get -EROFS
but we can use O_WRONLY (=1) and != FMODE_WRITE (=2) then we can map the descriptor to memory and write ;)


#drwxr-xr-x 2 root root 4096 2008-01-28 15:46 test
#su - shao

Without write permissions, shao has appended

open("/test", O_WRONLY) = -1 EISDIR (Is a directory)
open("/test", O_RDWR) = -1 EISDIR (Is a directory)
open("/test", O_RDONLY|O_APPEND) = 3

O_APPEND succeed and kernel give us 3rd descriptor.

If we write with write() syscall:

open("/tmp/test", O_RDONLY|O_APPEND) = 3
lseek(3, 0, SEEK_END) = 5
write(3, ptrace: umoven: Input/output error
0x41, 1) = -1 EBADF (Bad file descriptor)
close(3) = 0

write() syscalls return EBADF, he don't let us modify this kind of descriptor, he did a check.
mmap() syscall return -1

Well, from user space we can't exploit this.

9 comentarios:

Hugo dijo...

Hi Jesus,

Good post; about the screenshot, it's gdb with mammon's gdbinit colorized, right?

Thanks

Jesús dijo...

Hi Hugo,

no, its radare, coded by pancake and some ora8 code.

radare.nopcode.org

regards.

Hugo dijo...

Radare, ok. Great tool.

If we both are from Barcelona... why are we writing in english? :-P

padraig dijo...

I'm glad you did, else I wouldn't have found this post :-P

My investigation of this bug leads me to believe that the effects of an actual exploit would be to truncate (as opposed to write or replace) files. What did your testing show?

Jesús dijo...

Hi,

with root i have erased /test/*

open("/test", O_RDONLY|O_TRUNC) = 3
close(3) = 0

But with non-root:
open("/test", O_RDONLY|O_TRUNC) = -1 EACCES (Permission denied)

I have fuzzed all params, and I beleave that is not explotable.

Jesús dijo...

Maybe at 2.6.23.x kernel you can make a open("directory",O_TRUNC) with a non root user, I will test it as son as I could.

root dijo...

buen blog, estamos en contacto para próximas referencias

Anónimo dijo...

Here:
http://rhn.redhat.com/errata/RHSA-2008-0055.html

It says that:
"A local unprivileged
user could truncate directories to which they had write permission"

On the above example, your unprivileged user didn't have write permission on the directory. This is why it didn't work as expected.

Even if the directory contains read-only files, an unprivileged user that has write permission to the directory he can truncate its contents

Jesús dijo...

Hi,
thanks alot :)

a flaw related:
if your code has some permissions, and make an exec of a code with exec permissions but don't have read permissions, the exec call will replace the memory image of your code with the memory image of the executed one, and can be inspected.