InterKosenCTF Image Extractor writeup
Challenge
My hated friend releases a service which extracts images from a document. I want to break it to read /flag.
Solution
docx ファイルをアップロードすると内部の画像ファイルを取り出してくれるサービス
そしてサーバー内の /flag を読み出すとフラグを得られる
docx ファイルは zip ファイルでそのまま解凍すると word/media ディレクトリ内にドキュメント内の画像が保存されている
ソースコードが与えられるので main.rb を読んでいく
アップロード部分
files = `zipinfo -1 #{filename}`
raise "ERROR" if files.lines.grep(/^word\/media\//).empty?
アップロードしたファイルの中に word/media ディレクトリがあることをチェックし、zip ファイルのまま workdir / (hash).zip に保存
表示部分
@images = `zipinfo -1 #{zipfile}`.lines.grep(/^word\/media\/[A-Za-z0-9_]+\.[A-Za-z0-9_]+/).map do |path|
path.delete_prefix("word/media/")
zip の word/media ディレクトリ内のファイルを表示
ダウンロード部分
zipfile = File.join("workdir", params[:name] + ".zip")
filedir = File.join("workdir", SecureRandom.hex(16))
file = File.join(filedir, params[:image])
system("unzip -j #{zipfile} word/media/#{params[:image]} -d #{filedir}")
if File.exists?(file)
send_file(file)
word/media の中から指定されたファイル名を探し、解凍してダウンロードする
実装的にディレクトリトラバーサルは難しそうなのでシンボリックリンクで /flag を読み出す
ln -s /flag test.b
上記コマンドで作成した test.b を word/media ディレクトリに入れ zip 化し、docx ファイルにしてアップロードする。そしてサービスから test.b をダウンロードするとフラグが含まれている