fujiike.jp

いろいろあるので、いろいろ書いていく。

セキュアなプロダクトづくりで意識していること 2020-12-16

この記事は、 Makuake Advent Calendar 2020 16日目の記事です。

この記事では、自分が「セキュアなプロダクトづくり」をするときに考えていることを書きながら整理してみます。

最後までコード出てきません。

なぜこの記事を書くのか

自分がいまプロダクトの中で扱っている領域は、一般的なソフトウェアエンジニアよりはセキュリティに関する関心度合いが高い、と言っていいと思う。

セキュリティはソフトウェアエンジニアにとっては、大抵あとから学ぶもので、体系的な知識が身についている人の数は少ないと感じる。自分自身もご多分に漏れず、必要に迫られていくつかの観点からセキュリティに携わるようになった立場だ。

そこで、現場レベルで意識していることをまとめて、同様の悩みを抱える人の参考になるといいと思った。いわゆるセキュリティ担当などではないため、そこは注意してほしい。

よりきちんと学びたい人は、 IPA などの公的な資料にあたるといいと思う。

disclaimer

今回の「セキュリティ」「セキュア」といった用語の対象範囲は「WEBサービス」や「WEBシステム」であり、それ以外のいかなる範囲についても想定していません。

またこれを守っていても必ずしも安全というわけではなく、現場で運用しうる範囲でこういったことを気をつけるといいと思う、という範囲の見解の共有にとどまります。

セキュリティ対策をどんな角度から考えるか

セキュリティ対策にはいくつかの角度があり、それぞれで対策を施すことでプロダクトの安全性を向上させたり、維持することができる。

自分の観点をまとめると以下のような感じ。

  • すでに知られている攻撃手法による攻撃が成立する穴を作らない
  • 基準を設けて、安全であることを継続的・定期的に確認する
  • 攻撃が成立してしまった場合の被害範囲を減らす
  • 攻撃を素早く検知できる体制を整える

それぞれについて具体的に見ていく。

すでに知られている攻撃手法による攻撃が成立する穴を作らない

セキュリティ対策と言ってまず思いつくのはこれだと思う。

攻撃は何もないところから発生することはほとんどなく(※ゼロデイ攻撃と言われるような例外を除く)、脆弱性というソフトウェア側の弱点が存在し、その穴を突くようにして攻撃が成立する、というのが一般的だ。

とはいえ、脆弱性そのものよりは、攻撃方法に著名な名前がついているケースが多い。

攻撃方法のリストは 代表的な 10 種類の脆弱性 (ソフトウェア等におけるセキュリティ上の弱点) などがわかりやすい。

自分の場合、クライアントサイドとAPIサーバーを分けたシステム開発をすることがほとんどのため、以下のような観点で脆弱性がないかを日常的に警戒している。

※ ()内は関連しそうなキーワード

  • 適切な権限を持つユーザーのみがデータにアクセスできるか(CSRF)
  • 入力値のチェックやサニタイズなどを正しく行っているか(XSS, SQLインジェクション)
  • ユーザーの認証・認可状況を偽造された場合に検知できるか(XSS)
  • ユーザーの操作に対して不適切なスクリプトを混入させる余地がないか(クリックジャッキング・フォームジャッキング)
  • 保持・漏洩してはならないデータが自社のサーバー上にログとして書き出されたりしないか(情報漏洩)

基本的にはこうしたポイントを押さえつつ、頭から終わりまで、実行される(であろう)スクリプトやプログラムの中に、よく知られる攻撃手法が成立する余地がないか気にしていくことになるのだけれど、近年は基本的なプログラムのセキュリティが向上していることもあって、成功する攻撃手法が限定されてきているようだ。

後述する「被害範囲を減らす」項目で権限管理などができていて、VPCなどの設定がきちんとされているケースにおいては、クライアントサイドのJavaScriptをハックして、偽装した権限で不正な操作をしたり、ユーザーをフィッシングサイトに誘導するといったことが主流になりつつあるようで、リクエストヘッダの検証やレスポンスヘッダでの制御などの重要性が高まっているように思う。

基準を設けて、安全であることを継続的・定期的に確認する

プロダクトはどんどん更新されるので、ある時点で脆弱性が発見されなかったからといってつねに安全であるとは限らない。

脆弱性がないかを継続的に監視するにあたっての基準は、ある程度普及した機関によって出されているものを基準にすると網羅的にチェックできる。

例えば、 OWASP が出しているチェックリストなどは参考になる。

自分は参照しやすいこともありよく、 ueno1000/secreq にあるPDFを参照している。

これらのチェックリストに批准しているかどうかは、いくつかの方法でチェックできる。(方法によっては完全ではないがかなりの割合に対応できる)

下記の方法で、プロジェクトの状況や会社の規模に合ったものを組み合わせて選んでいくのが良さそう。

  • チェックリストの確認によるセルフチェック
  • OWASP ZAP などの自動診断ツールによる自動・定期チェック
  • 診断会社などを活用した脆弱性診断

攻撃が成立してしまった場合の被害範囲を減らす

攻撃が成立してしまった際に発生するのは、成立した箇所に与えられている権限の範囲でなんでもできるという状態だ。

そのため、1サーバーで整理しているシステムのsudo権限などが奪われてしまうとほとんどなんでもできてしまう。

これは攻撃成立時のリスクが非常に高い状態と言える。

普段から可能であれば、AWSがGCPでいうところのIAMや、サーバー内の実行ユーザーなどの権限、セキュリティグループなどの接続許可設定を、それぞれ必要最小限に絞っておくということをオススメしたい。

(これ、一般的なインフラチームやSREなどでは本来当たり前の水準なんだと思うのだけど、かなりレベルの高いチームでないとなかなか守れていないと思う。観測範囲N=7社ぐらいの感想)

かくいう自分もプライベートでは割とガバい感じでやってしまうことが多い(S3 Full Accessつけるとか・・・)ので頑張っていきたい。

管理画面の運営ユーザーなども、運営ユーザーごとに適切な権限が振り分けられていれば、ハックされてもその人が操作できる範囲でしか悪事が働けないなど、被害を「不幸中の幸い」の規模に止めることができる(かもしれない)。

攻撃を素早く検知できる体制を整える

DoS攻撃やDDoS攻撃などはこの角度での対策ができていないといつでもサイトをダウンさせられてしまう感じになる。

(いや、まあDDoSぐらいになるとかなり強いチーム・ソフトウェアじゃないとどうにもならないと思うけれど・・・)

上記のような対策をしていてもなお、様々な形でソフトウェアは攻撃に晒されるので、攻撃が成立してしまうと異常をきたすメトリクスなどを日常的に監視できていると良さそう。

マクアケではこの辺りはSREチームの恩恵でかなり監視されていると感じてます(唐突なマクアケ推し)。

というわけで

非常にざっくりした全体像だけれど、セキュリティについて気にしていることを書いてみた。

これ以外にも、例えばAPIキーの管理方法とかソフトウェアの外で起こる問題もたくさんあるので、より広い観点でも気にすることはあるけど、ここに挙げたようなことを意識していなかったような段階であれば、意識するだけでプロダクトのセキュリティレベルは結構上がるんじゃないかな、と思ったりしています。

本日はこれにて終わりです。