From 9a3476501355b14601a4cdd0e99f9f36f5f4d41f Mon Sep 17 00:00:00 2001 From: Kentaro Ohkouchi Date: Thu, 25 Feb 2021 16:42:57 +0900 Subject: [PATCH] =?UTF-8?q?OWASP=20ZAP=E3=81=AE=E8=A8=AD=E5=AE=9A=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - README に詳細な手順を追加 - 各種 context の追加 - HTTP_URL, HTTPS_URL に ZAP Proxy のホスト名を使用するよう修正 - CSRFトークン, セッションIDの修正 --- docker-compose.owaspzap.yml | 5 ++ dockerbuild/docker-php-entrypoint | 70 +++++++++++++++++++++++++++ dockerbuild/php.ini | 5 ++ zap/README.md | 56 ++++++++++++++++++++++ zap/admin.context | 79 ++++++++++++++++++++++++++++++ zap/front_guest.context | 71 +++++++++++++++++++++++++++ zap/front_login.context | 80 +++++++++++++++++++++++++++++++ zap/options.properties | 42 +--------------- 8 files changed, 368 insertions(+), 40 deletions(-) create mode 100755 dockerbuild/docker-php-entrypoint create mode 100644 dockerbuild/php.ini create mode 100644 zap/admin.context create mode 100644 zap/front_guest.context create mode 100644 zap/front_login.context diff --git a/docker-compose.owaspzap.yml b/docker-compose.owaspzap.yml index 220d7802c6..dac730765a 100644 --- a/docker-compose.owaspzap.yml +++ b/docker-compose.owaspzap.yml @@ -1,6 +1,11 @@ version: "3" services: + ec-cube: + environment: + # Use Zap Proxy + HTTP_URL: https://ec-cube/ + HTTPS_URL: https://ec-cube/ zap: build: context: ./zap diff --git a/dockerbuild/docker-php-entrypoint b/dockerbuild/docker-php-entrypoint new file mode 100755 index 0000000000..d09f34755c --- /dev/null +++ b/dockerbuild/docker-php-entrypoint @@ -0,0 +1,70 @@ +#!/bin/sh +set -e + +BASE="/var/www/app" + +rm -f /usr/local/etc/php/conf.d/docker.ini + +# php config +if [ -n "${TZ}" ]; then + echo "date.timezone = ${TZ}" >> /usr/local/etc/php/conf.d/docker.ini +fi + +if [ -n "${PHP_MEMORY_LIMIT}" ]; then + echo "memory_limit = ${PHP_MEMORY_LIMIT}" >> /usr/local/etc/php/conf.d/docker.ini +fi + +PHP_DISPLAY_ERRORS=${PHP_DISPLAY_ERRORS:-Off} +if [ -n "${PHP_DISPLAY_ERRORS}" ]; then + echo "display_errors = ${PHP_DISPLAY_ERRORS}" >> /usr/local/etc/php/conf.d/docker.ini +fi + +if [ -n "${PHP_MAX_INPUT_VARS}" ]; then + echo "max_input_vars = ${PHP_MAX_INPUT_VARS}" >> /usr/local/etc/php/conf.d/docker.ini +fi + +PHP_EXPOSE_PHP=${PHP_EXPOSE_PHP:-Off} +if [ -n "${PHP_EXPOSE_PHP}" ]; then + echo "expose_php = ${PHP_EXPOSE_PHP}" >> /usr/local/etc/php/conf.d/docker.ini +fi + +if [ -n "${PHP_MAX_EXECUTION_TIME}" ]; then + echo "max_execution_time = ${PHP_MAX_EXECUTION_TIME}" >> /usr/local/etc/php/conf.d/docker.ini +fi + +if [ -n "${PHP_POST_MAX_SIZE}" ]; then + echo "post_max_size = ${PHP_POST_MAX_SIZE}" >> /usr/local/etc/php/conf.d/docker.ini +fi + +if [ -n "${PHP_UPLOAD_MAX_FILESIZE}" ]; then + echo "upload_max_filesize = ${PHP_UPLOAD_MAX_FILESIZE}" >> /usr/local/etc/php/conf.d/docker.ini +fi + + +# Configure OPcache for Maximum Performance +if [ -n "${PHP_OPCACHE_MEMORY_CONSUMPTION}" ]; then + echo "opcache.memory_consumption = ${PHP_OPCACHE_MEMORY_CONSUMPTION}" >> /usr/local/etc/php/conf.d/docker.ini +fi +if [ -n "${PHP_OPCACHE_MAX_ACCELERATED_FILES}" ]; then + echo "opcache.max_accelerated_files = ${PHP_OPCACHE_MAX_ACCELERATED_FILES}" >> /usr/local/etc/php/conf.d/docker.ini +fi + +# Don't Check PHP Files Timestamps +if [ -n "${PHP_OPCACHE_VALIDATE_TIMESTAMPS}" ]; then + echo "opcache.validate_timestamps = ${PHP_OPCACHE_VALIDATE_TIMESTAMPS}" >> /usr/local/etc/php/conf.d/docker.ini +fi + +# Configure the PHP realpath Cache +if [ -n "${PHP_REALPATH_CACHE_SIZE}" ]; then + echo "realpath_cache_size = ${PHP_REALPATH_CACHE_SIZE}" >> /usr/local/etc/php/conf.d/docker.ini +fi +if [ -n "${PHP_REALPATH_CACHE_TTL}" ]; then + echo "realpath_cache_ttl = ${PHP_REALPATH_CACHE_TTL}" >> /usr/local/etc/php/conf.d/docker.ini +fi + + +# first arg is `-f` or `--some-option` +if [ "${1#-}" != "$1" ]; then + set -- apache2-foreground "$@" +fi +exec "$@" diff --git a/dockerbuild/php.ini b/dockerbuild/php.ini new file mode 100644 index 0000000000..8482f7ea93 --- /dev/null +++ b/dockerbuild/php.ini @@ -0,0 +1,5 @@ +; Optimizations for Symfony, as documented on http://symfony.com/doc/current/performance.html +opcache.max_accelerated_files = 20000 +opcache.memory_consumption=256 +realpath_cache_size = 4096K +realpath_cache_ttl = 600 diff --git a/zap/README.md b/zap/README.md index 1841a51fe9..c3fb4f3de8 100644 --- a/zap/README.md +++ b/zap/README.md @@ -4,3 +4,59 @@ 必ずローカル環境の Docker でのみ使用し、稼動中のサイトには決して使用しないでください。 意図せずデータが更新されたり、削除される場合があります。 テストは自己責任で実施し、株式会社イーシーキューブ及び、関連する開発コミュニティは一切の責任を負いかねますのであらかじめご了承ください。 + +## Quick Start + +**Attention!** 意図しない外部サイトへの攻撃を防ぐため、 OWASP ZAP は必ず **プロテクトモード** で使用してください + +1. docker-compose を使用して EC-CUBE をインストールします + ```shell + # MySQL を使用する例 + docker-compose -f docker-compose.yml -f docker-compose.mysql.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml up -d + # PostgreSQL を使用する例 + docker-compose -f docker-compose.yml -f docker-compose.pgsql.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml up -d +1. テスト用のデータを生成します ``` + ```shell + # MySQL を使用する例 + ## require-dev のパッケージをインストールしておく + docker-compose -f docker-compose.yml -f docker-compose.mysql.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml exec ec-cube composer install + ## ダミーデータを生成 + docker-compose -f docker-compose.yml -f docker-compose.mysql.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml exec ec-cube php ctests/acceptance/_bootstrap.php + ## メールアドレスを zap_user@example.com に変更 + docker-compose -f docker-compose.yml -f docker-compose.mysql.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml exec mysql mysql --user=eccube_db_user --password=password eccube_db -e "UPDATE dtb_customer SET email = 'zap_user@example.com' WHERE customer_id = (SELECT customer_id FROM (SELECT MAX(customer_id) FROM dtb_customer WHERE status = 2 AND del_flg = 0) AS A);" + + # PostgreSQL を使用する例 + ## require-dev のパッケージをインストールしておく + docker-compose -f docker-compose.yml -f docker-compose.pgsql.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml exec ec-cube composer install + ## ダミーデータを生成 + docker-compose -f docker-compose.yml -f docker-compose.pgsql.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml exec ec-cube php ctests/acceptance/_bootstrap.php + ## メールアドレスを zap_user@example.com に変更 + docker-compose -f docker-compose.yml -f docker-compose.pgsql.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml exec postgres psql --user=eccube_db_user eccube_db -c "UPDATE dtb_customer SET email = 'zap_user@example.com' WHERE customer_id = (SELECT MAX(customer_id) FROM dtb_customer WHERE status = 2 AND del_flg = 0);" + ``` +1. OWASP ZAP を起動します。Firefox 以外のブラウザで `http://localhost:8081/zap/` へアクセスすると、OWASP ZAP の管理画面が表示されます +1. Firefox を起動し、設定→ネットワーク設定→接続設定からプロキシーの設定をします + - **手動でプロキシーを設定する** を選択 + - HTTPプロキシー: localhost, ポート: 8090 + - **このプロキシーを FTP と HTTPS でも使用する** にチェックを入れる +1. Firefox に SSL ルート CA 証明書をインポートします + - ローカルの `path/to/ec-cube/zap/owasp_zap_root_ca.cer` に証明書が生成されています + - 設定→プライバシーとセキュリティ→証明書→証明書を表示から証明書マネージャーを表示 + - 認証局証明書→読み込むをクリックし、 `path/to/ec-cube/zap/owasp_zap_root_ca.cer` を選択 + - **この認証局によるウェブサイトの識別を信頼する** にチェックを入れ、 OK をクリック、設定を閉じます +1. Firefox で `https://ec-cube/` へアクセスし、プロキシー経由で EC-CUBE にアクセスできるのを確認します。 +1. コンテキストをインポートします。 + ```shell + ## 管理画面用 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml exec zap zap-cli -p 8090 context import /zap/wrk/admin.context + ## フロント(ログイン用) + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml exec zap zap-cli -p 8090 context import /zap/wrk/front_login.context + ## フロント(ゲスト用) + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.owaspzap.yml exec zap zap-cli -p 8090 context import /zap/wrk/front_guest.context + ``` + **Note:** *複数のコンテキストを同時にインポートすると、セッションが競合してログインできなくなる場合があるため注意* + {: .notice--warning} +1. OWASP ZAP のツールバーにある [Forced User Mode On/Off ボタン](https://www.zaproxy.org/docs/desktop/ui/tltoolbar/#--forced-user-mode-on--off) を ON にすると、OWASP ZAP の自動ログインが有効になり、ユーザーログイン中のテストが有効になります +1. テストを実施します + 1. Firefox でページを巡回(手動探索)します + 1. 手動探索して検出された URL に対して動的スキャンを実施します + 1. アラートの検出を確認します diff --git a/zap/admin.context b/zap/admin.context new file mode 100644 index 0000000000..22cc048a20 --- /dev/null +++ b/zap/admin.context @@ -0,0 +1,79 @@ + + + + admin + + true + \Qhttps://ec-cube/admin\E.* + + Db.MySQL + Db.PostgreSQL + Db.SQLite + Language.JavaScript + Language.PHP + OS.Linux + OS.MacOS + SCM.Git + WS.Apache + Db + Db.CouchDB + Db.Firebird + Db.HypersonicSQL + Db.IBM DB2 + Db.Microsoft Access + Db.Microsoft SQL Server + Db.MongoDB + Db.Oracle + Db.SAP MaxDB + Db.Sybase + Language + Language.ASP + Language.C + Language.JSP/Servlet + Language.Java + Language.Python + Language.Ruby + Language.XML + OS + OS.Windows + SCM + SCM.SVN + WS + WS.IIS + WS.Tomcat + + + org.zaproxy.zap.model.StandardParameterParser + {"kvps":"&","kvs":"=","struct":[]} + + + org.zaproxy.zap.model.StandardParameterParser + {"kvps":"&","kvs":"=","struct":[]} + + + 2 + \Qログイン認証の有効期限切れの可能性があります\E +
+ https://ec-cube/admin/index.php + login_id={%username%}&password={%password%}&transactionid=xxx&mode=login + https://ec-cube/admin/index.php +
+
+ + 55;true;YWRtaW4=;2;YWRtaW4=~cGFzc3dvcmQ=~ + + 55 + + 0 + + + 0 + +
+ + AND + -1 + + + + diff --git a/zap/front_guest.context b/zap/front_guest.context new file mode 100644 index 0000000000..ea088c047e --- /dev/null +++ b/zap/front_guest.context @@ -0,0 +1,71 @@ + + + + front_guest + + true + \Qhttps://ec-cube\E.* + \Qhttps://ec-cube/admin\E.* + + Db.MySQL + Db.PostgreSQL + Db.SQLite + Language.JavaScript + Language.PHP + OS.Linux + OS.MacOS + SCM.Git + WS.Apache + Db + Db.CouchDB + Db.Firebird + Db.HypersonicSQL + Db.IBM DB2 + Db.Microsoft Access + Db.Microsoft SQL Server + Db.MongoDB + Db.Oracle + Db.SAP MaxDB + Db.Sybase + Language + Language.ASP + Language.C + Language.JSP/Servlet + Language.Java + Language.Python + Language.Ruby + Language.XML + OS + OS.Windows + SCM + SCM.SVN + WS + WS.IIS + WS.Tomcat + + + org.zaproxy.zap.model.StandardParameterParser + {"kvps":"&","kvs":"=","struct":[]} + + + org.zaproxy.zap.model.StandardParameterParser + {"kvps":"&","kvs":"=","struct":[]} + + + 0 + + -1 + + 0 + + + 0 + +
+ + AND + -1 + + + + diff --git a/zap/front_login.context b/zap/front_login.context new file mode 100644 index 0000000000..0a2e1b77e5 --- /dev/null +++ b/zap/front_login.context @@ -0,0 +1,80 @@ + + + + front_login + + true + \Qhttps://ec-cube\E.* + \Qhttps://ec-cube/admin\E.* + + Db.MySQL + Db.PostgreSQL + Db.SQLite + Language.JavaScript + Language.PHP + OS.Linux + OS.MacOS + SCM.Git + WS.Apache + Db + Db.CouchDB + Db.Firebird + Db.HypersonicSQL + Db.IBM DB2 + Db.Microsoft Access + Db.Microsoft SQL Server + Db.MongoDB + Db.Oracle + Db.SAP MaxDB + Db.Sybase + Language + Language.ASP + Language.C + Language.JSP/Servlet + Language.Java + Language.Python + Language.Ruby + Language.XML + OS + OS.Windows + SCM + SCM.SVN + WS + WS.IIS + WS.Tomcat + + + org.zaproxy.zap.model.StandardParameterParser + {"kvps":"&","kvs":"=","struct":[]} + + + org.zaproxy.zap.model.StandardParameterParser + {"kvps":"&","kvs":"=","struct":[]} + + + 2 + \Qalt="ログイン"\E +
+ https://ec-cube/frontparts/login_check.php + login_email={%username%}&login_pass={%password%}&transactionid=xxx&mode=login&url=/mypage/login.php + https://ec-cube/mypage/ +
+
+ + 110;true;emFwX3VzZXI=;2;emFwX3VzZXJAZXhhbXBsZS5jb20=~cGFzc3dvcmQ=~ + + 110 + + 0 + + + 0 + +
+ + AND + -1 + + + + diff --git a/zap/options.properties b/zap/options.properties index fa8445ac46..5cdcc9c9d7 100644 --- a/zap/options.properties +++ b/zap/options.properties @@ -1,45 +1,7 @@ view.locale=ja_JP api.disablekey=true fuzz.defaultCategoryName=dirbuster -anticsrf.tokens.token\(0\).name=_csrf_token +anticsrf.tokens.token\(0\).name=transactionid anticsrf.tokens.token\(0\).enabled=true -anticsrf.tokens.token\(1\).name=_csrf -anticsrf.tokens.token\(1\).enabled=true -anticsrf.tokens.token\(2\).name=_token -anticsrf.tokens.token\(2\).enabled=true -anticsrf.tokens.token\(3\).name=_shopping_order[_token] -anticsrf.tokens.token\(3\).enabled=true -anticsrf.tokens.token\(4\).name=form[_token] -anticsrf.tokens.token\(4\).enabled=true -anticsrf.tokens.token\(5\).name=shopping_shipping[_token] -anticsrf.tokens.token\(5\).enabled=true -httpsessions.tokens.token\(0\).name=eccube +httpsessions.tokens.token\(0\).name=ecsessid httpsessions.tokens.token\(0\).enabled=true -httpsessions.tokens.token\(1\).name=ecsessid -httpsessions.tokens.token\(1\).enabled=true -httpsessions.tokens.token\(2\).name=phpsessid -httpsessions.tokens.token\(2\).enabled=true -## Filtering out false positives in PATH Traversal -globalalertfilter.filters.filter\(0\).ruleid=6 -globalalertfilter.filters.filter\(0\).newrisk=-1 -globalalertfilter.filters.filter\(0\).url=https://ec-cube/products/add_cart/[0-9]+ -globalalertfilter.filters.filter\(0\).urlregex=true -globalalertfilter.filters.filter\(0\).param= -globalalertfilter.filters.filter\(0\).paramregex=false -globalalertfilter.filters.filter\(0\).attack= -globalalertfilter.filters.filter\(0\).attackregex=false -globalalertfilter.filters.filter\(0\).evidence= -globalalertfilter.filters.filter\(0\).evidenceregex=false -globalalertfilter.filters.filter\(0\).enabled=true -## Filtering out false positives in SQL Injection -globalalertfilter.filters.filter\(1\).ruleid=40018 -globalalertfilter.filters.filter\(1\).newrisk=-1 -globalalertfilter.filters.filter\(1\).url=https://ec-cube/entry -globalalertfilter.filters.filter\(1\).urlregex=false -globalalertfilter.filters.filter\(1\).param=mode -globalalertfilter.filters.filter\(1\).paramregex=false -globalalertfilter.filters.filter\(1\).attack=confirm OR 1=1 -- -globalalertfilter.filters.filter\(1\).attackregex=false -globalalertfilter.filters.filter\(1\).evidence= -globalalertfilter.filters.filter\(1\).evidenceregex=false -globalalertfilter.filters.filter\(1\).enabled=true