freeeの開発情報ポータルサイト

新人研修でHardening!

こんにちは、freeeのCSIRT専属エンジニアの杉浦英史です。 2018年4月、freeeは新卒3期生として27名もの新人さんをお迎えしました。 会社に入社すると、最初に待っているのは?

そう、新人研修ですね。

今年は、freee史上最も中身の濃い研修が行われていますが、 今回は、CSIRTが担当したセキュアコーディング研修について紹介します。 この研修は、4月中旬の3日間に渡って行われたものですが、8名の選りすぐりの新人達に参加してもらいました。

セキュアコーディング研修と聞くと、コーディングべからず集みたいなものを解説する座学を思い浮かべてしまうかもしれませんが、そんな生半可なものではありません。

Hardening!

Hardeningと呼ばれるトレーニングをみっちりやってもらいました。

スケジュールはこんな感じです。

半日座学の後は、1日半かけて修正、最終日の半日で攻撃を受けて、最後の半日で解説
Hardening実習スケジュール

最初の半日で、OWASP Top10や過去の事例に基づいた実際の攻撃手法の概略と、Hardeningのルールを説明したら、すぐにトレーニング開始です。

Hardeningというのは、チーム対抗戦で行われる競技です。今回は、4名ずつの2チームに分かれて対戦を行いました。

f:id:eiji-sugiura:20180501120140p:plain
実習環境
全てのチームに脆弱性が仕込まれた同じwebサービスを渡されるので、メンバは脆弱な点を探し出して修正し、さらに堅牢化してサービスとしての質を競います。 ちなみに、脆弱なwebサービスはfreeeが実際に提供しているサービスを CSIRTが腕によりをかけて改悪したものです。もちろん元のコードを参照するのは無しですよ。

ところで、守らなければならないのは、webサービスです。アプリケーションを動作させる環境を含めて、守らなければなりません。 日頃意識したことがないであろう、アプリケーションでのセッション管理、サニタイズ、Unixでのプロセス管理、ファイアウォールの設定やログの意味を調べ、攻撃への対処方法を編み出すことになります。

脆弱性の修正、堅牢化中です。

2日目の新人さん達の様子です。

会議室で作業している様子
2日目午後の様子
会議室にこもり議論しつつ、進めていくチーム。

大きなクッションでくつろぎながら作業している様子
寝そべってますけど、ちゃんと仕事しています。
地下のスペースで楽な姿勢で、集中しているチーム。

チームカラーの違いが出ていますね。

新人さん達の中には、コンピュータサイエンスを学びエンジニアとして入社したメンバーもいますが、全く違う分野を学んできたメンバーもいます。

デザイナーとして入社した人のPull Request。XSSとSQL Injectionに関する修正が出され、両方ともマージされている
PullRequest

UXデザイナーとして入社した新人さんは、自分がチームに貢献できなくて申し訳ないと思っていたようですが、彼はちゃんと新人研修で学んだRailsチュートリアルを読み直して、コード上の誤りを発見して、周りに協力を求めた上で、修正するためのPull Requestを出していました。すばらしい!側で見守っていたおじさんは、涙が出そうでした。

Slackでの一幕。杉浦に「本当に防御できたのですか?と聞かれ、『調べます!』と回答する新人」
ちょっとしたツッコミ
もちろん、見守るだけではなくて、折角のSYN Flooding対策の動作確認を行なっていない新人さんがいたので、ツッコミを入れたりもしています。

2日目の午後になると、彼らは仕込んだ脆弱性のうち半分を修正してしまいました。

攻撃と防御

さて、与えられた修正期間は1.5日でした。その期間が過ぎ去ると、おじさん達が攻撃を開始します。

まずは、空いているportを探して見ましたが、ちゃんとFirewallを用いて、不要なportは閉じられていました。

SYN floodを受けているのに気付いて「たぶん影響なし」
SYN Flood?
探索活動も捕らえられてしまいました。ログもちゃんと観測していますね。 この時の探索で、SSH port*1を発見しましたが、すぐには悪用できないように対策されていました。

稼動状況のグラフ
攻撃中の稼働状況

攻撃時間の後半は、DoSからDDoSに攻撃方法を変化させました。ここで、グラフでは分かりにくいですが、対処方法の差が少し出始めました。

あらかじめ仕込んでいた脆弱性を狙ってみましたが、悪用が簡単なSQL injectionは、修正されていました。 でも、情報を搾取する糸口が全くないわけではないようでした。

結果は?

得点は、サービス稼働率と脆弱性対処数で評価することにしました。 サービス稼働率 Aチームが86% Bチームが85%

サービス稼働率は、Landing Pageの15秒以内での到達率と、E2E testの完走率の平均で評価したものです。 チームAは、より優れたSYN Flooding対策を施したことにより、Landing Pageの到達率を上げることができました!

脆弱性対処/報告数 Aチーム15% Bチーム18%

脆弱性対処数は単純な数の足し算ではなく、脆弱性を難しさに応じて傾斜配点*2し、対処されていたら+1点、テンプレートに従って報告がまとまっていればさらに+1点と評価しました。

両チームとも、アプリケーション自身が改竄されるような深刻な事態には至りませんでしたが、queryに細工することで、他のアカウントの情報が盗み見ることができてしまう脆弱性が残っていました。 debug modeによる情報漏洩に気づけたかどうか、そして質の良いレポート数の多さで、チームBが優勢となりました。

ということで、結果としては、痛み分けです。

競技を終えて

競技後のアンケートでは、「おじさん達にボコボコにされた」「もっと前提知識があれば...」といった趣旨の指摘をいただきましたが、あえて背伸びをしてもらうための研修という位置付けにした結果だと思います。

新人研修でHardeningを行うのは、「脆弱性対策として、多層防御を行うには、そもそも、ログをとって、検知しないと対処はできない」 といった、技術的にセキュリティ対策を理解することだけが、目的ではありません。 以下の状況を身を以て体験することが、社会人として仕事を始めるにあたって必要ではないかと考えたからです。

  • 実際に問題が起きた時には、訓練の時以上の質で、対処を行うのは難しい
  • 優先度をつけて作業を行わないと、最大の効果は望めない

今回、与えられる実習環境、ソースコードは、競技開始まで、誰も触ったことがないものでした。 それぞれが得意な分野を持ち寄って、未知の問題を血眼になって解決する時間って、とっても貴重なんですよ!

サービスで実際に動いているものを基にした真面目なHardeningなんて、freeeに入らない限りできない経験です。 「あの時あんなこと言ってたなー。」と、一つでも思い出していただければ、嬉しいです。

今回のHardeningは、せっかくなので7月くらいに新卒以外の人にもやってもらう*3予定です。freeersの皆さま、お楽しみに!

そういえば、勝った方のチームに、ビールを一杯おごる約束になってたのですが、どちらも勝ってはいるので、8人みんなにビールおごらないとね。

*1:port番号は変更されていました

*2:両チーム共に仕込んだ脆弱性の半分は修正していましたが、簡単なものから修正された結果、2割の得点率になっています

*3:ということで、ネタバレ禁止になっています。仕込んだ脆弱性については詳しく触れていません