社内でのプロダクト脆弱性診断の方法、継続することで見つかる脆弱性の傾向の変化

プレイドでは、プロダクトの脆弱性診断を社内でも行なっています。
この記事では、社内で脆弱性診断を行なっている理由や、どのように診断から修正までを行なっているか、また社内で脆弱性診断をやることでどのような変化が起きたかについて紹介します。

社内での脆弱性診断と外部に依頼する脆弱性診断の違い

プレイドが運営するKARTEは、マイクロサービスアーキテクチャで構築されており、KARTE内部でも複数のプロダクトが存在しています。そのため、新しいプロダクトが増える機会も多く、リリースをする前に脆弱性診断を行うことが多いです。

後ほど紹介しますが、脆弱性診断の記録はNotionで管理されており、記録上は36日ごとに何かしらの脆弱性診断を行なっています。社内で行う脆弱性診断の依頼から結果の報告(フィードバック)までは、おおよそ1-3週間ぐらいで行なっており、中央値は11日となっています。

おおよそ1ヶ月に1つのプロダクトの脆弱性診断を行ない、2週間前後で見つけた脆弱性の報告までを行なっているイメージです。また、脆弱性診断をするセキュリティチームは、修正のコードレビューも行い、修正も大体1週間程度で終わるものが多いです。
社内で脆弱性診断をするメリットの1つは、このようなサイクルの早さを実現できることです。

KARTEは複雑な機能を持つプロダクトが多く、脆弱性診断を正しく行うには、そのプロダクトのアーキテクチャを理解する必要があります。こういった学習のコストやそのコミュニケーションのコストを低く保てるのも、社内で脆弱性診断を行うメリットの1つです。
実際に社内の脆弱性診断では、ソースコードやインフラの設定なども確認できるため、ホワイトボックステストを基本としています。

一方で、社内で脆弱性診断を行うデメリットとしては、脆弱性診断を行う労力がかかることです。外部に依頼する脆弱性診断は、この労力を外部に委託できることがメリットです。

また、外部に依頼する脆弱性診断は、第三者の目線で脆弱性診断を行なってもらえることもメリットです。当たり前のことですが、社内の脆弱性診断では第三者目線でのチェックができません。

それぞれを比較してみると次のようなイメージとなります。
(細かな条件は会社によって異なるので、おおまかなイメージとして捉えてください)

期間 労力 コミュニケーションコスト 診断方法 第三者視点
社内での脆弱性診断 1-3週間 内部 低め ホワイトボックス なし
外部での脆弱性診断 1-2ヶ月 外部 あり ケースバイケース(ブラックボックスが多め) あり

プレイドでは、社内の脆弱性診断と外部の会社に依頼する脆弱性診断を組み合わせています。
普段のセキュリティレビューは社内で行いますが、定期的に外部の会社に依頼して脆弱性診断を行なっています。
これら2つの脆弱性診断は、競合するものではないため、2つを組み合わせて行うことがセキュリティをより高めることに繋がっています。

社内の脆弱性診断の流れ

実際に社内の脆弱性診断をどのような流れで行なっているかを見ていきます。
大きく分けて次のような流れで行なっています。

  1. 依頼
  2. ヒアリング
  3. 脆弱性のチェック
  4. フィードバック
  5. 修正/レビュー
  6. 再チェック

社内では、この一覧の流れをセキュリティレビューと呼んでいます。

開発をしてるチームから依頼が来たら、ヒアリングシートをもとにヒアリングを行います。
ヒアリングでは、そのプロダクトのアーキテクチャ、脆弱性診断のスコープ、どういう問題が起きると一番困るかといった認識合わせを行います。

そして、セキュリティチームで脆弱性のチェックをします。

脆弱性のチェックが完了したら、見つかった脆弱性や修正方法などを確認するフィードバックします。その後、フィードバックをもとに開発チームで修正を行なってもらいます。この際に、セキュリティチームでも修正のPull Requestをレビューします。

修正が完了したら、再チェックをして、問題がないことを確認します。

社内の脆弱性診断の流れ.png

社内での脆弱性診断の流れは、このような感じになっています。
もう少し具体的にどのようなことをしているのかをステップごとに見ていきます。

1.依頼

脆弱性診断は開発チームからの依頼で始まります。
多くの場合は、新しいプロダクトや機能をリリースする前に依頼が来ます。

依頼者には、脆弱性診断に関するヒアリングシートを埋めてもらいます。
後ほど紹介しますが、脆弱性診断のヒアリング、脆弱性の調査内容、報告などはNotionで管理しています。

具体的には、診断対象のNotionページを作成し、次のような内容のヒアリング項目を書いてもらっています。

# ヒアリング項目

- 現状のステータス
    - %{Year}-%{month}: closed beta
    - %{Year}-xx: public beta
- レビュー完了の目安
    - yyyy-mm-dd
- 防ぎたいこと
    - xxx

### レビューされる側での準備

- コードの場所
    - [ ]  GitHubのURLなど
- ドキュメント
    - 使い方の資料
        - [ ]  プロジェクトでのセットアップ手順や機能確認のための資料などがあると望ましい
    - 構成図などの資料(あれば)
        - [ ]  色々と資料とかを貼っておく
- レビュー環境
    - [ ]  evaluation 環境(可能ならば2プロジェクトを用意するか、セットアップ手順を共有してもらう)
- ロギングの情報
    - Datadog:
    - Sentry:
    - Slack:
    - その他:

このヒアリングシートをもとに、セキュリティチームと開発チームでヒアリングミーティングを行います。

2.ヒアリング

ヒアリングミーティングでは、開発チームとセキュリティチームで脆弱性診断のスコープや、どういう問題が起きると一番困るかといった認識合わせを行います。

"どういう問題が起きると一番困るか"というのは、言い換えると防ぎたいことです。
開発チームは、自分たちでどういう問題が起きると困るかを考えてもらうことで、診断結果のフィードバックを受けた時に気を付ける場所が明確になります。
セキュリティチームは、そのプロダクトを初めて触るケースも多いため、どういう問題が起きると困るかを知ることが診断する上で重要です。

また、開発チームに該当のプロダクトのアーキテクチャなども説明してもらいながら、起きうる問題をヒアリングミーティングで洗い出していきます。
話しながら、セキュリティチームはどういう攻撃の可能性がありそうかなどがわかってくるので、開発チームの防ぎたいことと照らし合わせながら互いの認識を合わせていきます。

ヒアリングミーティングで一番重要なのは、開発チームとセキュリティチームで議論しながら、互いの認識を合わせていくことです。
脆弱性診断は、どちらか一方の仕事ではなく、開発チームとセキュリティチームが協力して行うものであるためです。

3.脆弱性のチェック

おそらく、ここが社内で脆弱性診断をする中で一番大変な部分です。
コストはかかりますが、社内で脆弱性診断を行うメリットの1つは、この部分にあります。

社内でやることで診断中のコミュニケーションコストを最小化できます。また、フィードバックや修正のレビューなども診断した人が行うことで、より内容の濃いものになります。

プレイドでは、セキュリティチームとは別に横軸のバーチャル組織として「セキュリティ組」があります。セキュリテイ組には、セキュリティに関心はあるがセキュリティの知識を深くは持っていないエンジニアもいます。

社内で脆弱性診断する際は「XXXのセキュリティレビューをやってみる会」という形で、セキュリティ組も任意参加で一緒に脆弱性診断を行なっています。

セキュリティ組はいろいろなプロダクトのチームに所属しているエンジニアの集まりなので、セキュリティ組も脆弱性診断を通してセキュリティの知識を深めることができます。このようなことができるのも、社内で脆弱性診断をやっているからこそです。

ここからは、具体的な脆弱性の調査や管理方法について紹介します。

Notionでの脆弱性調査の管理

プレイドでは、脆弱性を調査した結果の管理はNotionで行なっています。
Notionを利用する主な理由は、ヒアリングやフィードバックなども利用するため一元管理できるのと、開発チームも使うツールであるため、開発チームとのコミュニケーションコストを下げるためです。

最初は、別のツールで管理していましたが、Notionのデータベースなどを利用すれば十分管理できることがわかり、Notionへ移行しました。

セキュリティレビュー(脆弱性診断の一連の流れのこと)では、次の3つのNotionデータベースをRelationで繋ぎ管理しています。

  • セキュリティレビュー のテーブル
  • 診断対象のAPI のテーブル
  • チェック項目 のテーブル

3つのNotionデータベース

これらのNotionページを使って、次のような流れでプロダクトのページやAPIを一個ずつ網羅的にチェックしていきます。

  1. ヒアリングで"セキュリティレビュー"に新しいページを作成
  2. "診断対象のAPI"にチェックするAPIのリストを作成
    • BurpSuiteのプラグインを使って、リクエスト/レスポンスの内容をNotionのテーブルにペーストすることで、一括でAPIのリストを作成
  3. APIごとに"チェック項目"を紐づけて、実際にチェックした内容を記録
    • チェック内容、脆弱性の種類、結果などを記録

Notionのテンプレートでテンプレートページ自身をデータベースのFilterに指定することで、テンプレートからページを作るだけで、自動的にプロジェクトで絞り込んだ状態のデータベースを表示できます。このデータベースに新しいアイテムを追加すると、自動的にプロジェクトに紐づきます。

言葉ではわかりにくいですが、"Self-Referencing Filters"というテクニックを使うと、Notionのページを作るだけで自動的にRelationを設定したデータベースを作れます。

詳しい内容はNotionの話になってしまうので省略しますが、SpreadSheetではなくNotionにまとめるメリットは、すべてのセキュリティレビューの結果が一元管理できることです。後ほど紹介しますが、このデータをもとにセキュリティレビューにおける脆弱性の傾向を見ることができます。

脆弱性の調査

セキュリティには網羅性が重要であるため、一般的な脆弱性診断と同じように、対象のプロダクトのページやAPIをチェックしていきます。この際にはツールとしてBurp Suiteを主に使いながら、APIをチェックしています。

機械的な自動チェックツールを回すのではなく、セキュリティチームの人間が手動でチェックしています。これは、自動チェックツールだけではどうしても見つけられない脆弱性もあるため、さまざまな方法を組み合わせてチェックすることで、より網羅性を高めています。

また、セキュリティチームはソースコードも見ながら診断していくホワイトボックステストをしています。ソースコードだけではなく、AWSやGCPなどのインフラの設定も実際に確認しながら問題ないかを確認していきます。
このようなホワイトボックステストができるのも、社内で脆弱性診断を行うメリットの1つです。

脆弱性診断には、脆弱性に関する知識も必要になります。しかし、一般的なXSSやSQL Injectionなどの脆弱性を見つける場合においては、必ずしも高度なセキュリティの知識が必要となるわけではありません。

KARTEはさまざまな機能がありますが、サービスとしては一般的なWebサービスの形で提供されているのがほとんどです。そのため、攻撃の入り口となるAttack Surface自体は、普通のWebサービスと同じくリクエストを受け付けるAPIとなります。

APIを定義しているハンドラーのソースコードや実際に出力されるログなどを見て、どのような問題が起きるかを調べていくことができます。実際に脆弱性となる攻撃を成立を成功させるのが難しくても、問題が起きる可能性は見つけることができます。

攻撃が成立した状態でフィードバックできるのが理想ですが、攻撃が成立しなくても問題が起きる可能性を伝えられることは重要です。(一般的な外部の脆弱性診断では、攻撃が成立してない脆弱性を報告するのは敷居が高くなりがちであるため、報告されない可能性があります)

どちらにしてもセキュリティの知識はある方がより深く調査できるため、セキュリティチームはセキュリティの知識を深めることが重要です。近年は、セキュリティのリソースや攻撃方法の情報がオープンになっているため、いろいろな方法で調べながら調査するのが重要です。

セキュリティの専門家であっても、あらゆるセキュリティに詳しい人はいません。そのため、プロダクトのアーキテクチャーをもとに攻撃ポイントとなる部分を都度調べていくことが重要です。

4.フィードバック

脆弱性の調査が一通り終わったら、開発チームにフィードバックをします。
フィードバックミーティングでは、見つかった脆弱性や修正方法などを確認します。

多くの脆弱性診断はプロダクトをリリースする前に行うことが多いです。リリース前には直しておきたい問題はそれを伝え、どういう修正方法が考えられるかも一緒に伝えていきます。
見つけた脆弱性には、それぞれ重大度(Severity)を設定しているため、基本的には重大度の高いものは修正する形になります。

フィードバックミーティングは、脆弱性が見つからなくても基本的には実施しています。
これは、フィードバックミーティングでは、どういう攻撃を試したかやそれがうまく通らなかったといった攻撃方法についても話をしたりすることが多いためです。

うまくいかなかった攻撃についても話すことで、どういうポイントが狙われるのかが伝わるため、次からの開発ではそれを意識して改善しやすくなります。
実際に、同じ開発チームに何度もセキュリティチェックをしてると、ヒアリングの際に開発者の方からどういう対策をしているかという話をしたりしてくれることが増えたりしていると感じます。

5. 修正/レビュー

フィードバックミーティングで伝えた問題の修正を行なってもらいます。基本的には、見つかった脆弱性ごとにGitHubへIssueを作成しておきます。

開発チームはそれを修正して、Pull Requestを作成してもらいます。その際には、セキュリティチームもレビューして修正が問題ないかを確認します。

言われたから直すのでなく、どういう問題があるかを理解して直すところまでをやるのがセキュリティレビューの目的です。この辺は、普通のバグ修正とあまり変わらないです。

6. 再チェック

修正が完了したら、必要に応じて脆弱性が修正できてるかを再チェックします。
ここは、シンプルに同じ攻撃が通らなくなってることをチェックするだけです。

社内の脆弱性診断のまとめ

社内の脆弱性診断では、これらの1-4を大体1-3週間ぐらいで行っています(中央値は11日)。
修正と再チェックも、大体は1週間程度で完了しています。この一連の流れによって、実害があるような脆弱性は、リリース前には修正できる状態になっています。

社内で脆弱性診断をするメリットの1つは、こういったサイクルを素早く回せるところにあります。外部の会社に脆弱性診断を依頼した場合、依頼から診断結果(フィードバック)が来るまで、大体2ヶ月程度はかかることが多いです。

1つ重要なポイントとしては、社内の脆弱性診断をリリースのブロッカーとしては設定してないということです。ヒアリングやフィードバック時にこの話をすることが多いですが、社内の脆弱性診断の目的はあくまでプロダクトセキュリティの改善のためです。

「脆弱性診断をしないとリリースできない」というようなブロッカーとして扱うと、脆弱性診断を通さないとリリースできないというような形式的なものへとなりやすいです。
セキュリティレビューはあくまでプロダクトの改善のプロセスとして存在しているので、形式的なチェックには意味がありません。

そのため、リリースはあくまで開発チーム側に意思決定を任せています。もちろん、影響の大きな問題が見つかった場合は、リリース前に修正してもらうようにしています。
もし開発チームの方で修正が難しい場合は、セキュリティチームが修正を手伝うこともあります。

これは、社内では脆弱性診断のことを"セキュリティレビュー"と呼んでいることにも関係しています。脆弱性診断はリリースの前にすることが多いですが、実際にはどのタイミングでも使って欲しいからです。単なる"脆弱性診断"ではなく、広い意味でのセキュリティをレビューする場であるべきです。

実際に、セキュリティレビューをやっていると設計段階のレビューが依頼されることもあります。このようにセキュリティレビューが前倒ししていくことはあるので、必ずしも今のプロセスが完成系ではないと思っています。

社内で脆弱性診断をすることで、変わってきたこと

ここまでで、社内で行っている脆弱性診断の流れを紹介しました。
プレイドでは、このような脆弱性診断を3年以上続けています。そのため、KARTEのさまざまなプロダクトに対する脆弱性診断のデータが蓄積されています。

社内での脆弱性診断の記録(ヒアリング、フィードバック、見つけた脆弱性など)は、すべてNotionにまとまっています。
これらのデータをもとに、社内での脆弱性診断を通して、どのような変化があったのかを見ていきます。

脆弱性スコア

社内での脆弱性診断では、脆弱性に対してCritical、High、Medium、Low、Infoのラベルを付けています。"脆弱性"と一言に言っても、その影響度はさまざまです。

ここでは、わかりやすさのために脆弱性の影響度を数値化して、それぞれのラベルに対して次のようなスコアを設定しています。

脆弱性のラベル 脆弱性スコア
Critical 4
High 3
Medium 2
Low 1
Info 0

スコアが高いほど、脆弱性の影響度が高い(実際に発生した場合の影響範囲が広い)ことを示します。この記事では、このラベルに応じた数値のことを"脆弱性スコア"と呼びます。

社内での脆弱性診断の変化を見るのに、この脆弱性スコアをベースにしてみていきます。

典型的な脆弱性は減ってくる

KARTEの多くのプロダクトではMongoDBを使っています。そのため、初期の脆弱性診断では、Mongo Query Injection(NoSQL Injection)が多く見つかっていました。

脆弱性診断のフィードバックでは、このMongo Query Injectionの対処方法としてリクエストのバリデーションについての話をしていました。
また、Mongoのクエリでは$から始まるキーが特別な意味を持つオペレータとなります。リクエストのbodyやパラメータに$から始まるキーがある場合は、一律でリクエストを弾くという軽減策も有効です。

  • Express Mongo Sanitize
    • Expressで$から始まるキーを持つreq.bodyreq.paramsを弾くミドルウェア

フィードバックミーティング、セキュリティ月報(月に一度セキュリティに関するニュースを社内で共有するもの)、セキュリティガイドラインなどでこのような対策について広めていくことで、Mongo Query Injectionの問題は減ってきました。

実際にデータとしてのMongo Query Injectionに関する脆弱性スコア(脆弱性の影響を加味した値)の変化を見てみます。これらのデータは時系列に並べていますが、基本的には異なるプロダクトの脆弱性診断の結果を合算したものです。

社内で脆弱性診断を始めた頃は、Mongo Query Injectionが多く見つかり、その脆弱性スコアも高いものが多くありました。その後、Mongo Query Injectionの問題の数自体も減少し、見つかった場合も脆弱性スコアが低くため、実際の影響も小さくなっています。(実際にはLowというラベルがついた脆弱性になっていて、実害はほぼないような問題になっている)

発見されたNoSQLInjectionの脆弱性スコアの推移

実際に脆弱性診断をしていると、リクエストに関してバリデーションが行われるのが当たり前となってきています。また、仮にリクエストのバリデーションが抜けている場合でも、Express Mongo Sanitizeのような影響を軽減できる仕組みが入っていることが多く、実際の影響度は低くなっています。

Mongo Query Injectionだけではなく、Cross-site request forgery (CSRF)や古典的なXSSなども同様に減少してきています。

もう少し脆弱性スコアの変化を詳細に見てみます。

見つかった脆弱性の数と脆弱性スコアの変化

次の図は、脆弱性診断で見つかった脆弱性の数とその脆弱性のスコアの変化を時系列でまとめたグラフです。脆弱性診断ごとに見つかった脆弱性の数と脆弱性スコアの合計値の推移を表示しています。

脆弱性診断で見つかった脆弱性の数とその脆弱性のスコアの変化

グラフを見ていくと、見つかった脆弱性の数自体は微減であまり変化はないです。一方で、脆弱性のスコアの合計自体は減少傾向にあります。これは、問題が見つかっても脆弱性の影響度が小さくなっていることを示しています。

より詳細に見ていくために、脆弱性のスコアを、脆弱性のラベルごとに分解して積み上げてみます。ここでは、次のように脆弱性のラベルごとに色分けしています。

脆弱性のラベル スコア カラー
Critical 4 なし
High 3
Medium 2 黄色
Low 1
Info 0 なし

脆弱性スコアをラベルで分解して積み上げたグラフは、次のようになります。

脆弱性スコアをラベルで分解して積み上げたグラフ

最初はHigh(赤)とMedium(黄色)が多いですが、少しずつその数は減少していることがわかります。
これは脆弱性スコアの高い(影響度が高い)脆弱性が減っていることを示しています。

プロダクトごとの脆弱性診断の実施回数と脆弱性スコアの変化

これまでのグラフは、すべてのプロダクトの脆弱性診断の結果を合算したものです。

社内の脆弱性診断では、毎回同じプロダクトの同じ場所を診断するのではなく、新しいプロダクトや新しい機能に対して脆弱性診断をすることが多いです。いくつかのプロダクトでは、脆弱性診断の実施回数や診断の範囲は異なりますが、複数回実施しているプロダクトもあります。

次の表は、プロダクトごとの脆弱性診断の実施回数とその脆弱性のスコアの変化をまとめたものです。

プロダクトごとの脆弱性診断の実施回数とその脆弱性のスコアの変化

同じプロダクトでも、異なる場所を診断することが多いため、実施回数と脆弱性スコアは必ずしも相関があるわけではありません。しかし、実施回数の1回目は脆弱性スコアの高いプロダクトが多く、回数を重ねると極端に大きな脆弱性スコアにはならない傾向があります。

これは、開発チームの中でセキュリティに関する知識や経験が蓄積されていることを示唆しています。

社内で脆弱性診断をすることで、変わってきたことのまとめ

ここまでで、社内での脆弱性診断の記録をもとにデータで見える変化を紹介しました。

脆弱性診断で見つける脆弱性の数は微減ですが、脆弱性スコアをみると脆弱性の影響度は小さくなっていることがわかります。同じ脆弱性でも、リスクを軽減する仕組みが入ってくることにより、脆弱性の実際の影響度は低くなっています。

プロダクトを開発し続けている以上、脆弱性が1つもないということはありません。典型的な脆弱性が減ってきたことで、セキュリティチームはより複雑な脆弱性を見つけることに労力を使えるようになってきている可能性もあります。

今回は詳細を省略していますが、プロダクトごとに見つかる脆弱性の傾向も異なることが多いです。脆弱性のデータはプロダクトごとにも蓄積されているため、今後はこのデータを活かしてよりセキュリティを改善していくことができると考えています。

まとめ

この記事では、社内の脆弱性診断の流れと、社内で脆弱性診断をすることで変わってきたことを紹介しました。

社内でやる脆弱性診断と外部の会社に依頼する脆弱性診断では、それぞれメリットとデメリットがあります。これらは、対立するものではないため、プレイドではどちらの脆弱性診断も行なっています。

脆弱性診断では脆弱性を見つけることも重要ですが、それ以上にプロダクトのセキュリティを改善に繋げることが重要です。社内では脆弱性診断のことを"セキュリティレビュー"と呼んでいますが、これは脆弱性診断を通してプロダクトのセキュリティを改善することを目的としているためです。

また、プレイドでは複数のプロダクトがありますが、アーキテクチャなどの仕組みがすべて異なるプロダクトは多くありません。そのため、1つのプロダクトで見つけた問題は、他のプロダクトの改善にも活かせることが多いです。セキュリティレビューを重ねることで、プロダクトのセキュリティの底上げに繋がっています。

セキュリティの改善を目的とした場合、脆弱性の診断のサイクルを短くすることが重要です。より短くサイクルで回すことで、より早くプロダクトのセキュリティを改善できます。

セキュリティレビューは、基本的にプロダクトごとに行います。その結果を周知(社内ではセキュリティ月報で全体に周知)することで、他のプロダクトのセキュリティの改善にも繋がります。
また、問題を周知することで、まだ設計段階のプロダクトに対してもセキュリティの意見を求められる機会が増えます。

セキュリティレビューは、脆弱性診断という単独でみると診断する人の負荷は高いです。しかし、脆弱性診断から派生した一連のセキュリティを強化するイベントとしてみると、いろいろなメリットがあります。

脆弱性診断で見つけた問題を解説やデモすることで、開発チームは脆弱性をより自分ごととして理解できます。
また、脆弱性診断で見つけた問題は他のプロダクトでも起きる可能性があるため、使われるガイドラインとしてまとめる価値があります。
さらに、脆弱性診断の結果(脆弱性が見つからなくても)を社内で共有することで、他のプロダクトの開発チームにもセキュリティの意識を高めることができます。

こうしたメリットなどがあるため、プレイドでは社内でセキュリティレビュー(脆弱性診断)を行っています。


CX(顧客体験)プラットフォーム「KARTE」を運営するPLAIDでは、脆弱性診断を通してプロダクトセキュリティを向上していくエンジニアを募集しています。
詳しくは、弊社採用ページをご覧ください。