こんにちは、北海道から freee PSIRT(Product Security Incident Response Team)に参加している yu です。 今年は雪が少ないな〜と思っていたら最近ドカドカ降るようになってきて、1日デスクで集中した後に外に出ようとすると玄関のドアが雪で開かない日もありました。雪国エンジニアの各位、除雪も忘れず頑張っていきましょう!
さて、この記事では前回の記事で bucyou が紹介した開発合宿において、私と同僚の tomoya さんで取り組んだ freee の Attack Surface Management(以下、ASM)について紹介します。
ASM とは
ASM、Attack Surface Management という用語はさまざまなところで異なる定義がされており、私自身、この言葉を使うときにはまだ少しだけ違和感があります。 国内では昨年の5月に経済産業省が導入ガイダンスを発表したことを切っ掛けに広く普及し、ここに記載されている定義が一般的になっている印象です。
ASM とは、外部(インターネット)からアクセス可能な IT 資産の情報を調査し、それらに存在する脆弱性を継続的に評価する取り組みである。
(経済産業省: 『ASM(Attack Surface Management)導⼊ガイダンス 外部から把握出来る情報を⽤いて⾃組織の IT 資産を発⾒し管理する』, P4)
ただ、実際には Attack Surface という用語はかなり広範な概念であり、オフィスのネットワークや開発に使用している外部サービス、サプライチェーンなどその対象は多岐に渡ると考えています。 そのため、ASM という言葉を使うときにはその文脈によって意味合いが異なる可能性があることに留意した上で、この記事を読んでいただければ幸いです。
freee で ASM に取り組む意義
ASM における攻撃面の特定と脆弱性の発見は、多くの場合 OSINT*1 とさまざまなスキャンツールを組み合わせて行われます。
そしてインターネット上に公開されているエンドポイントにおいて不用意なポートが解放されていたり、任意コード実行が可能な脆弱性が存在していたりすることはセキュリティ上の大きなリスクとなります。
一方で、freee のプロダクトではクラウドインフラ環境の構築に IaC を採用しており、構築段階からセキュアな状態を再現し、また、各種センサーを通じて不用意な変更を検出するようにしています。 自動化したコンテナイメージのスキャンやアプリケーションの脆弱性管理も進んできています。この状態で、ASM に取り組む意義はあるのでしょうか?
答えは Yes で、freee 会計や freee 人事労務といった機微な情報を扱うプロダクトは上述のようなガードレールを築いている一方で、諸事情で前述の仕組みから外れて作られたページなど(詳細は省きますが、心当たりはあります・・・)、一部の資産がこのガードレールから外れた場所に存在する懸念があります。
こうしたさまざまな資産とその脆弱性を管理するための取り組みとして、いわゆる ASM に開発合宿で取り組むことにしました。
ASM ツールの概要設計
開発合宿で与えられた時間は24時間しかないので、同僚の tomoya さんとチームを組んで技術調査や簡単な設計を行ってから開発合宿に臨みました。
あわよくば余った時間に酒盛りもできるのでは、と考えてすらいましたが、現実はいつだって厳しいのです。
攻撃面 (Attack Surface) の収集
攻撃面の収集は、組織がすでに収集している情報を使うか、攻撃者と同様に外部から OSINT を行うか、またはその両方というアプローチがあります。 両方組み合わせるのがベターですが、限られた時間で実装する MVP*2 として、今回は攻撃者と同じアプローチを採用しました。 また、こうした調査は時間をかければかけるほど精度が上がりますが、少ない時間で効果的な結果を得るためにスコープを freee.co.jp のサブドメインに絞りました。
事前にいくつかのツールを試用し、ある程度精度が高く、かつ実装に組み込みやすい subfinder を採用しました。 Go で Package を提供していてアプリケーションに組み込みやすい点や、passive enumeration であり対象のサーバーに負荷を掛けないことも採用の一因です(もちろんツールによってメリットデメリットはあります)。
subfinder は同種のツールの中でも速度性能が高いため、 AWS Lambda で実行してその結果を S3 に保存することにしました。
脆弱性の検出と評価
続いてリストアップしたサブドメインに対する脆弱性の検出と評価を行います。 これは ECS Task で nmap を実行することにしました。 nmap はポートスキャンツールとして有名ですが、NSE(Nmap Scripting Engine)という機能を使うことで、様々な拡張機能を利用することができます。
今回実装したシステムではサブドメインの列挙と脆弱性の検出を自動で実行するため、freee 社外でホストされているサーバーも対象となるおそれがあります。 そのため、脆弱性の検出には攻撃的なリクエストを行うものは利用せず、vulners という NSE を利用しました。
これは nmap で検出した software とそのバージョン情報を vulners.com の脆弱性データベースに問い合わせて脆弱性の有無を確認するものであり、ポートスキャナー以上の追加の攻撃を行わない点が今回の要件にフィットしました。
実行環境は AWS Lambda を使ってサブドメインごとに並列実行することも考えましたが、接続先への負荷も考慮し、ECS Task で直列実行することにしました。
自動化
上記二つをローカルで実行するスクリプトを書くぐらいであれば、数時間で実装することができます。 ただし継続的に、機械的に実行することが重要であると考え、この期間内に AWS 上の定期実行環境の構築も行いました。
IAM Role や ECS Task Role や ECS Task 実行 Role などを作成するのに苦労し、時刻はすでに AM 3:00。 何度やってもうまくいかなった時の原因が私の typo だったときは顔から火を吹いたものです。ごめん tomoya さん・・・
気持ちが昂って Slack で月に吠えたりしたのもこの時間です。
完成!
朝の7時前に完成した雰囲気が出てきたので仮眠をとり、少し寝てからデバッグと修正を行い、24時間後である 13:00 にギリギリ完成しました。 ECS Task を実行して帰路につき、会社に戻った後にデータベースに実行結果が保存されていることを確認しました。保存されていた結果については内緒です。
事業会社が自分たちで開発するメリット
現在 ASM のソリューションは国内外で提供されており、それらは今回私たちが作ったものよりもはるかに高度な機能を提供しています。 もちろんコーディングは楽しいですが、仕事として実装する以上楽しむことだけが目的ではありません。
完成度においては既存製品より大きく劣るかもしれませんが、自分たちのためだけに作ることで、日常的に使うコミュニケーションツールやワークフロー、監視基盤などに統合しやすいことは大きなメリットです。 また、今回は攻撃者寄りのアプローチを取りましたが、今後は組織の中の情報と外部から得られる情報を組み合わせることで、外部の攻撃者よりも精度の高い攻撃対象のリストを作り出すことも可能です。
保守コストが大きな問題となることもありますが、今回は枯れた技術を使っているためほとんど問題にならない範疇と考えています。 これからも業務の合間を縫って、より効果的で、より freee に合った ASM の実装を進めていきます。
謝辞
緊急性の高い差し込み作業が多くなりがちなセキュリティチームにとって、開発だけに集中できるこの合宿は1年で1番楽しみにしている社内イベントです。 社員数も増えてもう合宿は無理か・・・と思っていた中でこの実現に尽力してくれた開発合宿運営のみなさま、本当にありがとうございました!