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:
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.
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.
Comentarios
Good post; about the screenshot, it's gdb with mammon's gdbinit colorized, right?
Thanks
no, its radare, coded by pancake and some ora8 code.
radare.nopcode.org
regards.
If we both are from Barcelona... why are we writing in english? :-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?
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.
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
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.