SECCON Beginners CTF 2018に参加しました

惨敗した

どうも、チーム「あれがななち」の「あれが」担当のながてちです。

2018/5/26(土) 13:00 から 2018/5/27(日) 13:00 まで行われたSECCON Beginners CTF 2018ますぐれとチームを組んで参加しました。

CTFの大会に出たことないガチ初心者だったのですが、「初めてCTFに参加される方」を対象にしたCTFの大会が開かれるとのことだったので、これを機にやるぞ~って感じで大会に臨みました。

結果はというと、

388ポイントで242位でした。
なんとも言い難い点数と順位…。

これで「初心者向け」のCTFなので、かなり厳しいな…って感じで終わりました。

ちなみに競技中は寝る間も惜しんで考えてました。ぽえ~

Write Up

需要あるか分かりませんが、自分が解いた部分のWrite Upを書こうと思います。

自分はおもに「Web」と「Misc」を担当しました。

[Warmup] Greeting | Web 51点

問題ページの下に思いっきりソースコードが書いてあったのでPHP分からないながら頑張って読んだら、
「Cookieのnameにadminがセットされている」状態で「name(フォーム)の入力がなければ」FLAGが降ってくるなって考えました。

なので一度adminを入力してわざと偽管理者になり(Cookieをセットするため)、管理者ツールでフォームの変数をnameからnam(適当)にして名前を変更するボタンを押すと、FLAGが降ってきます。

FLAGはctf4b{w3lc0m3_TO_ctf4b_w3b_w0rd!!}

Gimme your comment | Web 78点

お問い合わせフォームに

<script>
  alert('おいす~');
</script>

と入力して送信するとちゃんと動くことから、クロスサイトスクリプティングでいけるなって思いました。

問題文に巡回者のソースコードが与えられていたので、読むと、

  1. comment_contentという名前のフォームに「投稿ありがとうございます。大変参考になりました。」と入力する
  2. submitボタンを押す
  3. サヨナラする

という行動をしていたので、「フォームにuser-agentの情報を入力させてsubmitさせればFLAG降ってくるな」と考えました。

そんな感じで送信したお問い合わせがこんなかんじ

<input type="text" name="comment_content">
<script>
  $(document).ready(function () {
    var userAgent = window.navigator.userAgent.toLowerCase();
    document.getElementsByClassName("form-control")[0].value = userAgent ;
  });
</script>

わざとnameがvomment_contentなダミーフォームをつくり、そこに「投稿ありがとう~」を入力させて、ちゃんとしたほうのフォームに自動入力させたuser-agent情報をsubmitさせます。

これを実行するとこんな感じ

すでに入力されてるのは自分のuser-agentですね。

FLAGはctf4b{h4v3_fun_w17h_4_51mpl3_cr055_5173_5cr1p71n6}

ちなみにこの方法だと、次の問題「Gimme your comment REVENGE」で自動入力ができなくなって死にます()

[Warmup] plain mail | Misc 51点

パケット解析問題
ちょうど大会前にパケット解析の問題をやってたので、よっしゃ~って感じで解きました。

問題文からmailが関係してるんだろうな~ってことでWireSharkで開いてSMTPでフィルタリング。
すると、「いまから2通のメールを送るよ、1通目はzipファイル、2通目はパスワード」みたいなメールがみつかるので、それ通りにメールのパケットを見ていって、zipを手に入れてパスワードを入力して中にあるFLAG.txtを取り出しました。

WireSharkにはオブジェクトをエクスポートする便利な機能があるので、それを使ってzipファイルを取り出しました。

FLAGはctf4b{email_with_encrypted_file}

てけいさんえくすとりーむず | Misc 55点

100問を300秒でてけいさんできるかな。

自分はできないので、Rubyでコードを組んで自動化しました。

require 'socket'

port = TCPSocket.open("tekeisan-ekusutoriim.chall.beginners.seccon.jp",8690)

res = 0

puts(port.gets()) #1
puts(port.gets()) #2
puts(port.gets()) #3
puts(port.gets()) #4
puts(port.gets()) #5
puts(port.gets()) #6
puts(port.gets()) #7
puts(port.gets()) #8
puts(port.gets()) #9
puts(port.gets()) #10
puts(port.gets()) #11

for i in 1..100 do
    puts(port.gets())
    popo = ""
    read = port.getc().chomp
    while read!="="
        popo = popo + read.to_s
        read = port.getc().chomp
    end
    puts ("#{popo} = ")

    a,po,b = popo.chomp.split(" ").map(&:to_s)
    if po == "+"
        res = a.to_i + b.to_i
    elsif po == "-"
        res = a.to_i - b.to_i
    elsif po == "*"
        res = a.to_i * b.to_i
    end
    puts(res)
    port.puts(res)

end 

puts(port.gets())
puts(port.gets())
puts(port.gets())  

苦労したのはRubyのgets()だと、1行まるまる読み込もうとして、入力待ちの部分まで巻き込んでしまい、実行が止まることをどうやって解消しようかという問題です。

getc()という、1文字だけ読み出すというメソッドがあることが分かったので、それを使って入力手前まで読み込むという手法で解決させました。

FLAGはctf4b{ekusutori-mu>tekeisann>bigina-zu>2018}

100問の計算を自動で実行してるのを見てると、何とも言えない達成感がありますね…。

おしまい

なんだかんだいって楽しかったです。
精進します。