5/16日(土)に開催された「脆弱性を直して学ぶ!Webセキュリティハンズオン by Recruit」について,個人的な振り返りです.
概要
内容としてはbadsns2019という20個の脆弱性を埋め込んだ簡易Twitterのようなものに対して,脆弱性を調べて対策するというものでした.事前課題は上記の修正であり,イベント当日は各脆弱性の解説,デモ,良い対策手法についての解説をしていただきました.
badsns2019は研修の内容らしく,レベルが高いにも関わらず解説が丁寧にまとまっていた印象です.また,こういった類のイベントには珍しく,Dockerで環境を再現して後からでも演習に挑戦できる点が好ましいと感じました.
事前課題
きっかけ
私がこのイベントを知ったきっかけはセキュリティ・キャンプのslackで,知ったときにはすでに締め切り3日前くらいだったので慌てて事前課題に取り組みました.元となるコードはGitHubに上がっており,2019年当時の資料はspeakerdeck(1,2)に公開されています.
環境としてはDockerの上にRailsで実装されている形で,DockerもRailsも触ったことがなかった私にとっては最初の敷居が高くて心が30度くらい折れました….
作業ログ
作業ログはこのようになっていますが,解説を受けた後の感想としては「迷走してるなぁ…」という感じですね.見返した感じツールとしてはBrakeman,Burp Suite,Vuls,OWASP ZAPあたりを使っていて,OWASP ZAP以外はある程度効果を発揮しているように思えます.というかOWASP ZAPも初めて使ったので単に使いこなせてないだけの可能性が高そう.あとログはGistにペタペタ貼るのが面倒なので割愛しますが,Brakemanでインジェクション系とWask Hash(MD5),VulsでGhostscriptの問題が出てきました.
脆弱性の修正に関しては,ツールで引っかかったものを都度修正しているものの,一部時間切れで間に合わなかったものもあり悔しい結果となりました.
紹介された脆弱性
有名どころを多く含む,埋め込まれた20個の脆弱性が紹介されました.なお,脆弱性のタイトルのリンクはソースコードへのリンクとしています.また,ここでの説明は聞き逃した部分もありそうで,正確性は保証できません.他の人がWriteupを上げるらしいので詳しいデモなどに関してはそちらをご覧ください(丸投げ).
login_idとpassを投げてログインするが,プレースホルダを使用していないためlogin_idに’ or ‘などとすると入れる脆弱性.対策としてはプレースホルダの使用や,Railsのハッシュ形式の機能を利用することが挙げられる.
params[:user]をほぼそのままUser.createにつっこんでいるものの管理者権限を示すuser.adminも入っていくので,Burpなどでリクエストを編集すれば管理者権限付きのユーザが作成できる.対策としてはストロングパラメータの使用が挙げられる.
3.パストラバーサル
user[:icon_file_name]にパストラバーサルが存在する.デモではBurpで登録時のリクエストを編集してuser[:icon_file_name]を../../../../../../etc/passwdというような形で/etc/passwdを読み取っていた.対策としてはbasenameでファイル名だけとるか,realpathで正規化したパスに対して予め設定したbase_pathに対してstart_withで判断するなどが挙げられる.
params[:resize_max_pixel]がバッククォートで囲まれた(シェルで実行される)部分に入っているため,任意のコマンドが実行できる.これもデモとしてユーザ登録時のアイコン画像をアップロードするところで,Burpでリクエストを編集して,secrets.ymlを読み出したりしていた.対策としてはSystem関数の使用や,今回ならラッパー関数の使用が挙げられる.
前提として,このシステムではphpが動くので,もしphpが上がればサーバ側でいろいろ実行できる.しかし,バリデーションが不十分なため,png.phpというファイル名でMIMEをimage/phpなどとして送り込めばアップロードが可能となる.対策としては正規表現の正しい使用の他,ライブラリで画像形式であることの確認や,マジックバイトの確認が挙げられる.
6.個人情報漏洩
idのみを指定してレコード丸々返してるせいで,レコードに含まれるemailやpass(MD5)が見れてしまうという脆弱性.対策としてはSELECTで必要なカラムだけ指定することが挙げられる.
orderにSQLインジェクションが可能.ブラインドSQLインジェクションでcase文と合わせてパスハッシュの特定や,SELECT文も入るのでいろいろ見ることができる.対策としてはホワイトリスト化(要件的にname ASCかname DSCのみ通す)が挙げられる.
8.個人情報漏洩
6番とほぼ同じ.
ここにもSQLインジェクションが入る.対策は1番と同じ.
10.Stored XSS
DBのfeedsテーブルにはexifというカラムがあり,それをindex.jsでinnerHTMLにつっこんでいる.exifにHTMLタグなどが入っていると,XSSが発動する.exifの操作にはexiftoolが便利.対策としてはhtmlの特殊文字のエスケープ,fragmentを作成してからtextContentに$captionを入れる,vue.jsやreactなどモダンなフレームワークを使うことが挙げられる.
open関数にparams[:url]が直接入るため,|などでコマンドをつなげることができる.対策としてはNet::HTTP.newを使用することが挙げられる.open関数は便利すぎるのでNet::HTTP.new,File.open,System関数などを必要に応じて使い分けることが肝要.
ちょうど回線が不安定になって聞き逃した部分.「ogタグのリンクをローカルに書き換える.対策:同上」とのメモがある.
別回線を使うために部屋を移動していた部分.聞き逃したらしい.「ホスト名をIPアドレスとして対策」とのメモがある.おそらく一般的なSSRFの対策.
14.暗号利用モード
リセットトークン生成時に,暗号の利用モードとしてECBモードを利用している.有名な話ではあるがECBモードは脆弱である.対策としてはCBCモードなど他の利用モードの使用や,署名の付加,SecureRandomの使用(DBのschema変更が必要)などが挙げられる.
15.JWT検証アルゴリズム
セッショントークンの検証時,署名部分の検証をしていないためなりすましが可能.具体的にはセッショントークンをブロックで区切り,base64デコード,ID部分を書き換え,base64エンコード,送出.という手順で可能.対策としては検証に使用するアルゴリズムを明示的に指定すること.falseではなくtrue, { algorithm: “HS256” }へ.
今回使用されているRailsのバージョンは5.2.0となっている.Railsの5.2.0にはCVE-2019-5418が存在しており,これにより任意ファイル読み出しが可能となる.対策としてはバージョンアップが理想的だが,現実には難しいことが多いためその場合はrender file時にformatを指定することが挙げられる.
17.Ghostscript脆弱性による任意コマンド実行
DockerfileにてGhostscriptのバージョンが9.18に指定されているものの,いくつかの脆弱性が指摘されている.Vulsをかけたところ,CVE-2018-18284,CVE-2016-7978,CVE-2016-7979などが出てきた.対策としてはバージョンアップか,ImageMagicとGhostscriptの連携解除が挙げられる.
18.バックドア
Dockerfileにてommadawn46/mal1c10us-ng1nxが指定されているものの,これにはb4ckd00rが含まれる.具体的な動作を見る時間はなかったためとりあえず消したが,デモによるとホスト名をb4ckd00rにするとコマンドが実行できるらしい.対策としてはベースコンテナを信頼できるものに変更すること.
19.ハッシュアルゴリズム
各所でパスワードのハッシュにMD5が使われている(例)が,MD5は脆弱である.試しにHACKERMANのpass(be121740bf988b2225a313fa1f107ca1)をGoogleで検索すると,元はawesomeであることがわかる.対策としてはbcryptなど強力なハッシュの利用が最善だが,パスワードのリセットが難しい場合はハッシュの重ねがけが次善の策となる.
20.ログ
./log/production.logに平文パスワードが出力される.対策としてはRailsの機能でパスワードにフィルタをかけることが挙げられるらしい.
感想
事前課題にかける時間が少なく歯痒い思いをする部分はありましたが,丁寧な解説を含め久々に楽しかったです.コロナでありとあらゆるイベントが中止になっているなかでこういったイベントに参加できたことは素直に嬉しいですね.あと,DockerやRailsについての勉強としても規模感がちょうど良かったです.
Dockerfileのおかげで表彰していただいたので,『Practical Cloud Security』か『Web Application Security』で深堀りしていきたいと思っています.あと,みんな当然のようにRailsを知ってて焦りを覚えたので,これからはそっちもやってみたい.
当日は長丁場でしたが,丁寧な解説でとても勉強になりました.ありがとうございました.