Dome9 ShiftLeft (Preview) を試した~アプリもIaCテンプレートもコンテナイメージもスキャンする~
中山です
SaaSを使っていると、いきなり新機能が使えるようになるってありますよね。
ある日、Dome9にログインしたら見慣れないアイコンが・・・
開くとこんな感じでした。
見たところ、以下の対象のセキュリティスキャンを実行するコマンドラインツールのようです。
- アプリケーションソースコード
- IaCテンプレート
- コンテナイメージ
なお、CI/CDパイプラインに組み込んで利用することを想定しているようです。
この機能についてはGitHubのパブリックリポジトリでも概要が紹介されていますので、気になる方は覗いてみてください。
製品ドキュメントにも機能の説明が記載されています。
ということで、早速使ってみました。
この記事を執筆している2020年12月13日時点で、この機能はプレビューとして提供されています。一般提供開始時には異なる名称や機能として提供される場合があります。
やってみた
最初にご紹介したウィザードから続けてやっていきます。 なお、検証はCloud9の環境(Amazon Linux 2)で行いますが、WindowsおよびMacもサポートしています。
ツールのダウンロード
まず、ツールをダウンロードして実行できるようにします。 (ウィザードで表示された手順から少し修正してます)
wget https://shiftleft-prod.s3.amazonaws.com/blades/shiftleft/bin/linux/amd64/0.0.29/shiftleft chmod +x shiftleft mkdir ~/bin mv shiftleft ~/bin/
また、Dome9のAPIキーを発行して環境変数に設定します。
export CHKP_CLOUDGUARD_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx export CHKP_CLOUDGUARD_SECRET=xxxxxxxxxxxxxxxxxxxx
最後にバージョンだけ確認します。
shiftleft --version
0.0.29
これで準備完了です。
この感じであればCodeBuildでの利用も簡単そうですね。
ツールのインストール手順はこちらでも確認できます。
アプリケーションコードの分析
最初にアプリケーションコードのスキャンを実行してみたいと思います。
ちなみに、shiftleftの各機能は「ブレード」と呼ばれ、どのブレードを利用するかはサブコマンドで指定します。 現在は3つですが、今後増えていくのでしょうか?(わくわく)
アプリケーションを用意する
まずは、スキャン対象のアプリケーションを用意します。
今回はこちらのやられアプリを使ってみました。
git clone https://github.com/yahoo/webseclab.git
分析
ブレードの利用方法はこんな感じです。
$ shiftleft code-scan -h NAME code-scan DESCRIPTION source-code/image security and visibility into the risk analysis of projects SYNOPSIS code-scan [OPTIONS] [ -s <source_folder> | -i <image_path> ] OPTIONS -s, -src, --source <string> path to source code directory -i, -img, --image <string> path to docker image tar format -t, -T, --timeout <int> scan timeout in seconds (default: 600 for source code, 900 for docker image) -x, -X, --exclude <string> path to exclude from scanning (.gitignore syntax) -d, -D, --debug debug output -j, -J, --json json output -nc, -NC, --no-cache do not take results from previous scans -np, -NP, --no-proxy do not use system proxy settings -nb, -NB, --no-blame do not use Git blame on scanned files -v, -V, --version show version -h, -H, --help show help EXAMPLE code-scan -x tests/** -x static/** -s /home/project code-scan -t 900 -i /home/image.tar
で、結果がこちら。
$ shiftleft code-scan -s webseclab/ INFO [08-12-2020 15:57:34.424] SourceGuard Scan Started! INFO [08-12-2020 15:57:35.087] Project name: webseclab path: webseclab INFO [08-12-2020 15:57:35.087] Scan ID: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxx INFO [08-12-2020 15:57:48.462] Scanning ... INFO [08-12-2020 15:57:55.562] Analyzing ... Action: BLOCK Code Findings: - ID: 50000000-0000-0000-0000-000000000024 Name: "hardcoded_ip" Description: "Hardcoded IP addresses is vulnerable to Denial of Service attack on the service at this address or spoof the IP address. Such an attack is always possible, but in the case of a hardcoded IP address the fix will be much slower, which will increase an attack's impact. make the IP address configurable." - SHA: cc88a39b3b39aca4926108cfb5492f3c1c1278085b2ca2875a83ab212eb1bfe8 Path: webseclab/static.go - SHA: c3865f1c8aa8044d29476161d5269cc47ccf92419b6b01d4ec611562123af228 Payload: xx.xx.xx.xx Lines: [1072] - SHA: af9a718122857ba25e35e2e387cde52a3fc6db6a00c5b4e94d4bf306fa3f6bc7 Path: webseclab/ip.go - SHA: 0a2fdab236cc01d85d7444687df7e6e1b87fe6d3ba786899329e856e56c99894 Payload: yy.yy.yy.yy Lines: [35 41] - SHA: d6fae90675bcc4fc8782e38d96c3c5e9999347d06ca42467fa2a61f1f9060fb9 Path: webseclab/ip_test.go - SHA: e14759884124ebda2598c31b6398bac1aa681bec9f10cf3937df021c72e9ea91 Payload: zz.zz.zz.zz Lines: [96] Content Findings: - ID: 10000000-0000-0000-0000-000000000017 Name: "username" Description: "Possible hardcoded username" - SHA: 71491b47c58c935cd368f069492ca042f7eec72f9d72684c8e50a3c6e07417ab Path: webseclab/templates/xss/reflect/js6_bug7208690 - SHA: bc3e897431b03f17bef1b5e8b7c8bcb341b6e6f6ee9c3fa65d1e42f6878d734b Payload: userid="dsa*** Lines: [43 43] - SHA: a8767bc9be3bed443fd3f74fd635cb4b0bbd53aaca5a755373bf3834a8b423b1 Payload: user="Dmi*** Lines: [102] - SHA: cc88a39b3b39aca4926108cfb5492f3c1c1278085b2ca2875a83ab212eb1bfe8 Path: webseclab/static.go - SHA: bc3e897431b03f17bef1b5e8b7c8bcb341b6e6f6ee9c3fa65d1e42f6878d734b Payload: userid="dsa*** Lines: [455 455 1154 1154] - SHA: a8767bc9be3bed443fd3f74fd635cb4b0bbd53aaca5a755373bf3834a8b423b1 Payload: user="Dmi*** Lines: [514 1213] - SHA: 307b0f96553e1150a2726be2e075b9befc0d16c98050c87efea6ecbb46c5c6aa Payload: userid="dan*** Lines: [1070 1070] - SHA: 0b359fc357e5de4e721b51ce774daeeb7acd0f3e6bad65f067ad79c82fcc2bcf Payload: user="Dan*** Lines: [1072] - SHA: 71491b47c58c935cd368f069492ca042f7eec72f9d72684c8e50a3c6e07417ab Path: webseclab/templates/xss/reflect/js3_bug7208690 - SHA: bc3e897431b03f17bef1b5e8b7c8bcb341b6e6f6ee9c3fa65d1e42f6878d734b Payload: userid="dsa*** Lines: [43 43] - SHA: a8767bc9be3bed443fd3f74fd635cb4b0bbd53aaca5a755373bf3834a8b423b1 Payload: user="Dmi*** Lines: [102] - SHA: 48474b70035adce4b2e21adc319dd11251c62f56d69c0fd740cee4acf31d14e1 Path: webseclab/templates/xss/reflect/js3_search_fp - SHA: 307b0f96553e1150a2726be2e075b9befc0d16c98050c87efea6ecbb46c5c6aa Payload: userid="dan*** Lines: [2 2] - SHA: 0b359fc357e5de4e721b51ce774daeeb7acd0f3e6bad65f067ad79c82fcc2bcf Payload: user="Dan*** Lines: [4] Please see full analysis: https://portal.checkpoint.com/Dashboard/SourceGuard#/scan/sourcecode/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxx
IPアドレスやユーザー名のハードコードを指摘してくれています。
詳細なレポートも参照できるようですが、現在は見ることができないようでした。
IaCテンプレートの分析
次にTerraformのテンプレートをスキャンしてみます。
Terraformテンプレートを用意する
今回はこちらのテンプレートを利用してみました。
hashicorp / terraform-elasticache-example
git clone https://github.com/hashicorp/terraform-elasticache-example.git
分析
ブレードの使い方はこんな感じです。
$ shiftleft iac-assessment -h INFO [08-12-2020 16:29:36.073] blade iac-assessment updated (0.0.13) Usage of iac-assessment: -D, --debug debug output flag -d, --directory string work dir (default is temp dir) -h, --help show usage -j, --json replace stdout human readble output with json format -l, --logic string rule logic to run on (cannot be used combined with ruleset ID) -p, --path string path to terraform project directory or execution-plan file (required) -r, --ruleset int ruleset ID to run on (cannot be used combined with rule logic) -s, --severity-level string severity level [Unknown Low Medium High Critical] (default "Low") -t, --severity-threshold int severity-level threshold (default 1) -v, --variable string:string key:value variables to be replaced inside the terraform files -V, --version show version
スキャンの際にはRuleset IDを指定する必要があり、どのようなルールセットがあるかはコンソールから確認できます。
RulesetのIDはRulesetの詳細画面で確認できます。
で、結果はこんな感じです。 (結果は一部省略しています)
$ shiftleft iac-assessment -p terraform-elasticache-example/ -r -64 [ { "error": null, "testedCount": 0, "relevantCount": 0, "nonComplyingCount": 0, "exclusionStats": { "testedCount": 0, "relevantCount": 0, "nonComplyingCount": 0 }, "entityResults": [], "rule": { "name": "Ensure the default security group of every VPC restricts all traffic", "severity": "High", "logic": "aws_default_security_group should not have ingress with [cidr_blocks contain ['0.0.0.0:0'] or ipv6_cidr_blocks contain ['::/0']] or egress with [cidr_blocks contain ['0.0.0.0:0'] or ipv6_cidr_blocks contain ['::/0']]", "description": "A VPC comes with a default security group whose initial settings deny all inbound traffic, allow all outbound traffic, and allow all traffic between instances assigned to the security group. If you dont specify a security group when you launch an instance, the instance is automatically assigned to this default security group. Security groups provide stateful filtering of ingress/egress network traffic to AWS resources. It is recommended that the default security group restrict all traffic.", "remediation": "1. Run aws ec2 describe-security-groups\n2. For each group allow ingress for 0.0.0.0/0 or egress for 0.0.0.0/0\n2.1 Run aws ec2 delete-security-configuration --group-ids <group>", "complianceTag": "Network Security", "domain": "", "priority": "", "controlTitle": "", "ruleId": "D9.TF.AWS.NET.03", "logicHash": "/IPcpUSwgQ/STK1z16mk5Q", "isDefault": false }, "testPassed": true }, . . . . . { "error": null, "testedCount": 1, "relevantCount": 1, "nonComplyingCount": 0, "exclusionStats": { "testedCount": 0, "relevantCount": 0, "nonComplyingCount": 0 }, "entityResults": [], "rule": { "name": "Ensure no security groups allow ingress from 0.0.0.0/0 to SSH (TCP:22)", "severity": "High", "logic": "aws_security_group should not have ingress with [(from_port<=22 and to_port>=22) and (cidr_blocks contain ['0.0.0.0:0'] or ipv6_cidr_blocks contain ['::/0'])]", "description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as SSH to port 22.", "remediation": "1. Run aws ec2 describe-security-groups\n2. For each group allow ingress for 0.0.0.0/0 to SSH (port 22/tcp)\n2.1 Run aws ec2 delete-security-configuration --group-ids <group>", "complianceTag": "Network Security", "domain": "", "priority": "", "controlTitle": "", "ruleId": "D9.TF.AWS.NET.01", "logicHash": "JiUx1BQqhxV9pvK+hiNJCw", "isDefault": false }, "testPassed": true }, . . . . . { "error": null, "testedCount": 1, "relevantCount": 1, "nonComplyingCount": 0, "exclusionStats": { "testedCount": 0, "relevantCount": 0, "nonComplyingCount": 0 }, "entityResults": [], "rule": { "name": "Ensure routing tables for security groups peering are \"least access\"", "severity": "High", "logic": "aws_security_group should not have ingress.cidr_block contain-any ['0.0.0.0/0'] and (ingress.from_port=0 and ingress.to_port=65535)", "description": "Once a VPC peering connection is established, routing tables must be updated to establish any connections between the peered security groups. These routes can be as specific as desired - even peering a security groups to only a single host on the other side of the connection.", "remediation": "1. Run aws ec2 describe-security-groups\n2. For each group allow ingress for 0.0.0.0/0 and ports from 0 to 65535\n2.1 Run aws ec2 delete-security-configuration --group-ids <group>", "complianceTag": "Network Security", "domain": "", "priority": "", "controlTitle": "", "ruleId": "D9.TF.AWS.NET.04", "logicHash": "rwHuW7JlcUDnYiAQL+lhPA", "isDefault": false }, "testPassed": true }, . . . . . { "error": null, "testedCount": 1, "relevantCount": 1, "nonComplyingCount": 0, "exclusionStats": { "testedCount": 0, "relevantCount": 0, "nonComplyingCount": 0 }, "entityResults": [], "rule": { "name": "Ensure no security groups allow ingress from 0.0.0.0/0 to RDP (TCP:3389)", "severity": "High", "logic": "aws_security_group should not have ingress with [(from_port<=3389 and to_port>=3389) and (cidr_blocks contain ['0.0.0.0:0'] or ipv6_cidr_blocks contain ['::/0'])]", "description": "Security groups provide stateful filtering of ingress and egress network traffic to AWS resources. It is recommended that no security group allows unrestricted ingress access to remote server administration ports, such as RDP to port 3389.", "remediation": "1. Run aws ec2 describe-security-groups\n2. For each group allow ingress for 0.0.0.0/0 to SSH (port 3389/tcp)\n2.1 Run aws ec2 delete-security-configuration --group-ids <group>", "complianceTag": "Network Security", "domain": "", "priority": "", "controlTitle": "", "ruleId": "D9.TF.AWS.NET.02", "logicHash": "TBUK7gxQYDkAhAmTQGesng", "isDefault": false }, "testPassed": true }, . . . . . { "error": null, "testedCount": 0, "relevantCount": 0, "nonComplyingCount": 0, "exclusionStats": { "testedCount": 0, "relevantCount": 0, "nonComplyingCount": 0 }, "entityResults": [], "rule": { "name": "Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket", "severity": "High", "logic": "aws_s3_bucket should not have logging isEmpty()", "description": "S3 Bucket Access Logging generates a log that contains access records for each request made to your S3 bucket. An access log record contains details about the request, such as the request type, the resources specified in the request worked, and the time and date the request was processed. It is recommended that bucket access logging be enabled on the CloudTrail S3 bucket.", "remediation": "1. Get the name of the S3 bucket that CloudTrail is logging to aws cloudtrail describe-trails --query trailList[*].S3BucketName\n2. Ensure Bucket Logging is enabled aws s3api get-bucket-logging --bucket <s3_bucket_for_cloudtrail>\n3. Ensure command does not returns empty output.", "complianceTag": "Logging", "domain": "", "priority": "", "controlTitle": "", "ruleId": "D9.TF.AWS.LOG.05", "logicHash": "Z841/7ZEPBuqMMOomARnLg", "isDefault": false }, "testPassed": true } ]
今回スキャンしたテンプレートではルールセットに反する設定は含まれていませんでしたが、こんな感じで評価を行うことができます。
コンテナイメージの分析
最後にコンテナイメージのスキャンを実行します。
まず、ブレードの使い方を確認します。
$ shiftleft image-scan -h NAME image-scan DESCRIPTION source-code/image security and visibility into the risk analysis of projects SYNOPSIS image-scan [OPTIONS] [ -s <source_folder> | -i <image_path> ] OPTIONS -s, -src, --source <string> path to source code directory -i, -img, --image <string> path to docker image tar format -t, -T, --timeout <int> scan timeout in seconds (default: 600 for source code, 900 for docker image) -x, -X, --exclude <string> path to exclude from scanning (.gitignore syntax) -d, -D, --debug debug output -j, -J, --json json output -nc, -NC, --no-cache do not take results from previous scans -np, -NP, --no-proxy do not use system proxy settings -nb, -NB, --no-blame do not use Git blame on scanned files -v, -V, --version show version -h, -H, --help show help EXAMPLE image-scan -x tests/** -x static/** -s /home/project image-scan -t 900 -i /home/image.tar
このブレードではローカルのDockerイメージをスキャンするようです。
コンテナイメージを用意する
ここでは、こちらのやられアプリを利用します。
ローカルに保存します。 ディスクの容量にはご注意ください。
docker save bkimminich/juice-shop -o juice-shop.tar
分析
スキャンしてみた結果がこちらになります。 (一部省略しています)
$ shiftleft image-scan -i juice-shop.tar -t 1800 INFO [08-12-2020 17:14:56.395] SourceGuard Scan Started! INFO [08-12-2020 17:14:59.284] Project name: juice-shop path: /tmp/SourceGuard302921902 INFO [08-12-2020 17:14:59.284] Scan ID: zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz-zzzzzz Action: BLOCK Content Findings: - ID: 10000000-0000-0000-0000-000000000004 Name: "aws_secret_access_key" Description: "Possible AWS secret access key" - SHA: 55650c62ef91cc1f928129b8d4060d899faf4d1d648b7ef4a49448fdc03562fa Path: /tmp/juice-shop/frontend/dist/frontend/vendor-es5.js - SHA: c93f89907a369302d16739ae8a885da65c2b6ecac41992a7b2072f869df47278 Payload: key:"_getAn*** Lines: [1] Packages Findings: - Package Path: /usr/local/lib/node_modules/npm/node_modules/libnpm/package.json Package Manager: npm Severity: CRITICAL - bin-links ^ 1.1.2 Severity: CRITICAL Line: 35 CVEs Findings: - ID: CWE-434 Description: The software allows the attacker to upload or transfer files of dangerous types that can be automatically processed within the product's environment. Severity: CRITICAL Last Modified: 0001-01-01T00:00:00Z - ID: CWE-61 Description: The software, when opening a file or directory, does not sufficiently account for when the file is a symbolic link that resolves to a target outside of the intended control sphere. This could allow an attacker to cause the software to operate on unauthorized files. Severity: HIGH Last Modified: 0001-01-01T00:00:00Z - ID: CWE-119 Description: The software performs operations on a memory buffer, but it can read from or write to a memory location that is outside of the intended boundary of the buffer. Severity: HIGH Last Modified: 0001-01-01T00:00:00Z - Package Path: /juice-shop/package-lock.json Package Manager: npm Severity: CRITICAL - yargs-parser 13.1.2 Severity: MEDIUM Line: 8115 CVEs Findings: - ID: CVE-2020-7608 Description: yargs-parser could be tricked into adding or modifying properties of Object.prototype using a "__proto__" payload. Severity: MEDIUM Last Modified: 2020-06-05T15:23:00Z - class-utils 0.3.6 Severity: UNKNOWN Line: 1579 CVEs Findings: - ID: CVE-2008-5856 Description: Directory traversal vulnerability in scripts/export.php in ClaSS before 0.8.61 allows remote attackers to read arbitrary files via directory traversal sequences in the ftype parameter. Severity: UNKNOWN Last Modified: 2017-09-29T01:32:00Z . . . . . - Package Path: /usr/local/lib/node_modules/npm/node_modules/boxen/package.json Package Manager: npm Severity: Please see full analysis: https://portal.checkpoint.com/Dashboard/SourceGuard#/scan/image/zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz-zzzzzz
アクセスキーのハードコードの他、パッケージの脆弱性についての指摘が表示されました。
まとめ
とりあえず機能をひと通り利用してみました。 CI/CD環境への組み込みは非常に簡単に実現できそうですね。 肝心の検出精度やどのような脆弱性の検出をサポートしているかについては情報があまりなかったので、一般提供開始時に改めて確認してみたいと思います。
インフラのプロビジョニングやアプリケーションのデプロイ前に脆弱性を検出するというアプローチは今後より一般化していくと思います。 機会があればこういったアプローチを提案に盛り込んでいきたいと思います。
現場からは以上です。