Dreamhack Wargame Web Exercises Stage 1
Dreamhack Wargame Web Stage 1 Writeups
Overview
Dreamhack is an online Korean collection of challenges from a variety of challenges. I am focusing on the web challenges starting at the stage 1 challenges outlined in this post.
Challenges
Cookie
We are first greeted with a basic web app that has a few tabs and a login function.
Looking at the source code we see default credentials for a guest account are commented out.
Logging in with these we get a message telling us that we aren’t admin. Based on the name of the challenge there is a cookie called username with the current value of guest.
Change this to admin and we get the flag.
DH{7952074b69ee388ab45432737f9b0c56}
Carve Party
This is a fun challenge that just involves clicking a pumpkin 10000 times to eventually reveal the flag.
I made a simple script for this that just uses the pyautogui library to left click 10000 times at the spot of my curser. A more elaborate way using positioning on the html document is possible but I would rather make my computer unusable for 15 minutes as the program does 10000 clicks.
import pyautogui
for i in range(10000):
pyautogui.click()
Once it gets to 0 the flag appears under the pumpkin.
DH{I_lik3_pumpk1n_pi3}
File Download 1
This challenge gives us a web app that allows for memos to be uploaded and viewed.
I made a test memo to see what happened and discovered that they can be read once uploaded using the read function. The syntax for this is read?name=test
. Instead of reading my own memo I decided to read flag.py to get the flag. This was not the answer but going one directory down let us access the correct file.
XSS 1
We are first brought to the main page with tabs for xss, memo and flag.
XSS has a script alert 1 present in the url which sends the alert when you load the page. This shows that the website is vulnerable to XSS.
The memo page is the output for the web app. Anything you put into the URL is posted on the content section of the page.
Looking at the source code we see 2 functions of importance. These are the flag and read_url functions. We can see that in these functions a cookie is created that has the flag. So we need to use XSS to read this cookie to get the flag.
@app.route('/flag', methods=['GET', 'POST'])
def flag():
if request.method == 'GET':
return render_template('flag.html')
elif request.method == 'POST':
xss = request.form.get('xss')
if not read_url(xss, {'name': 'flag', 'value': FLAG}):
return '<script>alert("wrong??");history.go(-1);</script>'
return '<script>alert("good");history.go(-1);</script>'
def read_url(url, cookie={'name': 'name', 'value': 'value'}):
cookie.update({'domain':'127.0.0.1'})
try:
options = webdriver.ChromeOptions()
for _ in ['headless', 'window-size=1920x1080', 'disable-gpu', 'no-sandbox', 'disable-dev-shm-usage']:
options.add_argument(_)
driver = webdriver.Chrome('/chromedriver', options=options)
driver.implicitly_wait(3)
driver.set_page_load_timeout(3)
driver.get('http://127.0.0.1:8000/')
driver.add_cookie(cookie)
driver.get(f'http://127.0.0.1:8000/xss?xss={urllib.parse.quote(url)}')
except:
driver.quit()
return False
driver.quit()
return True
Having discovered the memo page earlier we know that this is an output and that we will need to use it to read the cookie. This is a simple script that uses the cookie as the output for the memo.
<script> location.href="/memo?memo="+document.cookie; </script>
When we go back to the memo page we see the flag output.
DH{2c01577e9542ec24d68ba0ffb846508e}
Simple SQLi
This is a simple SQLi challenge that gives a log in page and wants us to get admin access.
All we have to do is inject admin"--
into the username section to gain access. Once logged in we have a plain text page with the flag.
DH{1f136225e316add7bff3349ab1dd5400}
Pathtraversal
We are given a get user info function that shows us the information based on 2 users that are in the system. These are admin and guest.
The source code shows us the get_info function which takes in the user input userid and outputs it as the info.
@app.route('/get_info', methods=['GET', 'POST'])
def get_info():
if request.method == 'GET':
return render_template('get_info.html')
elif request.method == 'POST':
userid = request.form.get('userid', '')
info = requests.get(f'{API_HOST}/api/user/{userid}').text
return render_template('get_info.html', info=info)
When we enter guest and admin they are assigned to the values of 0 or 1 which handles the output. Any other entry results in undefined which means we cannot look at a file directly. The solution to this is as simple as changing the file associated with a user in chrome developer tools.
Once we refresh the page we get.