ソフトウェアの開発環境は通常の環境と違う対策が必要です。その理由は開発環境には
- 他人が書いた未検証のモノ
- 自分が書いた実験用のモノ
- 他人または自分が書いた作りかけのモノ
- 制御された環境での利用を前提としたモノ
- 意図的に利用している新しいモノ(リリース前のソフトウェアなど)
- 意図的に利用している古いモノ(古いシステムサポートためなど)
※モノにはコード/ライブラリ/ツール/アプリ/システム などがあります。
などがある為です。開発環境はその他の環境に比べ「とにかく危険なモノがいっぱい」です。
更に最近ではソーシャルコーディングが当たり前になり、他人が書いた未検証のコードがどんどん実行される状態も当たり前です。それも1つ2つのライブラリではなく、依存性から何百、場合によっては何千というライブラリなどが自動的にダウンロードされ実行されています。
これがどういう状況かというと「PCがやっと使えるくらいのユーザーが、インターネットからプログラムをダウンロードしまくって実行している状況」とあまり変わりません。
開発環境を安全にできるのか?
「とにかく危険なモノがいっぱい」である一般的な開発環境を、普通のIT環境のように安全にできるか?考えてみます。
- 「全て検証してできるだけリスクを少なくし何とかしよう」
↓
・開発者の仕事は脆弱性調査と発見ではない。
・普通は自分が作るモノだけで手一杯、扱うモノ全ての安全性を確認するのは無理。
・ソーシャルコーディングで不正なコードが混入していないか確認するのは無理。(npmパッケージでパッケージが削除された際に依存関係で騒ぎになった例からも明らか。更新前に全てモノの安全性を検証していたら開発にならない)
- 「少なくとも既知の脆弱性修正に対応してリスクに対応しよう」
↓
・検証できていない新しいモノを次々利用するので”既知の脆弱性修正”は役立たない場合が多い。(リリース前のモノは脆弱性修正があっても普通は脆弱性修正として扱われない)
・わざと古いモノを利用する場合も多い。(インターネットに公開せず、管理された環境で利用するモノは古いまま。これらがメンテナンス用に開発環境に存在することは普通)
・古いモノの中には隠れた”既知の脆弱性が多数存在”することが多い。
・最新安定版のモノでも隠れた”未知の脆弱性が多数存在”することが多い。
・これらのために脆弱性を修正して安全にすることは無理。
- 「自分の書いたコードは完璧にしよう」
↓
・作りかけのモノ、実験用やプロトタイプ用、管理された運用環境用のモノにセキュリティコストを掛けすぎるのはビジネス上無理。
- 「仮想環境やDockerを使えば大方安全(ではない)」
↓
・普通に使っている場合、外から仮想環境やDocker環境の中には入れないが、仮想環境やDocker環境の中から外は出放題。(悪意のあるプログラムがあると内部ネットワークにアクセス仕放題)
少し考えただけでも安全な開発環境を作るのはほとんど不可能だと解ります。脆弱性があること、悪意があるプログラムが存在することを前提とした対策が必要だと解ります。
開発環境を安全にできないなら、分離すれば良い
開発環境をIT利用者環境と同等レベルくらいまで安全にすることはほとんど無理なので「許容可能な範囲のリスクに抑えて利用する」するしかありません。主な脆弱性を持つモノは既に記載したこれらです。
- 他人が書いた未検証のモノ
- 自分が書いた実験用のモノ
- 他人または自分が書いた作りかけのモノ
- 制御された環境での利用を前提としたモノ
- 意図的に利用している新しいモノ(リリース前のソフトウェアなど)
- 意図的に利用している古いモノ (古いシステムサポートためなど)
脆弱性を攻撃する攻撃元はメール/ブラウザ/その他のネットワーク接続です。
これらのリスクに対する対策は複雑で困難です。
こういう場合はコンピュータサイエンス原則の1つであるDivide and Conquer(複雑な問題を分離/分割して解決)です。開発環境を分離して、許容可能なリスクに抑えて利用します。ダウンロードしたモノに含まれる不正コードや脆弱性、開発環境にある脆弱なモノなどの受け入れざるを得ないリスクは受け入れ、可能な緩和策を実行します。
そのためには以下のような対策を行います。
- 開発環境のネットワークは他のネットワークから”適切”に分離する。
- ネットワーク的に確実に分離する。運用環境からも確実に分離する。(物理的またはVLAN)
- 通常のネットワークサービス(メール、ブラウザ、ファイルサーバーなど)は利用しない、利用できないようにする。
- インターネットも”他”のネットワークの1つ。
Webアプリの場合、クロスサイト攻撃(XSSやCSRF)が問題になるので、開発環境からはプロキシサーバーを用いホワイトリスト型でアクセス制御し、許可したサイト/サービス以外へのアクセスは禁止する。
SNSサイトへのアクセスなどは論外。ソースコードダウンロード等に必要なサイトは仕方ないので利用(リスクの許容)する。※参考 - 開発者に開発業務用とそれ以外の環境、それぞれにアクセスできるリソース(物理的に別のPCなど)か仕組み(仮想マシンとVLAN)を提供する。
- 開発者に開発環境を分離する意味を確実に理解させる。
- 人的脆弱性が最大のリスクです。「面倒だから」と開発者のPCでルーティングして開発環境とそれ以外の環境をつなげてしまう、リスクがある外部Webサイトにアクセスできるようにしてしまうようでは意味がない。
- 開発環境での不正アクセスを検知/検出する。(開発環境以外でもすべき)
- 万が一、ライブラリなどに不正コードが含まれていてネットワークをスキャンされた場合などは攻撃を検知/検出できるようにしておく。(OSSならSnortなどが利用できる)
- プロキシサーバーでホワイトリスト以外のアクセスを記録し、検証する。
- 開発用のPCも不正なプロセスなどがないか定期的にチェックする、利用状況を記録し後で検証できるようにする。(OSSならOSSEC HIDSなどが利用できる)
- 開発環境には盗まれたり、壊されたりして困る物は置かない。
- インシデント発生時(侵入されてしまった場合)にコードが盗まれるのは仕方ないので諦める(リスクの許容)どうしても諦めれない場合、プロジェクト毎に開発環境を分離してリスクを軽減する。
- コードを保存したサーバー(Gitサーバーなど)は十分に保護する。
- 顧客データなどは開発環境には置かない、アクセスできるようにしない。
いろいろあって大変そうに見えます。しかし、開発環境を一般環境と同程度に安全にすることは論理的には可能ですが、事実上不可能です。開発環境を一般環境と同程度に安全にする(ある程度検証されたモノだけを使う)より、上記の対策を実施する方が圧倒的に少ないリソースかつ現実的なリソースで実現できます。
緩くしすぎに注意!
幾ら脆弱性があることが前提の開発環境だから、といってもどこまでセキュリティを緩くするか?(リスクを許容するか?)はよく考える必要があります。
開発専用DBでテストデータしか入っていない物ならDBにパスワード無しで接続できるくらいなら許容可能でしょう。
しかし、sshで鍵のパスフレーズ無し/パスワード無しで他のマシンにrootで自由にログインできるようにしたり、普段自分が使うアカウントでsudoがパスワード無しで使えてしまうのは許容範囲外とすべきでしょう。トロイの木馬などで簡単に完全に乗っ取られてしまいます。開発環境でも少なくともマシンの管理者権限くらいはある程度はリスク対策をしておくべきだと思います。
SSRF、不適切な設定で分離したネットワークを台無しにしないように注意しましょう!
また脆弱性があることが前提である開発環境ですが、更新できるモノはできるだけ更新した方が良いです。攻撃者が利用できるモノは少ないに越したことはありません。
まとめ
対策のポイントは
- 攻撃されたら検知できるようにすること
- 適切に分離すること
- 盗まれたり、壊されたりして困るモノを置かない、アクセスさせない
です。この方法は詳しく解説していませんが、Snort、OSSEC HIDSなどを使って検知できます。ログに取るだけでは恐らく見ないのでアラートメールを送信する、などの仕組みは必須だと思います。攻撃を検知できるようにする対策の必要性は開発環境に限った事ではありません。
ISO27000でも開発環境や運用環境の分離を要求しています。開発環境のセキュリティ対策はそもそも脆弱/危険なモノが沢山あり、それら脆弱性/危険性の調査/修正/対策はリソース的な問題で不可能です。対策できないことを前提とせざるを得ません。
部外者がアクセスしない開発環境用や運用環境用のモノ、例えば Jenkinsに、に脆弱性があったら困った事になる、という状況は利用している開発環境/運用環境自体に脆弱性があることを意味します。この場合、改善を検討した方が良いです。ネットワーク的、システム的な環境は直ぐには変えれないと思いますが、少なくとも利用者(この場合は開発者)に開発環境を分離する意味とその重要性を理解してもらうと良いと思います。
脆弱性/危険性ゼロを目指すことがセキュリティ対策ではない良い例の1つとして開発環境のセキュリティ対策を紹介しました。ITセキュリティ対策の目的は「ITシステムを許容可能なリスクの範囲内で利用する」です。開発者の一番身近にある環境が解りやすい例ですね。
開発環境からテスト/ステージング環境、ステージング環境から運用環境、とどうしても繋げる部分も必要になるでしょう。受け入れたリスクを正確に把握しておく事も重要です。残存リスクの識別/管理/改善も忘れないように行いましょう。
- SOHO・家庭の安全なネットワーク環境2018 (ネットワーク構成図&必要機器リスト付き)
おまけ
普段開発しかしない!という方の場合、開発環境を実マシン、通常業務環境/運用環境へのアクセスは仮想マシン+VLAN/物理的に別セグメントLANという構成にすると快適だと思います。この場合、少なくともselinuxやfirewalldは有効にして使う方が良いです。私はそうしています。
ネットワークを確実に分離するのはそれなりの知識が必要なので、ネットワークに詳しくない方は詳しい方と相談しながら実装すると良いと思います。
とは言っても諸事情でネットワークを分離し、それぞれのネットワークにそれぞれの用途用のプロキシーサーバーを設定して運用することはできない、という方も居ると思います。その場合、FirefoxとNoScriptを使いましょう。
プロキシを使うとネットワーク的に防御可能です。