こんにちは、クラウドセキュリティアーキテクトの大島悠司です。
Amazon Inspectorが、EC2インスタンスのdeep inspectionをサポートするようになりました。
従来は、OS標準搭載のパッケージマネージャーである yum や apt でインストールしたパッケージしか検知できませんでした。
今回のアップデートにより、プログラミング言語のパッケージマネージャーである pip や nmp でインストールしたパッケージも検知できるようになりました。
以前、InspectorがLambdaの診断対象をパターン別に検証したことがあり、今回も同様にパターン別に検証してみました。
- まずは結論から
- アップデート概要
- Deep Inspectionの有効化
- AWS System Manager ステートマネージャー を確認
- (1)pipコマンドで古いパッケージを取得(deep inspection設定前)
- (2)pipコマンドで古いパッケージを取得(deep inspection設定後)
- まとめ
まずは結論から
時間が無い方用に結論を述べます。
Amazon Inspectorは、EC2インスタンスのdeep inspection機能を使うことで、任意のパスにあるパッケージの脆弱性を診断することができます。
ただし、Lambdaに対する診断と同じようなアーティファクトを使用しているため、メタファイル名やパッケージ内のファイルパスを変更するなどした場合、アーティファクトから外れてしまい、検知できないと考えられます。
アップデート概要
- プログラミング言語のパッケージマネージャーからインストールしたパッケージも診断可能
- デフォルトのディレクトリパスだけだけでなく、カスタムディレクトリパスを追加することで、より柔軟なパッケージ検出可能
デフォルトディレクトリパスは以下
/usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64
- 2023 年 4 月 17 日以降にInspectorを有効化した場合は、deep inspectionも自動的に有効化される
- 追加料金なしで利用可能
Deep Inspectionの有効化
Inspectorの「設定」→「アカウント管理」を見ると、Amazon EC2スキャンの欄に「Deep inspection deactivated」と表示されています。
画面上部にある「Activate the deep inspection」ボタンがあるので押下します。
これで、有効化されました。
また、Organaization環境の場合、管理アカウントあるいはInspectorの委任先アカウントで、画面上部にある「Activate the deep inspection for your organization」ボタンから、全アカウントに対して一括で有効化ができます。
AWS System Manager ステートマネージャー を確認
Deep inspectionを有効化すると、AWS System Manager ステートマネージャーで以下の関連付けが作成されます。
- InspectorLinuxDistributor-do-not-delete
- InvokeInspectorLinuxSsmPlugin-do-not-delete
それぞれの関連付けドキュメントを確認してみます。
関連付け:InspectorLinuxDistributor-do-not-delete
ドキュメント:AmazonInspector2-InvokeInspectorSsmPluginLinux
InspectorのSSMプラグインをインストール/アンインストールしているようです。
{ "schemaVersion": "2.2", "description": "Install or uninstall a Distributor package.", "parameters": { "action": { "description": "(Required) Specify whether or not to install or uninstall the package.", "type": "String", "allowedValues": [ "Install", "Uninstall" ] }, "installationType": { "description": "(Optional) Specify the type of installation. Uninstall and reinstall: The application is taken offline until the reinstallation process completes. In-place update: The application is available while new or updated files are added to the installation.", "type": "String", "allowedValues": [ "Uninstall and reinstall", "In-place update" ], "default": "Uninstall and reinstall" }, "name": { "description": "(Required) The package to install/uninstall.", "type": "String", "allowedPattern": "^arn:[a-z0-9][-.a-z0-9]{0,62}:[a-z0-9][-.a-z0-9]{0,62}:([a-z0-9][-.a-z0-9]{0,62})?:([a-z0-9][-.a-z0-9]{0,62})?:(package|document)\\/[a-zA-Z0-9/:.\\-_]{1,128}$|^[a-zA-Z0-9/:.\\-_]{1,128}$" }, "version": { "description": "(Optional) The version of the package to install or uninstall. If you don't specify a version, the system installs the latest published version by default. The system will only attempt to uninstall the version that is currently installed. If no version of the package is installed, the system returns an error.", "type": "String", "default": "" }, "additionalArguments": { "description": "(Optional) The additional parameters to provide to your install, uninstall, or update scripts.", "type": "StringMap", "displayType": "textarea", "default": {}, "maxChars": 4096 } }, "mainSteps": [ { "action": "aws:configurePackage", "precondition": { "StringEquals": [ "platformType", "Linux" ] }, "name": "configurePackage", "inputs": { "name": "{{ name }}", "action": "{{ action }}", "installationType": "{{installationType}}", "version": "{{ version }}", "additionalArguments": "{{ additionalArguments }}" } } ] }
関連付け:InvokeInspectorLinuxSsmPlugin-do-not-delete
ドキュメント:AmazonInspector2-InvokeInspectorSsmPluginLinux
Linux用のInspectorのSSMプラグインを呼び出しているようです。
{ "schemaVersion": "2.2", "description": "Invokes inspector ssm plugin for linux", "parameters": { "Timeout": { "type": "String", "description": "Timeout in seconds for inspector ssm plugin", "default": "900", "allowedPattern": "^([0-9]|[1-9][0-9]+)$" }, "CpuLimit": { "type": "String", "description": "Cpu usage limit in percentage for inspector ssm plugin", "default": "65", "allowedPattern": "^([1-9]|[1-9][0-9])$|^(100)$" } }, "mainSteps": [ { "action": "aws:runShellScript", "name": "invokeInspectorSsmPluginLinux", "precondition": { "StringEquals": [ "platformType", "Linux" ] }, "inputs": { "runCommand": [ "#!/bin/bash", "#", "# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.", "#", "", "set -x", "", "function fail {", " echo $1", " echo $1 >&2", " exit 1", "}", "", "function retry {", " local attempt=0", " local max_attempts=5", " local delay=60", " while", " \"$1\" && break || {", " ((attempt++))", " echo \"Waiting for $delay second(s) before retrying...\"", " sleep $delay;", " }", " [[ $attempt -lt $max_attempts ]]", " do :; done", " if [[ $attempt -eq $max_attempts ]]; then", " echo \"Retries completed after $attempt attempts.\"", " fail \"$2\"", " fi", "}", "", "INSPECTOR_ROOT_DIR=\"/opt/aws/inspector\"", "INSPECTOR_SSM_PLUGIN=\"$INSPECTOR_ROOT_DIR/bin/inspectorssmplugin\"", "INSPECTOR_OUTPUT_DIR=\"$INSPECTOR_ROOT_DIR/var/output\"", "", "TIMEOUT=\"{{Timeout}}\"", "CPU_LIMIT=\"{{CpuLimit}}\"", "", "function is_installed {", " if [[ ! -f $INSPECTOR_SSM_PLUGIN ]]; then", " echo \"$INSPECTOR_SSM_PLUGIN does not exist\"", " (exit 1)", " else", " echo \"$INSPECTOR_SSM_PLUGIN exist\"", " fi", "}", "", "echo \"Checking the installation of inspector ssm plugin...\"", "retry is_installed \"Inspector ssm plugin is not installed. Exiting...\"", "echo \"Inspector ssm plugin is installed.\"", "", "echo \"Starting evaluation using inspector ssm plugin\"", "cmd=\"$INSPECTOR_SSM_PLUGIN -mode bpm -read-params-store -report-ssm-inventory -report-metrics-via-ssm-inventory -save-findings-as $INSPECTOR_OUTPUT_DIR/packages.txt -format text -timeout $(($TIMEOUT)) -cpulimit $(($CPU_LIMIT))\"", "$cmd", "status=$?", "if [ $status -eq 0 ]", "then", " echo \"Inspector ssm plugin linux ran successfully\"", " exit 0", "else", " fail \"Inspector ssm plugin did not run successfully\"", "fi" ] } } ] }
(1)pipコマンドで古いパッケージを取得(deep inspection設定前)
以下のインスタンスを用意しました。
以降の検証も全て同じインスタンスを利用します。
pipでnumpy1.21.3をインストールします。
$ pip install numpy==1.21.3 Defaulting to user installation because normal site-packages is not writeable Collecting numpy==1.21.3 Downloading numpy-1.21.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (15.7 MB) |████████████████████████████████| 15.7 MB 5.6 MB/s Installing collected packages: numpy Successfully installed numpy-1.21.3
インストールパスを確認すると、「/home/ssm-user」配下にインストールされているようです。
Name: numpy Version: 1.21.3 Summary: NumPy is the fundamental package for array computing with Python. Home-page: https://www.numpy.org Author: Travis E. Oliphant et al. Author-email: License: BSD Location: /home/ssm-user/.local/lib/python3.9/site-packages Requires: Required-by:
Inspectorを確認すると、検知結果がないことが確認できます。
これは、先ほどnumpyのインストールパスを確認した通り、Inspectorがデフォルトで検査する以下のパスにnumpyが存在しないためです。
/usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64
(2)pipコマンドで古いパッケージを取得(deep inspection設定後)
Inspectorの「全般設定」→「EC2スキャン設定」から、カスタムパスの「編集」を押下します。
先ほどの確認で、numpyは「/home/ssm-user」に存在することが分かっているので、そのパスを入力して「保存」を押下します。
deep inspectionのためのアプリケーションインベントリの収集は6時間毎に行われる仕様です。
今回は検証のため手動で実行します。
InvokeInspectorLinuxSsmPlugin-do-not-delete の関連付けが、Linux用のInspectorのSSMプラグインを呼び出すものなので、これを再適用します。
AWS System Manager ステートマネージャーで InvokeInspectorLinuxSsmPlugin-do-not-delete を選択し、「関連付けを今すぐ適用」を押下します。
以降の検証もこの再適用を繰り返し実施します。
すると、Inspectorの検出結果でnumpyの脆弱性が検知されています。
検知されたパッケージが存在するファイルパスも、deep inspectionで設定したパス配下であることが確認できます。
このファイルパスにあるMETADATAは、numpyのバージョンやライセンスなどの情報が書かれており、Inspectorはこのファイルを見て脆弱か否かを判定しているようです。
$ pwd /home/ssm-user/.local/lib/python3.9/site-packages/numpy-1.21.3.dist-info $ cat METADATA Metadata-Version: 2.1 Name: numpy Version: 1.21.3 Summary: NumPy is the fundamental package for array computing with Python. Home-page: https://www.numpy.org Author: Travis E. Oliphant et al. Maintainer: NumPy Developers Maintainer-email: numpy-discussion@python.org License: BSD Download-URL: https://pypi.python.org/pypi/numpy Project-URL: Bug Tracker, https://github.com/numpy/numpy/issues Project-URL: Documentation, https://numpy.org/doc/1.21 Project-URL: Source Code, https://github.com/numpy/numpy Platform: Windows Platform: Linux Platform: Solaris Platform: Mac OS-X Platform: Unix Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Science/Research Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: C Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Topic :: Software Development Classifier: Topic :: Scientific/Engineering Classifier: Typing :: Typed Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: POSIX Classifier: Operating System :: Unix Classifier: Operating System :: MacOS Requires-Python: >=3.7,<3.11 It provides: - a powerful N-dimensional array object - sophisticated (broadcasting) functions - tools for integrating C/C++ and Fortran code - useful linear algebra, Fourier transform, and random number capabilities - and much more Besides its obvious scientific uses, NumPy can also be used as an efficient multi-dimensional container of generic data. Arbitrary data-types can be defined. This allows NumPy to seamlessly and speedily integrate with a wide variety of databases. All NumPy wheels distributed on PyPI are BSD licensed.
以降、このMETADATAファイルに対して様々な変更を加え、Inspectorが検知できるのかを見ていきます。
(2-2)METADATAファイル名を変更
mvコマンドでファイル名を「METADATA」から「METADATAtest」に変更します。
$ pwd /home/ssm-user/.local/lib/python3.9/site-packages/numpy-1.21.3.dist-info $ mv METADATA METADATAtest $ ls INSTALLER LICENSE.txt LICENSES_bundled.txt METADATAtest RECORD REQUESTED WHEEL entry_points.txt top_level.txt
AWS System Manager ステートマネージャーで InvokeInspectorLinuxSsmPlugin-do-not-delete をの関連付けを再適用します。
すると、Inspectorで検知されませんでした。
(2-3)METADATAファイルパスを変更
mvコマンドでファイル名を「METADATAtest」から「METADATA」に戻します。
そして、mvコマンドで1つ上の階層に移動させます。
$ mv METADATAtest METADATA $ mv METADATA .. $ pwd /home/ssm-user/.local/lib/python3.9/site-packages/numpy-1.21.3.dist-info $ ls INSTALLER LICENSE.txt LICENSES_bundled.txt RECORD REQUESTED WHEEL entry_points.txt top_level.txt $ cd .. $ ls METADATA numpy numpy-1.21.3.dist-info numpy.libs
AWS System Manager ステートマネージャーで InvokeInspectorLinuxSsmPlugin-do-not-delete をの関連付けを再適用します。
すると、先ほどと同様にInspectorで検知されませんでした。
(2-4)METADATAファイルを削除
mvコマンドで「METADATA」を /tmp 配下に移動します。
$ pwd /home/ssm-user/.local/lib/python3.9/site-packages $ mv METADATA /tmp/ $ ls numpy numpy-1.21.3.dist-info numpy.libs $ ls /tmp/ METADATA
AWS System Manager ステートマネージャーで InvokeInspectorLinuxSsmPlugin-do-not-delete をの関連付けを再適用します。
すると、先ほどと同様にInspectorで検知されませんでした。
(2-5)METADATAファイルを書き換える
まずは、mvコマンドで「METADATA」を元のパスに移動します。
$ mv /tmp/METADATA numpy-1.21.3.dist-info/ $ cd numpy-1.21.3.dist-info/ $ ls INSTALLER LICENSE.txt LICENSES_bundled.txt METADATA RECORD REQUESTED WHEEL entry_points.txt top_level.txt
適当なエディタで「METADATA」を開き、Versionを「1.21.3」から「1.21.0」に書き換えます。
$ vim METADATA Metadata-Version: 2.1 Name: numpy Version: 1.21.0 Summary: NumPy is the fundamental package for array computing with Python. Home-page: https://www.numpy.org Author: Travis E. Oliphant et al. Maintainer: NumPy Developers (省略)
ファイル「METADATA」に記載のバージョン情報が書き換わっていることを確認します。
$ cat METADATA | grep ^Version Version: 1.21.0
AWS System Manager ステートマネージャーで InvokeInspectorLinuxSsmPlugin-do-not-delete をの関連付けを再適用します。
すると、Inspectorで検知されました。
Inspectorで詳細を確認すると、インストール済バージョンが書き換えた「1.21.0」で検知されていることが確認できます。
まとめ
以上の検証をまとめると、以下の表のようになります。
Amazon Inspectorのdeep inspectionを使って、EC2にインストールされたnumpyを様々なパターンで診断させた場合の結果
検証番号 | 条件 | 結果 |
---|---|---|
(1) | pipコマンドで古いパッケージを取得(deep inspection設定前) | METADATAで検知 |
(2) | pipコマンドで古いパッケージを取得(deep inspection設定後) | METADATAで検知 |
(2-2) | METADATAファイル名を変更 | 検知無し |
(2-3) | METADATAファイルパスを変更 | 検知無し |
(2-4) | METADATAファイルを削除 | 検知無し |
(2-5) | METADATAファイルを書き換える | METADATAで書き換えたバージョンとして検知 |
Inspectorのdeep inspection機能を使って、ユーザがパスを明示することで、pip や nmp でインストールしたパッケージであっても検知することができました。
ただし、メタファイル名やパッケージ内のファイルパスを変更するなどした場合、アーティファクトから外れてしまい、検知できないと考えられます。
冒頭にも紹介した通り、以前のブログでLambdaに対する診断も同様のパターン別検証をしており、その時と同様の結果になっています。
deep inspectionは便利な機能ですが、Inspectorのこのような特性を理解したうえで活用していければと思います。