DevSecOpsとは?安全性の高いシステムを開発するための14のタスク
レバテック開発部の松浪です。
皆さんはどの程度セキュリティ対策を実施できていますか?
SQLインジェクションやCSRFなどの攻撃が起きないかテストできていますか?
今回は今流行り(?)のDevSecOpsの概要とSecurityに関する14個のタスクについて紹介して、システム開発に関わるすべての方々に少しでも「セキュリティ対策やらんとあかんなぁ..」と思ってもらえたら嬉しいです。
DevSecOpsとは?
DevSecOps(デブセックオプス)には、
- Development(開発)
- Security(セキュリティ)
- Operations(運用)
の3つの言葉が含まれています。
要は、開発期間を短く、よりリリースの頻度を多く、そして、安全性の高いシステムを開発する手法です。
ただし、昨今は様々なサイバー脅威が存在しており、システムを脅威から完璧に防ぐことはほぼ不可能とされています。
安全性の高さを実現するためには、脅威を防ぐことはもちろん、攻撃を受けてから早期に回復できることも重要としています。
DevSecOpsでは開発と運用の両方の工程でセキュリティに関連する作業があります。
DevSecOpsのライフサイクルを示す図が、国防総省のガイドラインに掲載されていますので、よりイメージがつきやすいと思います。
※ DoD Enterprise DevSecOps Reference Design
なぜDevSecOpsが重要なのか?
昨今のシステムやソフトウェアは作って終わりではなく、継続的な改善となるべく早いサービスの提供が求められています。
そのため、企画→設計→開発→テスト→運用の開発工程を繰り返すというDevOpsがシステム開発の前提となってきています。
しかし、どれだけ完璧にDevOpsを実現できていたとしても、セキュリティリスクの考慮を怠った故に攻撃に遭い、多額の損害が発生する羽目になったり、せっかく作ったサービスを停止もしくは終了せざるを得なくなったりする事例は実際に数多くあります。
また、情報漏洩を発端にサービスに対する信頼を失い、利用者が競合他社のサービスに流れてしまうことも考えられます。
普段のシステム開発の中で日々、セキュリティ対策を打っておくことは、 企業が事業を継続させるため にも 顧客の信頼を守るため にも重要と言えます。
セキュリティ対策には何があるか?
DevSecOpsには計14個のSecurityに関するタスクがあります。
1. Threat Model(脅威モデル)
脅威モデルはシステムの全体図からどこにセキュリティリスクが含まれ得るか検討し、対策を予め考えておく一連の作業を指します。
では、どのような観点でセキュリティリスクを検討すればよいか?と言うと、マイクロソフトがSTRIDEという脅威モデルを行う際の観点を提唱してくれています。
- Spoofing(なりすまし)
- Tampering(改ざん)
- Repudiation(否認)
- Information disclosure(情報漏洩)
- Denial of service(DoS)
- Elevation of privilege(権限昇格)
の6つの観点でシステムが攻撃され得る箇所を検討して対策を考えます。
脅威モデルは弊社内の認証基盤チームでも実施したので、詳しくは別の機会にこのテックブログに掲載したいと思います。
2. Secure Coding(セキュアコーディング)
セキュアコーディングは、SQLインジェクションやXSSなどの攻撃が発生しないようにソースコードを書くことです。
そんなこと言われたって...と思われた方はOWASPから脆弱性のリスクが高いランキングTOP10とその対策方法が公開されているので、参考にするとよいでしょう。
例えば、権限によるアクセス制御において、下記のようなハードコーディングは避けるべきであるとしています。
if (user.hasRole("ADMIN")) || (user.hasRole("MANAGER")) {
deleteAccount();
}
このような実装方法は単純に間違いやすく、権限の種類が追加された時に考慮が漏れる場合があります。
この場合、権限に基づいて実行が可能か判断する関数を持たせると良いです。
if (user.hasPermission("DELETE_ACCOUNT")) {
deleteAccount();
}
3. Secure as Code(セキュアアズコード)
セキュアアズコードは、セキュリティに関連する設定値を手順書や社内ルールなどで制御するのではなく、コードで制御することです。
例えば、AWSのセキュリティグループで、HTTP(port80)とHTTPS(port443)のトラフィックのみ許可しておくこともSaCの1つと言えます。
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
4. SAST(静的アプリケーションセキュリティテスト)
SASTは、アプリケーションを実行させず、ソースコードを元に脆弱性がないか検査することです。
危険な脆弱性が見つかったらもちろんソースコードを修正します。
テストするにはGitHubのCode ScanningやAWSのCodeGuruなどのツールを利用します。
ソースコードを解析するため、使用しているプログラミング言語やフレームワークに対応しているツールを選定する必要があります。
また、偽陽性には注意が必要です。
例えば、普段のコーディング中にIDEが未使用のコードであると警告してきたにも関わらず、いざ消してみるとビルドやデプロイができず実は使用していたコードだった、という経験はないでしょうか?
静的なソースコードの解析には偽陽性が少なからず存在し、SASTが脆弱性なしと診断しても実際は脆弱性がある場合があります。逆も然りです。
5. DAST(動的アプリケーションセキュリティテスト)
DASTは、アプリケーションを実行させて脆弱性がないか検査することです。
クロスサイトスクリプティングやSQLインジェクションといった脆弱性が含まれていないか、実際にアプリケーションを実行してみて検査します。ソースコードは一切解析しません。
テストするにはOWASP ZAPやTenableなどのツールを利用します。
SASTとDASTどちらを実施すべきか?
結論、両方やるべきです。
SASTはソースコードを解析し、DASTは動作するアプリケーションを解析するため、検知できる脆弱性が異なります。
両方ともCI/CDに組み込み日頃から実施しているとより効果的です。
6. Pen Test(ペネトレーションテスト)
ペネトレーションテストは、実際にシステムに対して攻撃を仕掛けて脆弱性を発見しようとするテストです。
既知の脆弱性を利用して攻撃が可能か検査したり、特定のポートから侵入を試みたりします。
アメリカのIT企業ではホワイトハッカーと呼ばれるハッキングを試みてシステムの脆弱性を見つけるためのチームや役割が一般的に知られています。
日本においてはまだホワイトハッカーという役割があまり認知されていませんが、セキュリティ意識の高まりとともに徐々にその重要性が認識されるようになると思います。
テストするにはサイバートラストやGMOサイバーセキュリティなどの専門とする企業の力を借りるか、
NmapやMetasploitなどのツールを利用して実施することができます。
7. Digital Sign (電子署名)
電子署名は、信頼性を担保する仕組みのことです。
例えば、何らかのAPIを特定のユーザや別システムに公開する場合、悪意のある第3者がAPIに不正にアクセスするリスクがあります。(なりすまし)
また、正規の通信を傍受して改変され、APIが不正なリクエストを受け取ってしまうリスクもあります。(改ざん)
このようななりすましや改ざんを見抜くために電子署名を利用して、リクエスト元が送信者本人であり改ざんされていないことを検証することができます。
方法としては主に公開鍵暗号方式が知られています。
例えば、公開鍵暗号方式を利用して改ざんされていないことを検証する場合、
import * as crypto from 'crypto';
import axios from 'axios';
// メッセージの暗号化(受信側の公開鍵を使用)
const encryptedMessage = crypto.publicEncrypt(publicKey, Buffer.from(message)).toString('base64');
// 暗号化されたメッセージを送信
axios.post('https://hogeapi/decrypt', { message: encryptedMessage })
.catch(e => {});
import * as crypto from 'crypto';
import express from 'express';
const app = express();
// メッセージの復号化(受信側の秘密鍵を使用)
app.post('/decrypt', (req, res) => {
const encryptedMessage = req.body.message;
try {
const decryptedMessage = crypto.privateDecrypt(privateKey, Buffer.from(encryptedMessage, 'base64')).toString('utf8');
} catch (e) {}
});
と言う具合に、メッセージを送信する側が受信者の公開鍵を使用してメッセージを暗号化することで、暗号化されたメッセージは受信者の秘密鍵でのみ復号化できるようになります。
この結果、復号したメッセージが改ざんされていないことを保証できます。
8. Security Transfar(セキュリティトランスファー)
セキュリティトランスファーは、何らかのデータやファイル、ソースコードなどを別の環境へ安全に転送することを指します。
TLS/SSLやSSHのプロトコルを利用すれば通信が暗号化されるのでセキュアにデータを転送できますし、FTPSやSFTPのプロトコルを利用すればファイルを安全に転送できます。
結果として、不正なアクセスから保護したり改ざんを防ぐことができます。
ソースコードは現在ならGitHub ActionsやJenkinsを利用してビルド・デプロイを自動化していることがほとんどでしょう。
以前のシステム開発では本番環境のサーバ内に手動でファイルを転送したり作成したりするケースが見られましたが、現在はそのような手作業を通常行いません(と信じたい...)
9. Security Config(セキュリティコンフィグ)
セキュリティコンフィグは、本番環境におけるセキュリティに関する設定を行うことを指します。
主に下記のような作業があります。
- アクセス制御の設定:ユーザやグループの権限を設定し、必要最小限のアクセス権を付与する
- ネットワークの設定:ファイアウォールの設定やネットワークセグメンテーションを行い、不正アクセスを防止する
- ログと監視の設定:発生したイベントのログを記録し、異常な活動を早期に検出する
10. Security Scan(セキュリティスキャン)
セキュリティスキャンは、本番環境にデプロイする前にコードをスキャンしてセキュリティ上の問題がないか検証することを指します。
セキュリティスキャンにはSonarQubeやTrivyなどのツールがあります。
もちろん開発プロセスの初期段階からセキュリティスキャンを実施することが望ましいですが、本番と開発での環境の違いによる脆弱性を見つけたり最終確認するという意味でも本番環境にデプロイする前にスキャンするのは有効です。
11. Security Patch(セキュリティパッチ)
セキュリティパッチは、脆弱性を修正するための更新プログラムを適用することを指します。
更新プログラムを適用しなければ脆弱性を突いた攻撃が仕掛けられる可能性が残り続けるため、できるだけ早くセキュリティパッチを行うのが望ましいです。
できるだけ早くセキュリティパッチを行うには、 自動化されたテスト があることが重要になってきます。
パッチした後に自動化されたテストを実行すれば機能が動作することをすぐに保証できますが、自動化されていなければ手動で影響と動作を確認する羽目になります。
12. Security Audit(セキュリティ監査)
セキュリティ監査は、企業や組織の情報セキュリティ対策が適切に実施されているか第三者の視点で評価する作業を指します。
主な目的は、セキュリティ上の欠陥を発見し、改善策を提案することです。
多くの場合、事前に用意されたチェックリストを元に、運用体制に問題がないかチェックを受けます。
チェックの結果、問題があると指摘された箇所には対策を講じる必要があります。
セキュリティ監査を行うことで、企業はサイバー攻撃に対する備えを強化し、顧客や社会からの信頼を高めることができます。
13. Security Monitor(セキュリティ監視)
セキュリティ監視は、攻撃が発生していないか監視することを指します。
システムを監視して、サイバー攻撃や不正アクセス、情報漏洩などのインシデントを早期に発見・対処するための活動です。
監視するには、AWSであればGuardDutyやSecurity Hubを利用します。
監視の対象は内部のシステムも対象に含まれる。
アカウントを乗っ取られているケースや組織内部からの犯行によって攻撃を受けるケースも考えられるためです。
14. Security Analysis(セキュリティ分析)
セキュリティ分析は、セキュリティ監視によって検知された不正アクセスに対して何が起きているのか分析することを指します。
分析では不正アクセスに対して、どのような行動を取ったか確認して、改ざんされていないか・マルウェアなどを仕込まれていないか調査する。
また、誤検知(偽陽性)の可能性もあるので注意が必要です。
セキュリティ対策は何をすればよいか?(まとめ)
DevSecOpsを実現したいが何から手をつければいいかわからない...という場合、まずは脅威モデルから始めてみるのが良いかと思います。
脅威モデルはシステムの狙われやすいポイントを把握し、セキュリティリスクに対して効果的な対策を立てるための基礎となります。
対策の優先順位も付けられ、開発者のセキュリティに対する意識向上が見込め、開発プロセスにセキュリティ対策を組み込むきっかけにもなります。
もちろん計14個のSecurityに関するタスクをすべて実施できるに越したことはないですが、人も時間もお金も限られた中ですべてをこなすのは難しいと思います。
そもそもすべてこなしてもシステム内に潜む脆弱性をゼロにすることはできず、見つかった脆弱性すべてに対応できるとも限りません。
どれだけのリソースをセキュリティ対策に投資できるかは組織の方針に依ります。
逆に今よりもセキュリティ対策への投資を促進するために、組織自体に働きかけていくことも時には必要です。
これからセキュリティ対策を検討する方はぜひ、DevSecOpsを参考にしてみてください。
Discussion