Web サービススタートアップにおけるプロダクトセキュリティの始め方
今や情報セキュリティはあらゆる分野で重要視されるようになっていますが、自分がしばらく働いているWebサービス関連の業界では「どの段階から情報セキュリティに取り組めばよいか?」という疑問がしばしば話題になります。昨今のWebサービスの多くは昔からのソフトウェアプロダクト開発における設計→開発→納品というフローで完結するものではなく、高速にプロトタイプを作成して価値検証を繰り返しながら、徐々にサービスとして成熟していくというモデルが多いと思います。その場合、最初から制約を厳しくしてしまうことでプロダクト開発のスピードが鈍化しProduct Market Fit(PMF)に至らない、というリスクが起こりえます。さらに厳しい制約を設けすぎることで逆に対策を無視する、という悪い文化が根付いてしまう恐れもあります。
この記事では自分がもし今から「自分でスタートアップを立ち上げ、あるいは立ち上げ直後のスタートアップに開発者として参加した場合、どの時期にどういった施策をするか?」という観点での架空のロードマップをまとめてみました。事業の規模拡大のフェ=ズを 0→1(価値検証)、1→10(サービス化)、10→100(事業のスケール)という3つにおおまかに分けています。あくまで自分の経験則などであり権威的なガイドラインによるものではありませんが、どなたかの参考になれば幸いです。
0 → 1 フェーズ:MVPによる価値検証期
まず最初に MVP(Minimum Valuable Product) を構築しながら価値検証を繰り返しつつ、徐々にプロダクトを公開していくフェーズでの取り組みです。この時期はプロダクトが大きく変化することもあり、過剰にセキュリティ対策をしても意味がなくなってしまったりという無駄な投資になってしまうリスクもあります。また開発者に対して強い権限が付与されたり、インフラストラクチャやサービスの境界が曖昧になるといった状態もやむを得ないこともあります。
そんななかでもコストが小さく、また一定の効果があるところから取り組むのが最初のステップとして望ましいのではないかと思われます。ただし、プロダクトがスケールしてくると料金も比例して大きくなるサービスも多いので、利用料金の確認は定期的にするのをおすすめします。
ツール・サービスによる自動のセキュリティチェック
GitHubなどのサービスでは比較的安価にCI、継続的インテグレーションの機能を利用できます。これによってOSSで提供されているようなセキュリティチェックを設定し、開発しているプロダクトのコードが都度検査されるようにしておきます。いわゆる “DevSecOps” と呼ばれる領域のツールやシステムになります。設定および運用コストも大きくはないので、早い段階から活用できます。
- 静的解析(例:gosec、govulncheck)
- パッケージ脆弱性スキャン(例:trivy)
また各種クラウドプラットフォームで提供されているセキュリティチェックのサービスをとりあえず有効化しておくのもオススメです。課金額はサービスの利用スケールによって変動するので、プロダクトが小さいうちは大きなコストにはなりにくいです。
- AWS: Guard Duty, Security Hub
- Google Cloud: Security Command Center
これらのチェックで得られた結果をすべて対応・修正するのが望ましくはありますが、初期段階では定期的にチェックする機会を設けるだけで十分かと思います。
WAF(Web Application Firewall)の導入
構成にもよりますが最近のCDNサービスではWAF機能も同時に利用できる、あるいは付随させやすい構成になっているため、とりあえずでWAFを有効化するのもオススメです。WAFは基本的にパターンマッチによるルールで攻撃と見られるリクエストを記録、あるいは遮断します。そのため、主に一般化された攻撃パターン(SQL injection、XSSなど)か、あるいは特定のミドルウェアやパッケージの脆弱性を狙った攻撃しか対応できません。しかし、プロダクト開発初期にうっかりそういった脆弱性を入れ込んでしまった場合の保険にはなるため、序盤から導入しておくのも小さなコストで一定の効果が見込めるものとなります。
監査ログの収集
利用しているクラウドサービス、特にAWSやGoogle Cloudなどのクラウドプラットフォームにおいて監査ログを有効化し、一定期間保存するようにします。これも設定が容易で検索などを考えなければ比較的安価にログを長期保存できます。ログの活用方法は様々ですが、この段階ではまず問題が発生したときに何が起こったのかを調査するという目的でログ収集します。
オンプレミス環境の場合でもOSの監査ログ機能を有効化しておくなどできるといいですが、記録を実行環境から隔離・集約・保存するという観点では設定・運用のコストが高くなってしまいます。そういった観点でもなるべくこれから構築していくプロダクトは、クラウド上で運用するのが個人的なオススメです。
リスク、あるいは技術的負債の記録
本来であればリスクを特定、評価しそれをマネジメントする必要がありますが、前述したとおりこのフェーズではプロダクト自体が大きく変化を続けるためリスク自体も常に変動しつづけます。そのため(できれば回避するのが望ましいものの)やむをえず将来的にリスクとなりうる可能性がある設計、あるいは実装をする場合、それをメモ程度でよいので集約、記録しておくようにします。
大半のものはプロダクトの変化とともになくなる場合もありますが、中には特大級のリスクが潜在しているにも関わらず関係者一同が忘れてしまう、あるいは人が入れ替わることによって記録の継承がされないということがあります。あとからリスク特定をできるよう、リスク候補がリスト化されていると良いでしょう。
1 → 10 フェーズ:プロダクトのサービス化期
MVPを経てサービスとして世に広げ始める段階を想定しています。このあたりから扱うデータの重要度も変化してくることが予想され、本腰を入れ始める必要があります。
デプロイの自動化と堅牢化
プロダクトをWebサービスとしてデプロイする作業の自動化はヒューマンエラーの防止や作業コストの低減などの文脈で取り組まれることが多いですが、セキュリティの文脈でも有意義です。自動化によって開発者による作業とソフトウェア・サービスによる作業を分離することで、後述するアクセスコントロールの整備が容易になります。また監査観点でも開発者による作業の範囲やフローが明確化されたり極小化されたりすることで、追跡がしやすくなるというメリットもあります。
自動化に伴いデプロイに関するコンポーネント・リソースを直接開発者が操作する必要がなくなることで、デプロイに使うソースコード、パッケージ、コンテナイメージなどが不正に操作されるリスクを低減できます。万が一、開発者自身のCredentialを盗まれたとしてもそれだけでプロダクトを破壊したり情報を盗むといった行為が難しくなります。
アクセスコントロールの整備
デプロイの自動化と同様に、作業をする開発者やプロダクトを動かすためのサービスアカウントの権限を必要最低限にするなど、権限の整理をします。また環境を適切に分離することで、あるコンポーネントでセキュリティ侵害が発生しても影響範囲を極小化することができます。具体的にやることとしては概ね次の4つあたりかなと考えています。環境などにもよりそうですが、上にあるほど優先度が高いと考えられます。
- サービスアカウントや開発者の権限整理
- ネットワーク、コンピューティング環境、データベースなどをACLで分離
- 機微情報や秘匿値などを適切に暗号化する
- マイクロサービス間認証認可
開発者の権限についてはリソースの状況確認などまでできなくなると業務に支障が出たりするため、変更の権限や保存してある機微なデータへのアクセスを削るのが望ましいと思われます。逆にソフトウェア上で利用されるサービスアカウントは権限を最小化するのが良いでしょう。マイクロサービス間の認証認可は本来やるべきではあるものアーキテクチャ的に難しいケースも多いので状況に合わせてという感じになると思います。
脆弱性診断
ツールを使ったコードやパッケージの脆弱性は低コストに実施できますが、それだけでは見つけられない脆弱性も多くあります。特にプロダクトのビジネスロジックに依存した脆弱性や、アーキテクチャの問題によって引き起こされるものについては汎化されたツールで検出するのは困難です。
そのためある程度プロダクトがサービスとしての形をなしてきた段階で脆弱性診断(Penetration Test)を実施するのが望ましいです。脆弱性診断については社内にそのスキルを持ったメンバーがいない場合がほとんどと思われるので、外部の業者に依頼するのが良いでしょう。診断のための環境の準備やプロダクトの情報を開示するなどの調整作業は必要になりますが、専門的な診断を実施してくれます。
この目的で脆弱性診断をしてくれる業者を選ぶ場合、ツール類だけでの診断ではなく診断員の方がプロダクトの構成を考えた上で脆弱性がありそうなポイントを探してくれそうかどうか、というのが選定のポイントの一つになります。先述したとおり、この脆弱性診断で見つけたいのはアーキテクチャ上の穴やビジネスロジックにおける問題(特に認可の漏れ)などを発見したいとなった場合、診断する人の知識や経験に基づいて脆弱性を探してもらわないとなかなか致命的な問題が見つけられないからです。
ウォーターフォール型のプロジェクトであれば診断は一度だけで良いかもしれないのですが、Webサービス開発で多く見られるようなアジャイルなプロジェクトでは、時々刻々とプロダクトが変化します。そのため同じプロダクトでも定期的であったり大きな変化があるタイミングで再度診断を実施するのが望ましいです。
脆弱性・課題対応や修正のフロー化
0 → 1 のフェーズでツール類などを用いて脆弱性やセキュリティ上の問題検出について触れましたが、このフェーズでは検出された問題をどのように対応・修正していくかという指針を決めてちゃんと取り組んでいく段階であると考えます。
例えばCVSS(Common Vulnerability Scoring System)やSSVC(Stakeholder-Specific Vulnerability Categorization)といった脆弱性のリスク評価スコアを基準に、ある数値以上だったらN日以内に対応、そうでなければN週間以内に対応、というような指針です。もちろんこれらの数値が組織に対してのリスクを定量的に表しているかというとそんなことはなく、プロダクトの性質・環境・使われ方によって大きくリスクは異なります。そのため理想としては検出された脆弱性を一つずつどのようなものなのか理解し、自分たちのプロダクトにとってのリスク評価をした上で対応していくのが望ましいです。これを週次ぐらいの間隔でチーム内において確認する時間を作れると良いでしょう。
なお言うまでもありませんが、最もいいのは検出された脆弱性などを片っ端から直していくことです。
10 → 100フェーズ:サービスの拡大期
サービスの運用に道筋がたち、スケールしていくようになった時期を想定しています。基礎的な対策からより高度な対策を追加していくイメージになります。この頃には組織としても一定大きくなっていると予想され、それにともなった「型」を作ったり、多層的に防御や検出をしていける体制を整えていくような段階になってきます。
セキュリティ監視の充実
- VMやコンテナの挙動を監視するセンサーの導入(例 falco、osquery)
- VMやコンテナからのログ収集
- プロダクトが意図した挙動をしているかの外形監視
- クラウドリソースに意図しない変更が発生していないかの検査
近年のクラウドを活用したプロダクトではVMやコンテナは基本的に使い捨てにし、デプロイごとに新しいものへと切り替えて行きます。そのためインシデントがあった際にそのVMやコンテナ内で何があったのかを遡って調査できない場合もあります。また、VMやコンテナはビジネスクリティカルなデータベースなどへ直接アクセスできる強い権限を持っている場合が多く、異変があった場合に即座に気づきたいコンポーネントになっています。そのためにログ収集や内部のプロセスの状況を調査するセンサーを展開する必要があります。
外形監視についてはサイト信頼性観点での疎通確認だけでなく、ドメイン名周りの設定が意図せず変わっていないか、意図しない外部のスクリプトが読み込まれていないかを確認することで改ざんや乗っ取りが発生しないかを継続的に確認する意図があります。
またコンテナやVMだけでなく各種マネージド・サービスについても意図した設定が維持されているかというのを継続的に監視することでインシデントを早期発見できる場合があります。これらはすでに提供されているツール・サービス類などを利用してもいいですが、多くの場合プロダクトごとに異なる「期待される状態」があるので、それらとは別に継続的監視を用意するのが望ましいでしょう。
セキュリティログ分析
監視によって得られた情報を集約、分析できる基盤を構築して利活用します。多くの場合SIEM(Security Information & Event Manager )やそれに準ずるシステムによってこれを実現します。分析の目的は主に監査、異常検知、インシデントの確認や調査になります。
監査はいわゆる人間による監査もありますが、ポリシーをさだめて言語化・コード化し機械的・継続的にチェックすることで違反やインシデントを検出できます。この延長として通常とは異なるパターンのログを発見したり、ログに出現するindicator(IPアドレス、ドメイン名、ファイルのハッシュ値など)を継続的にIoC(Indicator of Compromise)と比較することで、これもインシデントの早期発見につながります。
各セキュリティ監視装置からアラート(インシデントの疑いがあるもの)が通知された際、それが本当にインシデントなのか(だったのか)はそのアラートに含まれる情報だけだと判断がつかないものも多いです。そのため関連する情報やログを突き合わせてインシデントだったかどうかを判断する必要がありますが、その際にも集約されたログが役に立ちます。
DLP
Data Loss Prevention のソリューションは原則として自分たちが観測可能な範囲のみから検知します。そのため原則としてデータが外部へ漏洩したことまでは検知できませんが、自分たちが扱う機微情報が適切なデータストアにのみ入っているかを確認する用途で利用できます。これは意図的、あるいは非意図的にでも機微なデータを持ち出してしまったり、不適切な範囲に公開してしまった場合、早期に検出したりそれを止めたりといった効果が期待されます。
DLPは機微情報(例えば個人情報になりうる氏名、住所、電話番号、メールアドレスなど)になりうる種類のデータを特定するのは得意ですが、それが本当に機微情報であるかという文脈は判断してくれません。例えば住所や電話番号も個人のものであれば扱いに注意が必要ですが、一般に公開されている店舗のものでも同様にDLPは検出します。また、多くのDLPソリューションでは日本語の対応が貧弱になりがちで精度がでにくいという問題もあります。そのため利用にあたっては条件の設定やどのような文脈で検出したものに対応するかなどを細かくルールチューニングしノイズを低減させる運用が必要です。
インシデント対応フロー整備・演習
事業内容によっては1 → 10のフェーズでやるかもしれないですが、組織として体制を整えるという文脈で 10 → 100のフェーズにおいてみました。インシデントは状況が千差万別であり、事前に起こりうる事象を想定して対応フローを決めていてもその斜め上をいく場合がほとんどです。しかし組織としての成熟度が上がったり組織が拡大したりした場合は手順を定めておくことで、属人性を低くしやすくなります。あと、BCPや各種セキュリティ関連の認証を取得する際にもこういった対応フローを定めておく必要があります。
先述したとおり、対応フローは定めてもなかなかそれを本番で実践するのは難しいため、必ず演習が必要です。これは机上でインシデント対応の進行を再現するでもいいですし、さらに本気でやる場合は抜き打ちでインシデントが発生したことにして対応をしてもらったり、さらには予告なしにRed Teamが本当の攻撃を仕掛けるというのも、対応の体制ができたのであればチャレンジしてみる価値はあると思います。
開発者セキュリティ教育
組織が拡大して開発者が増えるとそれぞれの得意分野などにムラがでてきて、セキュアな実装に関する理解度や温度感などもズレが生じてくることがあります。近年では多くのWebアプリケーションフレームワークがOSSなどで提供されており、それらを素直に使えばあまり脆弱な実装にはならないようになっていますが、それでもフレームワークのガイドを逸脱するような使い方をすると脆弱になりえます。そのため基本的なWebアプリケーションで起こりうる脆弱性の知識やその影響については一定の理解をしてもらい足並みをそろえる必要があると考えています。
基本的な脆弱性の知識などについては「体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践」(通称徳丸本)などで学ぶことができますが、一方で細かい実装のルール(例えばクレデンシャルの扱い方、データの保存の仕方、認証認可の方法)などについては組織ごとに異なってくるため、自分たちでガイドラインを整える必要があります。
まとめ
自分も最近はプロダクトセキュリティに関わる傍ら、一人の開発者としてプロダクトと向き合っており、以下のような考えを持ちながら取り組んでいます。
- 投資が少ないもの、不確実性が低い(一定の効果が見込める)ものはなるべく早期に導入していく。逆に投資が大きかったり不確実性の高いものについては導入時期を見極める。特にプロダクト自身が大きく変化していく可能性をよく考慮する
- 一方で実装したプロダクトがそのまま使われた場合、セキュリティ上の問題を含む技術的負債はいつか必ず返済する時が来る。なのでそのタイミングでは負債を積むとしても、それを返済することを念頭に置いて実装をするよう心がける
- 丁寧にできるところはフェーズに関わらず丁寧にやる
今回は思いつくものを列挙した感じなので抜け漏れなどもありそうですが、どなたかの参考になれば幸いです。もし他にもこういうのがありそう、この施策はこの段階でやったほうが良さそう、など別の主張があれば、ぜひ参考にさせてもらいたいので記事にしてもらえると嬉しいです。
Discussion