├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── auth-tests.yml │ ├── postprocess-ssp-telemetry.yml │ ├── record-ssp-stats.yml │ ├── update-website-stats.yml │ ├── update-zaptest-docker.yml │ ├── zap-vs-crawlmaze.yml │ ├── zap-vs-firingrange.yml │ ├── zap-vs-juiceshop.yml │ ├── zap-vs-owasp-benchmark.yml │ ├── zap-vs-ssti.yml │ ├── zap-vs-vulnerableapp.yml │ ├── zap-vs-wavsep-live.yml │ ├── zap-vs-wavsep-st-high.yml │ ├── zap-vs-wavsep.yml │ └── zap-vs-webseclab.yml ├── .gitignore ├── LICENSE ├── README.md ├── commit-i18n.sh ├── count-addon-downloads.py ├── count-zap-downloads.py ├── crontab.i18n ├── crontab.test ├── dockerfile ├── download-commit-update-i18n.sh ├── download-i18n.sh ├── init-repos.sh ├── pre-scan-prep.sh ├── raise-issue.py ├── record-stats.sh ├── scans ├── auth │ ├── README.md │ ├── auth_plan_tests.sh │ ├── bba-auth-test.yaml │ ├── dev_zap_test.sh │ └── plans_and_scripts │ │ ├── aspnet │ │ └── config │ │ ├── authtestcomplex │ │ ├── bbaplus.yaml │ │ └── config │ │ ├── authtestdelay │ │ ├── bbaplus.yaml │ │ └── config │ │ ├── authtestmulti │ │ ├── bbaplus.yaml │ │ └── config.disabled │ │ ├── authtestsimple │ │ ├── bbaplus.yaml │ │ └── config │ │ ├── authtesttotp │ │ ├── bbaplus.yaml │ │ └── config │ │ ├── bluesky │ │ ├── config │ │ └── notes.txt │ │ ├── ctflearn │ │ ├── config │ │ └── notes.txt │ │ ├── ginnjuice │ │ └── config │ │ ├── hackyourself │ │ └── config │ │ ├── infosecex │ │ ├── config │ │ └── notes.txt │ │ ├── insta │ │ ├── config │ │ └── notes.txt │ │ ├── linkedin │ │ └── config │ │ ├── mozbugz │ │ └── config │ │ ├── phpspark │ │ └── config │ │ ├── reddit │ │ └── config │ │ ├── spotify │ │ └── config.local │ │ ├── testasp │ │ └── config │ │ ├── testfire │ │ ├── bbaplus.yaml │ │ ├── config │ │ ├── csa.yaml │ │ ├── notes.txt │ │ └── testfire.zst │ │ ├── testhtml5 │ │ └── config │ │ ├── testphp │ │ ├── config │ │ └── notes.txt │ │ ├── webappsec │ │ ├── config.disabled │ │ └── note │ │ ├── wikipedia │ │ ├── config │ │ └── notes.txt │ │ └── zoom │ │ ├── config │ │ └── notes.txt ├── benchmark │ ├── benchmark-scorer.js │ └── cmdi │ │ ├── af-plan.yaml │ │ └── variant.js ├── crawlmaze │ ├── crawl-maze-score.js │ └── crawl-maze.yaml ├── firingrange │ ├── README.md │ ├── firing-range-score-main.js │ ├── fr-clickjacking.js │ ├── fr-clickjacking.yaml │ ├── fr-escape.js │ ├── fr-escape.yaml │ ├── fr-leakedcookie.js │ ├── fr-leakedcookie.yaml │ ├── fr-mixedcontent.js │ ├── fr-mixedcontent.yaml │ ├── fr-reflected.js │ ├── fr-reflected.yaml │ ├── fr-remoteinclude.js │ ├── fr-remoteinclude.yaml │ ├── fr-reverseclickjacking.js │ └── fr-reverseclickjacking.yaml ├── juiceshop │ ├── juice-shop-score.js │ └── juice-shop.yaml ├── ssti │ ├── ssti-score-main.js │ ├── ssti.sh │ └── ssti.yaml └── webseclab │ ├── ScoreWebSecLab.js │ └── webseclab.yaml ├── stats ├── bitly.py ├── docker.py ├── ghcr.py ├── github.py ├── group_count.gs ├── groups.py ├── stats.py ├── tel_postprocess.py ├── utils.py ├── website_stats2.py └── zap_services.py ├── stop-delete-docker.sh ├── tiptweets ├── README.md ├── rndtweet.py ├── rndtweetwrapper.sh └── tweets.txt ├── update-repos.sh ├── vulnerableApp ├── vulnerableApp_score.py ├── vulnerableApp_spider_scan.py └── zap-vs-vulnerableApp.sh ├── wavsep ├── wavsep_score.py ├── wavsep_spider_scan.py └── zap-vs-wavsep-1.5.sh ├── wivet ├── wivet-spider-ajax.py └── zap-vs-wivet.sh └── zap-backup-test.py /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | *.asp text 4 | *.aspx text 5 | *.c text 6 | *.gradle text 7 | *.gradle.kts text 8 | *.gs text 9 | *.i18n text 10 | *.java text 11 | *.js text 12 | *.jsp text 13 | *.md text 14 | *.php text 15 | *.pl text 16 | *.properties text 17 | *.py text 18 | *.sh text 19 | *.test text 20 | *.txt text 21 | *.xml text 22 | *.yaml text 23 | *.yml text 24 | *.zst text 25 | 26 | *.bat eol=crlf 27 | LICENSE text 28 | 29 | *.jar binary 30 | *.png binary 31 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | groups: 8 | gha: 9 | applies-to: version-updates 10 | patterns: 11 | - "*" 12 | -------------------------------------------------------------------------------- /.github/workflows/auth-tests.yml: -------------------------------------------------------------------------------- 1 | name: Run Auth Tests 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | # daily at 03:10 6 | - cron: '10 3 * * *' 7 | 8 | jobs: 9 | publish: 10 | name: Authentication Tests 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | with: 16 | persist-credentials: false 17 | - name: Pull nightly image 18 | run: docker pull ghcr.io/zaproxy/zaproxy:nightly 19 | - name: Authentication plan tests 20 | id: "test-auth-plans" 21 | if: ${{ ! cancelled() }} 22 | env: 23 | AUTH_SCANS_CREDS: ${{ secrets.AUTH_SCANS_CREDS }} 24 | run: | 25 | echo "$AUTH_SCANS_CREDS" | tee -a scans/auth/all_vars.env > /dev/null 26 | chmod -R a+w $(pwd) 27 | docker run --rm -v $(pwd):/zap/wrk/:rw --env-file scans/auth/all_vars.env -t zaproxy/zap-nightly /zap/wrk/scans/auth/auth_plan_tests.sh 28 | echo "\`\`\`yaml" >> $GITHUB_STEP_SUMMARY 29 | cat output/output.yml >> $GITHUB_STEP_SUMMARY 30 | echo "\`\`\`" >> $GITHUB_STEP_SUMMARY 31 | - name: Attach result 32 | uses: actions/upload-artifact@v4 33 | with: 34 | path: output/output.yml 35 | - name: Build Feature Branch and Raise PR 36 | if: ${{ ! cancelled() }} 37 | run: | 38 | # Setup git details 39 | export GITHUB_USER=zapbot 40 | git config --global user.email "12745184+zapbot@users.noreply.github.com" 41 | git config --global user.name $GITHUB_USER 42 | # Clone destination repo 43 | git clone -o upstream https://github.com/zaproxy/zaproxy-website.git 44 | cd zaproxy-website 45 | git remote add origin https://github.com/$GITHUB_USER/zaproxy-website.git 46 | # Setup env vars for later 47 | BRANCH="auth-tests-update" 48 | export GITHUB_TOKEN=${{ secrets.ZAPBOT_TOKEN }} 49 | # Build the feature branch 50 | git checkout -b $BRANCH 51 | cp -f ../output/output.yml site/data/scans/auth/output.yml 52 | ## Update the index to be sure git is aware of changes 53 | git update-index -q --refresh 54 | ## If there are changes: comment, commit, PR 55 | if ! git diff-index --quiet HEAD --; then 56 | gh repo set-default zaproxy/zaproxy-website 57 | git remote set-url origin https://$GITHUB_USER:$GITHUB_TOKEN@github.com/$GITHUB_USER/zaproxy-website.git 58 | git add . 59 | git commit -sm 'Authentication Tests Update' 60 | git push -u origin $BRANCH -f 61 | gh pr view --json mergedAt|jq -e '.mergedAt' && gh pr create -f 62 | fi 63 | -------------------------------------------------------------------------------- /.github/workflows/postprocess-ssp-telemetry.yml: -------------------------------------------------------------------------------- 1 | name: Post process the ZAP Telemetry data in SSP 2 | 3 | on: 4 | schedule: 5 | - cron: '30 * * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | record_stats: 10 | name: Post process the ZAP Telemetry data 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Setup Python 14 | uses: actions/setup-python@v5 15 | with: 16 | python-version: '3.x' 17 | - name: Clone zap-mgmt-scripts 18 | run: | 19 | # Setup git details 20 | export GITHUB_USER=zapbot 21 | export GITHUB_TOKEN=${{ secrets.ZAPBOT_TOKEN }} 22 | git config --global user.email "12745184+zapbot@users.noreply.github.com" 23 | git config --global user.name $GITHUB_USER 24 | git clone https://github.com/$GITHUB_USER/zap-mgmt-scripts.git 25 | 26 | - name: Sync the Stats 27 | run: | 28 | python -m pip install requests 29 | # Set up AWS CLI 30 | export AWSCLI_SSP_ACCESS=${{ secrets.AWSCLI_SSP_ACCESS }} 31 | export AWSCLI_SSP_SECRET=${{ secrets.AWSCLI_SSP_SECRET }} 32 | python -m pip install awscli 33 | mkdir ~/.aws 34 | echo "[default]" > ~/.aws/config 35 | echo "region = us-east-2" >> ~/.aws/config 36 | echo "[default]" > ~/.aws/credentials 37 | echo "aws_access_key_id = $AWSCLI_SSP_ACCESS" >> ~/.aws/credentials 38 | echo "aws_secret_access_key = $AWSCLI_SSP_SECRET" >> ~/.aws/credentials 39 | 40 | cd zap-mgmt-scripts/stats 41 | 42 | # The telemetry/raw directory should just contain unprocessed files so remain small 43 | # Move the current files so we don't delete any that come in while we are processing the current ones 44 | aws s3 mv s3://ssp-project-zap/telemetry/raw/ s3://ssp-project-zap/telemetry/process/ --recursive 45 | aws s3 sync s3://ssp-project-zap/telemetry/process/ telemetry/raw/ 46 | python3 tel_postprocess.py 47 | aws s3 mv telemetry/ s3://ssp-project-zap/telemetry/ --recursive 48 | aws s3 sync telemetry/raw/ s3://ssp-project-zap/telemetry/process/ --delete 49 | 50 | -------------------------------------------------------------------------------- /.github/workflows/record-ssp-stats.yml: -------------------------------------------------------------------------------- 1 | name: Collect Daily Stats in SSP 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | record_stats: 10 | name: Collect Daily SSP Stats 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Setup Python 14 | uses: actions/setup-python@v5 15 | with: 16 | python-version: '3.x' 17 | 18 | - name: Set up env 19 | run: | 20 | python -m pip install requests 21 | 22 | # Set up AWS CLI 23 | export AWSCLI_SSP_ACCESS=${{ secrets.AWSCLI_SSP_ACCESS }} 24 | export AWSCLI_SSP_SECRET=${{ secrets.AWSCLI_SSP_SECRET }} 25 | python -m pip install awscli 26 | mkdir ~/.aws 27 | echo "[default]" > ~/.aws/config 28 | echo "region = us-east-2" >> ~/.aws/config 29 | echo "[default]" > ~/.aws/credentials 30 | echo "aws_access_key_id = $AWSCLI_SSP_ACCESS" >> ~/.aws/credentials 31 | echo "aws_secret_access_key = $AWSCLI_SSP_SECRET" >> ~/.aws/credentials 32 | 33 | - name: Clone zap-mgmt-scripts 34 | run: | 35 | # Setup git details 36 | export GITHUB_USER=zapbot 37 | export GITHUB_TOKEN=${{ secrets.ZAPBOT_TOKEN }} 38 | git config --global user.email "12745184+zapbot@users.noreply.github.com" 39 | git config --global user.name $GITHUB_USER 40 | git clone https://github.com/$GITHUB_USER/zap-mgmt-scripts.git 41 | 42 | cp -R zap-mgmt-scripts/ master 43 | cp -R zap-mgmt-scripts/ gh-pages 44 | cd gh-pages 45 | git checkout gh-pages 46 | git remote set-url origin https://$GITHUB_USER:$GITHUB_TOKEN@github.com/$GITHUB_USER/zap-mgmt-scripts.git 47 | cd .. 48 | 49 | - name: Set envs 50 | run: | 51 | # c/o https://stackoverflow.com/questions/13168463/using-date-command-to-get-previous-current-and-next-month 52 | echo "START_MONTH=$(date +%Y-%m-1)" >> $GITHUB_ENV 53 | echo "THIS_MONTH=$(date -d '${{ env.START_MONTH }} -0 month' +%Y-%m)" >> $GITHUB_ENV 54 | echo "LAST_MONTH=$(date -d '${{ env.START_MONTH }} -1 month' +%Y-%m)" >> $GITHUB_ENV 55 | 56 | - name: Sync S3 files 57 | run: | 58 | mkdir project-zap 59 | mkdir project-zap/stats 60 | # Just sync the last 2 months worth of files 61 | echo "This month: ${{ env.THIS_MONTH }} last month: ${{ env.LAST_MONTH }}" 62 | aws s3 sync s3://ssp-project-zap/stats/ project-zap/stats/ --exclude "*" --include "*${{ env.THIS_MONTH }}*" --include "*${{ env.LAST_MONTH }}*" 63 | 64 | - name: Collect todays stats 65 | run: | 66 | export BITLY_TOKEN=${{ secrets.BITLY_TOKEN }} 67 | 68 | cd master/stats 69 | python3 stats.py collect 70 | 71 | # TODO raise an issue if not empty 72 | echo "Any errors?" 73 | cat errors.txt 74 | cd ../.. 75 | 76 | - name: Daily post process 77 | run: | 78 | cd master/stats 79 | python3 stats.py daily 80 | cd ../.. 81 | 82 | - name: Update S3 files 83 | run: | 84 | aws s3 sync project-zap/stats/ s3://ssp-project-zap/stats/ 85 | -------------------------------------------------------------------------------- /.github/workflows/update-website-stats.yml: -------------------------------------------------------------------------------- 1 | name: Update Website Stats 2 | 3 | on: 4 | schedule: 5 | # The monthly stats usually end up getting updates on the 2nd of each month 6 | - cron: '0 2 2 * *' 7 | workflow_dispatch: 8 | 9 | jobs: 10 | update_stats: 11 | name: Update Website Stats 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Setup Python 15 | uses: actions/setup-python@v5 16 | with: 17 | python-version: '3.x' 18 | 19 | - name: Set up env 20 | run: | 21 | python -m pip install requests 22 | python -m pip install awscli 23 | 24 | # Set up AWS CLI 25 | export AWSCLI_ACCESS=${{ secrets.AWSCLI_SSP_ACCESS }} 26 | export AWSCLI_SECRET=${{ secrets.AWSCLI_SSP_SECRET }} 27 | mkdir ~/.aws 28 | echo "[default]" > ~/.aws/config 29 | echo "[default]" > ~/.aws/credentials 30 | echo "aws_access_key_id = $AWSCLI_ACCESS" >> ~/.aws/credentials 31 | echo "aws_secret_access_key = $AWSCLI_SECRET" >> ~/.aws/credentials 32 | 33 | - name: Clone zap-mgmt-scripts and zaproxy-website 34 | run: | 35 | # Setup git details 36 | export GITHUB_USER=zapbot 37 | export GITHUB_TOKEN=${{ secrets.ZAPBOT_TOKEN }} 38 | git config --global user.email "12745184+zapbot@users.noreply.github.com" 39 | git config --global user.name $GITHUB_USER 40 | git config --global pull.rebase false 41 | git clone https://github.com/$GITHUB_USER/zap-mgmt-scripts.git 42 | 43 | git clone https://github.com/$GITHUB_USER/zaproxy-website.git 44 | 45 | # Update to the latest upstream 46 | cd zaproxy-website 47 | git remote set-url origin https://$GITHUB_USER:$GITHUB_TOKEN@github.com/$GITHUB_USER/zaproxy-website.git 48 | git remote add upstream https://github.com/zaproxy/zaproxy-website.git 49 | git checkout statistics 50 | git pull upstream main 51 | git reset --hard upstream/main 52 | git push origin --force 53 | 54 | - name: Sync S3 files 55 | run: | 56 | mkdir project-zap 57 | mkdir project-zap/stats 58 | # Just sync the subdirectories we need 59 | aws s3 sync s3://ssp-project-zap/stats/bitly/ project-zap/stats/bitly/ 60 | aws s3 sync s3://ssp-project-zap/stats/cfu/ project-zap/stats/cfu/ 61 | aws s3 sync s3://ssp-project-zap/stats/docker/ project-zap/stats/docker/ 62 | aws s3 sync s3://ssp-project-zap/stats/downloads/ project-zap/stats/downloads/ 63 | aws s3 sync s3://ssp-project-zap/stats/ghcr/ project-zap/stats/ghcr/ 64 | aws s3 sync s3://ssp-project-zap/stats/groups/ project-zap/stats/groups/ 65 | 66 | - name: Generate the stats data files 67 | run: | 68 | cd zap-mgmt-scripts/stats 69 | python stats.py website 70 | cd ../.. 71 | 72 | - name: Update the newer website stats 73 | run: | 74 | cd zap-mgmt-scripts/stats 75 | python website_stats2.py 76 | cd ../.. 77 | 78 | - name: Raise a PR on the website 79 | run: | 80 | cd zaproxy-website 81 | git add site/data/charts/* 82 | git commit -s -m "Updated monthly statistics" 83 | git push origin 84 | 85 | echo ${{ secrets.ZAPBOT_TOKEN }} | gh auth login --with-token 86 | gh pr create --fill 87 | -------------------------------------------------------------------------------- /.github/workflows/update-zaptest-docker.yml: -------------------------------------------------------------------------------- 1 | name: Update zaptest docker image 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | update_docker: 8 | runs-on: [ubuntu-latest] 9 | steps: 10 | - name: Update docker 11 | run: | 12 | git clone https://github.com/zapbot/zap-mgmt-scripts.git 13 | cd zap-mgmt-scripts 14 | docker login -u zapbot -p ${{ secrets.ZAPBOT_DOCKER }} 15 | docker build -t softwaresecurityproject/zap-testing -f dockerfile . 16 | docker push softwaresecurityproject/zap-testing 17 | -------------------------------------------------------------------------------- /.github/workflows/zap-vs-crawlmaze.yml: -------------------------------------------------------------------------------- 1 | name: ZAP vs Crawl Maze 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | scan: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Clone zap-mgmt-scripts and zaproxy-website 11 | run: | 12 | # Setup git details 13 | export GITHUB_USER=zapbot 14 | export GITHUB_TOKEN=${{ secrets.ZAPBOT_TOKEN }} 15 | git config --global user.email "12745184+zapbot@users.noreply.github.com" 16 | git config --global user.name $GITHUB_USER 17 | git clone https://github.com/$GITHUB_USER/zap-mgmt-scripts.git 18 | 19 | git clone https://github.com/$GITHUB_USER/zaproxy-website.git 20 | 21 | # Update to the latest upstream 22 | cd zaproxy-website 23 | git remote set-url origin https://$GITHUB_USER:$GITHUB_TOKEN@github.com/$GITHUB_USER/zaproxy-website.git 24 | git remote add upstream https://github.com/zaproxy/zaproxy-website.git 25 | git checkout -B crawlmaze 26 | git pull upstream main 27 | git reset --hard upstream/main 28 | git push --set-upstream origin crawlmaze --force 29 | 30 | - name: Scan Crawl Maze 31 | run: | 32 | cd zap-mgmt-scripts/scans/crawlmaze 33 | # Need to do this so the zap user in docker can write to the files 34 | touch all.yml zap.log 35 | chmod a+w all.yml zap.log 36 | 37 | # The first set of commands are a hack to create the zap-client-profile 38 | # as Selenium doesnt seem to allow us to do this in the ZAP Docker containers :/ 39 | 40 | docker run -v $(pwd):/zap/wrk/:rw \ 41 | -t ghcr.io/zaproxy/zaproxy:nightly sh -c \ 42 | "./zap.sh -cmd -silent -addoninstall client -autorun /zap/wrk/crawl-maze.yaml; \ 43 | cp /home/zap/.ZAP_D/zap.log /zap/wrk; \ 44 | ls -l /zap/wrk;" 45 | cp all.yml ../../../zaproxy-website/site/data/scans/crawlmaze/ 46 | ls -l 47 | 48 | - name: 'Upload zap.log' 49 | if: ${{ !cancelled() }} 50 | uses: actions/upload-artifact@v4 51 | with: 52 | name: zap.log 53 | path: ./zap.log 54 | 55 | - name: Raise a PR on the website 56 | run: | 57 | cd zaproxy-website 58 | 59 | # Update the index to be sure git is aware of changes 60 | git update-index -q --refresh 61 | ## If there are changes: comment, commit, PR 62 | if ! git diff-index --quiet HEAD --; then 63 | 64 | git add site/data/scans/crawlmaze/* 65 | git commit -s -m "Updated Crawl Maze Results" 66 | git push origin 67 | 68 | echo ${{ secrets.ZAPBOT_TOKEN }} | gh auth login --with-token 69 | gh pr create --fill 70 | 71 | fi 72 | -------------------------------------------------------------------------------- /.github/workflows/zap-vs-firingrange.yml: -------------------------------------------------------------------------------- 1 | name: ZAP vs Firing Range 2 | 3 | on: 4 | schedule: 5 | - cron: '0 2 * * *' # 2 am every day 6 | workflow_dispatch: 7 | 8 | jobs: 9 | scan: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Clone zap-mgmt-scripts and zaproxy-website 13 | run: | 14 | # Setup git details 15 | export GITHUB_USER=zapbot 16 | export GITHUB_TOKEN=${{ secrets.ZAPBOT_TOKEN }} 17 | git config --global user.email "12745184+zapbot@users.noreply.github.com" 18 | git config --global user.name $GITHUB_USER 19 | git clone https://github.com/$GITHUB_USER/zap-mgmt-scripts.git 20 | 21 | git clone https://github.com/$GITHUB_USER/zaproxy-website.git 22 | 23 | # Update to the latest upstream 24 | cd zaproxy-website 25 | git remote set-url origin https://$GITHUB_USER:$GITHUB_TOKEN@github.com/$GITHUB_USER/zaproxy-website.git 26 | git remote add upstream https://github.com/zaproxy/zaproxy-website.git 27 | git checkout -B firingrange 28 | git pull upstream main 29 | git reset --hard upstream/main 30 | git push --set-upstream origin firingrange --force 31 | 32 | - name: Scan Firing Range 33 | run: | 34 | cd zap-mgmt-scripts/scans/firingrange 35 | sections=( "escape" "mixedcontent" "reflected" "remoteinclude" "reverseclickjacking" "leakedcookie" "clickjacking") 36 | for s in "${sections[@]}" 37 | do 38 | cat fr-$s.js firing-range-score-main.js > firing-range-score.js 39 | 40 | docker run --user=root -v $(pwd):/zap/wrk/:rw -t ghcr.io/zaproxy/zaproxy:nightly zap.sh -cmd -silent -autorun /zap/wrk/fr-$s.yaml 41 | 42 | cp $s.yml ../../../zaproxy-website/site/data/scans/firingrange/ 43 | done 44 | 45 | - name: Raise a PR on the website 46 | run: | 47 | cd zaproxy-website 48 | 49 | # Update the index to be sure git is aware of changes 50 | git update-index -q --refresh 51 | ## If there are changes: comment, commit, PR 52 | if ! git diff-index --quiet HEAD --; then 53 | 54 | git add site/data/scans/firingrange/* 55 | git commit -s -m "Updated Firing Range Results" 56 | git push origin 57 | 58 | echo ${{ secrets.ZAPBOT_TOKEN }} | gh auth login --with-token 59 | gh pr create --fill 60 | 61 | fi 62 | -------------------------------------------------------------------------------- /.github/workflows/zap-vs-juiceshop.yml: -------------------------------------------------------------------------------- 1 | name: ZAP vs Juice Shop 2 | 3 | on: 4 | schedule: 5 | - cron: '30 3 * * 1' # 3:30 am every Monday 6 | workflow_dispatch: 7 | 8 | jobs: 9 | scan: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Clone zap-mgmt-scripts and zaproxy-website 13 | run: | 14 | # Setup git details 15 | export GITHUB_USER=zapbot 16 | export GITHUB_TOKEN=${{ secrets.ZAPBOT_TOKEN }} 17 | git config --global user.email "12745184+zapbot@users.noreply.github.com" 18 | git config --global user.name $GITHUB_USER 19 | git clone https://github.com/$GITHUB_USER/zap-mgmt-scripts.git 20 | 21 | git clone https://github.com/$GITHUB_USER/zaproxy-website.git 22 | 23 | # Update to the latest upstream 24 | cd zaproxy-website 25 | git remote set-url origin https://$GITHUB_USER:$GITHUB_TOKEN@github.com/$GITHUB_USER/zaproxy-website.git 26 | git remote add upstream https://github.com/zaproxy/zaproxy-website.git 27 | git checkout -B juiceshop 28 | git pull upstream main 29 | git reset --hard upstream/main 30 | git push --set-upstream origin juiceshop --force 31 | 32 | - name: Scan Juice Shop 33 | run: | 34 | # start Juice Shop 35 | docker run -d --rm -p 3000:3000 --network host bkimminich/juice-shop 36 | 37 | cd zap-mgmt-scripts/scans/juiceshop 38 | # Need to do this so the zap user in docker can write to the file 39 | touch all.yml 40 | chmod a+w all.yml 41 | docker run -v $(pwd):/zap/wrk/:rw --network host -t ghcr.io/zaproxy/zaproxy:nightly zap.sh -cmd -silent -autorun /zap/wrk/juice-shop.yaml 42 | cp all.yml ../../../zaproxy-website/site/data/scans/juiceshop/ 43 | 44 | - name: Raise a PR on the website 45 | run: | 46 | cd zaproxy-website 47 | 48 | # Update the index to be sure git is aware of changes 49 | git update-index -q --refresh 50 | ## If there are changes: comment, commit, PR 51 | if ! git diff-index --quiet HEAD --; then 52 | 53 | git add site/data/scans/juiceshop/* 54 | git commit -s -m "Updated Juice Shop Results" 55 | git push origin 56 | 57 | echo ${{ secrets.ZAPBOT_TOKEN }} | gh auth login --with-token 58 | gh pr create --fill 59 | 60 | fi 61 | -------------------------------------------------------------------------------- /.github/workflows/zap-vs-owasp-benchmark.yml: -------------------------------------------------------------------------------- 1 | name: ZAP vs OWASP Benchmark 2 | 3 | on: 4 | schedule: 5 | - cron: "0 6 * * *" # 6 am every day 6 | workflow_dispatch: 7 | 8 | jobs: 9 | scan: 10 | runs-on: ubuntu-22.04 11 | services: 12 | benchmark: 13 | image: owasp/benchmark 14 | ports: 15 | - 8443:8443 16 | options: --entrypoint runRemoteAccessibleBenchmark.sh 17 | steps: 18 | - name: Wait for the Benchmark service to be available 19 | run: | 20 | curl -k --head --retry 12 --retry-all-errors --retry-delay 5 https://localhost:8443/benchmark 21 | 22 | - name: Clone zap-mgmt-scripts and zaproxy-website 23 | run: | 24 | # Setup git details 25 | export GITHUB_USER=zapbot 26 | export GITHUB_TOKEN=${{ secrets.ZAPBOT_TOKEN }} 27 | git config --global user.email "12745184+zapbot@users.noreply.github.com" 28 | git config --global user.name $GITHUB_USER 29 | git clone https://github.com/$GITHUB_USER/zap-mgmt-scripts.git 30 | git clone https://github.com/$GITHUB_USER/zaproxy-website.git 31 | 32 | # Update to the latest upstream 33 | cd zaproxy-website 34 | git remote set-url origin https://$GITHUB_USER:$GITHUB_TOKEN@github.com/$GITHUB_USER/zaproxy-website.git 35 | git remote add upstream https://github.com/zaproxy/zaproxy-website.git 36 | git checkout -B owasp-benchmark 37 | git pull upstream main 38 | git reset --hard upstream/main 39 | git push --set-upstream origin owasp-benchmark --force 40 | 41 | - name: Scan OWASP Benchmark 42 | run: | 43 | cd zap-mgmt-scripts/scans/benchmark 44 | mkdir results 45 | sections=( "cmdi" ) 46 | for s in "${sections[@]}" 47 | do 48 | docker run --network=host --user=root -v $(pwd):/zap/wrk/:rw ghcr.io/zaproxy/zaproxy:nightly zap.sh \ 49 | -cmd -silent -config scanner.injectable=15 -autorun /zap/wrk/$s/af-plan.yaml 50 | cp results/$s.yml ../../../zaproxy-website/site/data/scans/benchmark/ 51 | done 52 | 53 | - name: Raise a PR on the website 54 | run: | 55 | cd zaproxy-website 56 | 57 | # Update the index to be sure git is aware of changes 58 | git update-index -q --refresh 59 | ## If there are changes: comment, commit, PR 60 | if ! git diff-index --quiet HEAD --; then 61 | 62 | git add site/data/scans/benchmark/* 63 | git commit -s -m "Updated OWASP Benchmark Results" 64 | git push origin 65 | 66 | echo ${{ secrets.ZAPBOT_TOKEN }} | gh auth login --with-token 67 | gh pr create --fill 68 | 69 | fi 70 | -------------------------------------------------------------------------------- /.github/workflows/zap-vs-ssti.yml: -------------------------------------------------------------------------------- 1 | name: ZAP vs SSTI 2 | 3 | on: 4 | schedule: 5 | - cron: '0 5 * * *' # 5 am every day 6 | workflow_dispatch: 7 | 8 | jobs: 9 | scan: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Clone zap-mgmt-scripts and zaproxy-website 13 | run: | 14 | # Setup git details 15 | export GITHUB_USER=zapbot 16 | export GITHUB_TOKEN=${{ secrets.ZAPBOT_TOKEN }} 17 | git config --global user.email "12745184+zapbot@users.noreply.github.com" 18 | git config --global user.name $GITHUB_USER 19 | git clone https://github.com/$GITHUB_USER/zap-mgmt-scripts.git 20 | 21 | git clone https://github.com/$GITHUB_USER/zaproxy-website.git 22 | 23 | # Update to the latest upstream 24 | cd zaproxy-website 25 | git remote set-url origin https://$GITHUB_USER:$GITHUB_TOKEN@github.com/$GITHUB_USER/zaproxy-website.git 26 | git remote add upstream https://github.com/zaproxy/zaproxy-website.git 27 | git checkout -B ssti 28 | git pull upstream main 29 | git reset --hard upstream/main 30 | git push --set-upstream origin ssti --force 31 | 32 | - name: Start V2SSTI 33 | run: | 34 | docker run -d -p 127.0.0.1:5000-5100:5000-5100 -p 127.0.0.1:6000-6100:6000-6100 -w /home d10g0mrs/websites_vuln_to_ssti sh ./start_all_services.sh 35 | 36 | - name: Scan V2SSTI 37 | run: | 38 | cd zap-mgmt-scripts/scans/ssti 39 | 40 | export file=all.yml 41 | 42 | # Need to do this so the zap user in docker can write to the file 43 | touch $file 44 | chmod a+w $file 45 | touch ssti-score.js 46 | chmod a+w ssti-score.js 47 | 48 | chmod +x ssti.sh 49 | 50 | docker run -v $(pwd):/zap/wrk/:rw --network="host" ghcr.io/zaproxy/zaproxy:nightly /zap/wrk/ssti.sh 51 | 52 | cp $file ../../../zaproxy-website/site/data/scans/ssti/ 53 | 54 | - name: Raise a PR on the website 55 | run: | 56 | cd zaproxy-website 57 | 58 | # Update the index to be sure git is aware of changes 59 | git update-index -q --refresh 60 | ## If there are changes: comment, commit, PR 61 | if ! git diff-index --quiet HEAD --; then 62 | 63 | git add site/data/scans/ssti/* 64 | git commit -s -m "Updated Vuln to SSTI Results" 65 | git push origin 66 | 67 | echo ${{ secrets.ZAPBOT_TOKEN }} | gh auth login --with-token 68 | gh pr create --fill 69 | 70 | fi 71 | -------------------------------------------------------------------------------- /.github/workflows/zap-vs-vulnerableapp.yml: -------------------------------------------------------------------------------- 1 | name: ZAP vs VulnerableApp 2 | 3 | on: 4 | workflow_dispatch: 5 | jobs: 6 | scan: 7 | runs-on: [ubuntu-latest] 8 | steps: 9 | - name: Start vulnerableApp 10 | run: docker run --rm -d -p 9090:9090 --network host --name=owasp-vulnerableapp sasanlabs/owasp-vulnerableapp:unreleased 11 | - name: Start ZAP 12 | run: docker run --rm -d -p 8090:8090 --network host ghcr.io/zaproxy/zaproxy:weekly zap-x.sh -daemon -host localhost -port 8090 -addoninstallall -addonupdate -config "api.addrs.addr.name=.*" -config api.addrs.addr.regex=true -config ajaxSpider.maxCrawlDepth=0 -config ajaxSpider.numberOfBrowsers=15 -config ajaxSpider.maxDuration=90 -config ajaxSpider.clickElemsOnce=false -config ajaxSpider.clickDefaultElems=false -config scanner.addQueryParam=true -config scanner.injectable=31 -config api.disablekey=true & 13 | - name: Run ZAP API script 14 | env: 15 | GITHUB_TOKEN: ${{ secrets.ZAPBOT_TOKEN }} 16 | run: docker run --rm --network host --env ZAPBOT_TOKEN=${{ secrets.ZAPBOT_TOKEN }} softwaresecurityproject/zap-testing ./zap-vs-vulnerableApp.sh -a -e 14 -p "St-Ins-Th-Low" -n vulnerableApp-weekly-RBJ-M-M -t "Rel, Beta, DomXSS" 17 | -------------------------------------------------------------------------------- /.github/workflows/zap-vs-wavsep-live.yml: -------------------------------------------------------------------------------- 1 | name: ZAP vs Wavsep - Live image, manual only 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | scan: 8 | runs-on: [ubuntu-latest] 9 | steps: 10 | - name: Start wavsep 11 | run: docker run --rm -d -p 8080:8080 owaspvwad/wavsep & 12 | - name: Start ZAP 13 | run: | 14 | docker run --rm -d -p 8090:8090 --network host ghcr.io/zaproxy/zaproxy:nightly zap-x.sh \ 15 | -daemon -host localhost -port 8090 -addonupdate -addoninstall domxss \ 16 | -config "api.addrs.addr.name=.*" -config api.addrs.addr.regex=true -config api.disablekey=true \ 17 | -config database.recoverylog=false -config pscans.maxBodySizeInBytes=10 & 18 | - name: Run ZAP API script 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.ZAPBOT_TOKEN }} 21 | run: | 22 | docker run --rm --network host --env ZAPBOT_TOKEN=${{ secrets.ZAPBOT_TOKEN }} softwaresecurityproject/zap-testing ./zap-vs-wavsep-1.5.sh \ 23 | -e 61 -n wavsep-1.5-live-RBJ-M-M -t "Rel, Beta, DomXSS" 24 | -------------------------------------------------------------------------------- /.github/workflows/zap-vs-wavsep-st-high.yml: -------------------------------------------------------------------------------- 1 | name: ZAP vs Wavsep, rel, beta, alpha rules, high strength 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | scan: 8 | runs-on: [ubuntu-latest] 9 | steps: 10 | - name: Start wavsep 11 | run: docker run --rm -d -p 8080:8080 owaspvwad/wavsep & 12 | - name: Start ZAP 13 | run: docker run --rm -v $(pwd):/home/zap/.ZAP_D/:rw -d -p 8090:8090 --network host ghcr.io/zaproxy/zaproxy:weekly zap-x.sh -daemon -host localhost -port 8090 -addonupdate -addoninstall ascanrulesAlpha -config "api.addrs.addr.name=.*" -config api.addrs.addr.regex=true -config api.disablekey=true & 14 | - name: Run ZAP API script 15 | env: 16 | GITHUB_TOKEN: ${{ secrets.ZAPBOT_TOKEN }} 17 | run: docker run --rm --network host --env ZAPBOT_TOKEN=${{ secrets.ZAPBOT_TOKEN }} softwaresecurityproject/zap-testing ./zap-vs-wavsep-1.5.sh -e 67 -p "St-High-Th-Med" -n "wavsep-1.5-weekly-RBA-H-M" -t "Rel, Beta, Alpha" 18 | -------------------------------------------------------------------------------- /.github/workflows/zap-vs-wavsep.yml: -------------------------------------------------------------------------------- 1 | name: ZAP vs Wavsep - Default 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | scan: 8 | runs-on: [ubuntu-latest] 9 | steps: 10 | - name: Start wavsep 11 | run: docker run --rm -d -p 8080:8080 owaspvwad/wavsep & 12 | - name: Start ZAP 13 | run: docker run --rm -d -p 8090:8090 --network host ghcr.io/zaproxy/zaproxy:weekly zap-x.sh -daemon -host localhost -port 8090 -addonupdate -addoninstall domxss -config "api.addrs.addr.name=.*" -config api.addrs.addr.regex=true -config api.disablekey=true & 14 | - name: Run ZAP API script 15 | env: 16 | GITHUB_TOKEN: ${{ secrets.ZAPBOT_TOKEN }} 17 | run: docker run --rm --network host --env ZAPBOT_TOKEN=${{ secrets.ZAPBOT_TOKEN }} softwaresecurityproject/zap-testing ./zap-vs-wavsep-1.5.sh -e 61 -n wavsep-1.5-weekly-RBJ-M-M -t "Rel, Beta, DomXSS" 18 | -------------------------------------------------------------------------------- /.github/workflows/zap-vs-webseclab.yml: -------------------------------------------------------------------------------- 1 | name: ZAP vs Webseclab 2 | 3 | on: 4 | schedule: 5 | - cron: '0 4 * * *' # 4 am every day 6 | workflow_dispatch: 7 | 8 | jobs: 9 | scan: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Clone zap-mgmt-scripts and zaproxy-website 13 | run: | 14 | # Setup git details 15 | export GITHUB_USER=zapbot 16 | export GITHUB_TOKEN=${{ secrets.ZAPBOT_TOKEN }} 17 | git config --global user.email "12745184+zapbot@users.noreply.github.com" 18 | git config --global user.name $GITHUB_USER 19 | git clone https://github.com/$GITHUB_USER/zap-mgmt-scripts.git 20 | 21 | git clone https://github.com/$GITHUB_USER/zaproxy-website.git 22 | 23 | # Update to the latest upstream 24 | cd zaproxy-website 25 | git remote set-url origin https://$GITHUB_USER:$GITHUB_TOKEN@github.com/$GITHUB_USER/zaproxy-website.git 26 | git remote add upstream https://github.com/zaproxy/zaproxy-website.git 27 | git checkout -B webseclab 28 | git pull upstream main 29 | git reset --hard upstream/main 30 | git push --set-upstream origin webseclab --force 31 | 32 | - name: Start Webseclab 33 | run: | 34 | docker run --network="host" -p 9090:9090 -d psiinon/webseclab 35 | 36 | - name: Scan Webseclab 37 | run: | 38 | cd zap-mgmt-scripts/scans/webseclab 39 | # Need to do this so the zap user in docker can write to the file 40 | touch reflected.yml 41 | chmod a+w reflected.yml 42 | docker run -v $(pwd):/zap/wrk/:rw --network="host" -t ghcr.io/zaproxy/zaproxy:nightly zap.sh -cmd -silent -autorun /zap/wrk/webseclab.yaml -config "scanner.injectable=11" -config "scanner.scanHeadersAllRequests=true" 43 | cp reflected.yml ../../../zaproxy-website/site/data/scans/webseclab/ 44 | 45 | - name: Raise a PR on the website 46 | run: | 47 | cd zaproxy-website 48 | 49 | # Update the index to be sure git is aware of changes 50 | git update-index -q --refresh 51 | ## If there are changes: comment, commit, PR 52 | if ! git diff-index --quiet HEAD --; then 53 | 54 | git add site/data/scans/webseclab/* 55 | git commit -s -m "Updated Webseclab Results" 56 | git push origin 57 | 58 | echo ${{ secrets.ZAPBOT_TOKEN }} | gh auth login --with-token 59 | gh pr create --fill 60 | 61 | fi 62 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | # ------- 3 | *.project 4 | *.settings 5 | 6 | # IDEA 7 | # ---- 8 | .idea 9 | .shelf 10 | /*.iml 11 | /*.ipr 12 | /*.iws 13 | 14 | # Workflows & scans 15 | # ------------------ 16 | output/ 17 | scans/auth/all_vars.env 18 | scans/auth/**/auth-report.json 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZAP Management Scripts 2 | This repo contains scripts for ZAP automation. 3 | 4 | The information maintained by this repo see the [ZAPbot Homepage](http://zapbot.github.io/zap-mgmt-scripts/index.html) 5 | 6 | ## ZAP Automated Tests 7 | The following instructions have been used to set up an AWS instance for running the ZAP automated tests - they will need tweaking for other environments. 8 | 9 | The current instance being used is a t2.medium running with Ubuntu trusty and 24Gb disk. 10 | 11 | From a bare bones install, as root run: 12 | * apt-get update -y 13 | * apt-get -y install python-pip 14 | * pip install zaproxy 15 | * pip install awscli 16 | * curl -sSL https://get.docker.com/ | sh 17 | * usermod -aG docker ubuntu 18 | 19 | As the user that will run the tests (default ubuntu) run: 20 | * git clone https://github.com/zapbot/zap-mgmt-scripts.git 21 | * git clone -b gh-pages --single-branch https://github.com/zapbot/zap-mgmt-scripts.git zap-mgmt-scripts_gh-pages 22 | 23 | In order to commit to the zapbot repo and to get aws sns messages the following files are also needed, for obvious reasons their contents arent given here ;) 24 | * .awssns 25 | * .gitconfig 26 | * .netrc 27 | 28 | 29 | -------------------------------------------------------------------------------- /commit-i18n.sh: -------------------------------------------------------------------------------- 1 | # Commit all of the i18n changes 2 | # Requires a ~/.netrc-api file present with valid credentials 3 | 4 | git config --global user.name "zapbot" 5 | git config --global user.email "zapbot@zaproxy.org" 6 | 7 | # Assume we're running in the zap-mgmt-scripts directory 8 | cd .. 9 | 10 | # zaproxy 11 | cd zaproxy 12 | git add src 13 | git commit -m "Latest files from Crowdin" 14 | git push origin 15 | curl --data '{ "title": "Latest files from Crowdin", "body": "Autogenerated PR from zapbot", "head": "zapbot:develop", "base": "develop" }' --netrc-file ~/.netrc-api https://api.github.com/repos/zaproxy/zaproxy/pulls 16 | cd .. 17 | 18 | # zap-extensions 19 | cd zap-extensions 20 | git add src 21 | git commit -m "Latest files from Crowdin" 22 | git push origin 23 | curl --data '{ "title": "Latest files from Crowdin", "body": "Autogenerated PR from zapbot", "head": "zapbot:master", "base": "master" }' --netrc-file ~/.netrc-api https://api.github.com/repos/zaproxy/zap-extensions/pulls 24 | cd .. 25 | 26 | # zap-extensions beta 27 | cd zap-extensions_beta 28 | git add src 29 | git commit -m "Latest files from Crowdin" 30 | git push origin 31 | curl --data '{ "title": "Latest files from Crowdin", "body": "Autogenerated PR from zapbot", "head": "zapbot:beta", "base": "beta" }' --netrc-file ~/.netrc-api https://api.github.com/repos/zaproxy/zap-extensions/pulls 32 | cd .. 33 | 34 | # zap-extensions alpha 35 | cd zap-extensions_alpha 36 | git add src 37 | git commit -m "Latest files from Crowdin" 38 | git push origin 39 | curl --data '{ "title": "Latest files from Crowdin", "body": "Autogenerated PR from zapbot", "head": "zapbot:alpha", "base": "alpha" }' --netrc-file ~/.netrc-api https://api.github.com/repos/zaproxy/zap-extensions/pulls 40 | cd .. 41 | -------------------------------------------------------------------------------- /count-addon-downloads.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # This script generates the dynamic data for http://zapbot.github.io/zap-mgmt-scripts/addons.html 3 | 4 | import glob,json,os,sys 5 | 6 | TAG = '2.7' 7 | 8 | # Number of days to chart 9 | days = 7 10 | 11 | # Maintain running totals so we can work out the differences 12 | counts = {} 13 | # The maximum number of download of each add-on over all days 14 | max = {} 15 | # The number of downloads by day+addon name 16 | downloads = {} 17 | # The dates 18 | dates = [] 19 | 20 | files = sorted(glob.glob('../zap-mgmt-scripts_gh-pages/stats/ext-releases-*')) 21 | # Need an extra day to get the right baseline 22 | files = files[-(days+1):] 23 | # Print out the column definitions 24 | sys.stdout.write(' [\'Add-on\' ') 25 | for file in files[1:]: 26 | date = file[-15:-5] 27 | sys.stdout.write(', \'' + date + '\'') 28 | dates.append(date) 29 | sys.stdout.write('],\n') 30 | 31 | for file in files: 32 | date = file[-15:-5] 33 | with open(file) as stats_file: 34 | stats = json.load(stats_file) 35 | 36 | for stat in stats: 37 | if (stat['tag_name'] == TAG): 38 | assets = {} 39 | for asset in stat['assets']: 40 | name = asset['name'] 41 | count = asset['download_count'] 42 | if (name in counts): 43 | assets[name] = (count - counts[name]) 44 | if (name in max): 45 | if (assets[name] > max[name]): 46 | # new max 47 | max[name] = assets[name] 48 | else: 49 | # first one 50 | max[name] = assets[name] 51 | else: 52 | # Baseline 53 | assets[name] = count 54 | counts[name] = count 55 | downloads[date + '-' + name] = assets[name] 56 | 57 | # Work out the top downloads 58 | top = sorted(max.items(), key=lambda x: (x[1],x[0]), reverse=True) 59 | top = top[:20] 60 | for addon in top: 61 | name = addon[0] 62 | sys.stdout.write(' [\'' + name + '\'') 63 | for date in dates: 64 | sys.stdout.write(', ') 65 | if (date + '-' + name in downloads): 66 | sys.stdout.write(str(downloads[date + '-' + name])) 67 | else: 68 | sys.stdout.write('0') 69 | sys.stdout.write('],\n') 70 | 71 | -------------------------------------------------------------------------------- /count-zap-downloads.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # This script generates the dynamic data for http://zapbot.github.io/zap-mgmt-scripts/downloads.html 3 | 4 | import glob,json,os,sys 5 | 6 | # The file names 7 | REL = 'v2.10.0' 8 | CORE = 'ZAP_2.10.0_Core.zip' 9 | CROSS = 'ZAP_2.10.0_Crossplatform.zip' 10 | LINUX = 'ZAP_2.10.0_Linux.tar.gz' 11 | UNIX = 'ZAP_2_10_0_unix.sh' 12 | MAC = 'ZAP_2.10.0.dmg' 13 | WIN32 = 'ZAP_2_10_0_windows-x32.exe' 14 | WIN64 = 'ZAP_2_10_0_windows.exe' 15 | 16 | counts = {} 17 | files = sorted(glob.glob('./stats/releases-*')) 18 | # Option to just show the last 180 days to prevent the chart getting too big 19 | files = files[-180:] 20 | for file in files: 21 | with open(file) as stats_file: 22 | stats = json.load(stats_file) 23 | 24 | if (stats['name'] == REL): 25 | assets = {} 26 | for asset in stats['assets']: 27 | name = asset['name'] 28 | count = asset['download_count'] 29 | if (name in counts): 30 | # Ignore negative numbers - can happen when files are replaced 31 | assets[name] = max((count - counts[name]), 0) 32 | else: 33 | assets[name] = count 34 | counts[name] = count 35 | if (files.index(file) == 0): 36 | # Ignore the first as its just for getting a baseline 37 | continue 38 | else: 39 | print(" ['%s', %d, %d, %d, %d, %d, %d, %d, '']," % (file[-15:-5], 40 | assets[WIN64], assets[WIN32], assets[UNIX], assets[LINUX], assets[MAC], assets[CROSS], assets[CORE])) -------------------------------------------------------------------------------- /crontab.i18n: -------------------------------------------------------------------------------- 1 | # 0 0 * * * cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./download-commit-update-i18n.sh 2 | 0 2 * * 0 cd /home/ubuntu/zap-mgmt-scripts/; tiptweets/rndtweettime.sh 3 | 0 3 1 * * zap-admin/scripts/report_addons_to_release.sh 4 | -------------------------------------------------------------------------------- /crontab.test: -------------------------------------------------------------------------------- 1 | 50 23 * * * cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./record-stats.sh 2 | # Monday - basic wavsep scans 3 | 0 11 * * 1 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:stable" -e "56" -n "wavsep-1.5-2.5.0-R-M-M" -t "Rel" -z "-addonupdate -addoninstall selenium -config database.recoverylog=false" > /home/ubuntu/wrk/test.out 4 | 0 16 * * 1 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:stable" -e "56" -n "wavsep-1.5-2.5.0-RB-M-M" -t "Rel, Beta" -z "-addoninstall ascanrulesBeta -addonupdate -config database.recoverylog=false" > /home/ubuntu/wrk/test.out 5 | 0 22 * * 1 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:weekly" -e "56" -n "wavsep-1.5-weekly-RB-M-M" -t "Rel, Beta" -z "-config database.recoverylog=false" > /home/ubuntu/wrk/test.out 6 | # Tuesday - all add-ons, Medium strength 7 | 0 11 * * 2 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:stable" -a -e "56" -n "wavsep-1.5-2.5.0-All-M-M" -t "All" -z "-addoninstallall -config database.recoverylog=false" > /home/ubuntu/wrk/test.out 8 | 0 22 * * 2 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:weekly" -a -e "56" -n "wavsep-1.5-weekly-All-M-M" -t "All" -z "-addoninstallall -config database.recoverylog=false" > /home/ubuntu/wrk/test.out 9 | # Wednesday - all add-ons, High strength 10 | 0 11 * * 3 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:stable" -a -e "66" -p "St-High-Th-Med" -n "wavsep-1.5-2.5.0-All-H-M" -t "All" -z "-addoninstallall -config database.recoverylog=false" > /home/ubuntu/wrk/test.out 11 | 0 22 * * 3 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:weekly" -a -e "66" -p "St-High-Th-Med" -n "wavsep-1.5-weekly-All-H-M" -t "All" -z "-addoninstallall -config database.recoverylog=false" > /home/ubuntu/wrk/test.out 12 | # Thursday - wivet 13 | # Dont use '-z "-addoninstall selenium -addonupdate"' until latest version of selenium works with FX 14 | 0 11 * * 4 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wivet/zap-vs-wivet.sh -d "ghcr.io/zaproxy/zaproxy:stable" -e "82" -n "wivet-2.5.0" -t "Ajax" > /home/ubuntu/wrk/test.out 15 | # Use htmlunit until latest version of selenium works with FX 16 | # 0 22 * * 4 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wivet/zap-vs-wivet.sh -d "ghcr.io/zaproxy/zaproxy:weekly" -e "82" -n "wivet-weekly" -t "Ajax" > /home/ubuntu/wrk/test.out 17 | 0 22 * * 4 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wivet/zap-vs-wivet.sh -d "ghcr.io/zaproxy/zaproxy:weekly" -e "82" -n "wivet-weekly" -t "Ajax" -z "ajaxSpider.browserId=htmlunit" > /home/ubuntu/wrk/test.out 18 | # 19 | # Friday - all add-ons, Insane strength 20 | 0 11 * * 5 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:stable" -a -e "66" -p "St-Ins-Th-Med" -n "wavsep-1.5-2.5.0-All-I-M" -t "All" -z "-addoninstallall -config database.recoverylog=false" > /home/ubuntu/wrk/test.out 21 | 0 22 * * 5 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:weekly" -a -e "66" -p "St-Ins-Th-Med" -n "wavsep-1.5-weekly-All-I-M" -t "All" -z "-addoninstallall -config database.recoverylog=false" > /home/ubuntu/wrk/test.out 22 | # Saturday - all add-ons, Low strength 23 | 0 11 * * 6 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:stable" -a -e "49" -p "St-Low-Th-Med" -n "wavsep-1.5-2.5.0-All-L-M" -t "All" -z "-addoninstallall -config database.recoverylog=false" > /home/ubuntu/wrk/test.out 24 | 0 22 * * 6 cd /home/ubuntu/zap-mgmt-scripts;/usr/bin/git pull;./stop-delete-docker.sh;sleep 30;wavsep/zap-vs-wavsep-1.5.sh -d "ghcr.io/zaproxy/zaproxy:weekly" -a -e "49" -p "St-Low-Th-Med" -n "wavsep-1.5-weekly-All-L-M" -t "All" -z "-addoninstallall -config database.recoverylog=false" > /home/ubuntu/wrk/test.out 25 | # Sunday - for now a day of rest, but in the future maybe differing thresholds? 26 | -------------------------------------------------------------------------------- /dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | LABEL maintainer="psiinon@gmail.com" 3 | 4 | ENV DEBIAN_FRONTEND noninteractive 5 | 6 | RUN apt-get update && apt-get install -q -y --fix-missing curl git python3-pip 7 | 8 | RUN pip3 install --upgrade zaproxy 9 | 10 | WORKDIR /zap 11 | 12 | copy wavsep wivet vulnerableApp /zap/ 13 | -------------------------------------------------------------------------------- /download-commit-update-i18n.sh: -------------------------------------------------------------------------------- 1 | # Runs all of the scripts required to create PRs for Crowdin changes 2 | 3 | # Assume we're running in the zap-mgmt-scripts directory 4 | 5 | ./update-repos.sh 6 | ./download-i18n.sh 7 | ./commit-i18n.sh 8 | -------------------------------------------------------------------------------- /download-i18n.sh: -------------------------------------------------------------------------------- 1 | # Trigger the Crowdin builds 2 | # Requires a ../zap-admin/build/crowdin-api-keys file present with valid credentials 3 | 4 | # Assume we're running in the zap-mgmt-scripts directory 5 | cd .. 6 | 7 | cd zap-admin/build 8 | ant -f build.xml crowdin-trigger-export-packages 9 | ant -f build.xml crowdin-download-translations 10 | 11 | -------------------------------------------------------------------------------- /init-repos.sh: -------------------------------------------------------------------------------- 1 | # Init all of the required repos 2 | # Requires a ~/.netrc file present with valid credentials 3 | 4 | # Assume we're running in the zap-mgmt-scripts directory 5 | cd .. 6 | 7 | # Clone the repos we dont need to update 8 | 9 | # Clone forks of the repos we need to update 10 | # and update the to sync with the originals 11 | # change zapbot to your user if required 12 | 13 | # zap-admin 14 | git clone https://github.com/zapbot/zap-admin.git 15 | cd zap-admin 16 | git remote add upstream https://github.com/zaproxy/zap-admin.git 17 | cd .. 18 | 19 | # zaproxy 20 | git clone https://github.com/zapbot/zaproxy.git 21 | cd zaproxy 22 | git remote add upstream https://github.com/zaproxy/zaproxy.git 23 | cd .. 24 | 25 | # zap-extensions 26 | git clone https://github.com/zapbot/zap-extensions.git 27 | cd zap-extensions 28 | git remote add upstream https://github.com/zaproxy/zap-extensions.git 29 | cd .. 30 | 31 | # zap-extensions beta 32 | git clone --branch beta https://github.com/zapbot/zap-extensions.git zap-extensions_beta 33 | cd zap-extensions_beta 34 | git remote add upstream https://github.com/zaproxy/zap-extensions.git 35 | cd .. 36 | 37 | # zap-extensions alpha 38 | git clone --branch alpha https://github.com/zapbot/zap-extensions.git zap-extensions_alpha 39 | cd zap-extensions_alpha 40 | git remote add upstream https://github.com/zaproxy/zap-extensions.git 41 | cd .. 42 | 43 | # zap-core-help 44 | git clone https://github.com/zapbot/zap-core-help.git 45 | cd zap-core-help 46 | git remote add upstream https://github.com/zaproxy/zap-core-help.git 47 | cd .. 48 | 49 | -------------------------------------------------------------------------------- /pre-scan-prep.sh: -------------------------------------------------------------------------------- 1 | # Runs all of the scripts required before scanning an app 2 | 3 | # Assume we're running in the zap-mgmt-scripts directory 4 | cd ../zaproxy 5 | /usr/bin/git pull 6 | cd .. 7 | cd zap-mgmt-scripts 8 | ./stop-delete-docker.sh 9 | -------------------------------------------------------------------------------- /raise-issue.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Raises an issue with the specified options. 5 | 6 | Usage example: 7 | 8 | ./raise-issue.py -t "Issue name" -f file -a zapbot -p changeme 9 | 10 | """ 11 | import argparse 12 | import json 13 | import requests 14 | 15 | def make_github_issue(title, owner, repo, user, password, body=None, assignee=None, milestone=None, labels=None): 16 | '''Create an issue on github.com using the given parameters.''' 17 | # Our url to create issues via POST 18 | url = 'https://api.github.com/repos/%s/%s/issues' % (owner, repo) 19 | # Create an authenticated session to create the issue 20 | session = requests.Session() 21 | session.auth = (user, password) 22 | # Create our issue 23 | issue = {'title': title, 24 | 'body': body, 25 | 'assignee': assignee} 26 | # 'milestone': milestone, 27 | # 'labels': labels} 28 | # Add the issue to our repository 29 | r = session.post(url, json.dumps(issue)) 30 | if r.status_code == 201: 31 | print('Successfully created Issue "%s"' % title) 32 | else: 33 | print('Could not create Issue "%s"' % title) 34 | print('Response:', r.content) 35 | 36 | 37 | def get_args(): 38 | parser = argparse.ArgumentParser(description=__doc__) 39 | 40 | parser.add_argument('-t', '--title', 41 | required=True, 42 | help='Issue title') 43 | 44 | parser.add_argument('-f', '--file', 45 | required=True, 46 | help='File containing the issue body') 47 | 48 | parser.add_argument('-o', '--owner', 49 | default='zapbot', 50 | help='Repo owner, e.g. zapbot') 51 | 52 | parser.add_argument('-r', '--repo', 53 | default='zap-mgmt-scripts', 54 | help='Repo, e.g. zap-mgmt-scripts') 55 | 56 | parser.add_argument('-u', '--user', 57 | default='zapbot', 58 | help='User, e.g. zapbot') 59 | 60 | parser.add_argument('-p', '--password', 61 | required=True, 62 | help='Password / credentials') 63 | 64 | parser.add_argument('-a', '--assignee', 65 | required=False, 66 | help='Assigne, e.g. zapbot') 67 | 68 | parsed_args = parser.parse_args() 69 | return vars(parsed_args) 70 | 71 | def main(): 72 | cli_args = get_args() 73 | 74 | with open(cli_args['file'], 'r') as content_file: 75 | content = content_file.read() 76 | 77 | make_github_issue(cli_args['title'], cli_args['owner'], cli_args['repo'], cli_args['user'], 78 | cli_args['password'], body=content, assignee=cli_args['assignee']) 79 | 80 | 81 | if __name__ == '__main__': 82 | main() 83 | -------------------------------------------------------------------------------- /record-stats.sh: -------------------------------------------------------------------------------- 1 | # Record the download stats 2 | 3 | git config --global push.default simple 4 | 5 | DATE=$(date --rfc-3339 date) 6 | curl https://api.github.com/repos/zaproxy/zaproxy/releases > ../zap-mgmt-scripts_gh-pages/stats/releases-${DATE}.json 7 | curl https://api.github.com/repos/zaproxy/zap-extensions/releases > ../zap-mgmt-scripts_gh-pages/stats/ext-releases-${DATE}.json 8 | 9 | # Generate the ZAP download page 10 | 11 | cat ../zap-mgmt-scripts_gh-pages/download.head > ../zap-mgmt-scripts_gh-pages/downloads.html 12 | python count-zap-downloads.py >> ../zap-mgmt-scripts_gh-pages/downloads.html 13 | cat ../zap-mgmt-scripts_gh-pages/download.tail >> ../zap-mgmt-scripts_gh-pages/downloads.html 14 | 15 | # Generate the ZAP add-ons page 16 | 17 | cat ../zap-mgmt-scripts_gh-pages/addon.head > ../zap-mgmt-scripts_gh-pages/addons.html 18 | python count-addon-downloads.py >> ../zap-mgmt-scripts_gh-pages/addons.html 19 | cat ../zap-mgmt-scripts_gh-pages/addon.tail >> ../zap-mgmt-scripts_gh-pages/addons.html 20 | 21 | cd ../zap-mgmt-scripts_gh-pages/ 22 | 23 | # Push to the repo 24 | 25 | git pull 26 | git add addons.html downloads.html stats 27 | git commit -m "Stats for ${DATE}" 28 | git push origin 29 | -------------------------------------------------------------------------------- /scans/auth/README.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | 1. Clone the repo. 4 | 1. Change directory into the repo. 5 | 1. Pull the docker image if you want/need to update: `docker pull ghcr.io/zaproxy/zaproxy:nightly` 6 | 1. Create `scans/auth/all_vars.env` with standard `key=value` pairs. Keys should be `=value`, ex: `foo_user=jsmith`, `foo_pass=demo1234` (assuming a target known as `foo`). 7 | 1. Run the tests: `docker run --rm -v $(pwd):/zap/wrk/:rw --env-file scans/auth/all_vars.env -t zaproxy/zap-nightly /zap/wrk/scans/auth/auth_plan_tests.sh` 8 | 9 | ## Types 10 | 11 | - stdbba - Browser Based Auth 12 | - bbaplus - Browser Based Auth with manual config or extra steps 13 | - csa - Client Script Auth 14 | 15 | > [!IMPORTANT] 16 | > If `output.yml` does not contain a result for a given Type, then that type is unnecessary because easier options exist. Ex: If BBA works there likely won't be a bbaplus/csa plan nor result. 17 | 18 | ## One-offs 19 | 20 | 1. To run a one-off: `docker run --rm -v $(pwd):/zap/wrk/:rw --env-file scans/auth/all_vars.env -t zaproxy/zap-nightly /zap/zap.sh -cmd -autorun /zap/wrk/scans/auth/plans_and_scripts/testfire/bbaplus.yaml`. 21 | 22 | ## Local Tests 23 | 24 | Some `config` files have been renamed to `config.local` to prevent the tests running in CI/CD. 25 | This is done when the sites are too careful in checking for potential abuse and are locking the accounts. 26 | To run locally you just need to rename the file, but also keep an eye out for lock out emails. -------------------------------------------------------------------------------- /scans/auth/auth_plan_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script for testing Automation Framework features 3 | 4 | runplan() 5 | { 6 | TARGET=$1 7 | FILE=$2 8 | TYPE=$3 9 | echo "Target: $TARGET Plan: $FILE" 10 | echo -ne "$INDENT$INDENT$TYPE:\n"|tee -a "$OUTPUT" > /dev/null 11 | echo -ne "$INDENT$INDENT$INDENT"auth:|tee -a "$OUTPUT" > /dev/null 12 | 13 | /zap/zap.sh -cmd -autorun "$FILE" 14 | RET=$? 15 | if [[ $TYPE == "stdbba" ]] 16 | then 17 | AUTHREPORT=../../auth-report.json 18 | else 19 | AUTHREPORT=auth-report.json 20 | fi 21 | if [ -f $AUTHREPORT ] 22 | then 23 | echo "Using data from the authentication report" 24 | AUTH=`jq -r '.summaryItems[] | select(.key == "auth.summary.auth") | .passed' $AUTHREPORT` 25 | 26 | if [ "$AUTH" == "true" ] 27 | then 28 | echo "PASS" 29 | echo " true"|tee -a "$OUTPUT" > /dev/null 30 | summary="${summary} Plan: $TYPE\tPASS\n" 31 | getreportdetails $AUTHREPORT 32 | else 33 | if [ "$AUTH" != "false" ] 34 | then 35 | echo "WARNING: did not get an expected value for the given key" 36 | fi 37 | echo "ERROR" 38 | echo " false"|tee -a "$OUTPUT" > /dev/null 39 | summary="${summary} Plan: $TYPE\tERROR\n" 40 | getreportdetails $AUTHREPORT 41 | RES=1 42 | fi 43 | rm $AUTHREPORT 44 | else 45 | echo "Using the result of the plan" 46 | if [ "$RET" != 0 ] 47 | then 48 | echo "ERROR" 49 | echo " false"|tee -a "$OUTPUT" > /dev/null 50 | summary="${summary} Plan: $TYPE\tERROR\n" 51 | RES=1 52 | else 53 | echo "PASS" 54 | echo " true"|tee -a "$OUTPUT" > /dev/null 55 | summary="${summary} Plan: $TYPE\tPASS\n" 56 | fi 57 | fi 58 | } 59 | 60 | getreportdetails() 61 | { 62 | AUTHREPORT=$1 63 | USER_SUCCESS=`jq -r '.summaryItems[] | select(.key == "auth.summary.username") | .passed' $AUTHREPORT` 64 | echo "$INDENT$INDENT$INDENT"username: $USER_SUCCESS|tee -a "$OUTPUT" > /dev/null 65 | PASS_SUCCESS=`jq -r '.summaryItems[] | select(.key == "auth.summary.password") | .passed' $AUTHREPORT` 66 | echo "$INDENT$INDENT$INDENT"password: $PASS_SUCCESS|tee -a "$OUTPUT" > /dev/null 67 | SESS_SUCCESS=`jq -r '.summaryItems[] | select(.key == "auth.summary.session") | .passed' $AUTHREPORT` 68 | echo "$INDENT$INDENT$INDENT"session: $SESS_SUCCESS|tee -a "$OUTPUT" > /dev/null 69 | VERIF_SUCCESS=`jq -r '.summaryItems[] | select(.key == "auth.summary.verif") | .passed' $AUTHREPORT` 70 | echo "$INDENT$INDENT$INDENT"verification: $VERIF_SUCCESS|tee -a "$OUTPUT" > /dev/null 71 | } 72 | 73 | RES=0 74 | 75 | mkdir -p /zap/wrk/output 76 | OUTPUT=/zap/wrk/output/output.yml 77 | # Remove output file in case it already exists 78 | rm -f $OUTPUT 79 | 80 | echo "Authentication tests" 81 | echo 82 | 83 | cd /zap/wrk/scans/auth/plans_and_scripts/ 84 | 85 | summary="\n\nSummary:\n========\n" 86 | INDENT=" " 87 | 88 | for TARGET in * 89 | do 90 | if [ -d "$TARGET" ] 91 | then 92 | if [ -f "$TARGET/config.disabled" ] 93 | then 94 | echo "Skipping $TARGET it has been disabled" 95 | continue 96 | fi 97 | summary="${summary}$TARGET\n" 98 | echo 99 | cd "$TARGET" 100 | echo "$TARGET:"|tee -a "$OUTPUT" > /dev/null 101 | if [ -f "config" ] 102 | then 103 | set -o allexport 104 | source "config" 105 | set +o allexport 106 | 107 | export password=$(eval echo \$\{TARGET\}_pass) 108 | export zappassword=${!password} 109 | 110 | export username=$(eval echo \$\{TARGET\}_user) 111 | export zapusername=${!username} 112 | 113 | echo -ne "$INDENT"|tee -a "$OUTPUT" > /dev/null 114 | echo -ne "site: \"$zapsite\"\n"|tee -a "$OUTPUT" > /dev/null 115 | 116 | if [ -f notes.txt ] 117 | then 118 | echo -ne "$INDENT"|tee -a "$OUTPUT" > /dev/null 119 | echo -ne "note: "|tee -a "$OUTPUT" > /dev/null 120 | echo "\"$(cat notes.txt)\""|tee -a "$OUTPUT" > /dev/null 121 | fi 122 | 123 | echo -ne "$INDENT"|tee -a "$OUTPUT" > /dev/null 124 | echo -ne "plans:\n"|tee -a "$OUTPUT" > /dev/null 125 | runplan $TARGET /zap/wrk/scans/auth/bba-auth-test.yaml "stdbba" 126 | else 127 | echo "No $TARGET/config file" 128 | fi 129 | 130 | shopt -s nullglob # May be no yaml files 131 | for file in *.yaml 132 | do 133 | runplan $TARGET /zap/wrk/scans/auth/plans_and_scripts/$TARGET/$file $(echo "$file"|cut -d"." -f1) 134 | sleep 2 135 | done 136 | shopt -u nullglob 137 | 138 | cd .. 139 | fi 140 | done 141 | 142 | echo -e "$summary" 143 | 144 | cat "$OUTPUT" 145 | -------------------------------------------------------------------------------- /scans/auth/bba-auth-test.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | contexts: 3 | - name: Default Context 4 | urls: 5 | - ${zapsite} 6 | includePaths: 7 | - ${zapsite}.* 8 | authentication: 9 | method: browser 10 | parameters: 11 | browserId: firefox-headless 12 | loginPageUrl: ${zaploginurl} 13 | loginPageWait: 5 14 | verification: 15 | method: autodetect 16 | sessionManagement: 17 | method: autodetect 18 | technology: {} 19 | users: 20 | - name: test-user 21 | credentials: 22 | password: ${zappassword} 23 | username: ${zapusername} 24 | parameters: {} 25 | jobs: 26 | - type: passiveScan-config 27 | parameters: 28 | disableAllRules: true 29 | rules: 30 | - name: Authentication Request Identified 31 | id: 10111 32 | threshold: medium 33 | - name: Session Management Response Identified 34 | id: 10112 35 | threshold: medium 36 | - name: Verification Request Identified 37 | id: 10113 38 | threshold: medium 39 | - type: requestor 40 | parameters: 41 | user: test-user 42 | requests: 43 | - url: ${zapsite} 44 | - type: passiveScan-wait 45 | parameters: {} 46 | - name: auth-test-report 47 | type: report 48 | parameters: 49 | template: auth-report-json 50 | theme: null 51 | reportDir: . 52 | reportFile: auth-report.json 53 | reportTitle: ZAP by Checkmarx Scanning Report 54 | displayReport: false 55 | sections: 56 | - summary 57 | - afenv 58 | - statistics -------------------------------------------------------------------------------- /scans/auth/dev_zap_test.sh: -------------------------------------------------------------------------------- 1 | # This script allows you to run the auth test you specify in your ZAP dev environment. 2 | # You need to either be in the top level zap-mgmt-scripts directory or in the scans/auth directory. 3 | # The scans/auth/all_vars.env must be present and contain suitable credentials for the target. 4 | # It will default to the "standard" BBA auth test unless you also specify the plan to use, with or without the .yaml extension. 5 | # To make it easier to see whats going change the AF plan to use a non headless browser and to display the report. 6 | 7 | MGMT_DIR=`pwd` 8 | BASE_DIR="$MGMT_DIR/scans/auth" 9 | 10 | echo "Num params $#" 11 | 12 | if [ "$#" -eq 0 ]; then 13 | echo "Usage: $0 []" 14 | exit 1 15 | fi 16 | 17 | if [ ! -d "$BASE_DIR" ] 18 | then 19 | if [ -d "plans_and_scripts" ] 20 | then 21 | MGMT_DIR=`realpath ../..` 22 | BASE_DIR="$MGMT_DIR/scans/auth" 23 | else 24 | echo "Not running in top zap_mgmt_scripts dir or in the scans/auth dir." 25 | echo "Run in one of those dirs or update this script to handle your use case :)" 26 | exit 1 27 | fi 28 | fi 29 | 30 | ZAP_DIR="$MGMT_DIR/../zaproxy" 31 | if [ ! -d "$BASE_DIR" ] 32 | then 33 | echo "No ZAP directory: $ZAP_DIR" 34 | exit 1 35 | fi 36 | 37 | PLAN_DIR="$BASE_DIR/plans_and_scripts" 38 | TEST=$1 39 | TEST_DIR="$PLAN_DIR/$TEST" 40 | if [ "$#" -eq 2 ] 41 | then 42 | # Support plan name with and without .yaml 43 | if [[ "$2" == *.yaml ]] 44 | then 45 | PLAN=$2 46 | else 47 | PLAN=$2.yaml 48 | fi 49 | fi 50 | 51 | if [ ! -d "$TEST_DIR" ] 52 | then 53 | echo "No such directory: $TEST_DIR" 54 | echo "Valid directories:" 55 | cd $PLAN_DIR 56 | ls -d */ 57 | exit 1 58 | fi 59 | 60 | if [ ! "$PLAN" == "" ] && [ ! -f "$TEST_DIR/$PLAN" ] 61 | then 62 | echo "No such plan: $TEST_DIR/$PLAN" 63 | echo "Valid plans:" 64 | cd $TEST_DIR 65 | ls *.yaml 66 | exit 1 67 | fi 68 | 69 | VARS_FILE="$BASE_DIR/all_vars.env" 70 | 71 | if [ ! -f "$VARS_FILE" ] 72 | then 73 | echo "No file $VARS_FILE" 74 | echo "This file much be present and contain suitable usernames and passwords." 75 | exit 1 76 | fi 77 | 78 | # Set up all of the env vars 79 | set -o allexport 80 | source "$VARS_FILE" 81 | source "$TEST_DIR/config" 82 | set +o allexport 83 | export password=$(eval echo \$\{TEST\}_pass) 84 | export zappassword=${!password} 85 | export username=$(eval echo \$\{TEST\}_user) 86 | export zapusername=${!username} 87 | 88 | echo "Testing $zapsite with user $zapusername" 89 | # Uncomment if you need to double check the password is correct - some special characters need escaping 90 | # echo "Password $zappassword" 91 | 92 | cd $ZAP_DIR 93 | 94 | if [ "$PLAN" == "" ] 95 | then 96 | ./gradlew run --args="-autorun $BASE_DIR/bba-auth-test.yaml" 97 | else 98 | ./gradlew run --args="-autorun $TEST_DIR/$PLAN" 99 | fi 100 | 101 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/aspnet/config: -------------------------------------------------------------------------------- 1 | zapsite=http://aspnet.testsparker.com 2 | zaploginurl=http://aspnet.testsparker.com/administrator/Login.aspx?r=/Dashboard/ 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/authtestcomplex/bbaplus.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | contexts: 3 | - name: Authentication Test 4 | urls: 5 | - https://authenticationtest.com 6 | includePaths: 7 | - https://authenticationtest.com.* 8 | authentication: 9 | method: browser 10 | parameters: 11 | loginPageUrl: https://authenticationtest.com/complexAuth/ 12 | loginPageWait: 2 13 | browserId: firefox-headless 14 | steps: 15 | - description: Make a Selection Dropdown 16 | type: CLICK 17 | xpath: "//*[@id=\"selectLogin\"]" 18 | timeout: 1000 19 | - description: Select Please Log Me In 20 | type: CLICK 21 | xpath: "/html/body/div/div/div[2]/form/div[3]/select/option[2]" 22 | timeout: 1000 23 | - description: Love form manipulation 24 | type: CLICK 25 | xpath: "//*[@id=\"loveForm\"]" 26 | timeout: 1000 27 | verification: 28 | method: response 29 | loggedInRegex: loginSuccess|mode=logout 30 | pollFrequency: 60 31 | pollUnits: requests 32 | pollUrl: "" 33 | pollPostData: "" 34 | sessionManagement: 35 | method: cookie 36 | technology: {} 37 | structure: {} 38 | users: 39 | - name: testuser 40 | credentials: 41 | username: ${zapusername} 42 | password: ${zappassword} 43 | jobs: 44 | - type: passiveScan-config 45 | parameters: 46 | disableAllRules: true 47 | rules: 48 | - name: Authentication Request Identified 49 | id: 10111 50 | threshold: medium 51 | - name: Session Management Response Identified 52 | id: 10112 53 | threshold: medium 54 | - name: Verification Request Identified 55 | id: 10113 56 | threshold: medium 57 | - type: requestor 58 | parameters: 59 | user: testuser 60 | requests: 61 | - url: ${zapsite} 62 | - type: passiveScan-wait 63 | parameters: {} 64 | - name: auth-test-report 65 | type: report 66 | parameters: 67 | template: auth-report-json 68 | theme: null 69 | reportDir: . 70 | reportFile: auth-report.json 71 | reportTitle: ZAP by Checkmarx Scanning Report 72 | sections: 73 | - summary 74 | - afenv 75 | - statistics 76 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/authtestcomplex/config: -------------------------------------------------------------------------------- 1 | zapsite=https://authenticationtest.com/complexAuth/ 2 | zaploginurl=https://authenticationtest.com/complexAuth/ 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/authtestdelay/bbaplus.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | contexts: 3 | - name: Authentication Test 4 | urls: 5 | - https://authenticationtest.com 6 | includePaths: 7 | - https://authenticationtest.com.* 8 | authentication: 9 | method: browser 10 | parameters: 11 | loginPageUrl: https://authenticationtest.com/delayChallenge/ 12 | loginPageWait: 2 13 | browserId: firefox-headless 14 | verification: 15 | method: response 16 | loggedInRegex: loginSuccess|mode=logout 17 | pollFrequency: 60 18 | pollUnits: requests 19 | pollUrl: "" 20 | pollPostData: "" 21 | sessionManagement: 22 | method: cookie 23 | technology: {} 24 | structure: {} 25 | users: 26 | - name: testuser 27 | credentials: 28 | username: ${zapusername} 29 | password: ${zappassword} 30 | jobs: 31 | - type: passiveScan-config 32 | parameters: 33 | disableAllRules: true 34 | rules: 35 | - name: Authentication Request Identified 36 | id: 10111 37 | threshold: medium 38 | - name: Session Management Response Identified 39 | id: 10112 40 | threshold: medium 41 | - name: Verification Request Identified 42 | id: 10113 43 | threshold: medium 44 | - type: requestor 45 | parameters: 46 | user: testuser 47 | requests: 48 | - url: ${zapsite} 49 | - type: passiveScan-wait 50 | parameters: {} 51 | - name: auth-test-report 52 | type: report 53 | parameters: 54 | template: auth-report-json 55 | theme: null 56 | reportDir: . 57 | reportFile: auth-report.json 58 | reportTitle: ZAP by Checkmarx Scanning Report 59 | sections: 60 | - summary 61 | - afenv 62 | - statistics 63 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/authtestdelay/config: -------------------------------------------------------------------------------- 1 | zapsite=https://authenticationtest.com/delayChallenge/ 2 | zaploginurl=https://authenticationtest.com/delayChallenge/ 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/authtestmulti/bbaplus.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | contexts: 3 | - name: Authentication Test 4 | urls: 5 | - https://authenticationtest.com/ 6 | includePaths: 7 | - https://authenticationtest.com.* 8 | authentication: 9 | method: browser 10 | parameters: 11 | loginPageUrl: https://authenticationtest.com/multiStepAuth/ 12 | loginPageWait: 2 13 | browserId: firefox-headless 14 | steps: 15 | - description: Fill Email 16 | type: USERNAME 17 | xpath: "//*[@id=\"email\"]" 18 | timeout: 1000 19 | - description: Email Next 20 | type: CLICK 21 | xpath: "/html/body/div/div/div[2]/form/input" 22 | timeout: 1000 23 | - description: Fill password 24 | type: PASSWORD 25 | xpath: "//*[@id=\"password\"]" 26 | timeout: 1000 27 | - description: Log In 28 | type: RETURN 29 | xpath: "/html/body/div/div/div[2]/form/input" 30 | timeout: 1000 31 | verification: 32 | method: response 33 | loggedInRegex: loginSuccess|mode=logout 34 | pollFrequency: 60 35 | pollUnits: requests 36 | pollUrl: "" 37 | pollPostData: "" 38 | sessionManagement: 39 | method: cookie 40 | technology: {} 41 | structure: {} 42 | users: 43 | - name: testuser 44 | credentials: 45 | username: ${zapusername} 46 | password: ${zappassword} 47 | jobs: 48 | - type: passiveScan-config 49 | parameters: 50 | disableAllRules: true 51 | rules: 52 | - name: Authentication Request Identified 53 | id: 10111 54 | threshold: medium 55 | - name: Session Management Response Identified 56 | id: 10112 57 | threshold: medium 58 | - name: Verification Request Identified 59 | id: 10113 60 | threshold: medium 61 | - type: requestor 62 | parameters: 63 | user: testuser 64 | requests: 65 | - url: ${zapsite} 66 | - type: passiveScan-wait 67 | parameters: {} 68 | - name: auth-test-report 69 | type: report 70 | parameters: 71 | template: auth-report-json 72 | theme: null 73 | reportDir: . 74 | reportFile: auth-report.json 75 | reportTitle: ZAP by Checkmarx Scanning Report 76 | sections: 77 | - summary 78 | - afenv 79 | - statistics 80 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/authtestmulti/config.disabled: -------------------------------------------------------------------------------- 1 | zapsite=https://authenticationtest.com/multiStepAuth/ 2 | zaploginurl=https://authenticationtest.com/multiStepAuth/ 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/authtestsimple/bbaplus.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | contexts: 3 | - name: Authentication Test 4 | urls: 5 | - https://authenticationtest.com 6 | includePaths: 7 | - https://authenticationtest.com.* 8 | authentication: 9 | method: browser 10 | parameters: 11 | loginPageUrl: https://authenticationtest.com/simpleFormAuth/ 12 | loginPageWait: 2 13 | browserId: firefox-headless 14 | verification: 15 | method: response 16 | loggedInRegex: loginSuccess|mode=logout 17 | pollFrequency: 60 18 | pollUnits: requests 19 | pollUrl: "" 20 | pollPostData: "" 21 | sessionManagement: 22 | method: cookie 23 | technology: {} 24 | structure: {} 25 | users: 26 | - name: testuser 27 | credentials: 28 | username: ${zapusername} 29 | password: ${zappassword} 30 | jobs: 31 | - type: passiveScan-config 32 | parameters: 33 | disableAllRules: true 34 | rules: 35 | - name: Authentication Request Identified 36 | id: 10111 37 | threshold: medium 38 | - name: Session Management Response Identified 39 | id: 10112 40 | threshold: medium 41 | - name: Verification Request Identified 42 | id: 10113 43 | threshold: medium 44 | - type: requestor 45 | parameters: 46 | user: testuser 47 | requests: 48 | - url: ${zapsite} 49 | - type: passiveScan-wait 50 | parameters: {} 51 | - name: auth-test-report 52 | type: report 53 | parameters: 54 | template: auth-report-json 55 | theme: null 56 | reportDir: . 57 | reportFile: auth-report.json 58 | reportTitle: ZAP by Checkmarx Scanning Report 59 | sections: 60 | - summary 61 | - afenv 62 | - statistics 63 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/authtestsimple/config: -------------------------------------------------------------------------------- 1 | zapsite=https://authenticationtest.com/simpleFormAuth/ 2 | zaploginurl=https://authenticationtest.com/simpleFormAuth/ 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/authtesttotp/bbaplus.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | contexts: 3 | - name: Authentication Test 4 | urls: 5 | - https://authenticationtest.com/ 6 | includePaths: 7 | - https://authenticationtest.com.* 8 | authentication: 9 | method: browser 10 | parameters: 11 | loginPageUrl: https://authenticationtest.com/totpChallenge/ 12 | loginPageWait: 2 13 | browserId: firefox-headless 14 | steps: 15 | - description: TOTP 16 | type: TOTP_FIELD 17 | cssSelector: "#totpmfa" 18 | timeout: 1000 19 | verification: 20 | method: response 21 | loggedInRegex: loginSuccess|mode=logout 22 | pollFrequency: 60 23 | pollUnits: requests 24 | pollUrl: "" 25 | pollPostData: "" 26 | sessionManagement: 27 | method: cookie 28 | technology: {} 29 | structure: {} 30 | users: 31 | - name: testuser 32 | credentials: 33 | totp: 34 | secret: I65VU7K5ZQL7WB4E 35 | period: 30 36 | digits: 6 37 | algorithm: SHA1 38 | username: ${zapusername} 39 | password: ${zappassword} 40 | jobs: 41 | - type: passiveScan-config 42 | parameters: 43 | disableAllRules: true 44 | rules: 45 | - name: Authentication Request Identified 46 | id: 10111 47 | threshold: medium 48 | - name: Session Management Response Identified 49 | id: 10112 50 | threshold: medium 51 | - name: Verification Request Identified 52 | id: 10113 53 | threshold: medium 54 | - type: requestor 55 | parameters: 56 | user: testuser 57 | requests: 58 | - url: ${zapsite} 59 | - type: passiveScan-wait 60 | parameters: {} 61 | - name: auth-test-report 62 | type: report 63 | parameters: 64 | template: auth-report-json 65 | theme: null 66 | reportDir: . 67 | reportFile: auth-report.json 68 | reportTitle: ZAP by Checkmarx Scanning Report 69 | sections: 70 | - summary 71 | - afenv 72 | - statistics 73 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/authtesttotp/config: -------------------------------------------------------------------------------- 1 | zapsite=https://authenticationtest.com/totpChallenge/ 2 | zaploginurl=https://authenticationtest.com/totpChallenge/ 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/bluesky/config: -------------------------------------------------------------------------------- 1 | zapsite=https://bsky.app 2 | zaploginurl=https://bsky.app/ 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/bluesky/notes.txt: -------------------------------------------------------------------------------- 1 | BBA is failing verification detection. -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/ctflearn/config: -------------------------------------------------------------------------------- 1 | zapsite=https://ctflearn.com 2 | zaploginurl=https://ctflearn.com/user/login 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/ctflearn/notes.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zapbot/zap-mgmt-scripts/ff010f59a1fa87f55bf111d0af6a9427e0a618c4/scans/auth/plans_and_scripts/ctflearn/notes.txt -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/ginnjuice/config: -------------------------------------------------------------------------------- 1 | zapsite=https://ginandjuice.shop 2 | zaploginurl=https://ginandjuice.shop/login 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/hackyourself/config: -------------------------------------------------------------------------------- 1 | zapsite=https://hack-yourself-first.com 2 | zaploginurl=https://hack-yourself-first.com/Account/Login 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/infosecex/config: -------------------------------------------------------------------------------- 1 | zapsite=https://infosec.exchange 2 | zaploginurl=https://infosec.exchange/auth/sign_in 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/infosecex/notes.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zapbot/zap-mgmt-scripts/ff010f59a1fa87f55bf111d0af6a9427e0a618c4/scans/auth/plans_and_scripts/infosecex/notes.txt -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/insta/config: -------------------------------------------------------------------------------- 1 | zapsite=https://www.instagram.com 2 | zaploginurl=https://www.instagram.com/accounts/login/ 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/insta/notes.txt: -------------------------------------------------------------------------------- 1 | BBA is failing due to popups. -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/linkedin/config: -------------------------------------------------------------------------------- 1 | zapsite=https://www.linkedin.com 2 | zaploginurl=https://www.linkedin.com/login 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/mozbugz/config: -------------------------------------------------------------------------------- 1 | zapsite=https://bugzilla.mozilla.org 2 | zaploginurl=https://bugzilla.mozilla.org/home 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/phpspark/config: -------------------------------------------------------------------------------- 1 | zapsite=http://php.testsparker.com 2 | zaploginurl=http://php.testsparker.com/auth/login.php 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/reddit/config: -------------------------------------------------------------------------------- 1 | zapsite=https://www.reddit.com 2 | zaploginurl=https://www.reddit.com/login/ 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/spotify/config.local: -------------------------------------------------------------------------------- 1 | zapsite=https://accounts.spotify.com 2 | zaploginurl=https://accounts.spotify.com/en/login 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/testasp/config: -------------------------------------------------------------------------------- 1 | zapsite=http://testasp.vulnweb.com 2 | zaploginurl=http://testasp.vulnweb.com/Login.asp -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/testfire/bbaplus.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | contexts: 3 | - name: Authentication Test 4 | urls: 5 | - ${zapsite} 6 | includePaths: 7 | - ${zapsite}.* 8 | authentication: 9 | method: browser 10 | parameters: 11 | loginPageUrl: ${zaploginurl} 12 | loginPageWait: 2 13 | browserId: firefox-headless 14 | steps: 15 | - description: Fill Username 16 | type: USERNAME 17 | cssSelector: "#uid" 18 | value: jsmith 19 | timeout: 1000 20 | verification: 21 | method: autodetect 22 | sessionManagement: 23 | method: autodetect 24 | users: 25 | - name: testuser 26 | credentials: 27 | username: ${zapusername} 28 | password: ${zappassword} 29 | jobs: 30 | - type: passiveScan-config 31 | parameters: 32 | disableAllRules: true 33 | rules: 34 | - name: Authentication Request Identified 35 | id: 10111 36 | threshold: medium 37 | - name: Session Management Response Identified 38 | id: 10112 39 | threshold: medium 40 | - name: Verification Request Identified 41 | id: 10113 42 | threshold: medium 43 | - type: requestor 44 | parameters: 45 | user: testuser 46 | requests: 47 | - url: ${zapsite} 48 | - type: passiveScan-wait 49 | parameters: {} 50 | - name: auth-test-report 51 | type: report 52 | parameters: 53 | template: auth-report-json 54 | theme: null 55 | reportDir: . 56 | reportFile: auth-report.json 57 | reportTitle: ZAP by Checkmarx Scanning Report 58 | sections: 59 | - summary 60 | - afenv 61 | - statistics 62 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/testfire/config: -------------------------------------------------------------------------------- 1 | zapsite=http://testfire.net 2 | zaploginurl=http://testfire.net/login.jsp -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/testfire/csa.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | contexts: 3 | - name: Authentication Test 4 | urls: 5 | - ${zapsite} 6 | includePaths: 7 | - ${zapsite}.* 8 | authentication: 9 | method: client 10 | parameters: 11 | script: ./testfire.zst 12 | scriptEngine: Mozilla Zest 13 | verification: 14 | method: autodetect 15 | sessionManagement: 16 | method: autodetect 17 | users: 18 | - name: testuser 19 | credentials: 20 | Username: ${zapusername} 21 | Password: ${zappassword} 22 | jobs: 23 | - type: passiveScan-config 24 | parameters: 25 | disableAllRules: true 26 | rules: 27 | - name: Authentication Request Identified 28 | id: 10111 29 | threshold: medium 30 | - name: Session Management Response Identified 31 | id: 10112 32 | threshold: medium 33 | - name: Verification Request Identified 34 | id: 10113 35 | threshold: medium 36 | - type: requestor 37 | parameters: 38 | user: testuser 39 | requests: 40 | - url: ${zapsite} 41 | - type: passiveScan-wait 42 | parameters: {} 43 | - name: auth-test-report 44 | type: report 45 | parameters: 46 | template: auth-report-json 47 | theme: null 48 | reportDir: . 49 | reportFile: auth-report.json 50 | reportTitle: ZAP by Checkmarx Scanning Report 51 | sections: 52 | - summary 53 | - afenv 54 | - statistics 55 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/testfire/notes.txt: -------------------------------------------------------------------------------- 1 | CSA is failing due to use of autodetect. 2 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/testfire/testfire.zst: -------------------------------------------------------------------------------- 1 | { 2 | "about": "This is a Zest script. For more details about Zest visit https://github.com/zaproxy/zest/", 3 | "zestVersion": "0.3", 4 | "title": "testfire.zst", 5 | "description": "", 6 | "prefix": "", 7 | "type": "StandAlone", 8 | "parameters": { 9 | "tokenStart": "{{", 10 | "tokenEnd": "}}", 11 | "tokens": {}, 12 | "elementType": "ZestVariables" 13 | }, 14 | "statements": [ 15 | { 16 | "windowHandle": "windowHandle1", 17 | "browserType": "firefox", 18 | "url": "http://testfire.net/login.jsp", 19 | "capabilities": "", 20 | "headless": true, 21 | "index": 1, 22 | "enabled": true, 23 | "elementType": "ZestClientLaunch" 24 | }, 25 | { 26 | "windowHandle": "windowHandle1", 27 | "type": "id", 28 | "element": "uid", 29 | "index": 2, 30 | "enabled": true, 31 | "elementType": "ZestClientElementClear" 32 | }, 33 | { 34 | "value": "jsmith", 35 | "windowHandle": "windowHandle1", 36 | "type": "id", 37 | "element": "uid", 38 | "index": 3, 39 | "enabled": true, 40 | "elementType": "ZestClientElementSendKeys" 41 | }, 42 | { 43 | "windowHandle": "windowHandle1", 44 | "type": "id", 45 | "element": "passw", 46 | "index": 4, 47 | "enabled": true, 48 | "elementType": "ZestClientElementClear" 49 | }, 50 | { 51 | "value": "demo1234", 52 | "windowHandle": "windowHandle1", 53 | "type": "id", 54 | "element": "passw", 55 | "index": 5, 56 | "enabled": true, 57 | "elementType": "ZestClientElementSendKeys" 58 | }, 59 | { 60 | "windowHandle": "windowHandle1", 61 | "type": "id", 62 | "element": "passw", 63 | "index": 6, 64 | "enabled": true, 65 | "elementType": "ZestClientElementSubmit" 66 | }, 67 | { 68 | "windowHandle": "windowHandle1", 69 | "type": "xpath", 70 | "element": "/html/body/table/tbody/tr[2]/td[2]/div/form/table/tbody/tr[3]/td[2]/input", 71 | "index": 7, 72 | "enabled": true, 73 | "elementType": "ZestClientElementClick" 74 | } 75 | ], 76 | "authentication": [], 77 | "index": 0, 78 | "enabled": true, 79 | "elementType": "ZestScript" 80 | } 81 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/testhtml5/config: -------------------------------------------------------------------------------- 1 | zapsite=http://testhtml5.vulnweb.com 2 | zaploginurl=http://testhtml5.vulnweb.com/ 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/testphp/config: -------------------------------------------------------------------------------- 1 | zapsite=http://testphp.vulnweb.com 2 | zaploginurl=http://testphp.vulnweb.com/login.php -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/testphp/notes.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zapbot/zap-mgmt-scripts/ff010f59a1fa87f55bf111d0af6a9427e0a618c4/scans/auth/plans_and_scripts/testphp/notes.txt -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/webappsec/config.disabled: -------------------------------------------------------------------------------- 1 | zapsite=http://zero.webappsecurity.com 2 | zaploginurl=http://zero.webappsecurity.com/login.html 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/webappsec/note: -------------------------------------------------------------------------------- 1 | Disabled: As of 2025-03-06 the target currently wants to switch to https during authentication, and use TLS 1.0 which is not compatible with modern browsers or default JVM settings. -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/wikipedia/config: -------------------------------------------------------------------------------- 1 | zapsite=https://en.wikipedia.org 2 | zaploginurl=https://en.wikipedia.org/w/index.php\?title=Special:UserLogin\&returnto=Main+Page 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/wikipedia/notes.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zapbot/zap-mgmt-scripts/ff010f59a1fa87f55bf111d0af6a9427e0a618c4/scans/auth/plans_and_scripts/wikipedia/notes.txt -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/zoom/config: -------------------------------------------------------------------------------- 1 | zapsite=https://zoom.us 2 | zaploginurl=https://zoom.us/signin#/login 3 | -------------------------------------------------------------------------------- /scans/auth/plans_and_scripts/zoom/notes.txt: -------------------------------------------------------------------------------- 1 | BBA is failing due to popups. -------------------------------------------------------------------------------- /scans/benchmark/benchmark-scorer.js: -------------------------------------------------------------------------------- 1 | var extAuto = control.getExtensionLoader().getExtension("ExtensionAutomation") 2 | var envVars = extAuto.getPlan(0).getEnv().getData().getVars() 3 | 4 | var OUTPUT_DIR = envVars.get('OUTPUT_DIR') 5 | var NAME = envVars.get('NAME') 6 | var VULNERABILITY = envVars.get('VULNERABILITY') 7 | var SCAN_RULES = envVars.get('SCAN_RULES').split(',') 8 | var NESTED_NODE_LEVEL = envVars.get('NESTED_NODE_LEVEL') 9 | var IGNORE_TREE_PATHS = envVars.get('IGNORE_TREE_PATHS').split(',') 10 | var VULNERABLE_TESTS = envVars.get('VULNERABLE_TESTS').split(',') 11 | 12 | var totalUrls = 0; 13 | var totalPassed = 0; 14 | var target = 'https://localhost:8443/benchmark'; 15 | 16 | var FileWriter = Java.type('java.io.FileWriter'); 17 | var PrintWriter = Java.type('java.io.PrintWriter'); 18 | 19 | var YAML_FILE = OUTPUT_DIR + "/" + VULNERABILITY + ".yml"; 20 | var fw = new FileWriter(YAML_FILE); 21 | var pw = new PrintWriter(fw); 22 | 23 | pw.println('section: ' + NAME); 24 | pw.println('url: ' + target); 25 | pw.println('details:'); 26 | 27 | function nodeHasAlert(node, rules) { 28 | var alerts = node.getAlerts(); 29 | for (var a in alerts) { 30 | var pluginId = String(alerts.get(a).getPluginId()); 31 | if (rules.indexOf(pluginId) >= 0) { 32 | return pluginId; 33 | } 34 | } 35 | return null; 36 | } 37 | 38 | function listChildren(node, level) { 39 | var j; 40 | for (j = 0; j < node.getChildCount(); j++) { 41 | var child = node.getChildAt(j); 42 | if (child.getChildCount() == 0 && level > NESTED_NODE_LEVEL) { 43 | var path = child.getHierarchicNodeName().substring(target.length).replace('()', ''); 44 | if (!IGNORE_TREE_PATHS.indexOf(path) >= 0) { 45 | totalUrls++; 46 | pw.println('- path: ' + path); 47 | let testName = path.split('/')[2] 48 | let testNumber = testName.substr(testName.length - 5) 49 | let vulnerable = VULNERABLE_TESTS.indexOf(testNumber) >= 0; 50 | let reported = false; 51 | pw.println(' vulnerable: ' + vulnerable); 52 | var pluginId = nodeHasAlert(child, SCAN_RULES); 53 | if (pluginId) { 54 | reported = true; 55 | pw.println(' reported: true'); 56 | pw.println(' rule: ' + pluginId); 57 | } else { 58 | reported = false; 59 | pw.println(' reported: false'); 60 | pw.println(' rule: ' + SCAN_RULES[0]); 61 | } 62 | if (vulnerable == reported) { 63 | totalPassed++; 64 | pw.println(' result: Pass') 65 | } else { 66 | pw.println(' result: FAIL') 67 | } 68 | } 69 | } else { 70 | listChildren(child, level + 1); 71 | } 72 | } 73 | } 74 | 75 | root = org.parosproxy.paros.model.Model.getSingleton(). 76 | getSession().getSiteTree().getRoot(); 77 | 78 | listChildren(root, 0); 79 | 80 | pw.println('tests: ' + totalUrls); 81 | pw.println('passes: ' + totalPassed); 82 | pw.println('fails: ' + (totalUrls - totalPassed)); 83 | pw.println('score: ' + Math.round(totalPassed * 100 / totalUrls) + '%'); 84 | pw.close(); 85 | 86 | print('Wrote output to', YAML_FILE); 87 | -------------------------------------------------------------------------------- /scans/benchmark/cmdi/af-plan.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "Benchmark" 5 | urls: 6 | - "https://localhost:8443/benchmark/cmdi-Index.html" 7 | includePaths: 8 | - "https://localhost:8443/benchmark/cmdi.*" 9 | excludePaths: [] 10 | authentication: 11 | parameters: {} 12 | verification: 13 | method: "response" 14 | pollFrequency: 60 15 | pollUnits: "requests" 16 | sessionManagement: 17 | method: "cookie" 18 | parameters: {} 19 | parameters: 20 | failOnError: true 21 | failOnWarning: false 22 | progressToStdout: true 23 | vars: 24 | OUTPUT_DIR: "/zap/wrk/results" 25 | NAME: "Command Injection" 26 | VULNERABILITY: "cmdi" 27 | SCAN_RULES: "90020" 28 | NESTED_NODE_LEVEL: 2 29 | IGNORE_TREE_PATHS: "" 30 | VULNERABLE_TESTS: "00006,00007,00015,00017,00077,00091,00092,00159,00172,00173,00174,00176,00293,00294,00295,00302,00303,00304,00306,00311,00407,00409,00480,00495,00496,00497,00498,00499,00500,00567,00568,00573,00574,00575,00576,00731,00740,00815,00816,00823,00824,00825,00968,00979,00981,00983,01064,01066,01190,01191,01192,01194,01270,01285,01286,01287,01288,01360,01361,01362,01363,01430,01441,01442,01446,01517,01531,01533,01601,01609,01610,01673,01674,01685,01689,01690,01691,01850,01851,01852,01864,01928,01929,01936,01938,01940,01942,01944,02059,02070,02137,02146,02147,02150,02151,02152,02154,02155,02243,02244,02249,02250,02251,02333,02334,02342,02343,02344,02411,02412,02414,02429,02430,02431,02432,02433,02496,02511,02512,02514,02515,02516,02517,02611,02612,02613" 31 | jobs: 32 | - name: "Add Scoring Script" 33 | type: "script" 34 | parameters: 35 | action: "add" 36 | type: "standalone" 37 | engine: "ECMAScript : Graal.js" 38 | name: "benchmark-scorer.js" 39 | file: "/zap/wrk/benchmark-scorer.js" 40 | - name: "Add Benchmark CMDi Variant Script" 41 | type: "script" 42 | parameters: 43 | action: "add" 44 | type: "variant" 45 | engine: "ECMAScript : Graal.js" 46 | name: "cmdi-variant.js" 47 | file: "/zap/wrk/cmdi/variant.js" 48 | - name: "Spider Benchmark CMDi Index" 49 | type: "spider" 50 | parameters: 51 | context: "Benchmark" 52 | user: "" 53 | url: "" 54 | maxDuration: 0 55 | maxDepth: 0 56 | maxChildren: 0 57 | - name: "Start Active Scan" 58 | type: "activeScan" 59 | parameters: 60 | context: "Benchmark" 61 | user: "" 62 | policy: "" 63 | maxRuleDurationInMins: 60 64 | maxScanDurationInMins: 60 65 | addQueryParam: false 66 | delayInMs: 0 67 | handleAntiCSRFTokens: false 68 | injectPluginIdInHeader: false 69 | scanHeadersAllRequests: true 70 | threadPerHost: 4 71 | policyDefinition: 72 | defaultStrength: "medium" 73 | defaultThreshold: "off" 74 | rules: 75 | - id: 90020 76 | name: "Remote OS Command Injection" 77 | threshold: "medium" 78 | strength: "medium" 79 | tests: 80 | - onFail: "INFO" 81 | statistic: "stats.ascan.90020.alerts" 82 | site: "" 83 | operator: "==" 84 | value: 126 85 | name: "Number of CMDi Alerts Raised" 86 | type: "stats" 87 | - name: "Run Scoring Script" 88 | type: "script" 89 | parameters: 90 | action: "run" 91 | type: "standalone" 92 | engine: "" 93 | name: "benchmark-scorer.js" 94 | -------------------------------------------------------------------------------- /scans/benchmark/cmdi/variant.js: -------------------------------------------------------------------------------- 1 | /* 2 | Variant Script for ignoring OWASP Benchmark pages that we don't want to attack. 3 | */ 4 | 5 | const List = Java.type("java.util.List"); 6 | 7 | function parseParameters(helper, msg) { } 8 | 9 | function setParameter(helper, msg, param, value, escaped) { } 10 | 11 | function getLeafName(helper, nodeName, msg) { 12 | if (helper.getParamList().isEmpty()) { 13 | return null; 14 | } 15 | return helper.getStandardLeafName(nodeName, msg, helper.getParamList()); 16 | } 17 | 18 | var ignored_paths = [ 19 | "/benchmark/cmdi-00/BenchmarkTest00077", 20 | "/benchmark/cmdi-00/BenchmarkTest00090", 21 | "/benchmark/cmdi-00/BenchmarkTest00091", 22 | "/benchmark/cmdi-00/BenchmarkTest00092", 23 | "/benchmark/cmdi-00/BenchmarkTest00093", 24 | "/benchmark/cmdi-01/BenchmarkTest00968", 25 | "/benchmark/cmdi-01/BenchmarkTest00969", 26 | "/benchmark/cmdi-01/BenchmarkTest00970", 27 | "/benchmark/cmdi-01/BenchmarkTest00978", 28 | "/benchmark/cmdi-01/BenchmarkTest00979", 29 | "/benchmark/cmdi-01/BenchmarkTest00980", 30 | "/benchmark/cmdi-01/BenchmarkTest00981", 31 | "/benchmark/cmdi-01/BenchmarkTest00982", 32 | "/benchmark/cmdi-01/BenchmarkTest00983", 33 | "/benchmark/cmdi-02/BenchmarkTest01850", 34 | "/benchmark/cmdi-02/BenchmarkTest01851", 35 | "/benchmark/cmdi-02/BenchmarkTest01852", 36 | "/benchmark/cmdi-02/BenchmarkTest01864", 37 | "/benchmark/cmdi-02/BenchmarkTest01865", 38 | ] 39 | 40 | function getTreePath(helper, msg) { 41 | var uri = msg.getRequestHeader().getURI(); 42 | var path = uri.getPath() 43 | if (/^\/benchmark\/cmdi-\d\d\/BenchmarkTest\d\d\d\d\d.html$/.test(path)) { 44 | return List.of(); 45 | } 46 | var method = msg.getRequestHeader().getMethod() 47 | if (method == "GET" && ignored_paths.indexOf(path) >= 0) { 48 | return List.of(); 49 | } 50 | return null; 51 | } 52 | -------------------------------------------------------------------------------- /scans/crawlmaze/crawl-maze-score.js: -------------------------------------------------------------------------------- 1 | // Score ZAP against Google Security Crawl Maze 2 | // 3 | // You will need to have run one or both of the ZAP spiders against https://security-crawl-maze.app/ 4 | 5 | // Expected results sourced from: 6 | // https://raw.githubusercontent.com/google/security-crawl-maze/master/blueprints/utils/resources/expected-results.json 7 | 8 | var expectedResults = [ 9 | "/javascript/frameworks/angular/event-handler.found", 10 | "/javascript/frameworks/angular/router-outlet.found", 11 | "/javascript/frameworks/angularjs/index.html#!/ng-href.found", 12 | "/javascript/frameworks/polymer/event-handler.found", 13 | "/javascript/frameworks/polymer/polymer-router.found", 14 | "/javascript/frameworks/react/search.found", 15 | "/javascript/frameworks/react/route-path.found", 16 | "/test/css/font-face.found", 17 | "/test/headers/content-location.found", 18 | "/test/headers/link.found", 19 | "/test/headers/location.found", 20 | "/test/headers/refresh.found", 21 | "/test/html/body/a/href.found", 22 | "/test/html/body/a/ping.found", 23 | "/test/html/body/applet/archive.found", 24 | "/test/html/body/applet/codebase.found", 25 | "/test/html/body/audio/source/src.found", 26 | "/test/html/body/audio/source/srcset1x.found", 27 | "/test/html/body/audio/source/srcset2x.found", 28 | "/test/html/body/audio/src.found", 29 | "/test/html/body/background.found", 30 | "/test/html/body/blockquote/cite.found", 31 | "/test/html/body/embed/src.found", 32 | "/test/html/body/form/action-get.found", 33 | "/test/html/body/form/action-post.found", 34 | "/test/html/body/form/button/formaction.found", 35 | "/test/html/body/frameset/frame/src.found", 36 | "/test/html/body/iframe/src.found", 37 | "/test/html/body/iframe/srcdoc.found", 38 | "/test/html/body/img/dynsrc.found", 39 | "/test/html/body/img/longdesc.found", 40 | "/test/html/body/img/lowsrc.found", 41 | "/test/html/body/img/src-data.found", 42 | "/test/html/body/img/src.found", 43 | "/test/html/body/img/srcset1x.found", 44 | "/test/html/body/img/srcset2x.found", 45 | "/test/html/body/input/src.found", 46 | "/test/html/body/isindex/action.found", 47 | "/test/html/body/map/area/ping.found", 48 | "/test/html/body/object/codebase.found", 49 | "/test/html/body/object/data.found", 50 | "/test/html/body/object/param/value.found", 51 | "/test/html/body/script/src.found", 52 | "/test/html/body/svg/image/xlink.found", 53 | "/test/html/body/svg/script/xlink.found", 54 | "/test/html/body/table/background.found", 55 | "/test/html/body/table/td/background.found", 56 | "/test/html/body/video/poster.found", 57 | "/test/html/body/video/src.found", 58 | "/test/html/body/video/track/src.found", 59 | "/test/html/doctype.found", 60 | "/test/html/head/base/href.found", 61 | "/test/html/head/comment-conditional.found", 62 | "/test/html/head/import/implementation.found", 63 | "/test/html/head/link/href.found", 64 | "/test/html/head/meta/content-csp.found", 65 | "/test/html/head/meta/content-pinned-websites.found", 66 | "/test/html/head/meta/content-reading-view.found", 67 | "/test/html/head/meta/content-redirect.found", 68 | "/test/html/head/profile.found", 69 | "/test/html/manifest.found", 70 | "/test/html/misc/string/dot-dot-slash-prefix.found", 71 | "/test/html/misc/string/dot-slash-prefix.found", 72 | "/test/html/misc/string/string-known-extension.pdf", 73 | "/test/html/misc/string/url-string.found", 74 | "/test/html/misc/url/full-url.found", 75 | "/test/html/misc/url/path-relative-url.found", 76 | "/test/html/misc/url/protocol-relative-url.found", 77 | "/test/html/misc/url/root-relative-url.found", 78 | "/test/javascript/interactive/js-delete.found", 79 | "/test/javascript/interactive/js-post-event-listener.found", 80 | "/test/javascript/interactive/js-post.found", 81 | "/test/javascript/interactive/js-put.found", 82 | "/test/javascript/interactive/listener-and-event-attribute-first.found", 83 | "/test/javascript/interactive/listener-and-event-attribute-second.found", 84 | "/test/javascript/interactive/multi-step-request-event-attribute.found", 85 | "/test/javascript/interactive/multi-step-request-event-listener-div-dom.found", 86 | "/test/javascript/interactive/multi-step-request-event-listener-div.found", 87 | "/test/javascript/interactive/multi-step-request-event-listener-dom.found", 88 | "/test/javascript/interactive/multi-step-request-event-listener.found", 89 | "/test/javascript/interactive/multi-step-request-redefine-event-attribute.found", 90 | "/test/javascript/interactive/multi-step-request-remove-button.found", 91 | "/test/javascript/interactive/multi-step-request-remove-event-listener.found", 92 | "/test/javascript/interactive/two-listeners-first.found", 93 | "/test/javascript/interactive/two-listeners-second.found", 94 | "/test/javascript/misc/automatic-post.found", 95 | "/test/javascript/misc/comment.found", 96 | "/test/javascript/misc/string-concat-variable.found", 97 | "/test/javascript/misc/string-variable.found", 98 | "/test/misc/known-files/robots.txt.found", 99 | "/test/misc/known-files/sitemap.xml.found" 100 | ] 101 | 102 | 103 | function findNode(scheme, path) { 104 | var uri = new URI(scheme + '://' + target + path, true); 105 | var n = siteTree.findNode(uri); 106 | if (n == null) { 107 | // Find parent then loop through child nodes checking for the URL path 108 | var parent = siteTree.findClosestParent(uri); 109 | if (parent) { 110 | for (var j = 0; j < parent.getChildCount(); j++) { 111 | var child = parent.getChildAt(j); 112 | if (child.getHierarchicNodeName().indexOf(path) > 0) { 113 | n = child; 114 | break; 115 | } 116 | } 117 | } 118 | } 119 | return n; 120 | } 121 | 122 | var HistoryReference = Java.type('org.parosproxy.paros.model.HistoryReference'); 123 | var URI = Java.type('org.apache.commons.httpclient.URI'); 124 | 125 | var FieldUtils = Java.type('org.apache.commons.lang3.reflect.FieldUtils'); 126 | 127 | function clientUrlExists(node, url) { 128 | const nodeUrl = node.getUserObject().getUrl() 129 | if (url == nodeUrl) { 130 | return true; 131 | } 132 | if (nodeUrl && nodeUrl.startsWith(url)) { 133 | return true; 134 | } 135 | for (var i = 0; i < node.getChildCount(); i++) { 136 | if (clientUrlExists(node.getChildAt(i), url)) { 137 | return true; 138 | } 139 | } 140 | return false; 141 | } 142 | 143 | var extClient = control.getExtensionLoader().getExtension("ExtensionClientIntegration"); 144 | var clientRoot; 145 | if (extClient) { 146 | clientRoot = FieldUtils.readField(extClient, "clientTree", true).getRoot(); 147 | } 148 | var found = 0; 149 | var foundStandard = 0; 150 | var foundAjax = 0; 151 | var foundClient = 0; 152 | var total = expectedResults.length; 153 | 154 | var target = 'security-crawl-maze.app'; 155 | var siteTree = org.parosproxy.paros.model.Model.getSingleton().getSession().getSiteTree(); 156 | 157 | var FileWriter = Java.type('java.io.FileWriter'); 158 | var PrintWriter = Java.type('java.io.PrintWriter'); 159 | 160 | var yamlFile = "/zap/wrk/all.yml"; 161 | var fw = new FileWriter(yamlFile); 162 | var pw = new PrintWriter(fw); 163 | 164 | pw.println('section: All URLs'); 165 | pw.println('target: ' + target); 166 | pw.println('details:'); 167 | 168 | for (var i in expectedResults) { 169 | var res = expectedResults[i]; 170 | var scheme = 'http'; 171 | var node = findNode(scheme, res); 172 | if (!node) { 173 | scheme = 'https'; 174 | node = findNode(scheme, res); 175 | } 176 | 177 | pw.println('- path: ' + res); 178 | var standardResult = "FAIL"; 179 | var ajaxResult = "FAIL"; 180 | var clientResult = "FAIL"; 181 | var passed = false; 182 | if (node) { 183 | passed = true; 184 | if (node.hasHistoryType(HistoryReference.TYPE_SPIDER)) { 185 | standardResult = "Pass"; 186 | foundStandard++; 187 | } 188 | if (node.hasHistoryType(HistoryReference.TYPE_SPIDER_AJAX)) { 189 | ajaxResult = "Pass"; 190 | foundAjax++; 191 | } 192 | if (node.hasHistoryType(HistoryReference.TYPE_CLIENT_SPIDER)) { 193 | clientResult = "Pass"; 194 | foundClient++; 195 | } 196 | } 197 | if (clientResult !== "Pass" && extClient && clientUrlExists(clientRoot, scheme + "://" + target + res)) { 198 | clientResult = "Pass"; 199 | passed = true; 200 | foundClient++; 201 | } 202 | if (passed) { 203 | found++; 204 | } 205 | pw.println(' scheme: ' + scheme); 206 | pw.println(' standard: ' + standardResult); 207 | pw.println(' ajax: ' + ajaxResult); 208 | pw.println(' client: ' + clientResult); 209 | } 210 | 211 | print('tests: ' + total); 212 | print('passes: ' + found); 213 | print('standardPasses: ' + foundStandard); 214 | print('ajaxPasses: ' + foundAjax); 215 | print('clientPasses: ' + foundClient); 216 | print('fails: ' + (total - found)); 217 | 218 | pw.println('tests: ' + total); 219 | pw.println('passes: ' + found); 220 | pw.println('standardPasses: ' + foundStandard); 221 | pw.println('ajaxPasses: ' + foundAjax); 222 | pw.println('clientPasses: ' + foundClient); 223 | pw.println('fails: ' + (total - found)); 224 | pw.println('score: ' + Math.round(found * 100 / total) + '%'); 225 | 226 | print('Done'); 227 | 228 | pw.close(); 229 | -------------------------------------------------------------------------------- /scans/crawlmaze/crawl-maze.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "Security Crawl Maze" 5 | urls: 6 | - "https://security-crawl-maze.app/" 7 | - "http://security-crawl-maze.app/" 8 | includePaths: [] 9 | excludePaths: [] 10 | authentication: 11 | parameters: {} 12 | verification: 13 | method: "response" 14 | pollFrequency: 60 15 | pollUnits: "requests" 16 | sessionManagement: 17 | method: "cookie" 18 | parameters: {} 19 | parameters: 20 | failOnError: true 21 | failOnWarning: false 22 | progressToStdout: true 23 | vars: {} 24 | jobs: 25 | - name: "add-script" 26 | type: script 27 | parameters: 28 | action: add 29 | type: standalone 30 | file: /zap/wrk/crawl-maze-score.js 31 | - parameters: 32 | maxDepth: 100 33 | name: "spider" 34 | type: "spider" 35 | tests: 36 | - onFail: "INFO" 37 | statistic: "automation.spider.urls.added" 38 | site: "" 39 | operator: ">=" 40 | value: 100 41 | name: "At least 100 URLs found" 42 | type: "stats" 43 | - parameters: 44 | numberOfBrowsers: 1 45 | maxCrawlDepth: 100 46 | name: "spiderClient" 47 | type: "spiderClient" 48 | - parameters: 49 | numberOfBrowsers: 1 50 | maxCrawlDepth: 100 51 | name: "spiderAjax" 52 | type: "spiderAjax" 53 | - name: "run-script" 54 | type: script 55 | parameters: 56 | action: run 57 | type: standalone 58 | name: crawl-maze-score.js 59 | -------------------------------------------------------------------------------- /scans/firingrange/README.md: -------------------------------------------------------------------------------- 1 | # ZAP Vs Firing Range 2 | 3 | The files in this directory are used to run ZAP against Firing Range and publish the results to https://www.zaproxy.org/docs/scans/firingrange/ 4 | 5 | They are run via the GitHub Action: 'ZAP vs Firing Range'. 6 | 7 | -------------------------------------------------------------------------------- /scans/firingrange/firing-range-score-main.js: -------------------------------------------------------------------------------- 1 | 2 | // This script will _not_ run on its own - it needs a set of fields prepended to it 3 | 4 | // Polyfill for Nashorn c/o https://stackoverflow.com/questions/47543566/scriptengine-javascript-doesnt-support-includes 5 | if (!Array.prototype.includes) { 6 | Object.defineProperty(Array.prototype, 'includes', { 7 | value: function(valueToFind, fromIndex) { 8 | if (this == null) { 9 | throw new TypeError('\"this\" is null or not defined'); 10 | } 11 | var o = Object(this); 12 | var len = o.length >>> 0; 13 | if (len === 0) { return false; } 14 | var n = fromIndex | 0; 15 | var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); 16 | function sameValueZero(x, y) { return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y)); } 17 | while (k < len) { if (sameValueZero(o[k], valueToFind)) { return true; } k++; } return false; 18 | } 19 | }); 20 | } 21 | 22 | var totalUrls = 0; 23 | var totalAlerts = 0; 24 | var target = 'https://public-firing-range.appspot.com/' + TARGET; 25 | 26 | var FileWriter = Java.type('java.io.FileWriter'); 27 | var PrintWriter = Java.type('java.io.PrintWriter'); 28 | 29 | var YAML_FILE = DIR + "/" + TARGET + ".yml"; 30 | var fw = new FileWriter(YAML_FILE); 31 | var pw = new PrintWriter(fw); 32 | 33 | pw.println('section: ' + NAME); 34 | pw.println('url: ' + target); 35 | pw.println('details:'); 36 | 37 | function nodeHasAlert(node, rules) { 38 | var alerts = node.getAlerts(); 39 | for (var a in alerts) { 40 | var pluginId = alerts.get(a).getPluginId(); 41 | if (rules.includes(pluginId)) { 42 | return pluginId; 43 | } 44 | } 45 | return null; 46 | } 47 | 48 | function listChildren(node, level) { 49 | var j; 50 | for (j=0;j MIN_LEVEL) { 53 | var path = child.getHierarchicNodeName().substring(target.length); 54 | if (! IGNORE_PATHS.includes(path)) { 55 | totalUrls++; 56 | pw.println('- path: ' + path); 57 | var pluginId = nodeHasAlert(child, RULES); 58 | if (pluginId) { 59 | totalAlerts++; 60 | pw.println(' result: Pass'); 61 | pw.println(' rule: ' + pluginId); 62 | } else { 63 | pw.println(' result: FAIL'); 64 | pw.println(' rule: ' + RULES[0]); 65 | } 66 | } 67 | } else { 68 | listChildren(child, level+1); 69 | } 70 | } 71 | } 72 | 73 | root = org.parosproxy.paros.model.Model.getSingleton(). 74 | getSession().getSiteTree().getRoot(); 75 | 76 | listChildren(root, 0); 77 | 78 | pw.println('tests: ' + totalUrls); 79 | pw.println('passes: ' + totalAlerts); 80 | pw.println('fails: ' + (totalUrls - totalAlerts)); 81 | pw.println('score: ' + Math.round(totalAlerts * 100 / totalUrls) + '%'); 82 | 83 | print('Done'); 84 | 85 | pw.close(); 86 | -------------------------------------------------------------------------------- /scans/firingrange/fr-clickjacking.js: -------------------------------------------------------------------------------- 1 | var DIR = "/zap/wrk/"; 2 | var NAME = "Clickjacking"; 3 | var TARGET = "clickjacking"; 4 | var RULES = [10020,10055]; 5 | var MIN_LEVEL = 1; 6 | var IGNORE_PATHS = ['/']; 7 | -------------------------------------------------------------------------------- /scans/firingrange/fr-clickjacking.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "Firing Range" 5 | urls: 6 | - "https://public-firing-range.appspot.com/clickjacking/" 7 | includePaths: [] 8 | excludePaths: [] 9 | authentication: 10 | parameters: {} 11 | verification: 12 | method: "response" 13 | pollFrequency: 60 14 | pollUnits: "requests" 15 | sessionManagement: 16 | method: "cookie" 17 | parameters: {} 18 | parameters: 19 | failOnError: true 20 | failOnWarning: false 21 | progressToStdout: true 22 | vars: {} 23 | jobs: 24 | - name: "add-script" 25 | type: script 26 | parameters: 27 | action: add 28 | type: standalone 29 | file: /zap/wrk/firing-range-score.js 30 | - parameters: {} 31 | name: "spider" 32 | type: "spider" 33 | tests: 34 | - onFail: "INFO" 35 | statistic: "automation.spider.urls.added" 36 | site: "" 37 | operator: ">=" 38 | value: 100 39 | name: "At least 100 URLs found" 40 | type: "stats" 41 | - parameters: {} 42 | name: "passiveScan-wait" 43 | type: "passiveScan-wait" 44 | - name: "run-script" 45 | type: script 46 | parameters: 47 | action: run 48 | type: standalone 49 | name: firing-range-score.js 50 | -------------------------------------------------------------------------------- /scans/firingrange/fr-escape.js: -------------------------------------------------------------------------------- 1 | var DIR = "/zap/wrk/"; 2 | var NAME = "Escaped XSS"; 3 | var TARGET = "escape"; 4 | var RULES = [40012]; 5 | var MIN_LEVEL = 2; 6 | var IGNORE_PATHS = ['/serverside/encodeUrl/a', '/serverside/escapeHtml/a']; 7 | -------------------------------------------------------------------------------- /scans/firingrange/fr-escape.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "Firing Range" 5 | urls: 6 | - "https://public-firing-range.appspot.com/escape/" 7 | includePaths: [] 8 | excludePaths: [] 9 | authentication: 10 | parameters: {} 11 | verification: 12 | method: "response" 13 | pollFrequency: 60 14 | pollUnits: "requests" 15 | sessionManagement: 16 | method: "cookie" 17 | parameters: {} 18 | parameters: 19 | failOnError: true 20 | failOnWarning: false 21 | progressToStdout: true 22 | vars: {} 23 | jobs: 24 | - name: "add-script" 25 | type: script 26 | parameters: 27 | action: add 28 | type: standalone 29 | file: /zap/wrk/firing-range-score.js 30 | - parameters: {} 31 | name: "spider" 32 | type: "spider" 33 | tests: 34 | - onFail: "INFO" 35 | statistic: "automation.spider.urls.added" 36 | site: "" 37 | operator: ">=" 38 | value: 100 39 | name: "At least 100 URLs found" 40 | type: "stats" 41 | - parameters: 42 | context: "" 43 | user: "" 44 | policy: "" 45 | maxRuleDurationInMins: 0 46 | maxScanDurationInMins: 0 47 | policyDefinition: 48 | defaultStrength: "medium" 49 | defaultThreshold: "off" 50 | rules: 51 | - id: 40012 52 | name: "Cross Site Scripting (Reflected)" 53 | threshold: "medium" 54 | strength: "default" 55 | name: "activeScan" 56 | type: "activeScan" 57 | - name: "run-script" 58 | type: script 59 | parameters: 60 | action: run 61 | type: standalone 62 | name: firing-range-score.js 63 | -------------------------------------------------------------------------------- /scans/firingrange/fr-leakedcookie.js: -------------------------------------------------------------------------------- 1 | var DIR = "/zap/wrk/"; 2 | var NAME = "Leaked httpOnly cookie"; 3 | var TARGET = "leakedcookie"; 4 | var RULES = [10011]; 5 | var MIN_LEVEL = 1; 6 | var IGNORE_PATHS = ['/', '/leakedcookie.js']; -------------------------------------------------------------------------------- /scans/firingrange/fr-leakedcookie.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "Firing Range" 5 | urls: 6 | - "https://public-firing-range.appspot.com/leakedcookie/" 7 | includePaths: [] 8 | excludePaths: [] 9 | authentication: 10 | parameters: {} 11 | verification: 12 | method: "response" 13 | pollFrequency: 60 14 | pollUnits: "requests" 15 | sessionManagement: 16 | method: "cookie" 17 | parameters: {} 18 | parameters: 19 | failOnError: true 20 | failOnWarning: false 21 | progressToStdout: true 22 | vars: {} 23 | jobs: 24 | - name: "add-script" 25 | type: script 26 | parameters: 27 | action: add 28 | type: standalone 29 | file: /zap/wrk/firing-range-score.js 30 | - parameters: {} 31 | name: "spider" 32 | type: "spider" 33 | tests: 34 | - onFail: "INFO" 35 | statistic: "automation.spider.urls.added" 36 | site: "" 37 | operator: ">=" 38 | value: 100 39 | name: "At least 100 URLs found" 40 | type: "stats" 41 | - parameters: {} 42 | name: "passiveScan-wait" 43 | type: "passiveScan-wait" 44 | - name: "run-script" 45 | type: script 46 | parameters: 47 | action: run 48 | type: standalone 49 | name: firing-range-score.js 50 | -------------------------------------------------------------------------------- /scans/firingrange/fr-mixedcontent.js: -------------------------------------------------------------------------------- 1 | var DIR = "/zap/wrk/"; 2 | var NAME = "Mixed content"; 3 | var TARGET = "mixedcontent"; 4 | var RULES = [10040]; 5 | var MIN_LEVEL = 1; 6 | var IGNORE_PATHS = ['xxx']; 7 | -------------------------------------------------------------------------------- /scans/firingrange/fr-mixedcontent.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "Firing Range" 5 | urls: 6 | - "https://public-firing-range.appspot.com/mixedcontent/" 7 | includePaths: [] 8 | excludePaths: [] 9 | authentication: 10 | parameters: {} 11 | verification: 12 | method: "response" 13 | pollFrequency: 60 14 | pollUnits: "requests" 15 | sessionManagement: 16 | method: "cookie" 17 | parameters: {} 18 | parameters: 19 | failOnError: true 20 | failOnWarning: false 21 | progressToStdout: true 22 | vars: {} 23 | jobs: 24 | - name: "add-script" 25 | type: script 26 | parameters: 27 | action: add 28 | type: standalone 29 | file: /zap/wrk/firing-range-score.js 30 | - parameters: {} 31 | name: "spider" 32 | type: "spider" 33 | tests: 34 | - onFail: "INFO" 35 | statistic: "automation.spider.urls.added" 36 | site: "" 37 | operator: ">=" 38 | value: 100 39 | name: "At least 100 URLs found" 40 | type: "stats" 41 | - parameters: {} 42 | name: "passiveScan-wait" 43 | type: "passiveScan-wait" 44 | - name: "run-script" 45 | type: script 46 | parameters: 47 | action: run 48 | type: standalone 49 | name: firing-range-score.js 50 | -------------------------------------------------------------------------------- /scans/firingrange/fr-reflected.js: -------------------------------------------------------------------------------- 1 | var DIR = "/zap/wrk/"; 2 | var NAME = "Reflected XSS"; 3 | var TARGET = "reflected"; 4 | var RULES = [40012]; 5 | var MIN_LEVEL = 2; 6 | var IGNORE_PATHS = ['/parameter/form', '/url/a']; 7 | -------------------------------------------------------------------------------- /scans/firingrange/fr-reflected.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "Firing Range" 5 | urls: 6 | - "https://public-firing-range.appspot.com/reflected/" 7 | includePaths: [] 8 | excludePaths: [] 9 | authentication: 10 | parameters: {} 11 | verification: 12 | method: "response" 13 | pollFrequency: 60 14 | pollUnits: "requests" 15 | sessionManagement: 16 | method: "cookie" 17 | parameters: {} 18 | parameters: 19 | failOnError: true 20 | failOnWarning: false 21 | progressToStdout: true 22 | vars: {} 23 | jobs: 24 | - name: "add-script" 25 | type: script 26 | parameters: 27 | action: add 28 | type: standalone 29 | file: /zap/wrk/firing-range-score.js 30 | - parameters: {} 31 | name: "spider" 32 | type: "spider" 33 | tests: 34 | - onFail: "INFO" 35 | statistic: "automation.spider.urls.added" 36 | site: "" 37 | operator: ">=" 38 | value: 100 39 | name: "At least 100 URLs found" 40 | type: "stats" 41 | - parameters: 42 | context: "" 43 | user: "" 44 | policy: "" 45 | maxRuleDurationInMins: 0 46 | maxScanDurationInMins: 0 47 | policyDefinition: 48 | defaultStrength: "medium" 49 | defaultThreshold: "off" 50 | rules: 51 | - id: 40012 52 | name: "Cross Site Scripting (Reflected)" 53 | threshold: "low" 54 | strength: "default" 55 | name: "activeScan" 56 | type: "activeScan" 57 | - name: "run-script" 58 | type: script 59 | parameters: 60 | action: run 61 | type: standalone 62 | name: firing-range-score.js 63 | -------------------------------------------------------------------------------- /scans/firingrange/fr-remoteinclude.js: -------------------------------------------------------------------------------- 1 | var DIR = "/zap/wrk/"; 2 | var NAME = "Remote Inclusion XSS"; 3 | var TARGET = "remoteinclude"; 4 | var RULES = [40012, 40026]; 5 | var MIN_LEVEL = 1; 6 | var IGNORE_PATHS = ['/']; 7 | -------------------------------------------------------------------------------- /scans/firingrange/fr-remoteinclude.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "Firing Range" 5 | urls: 6 | - "https://public-firing-range.appspot.com/remoteinclude/" 7 | includePaths: [] 8 | excludePaths: [] 9 | authentication: 10 | parameters: {} 11 | verification: 12 | method: "response" 13 | pollFrequency: 60 14 | pollUnits: "requests" 15 | sessionManagement: 16 | method: "cookie" 17 | parameters: {} 18 | parameters: 19 | failOnError: true 20 | failOnWarning: false 21 | progressToStdout: true 22 | vars: {} 23 | jobs: 24 | - name: "add-script" 25 | type: script 26 | parameters: 27 | action: add 28 | type: standalone 29 | file: /zap/wrk/firing-range-score.js 30 | - parameters: {} 31 | name: "spider" 32 | type: "spider" 33 | tests: 34 | - onFail: "INFO" 35 | statistic: "automation.spider.urls.added" 36 | site: "" 37 | operator: ">=" 38 | value: 100 39 | name: "At least 100 URLs found" 40 | type: "stats" 41 | - parameters: 42 | context: "" 43 | user: "" 44 | policy: "" 45 | maxRuleDurationInMins: 0 46 | maxScanDurationInMins: 0 47 | policyDefinition: 48 | defaultStrength: "medium" 49 | defaultThreshold: "off" 50 | rules: 51 | - id: 40012 52 | name: "Cross Site Scripting (Reflected)" 53 | threshold: "medium" 54 | strength: "default" 55 | - id: 40026 56 | name: "Cross Site Scripting (DOM)" 57 | threshold: "medium" 58 | strength: "default" 59 | name: "activeScan" 60 | type: "activeScan" 61 | - name: "run-script" 62 | type: script 63 | parameters: 64 | action: run 65 | type: standalone 66 | name: firing-range-score.js 67 | -------------------------------------------------------------------------------- /scans/firingrange/fr-reverseclickjacking.js: -------------------------------------------------------------------------------- 1 | var DIR = "/zap/wrk/"; 2 | var NAME = "Reverse ClickJacking"; 3 | var TARGET = "reverseclickjacking"; 4 | var RULES = [10020]; 5 | var MIN_LEVEL = 1; 6 | var IGNORE_PATHS = ['/', '/jsonpendpoint']; 7 | -------------------------------------------------------------------------------- /scans/firingrange/fr-reverseclickjacking.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "Firing Range" 5 | urls: 6 | - "https://public-firing-range.appspot.com/reverseclickjacking/" 7 | includePaths: [] 8 | excludePaths: [] 9 | authentication: 10 | parameters: {} 11 | verification: 12 | method: "response" 13 | pollFrequency: 60 14 | pollUnits: "requests" 15 | sessionManagement: 16 | method: "cookie" 17 | parameters: {} 18 | parameters: 19 | failOnError: true 20 | failOnWarning: false 21 | progressToStdout: true 22 | vars: {} 23 | jobs: 24 | - name: "add-script" 25 | type: script 26 | parameters: 27 | action: add 28 | type: standalone 29 | file: /zap/wrk/firing-range-score.js 30 | - parameters: {} 31 | name: "spider" 32 | type: "spider" 33 | tests: 34 | - onFail: "INFO" 35 | statistic: "automation.spider.urls.added" 36 | site: "" 37 | operator: ">=" 38 | value: 100 39 | name: "At least 100 URLs found" 40 | type: "stats" 41 | - parameters: {} 42 | name: "passiveScan-wait" 43 | type: "passiveScan-wait" 44 | - name: "run-script" 45 | type: script 46 | parameters: 47 | action: run 48 | type: standalone 49 | name: firing-range-score.js 50 | -------------------------------------------------------------------------------- /scans/juiceshop/juice-shop-score.js: -------------------------------------------------------------------------------- 1 | // Score ZAP against OWASP Juice Shop 2 | // 3 | // You will need to have run the ZAP AJAX Spider against a local instance of Juice Shop 4 | 5 | // Expected results sourced from manual exploring + the AJAX Spider 6 | 7 | var expectedResults = [ 8 | "GET http://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css", 9 | "GET http://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js", 10 | "GET http://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js", 11 | "GET http://localhost:3000/", 12 | "GET http://localhost:3000/ae.svg", 13 | "GET http://localhost:3000/api/Challenges/(name)", 14 | "GET http://localhost:3000/api/Feedbacks/", 15 | "GET http://localhost:3000/api/Quantitys/", 16 | "GET http://localhost:3000/assets/i18n/en.json", 17 | "GET http://localhost:3000/assets/public/favicon_js.ico", 18 | "GET http://localhost:3000/assets/public/images/carousel/1.jpg", 19 | "GET http://localhost:3000/assets/public/images/carousel/2.jpg", 20 | "GET http://localhost:3000/assets/public/images/carousel/3.jpg", 21 | "GET http://localhost:3000/assets/public/images/carousel/4.jpg", 22 | "GET http://localhost:3000/assets/public/images/carousel/5.png", 23 | "GET http://localhost:3000/assets/public/images/carousel/6.jpg", 24 | "GET http://localhost:3000/assets/public/images/carousel/7.jpg", 25 | "GET http://localhost:3000/assets/public/images/hackingInstructor.png", 26 | "GET http://localhost:3000/assets/public/images/JuiceShop_Logo.png", 27 | "GET http://localhost:3000/assets/public/images/products/apple_juice.jpg", 28 | "GET http://localhost:3000/assets/public/images/products/apple_pressings.jpg", 29 | "GET http://localhost:3000/assets/public/images/products/artwork2.jpg", 30 | "GET http://localhost:3000/assets/public/images/products/banana_juice.jpg", 31 | "GET http://localhost:3000/assets/public/images/products/carrot_juice.jpeg", 32 | "GET http://localhost:3000/assets/public/images/products/eggfruit_juice.jpg", 33 | "GET http://localhost:3000/assets/public/images/products/fan_facemask.jpg", 34 | "GET http://localhost:3000/assets/public/images/products/fan_girlie.jpg", 35 | "GET http://localhost:3000/assets/public/images/products/fruit_press.jpg", 36 | "GET http://localhost:3000/assets/public/images/products/green_smoothie.jpg", 37 | "GET http://localhost:3000/assets/public/images/products/lemon_juice.jpg", 38 | "GET http://localhost:3000/assets/public/images/products/melon_bike.jpeg", 39 | "GET http://localhost:3000/assets/public/images/products/permafrost.jpg", 40 | "GET http://localhost:3000/az.svg", 41 | "GET http://localhost:3000/font-mfizz.woff", 42 | "GET http://localhost:3000/ftp/legal.md", 43 | "GET http://localhost:3000/main.js", 44 | "GET http://localhost:3000/MaterialIcons-Regular.woff2", 45 | "GET http://localhost:3000/polyfills.js", 46 | "GET http://localhost:3000/rest/admin/application-configuration", 47 | "GET http://localhost:3000/rest/admin/application-version", 48 | "GET http://localhost:3000/rest/captcha/", 49 | "GET http://localhost:3000/rest/languages", 50 | "GET http://localhost:3000/rest/products/1/reviews", 51 | "GET http://localhost:3000/rest/products/search(q)", 52 | "GET http://localhost:3000/rest/user/whoami", 53 | "GET http://localhost:3000/runtime.js", 54 | "GET http://localhost:3000/socket.io/(EIO,sid,t,transport)", 55 | "POST http://localhost:3000/socket.io/(EIO,sid,t,transport)(40)", 56 | "GET http://localhost:3000/socket.io/(EIO,sid,transport)", 57 | "GET http://localhost:3000/socket.io/(EIO,t,transport)", 58 | "GET http://localhost:3000/styles.css", 59 | "GET http://localhost:3000/tutorial.js", 60 | "GET http://localhost:3000/vendor.js" 61 | ] 62 | 63 | function listChildren(node, array) { 64 | var j; 65 | var parentName = node.getHierarchicNodeName(); 66 | for (j=0;j -1) { 125 | if (foundUrls.indexOf(item) > -1) { 126 | pw.println (' ajax: Pass'); 127 | pass +=1; 128 | } else { 129 | pw.println (' ajax: FAIL'); 130 | fail +=1; 131 | } 132 | } else { 133 | pw.println (' ajax: New'); 134 | newu +=1; 135 | } 136 | } 137 | 138 | var total = pass + fail; 139 | pw.println('tests: ' + total); 140 | pw.println('passes: ' + pass); 141 | pw.println('fails: ' + fail); 142 | pw.println('score: ' + Math.round(pass * 100 / total) + '%'); 143 | 144 | print('tests: ' + total); 145 | print('passes: ' + pass); 146 | print('fails: ' + fail); 147 | print('new: ' + newu); 148 | print('Done'); 149 | 150 | pw.close(); 151 | -------------------------------------------------------------------------------- /scans/juiceshop/juice-shop.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "Juice Shop" 5 | urls: 6 | - "http://localhost:3000/" 7 | includePaths: [] 8 | excludePaths: [] 9 | authentication: 10 | parameters: {} 11 | verification: 12 | method: "response" 13 | pollFrequency: 60 14 | pollUnits: "requests" 15 | sessionManagement: 16 | method: "cookie" 17 | parameters: {} 18 | parameters: 19 | failOnError: true 20 | failOnWarning: false 21 | progressToStdout: true 22 | vars: {} 23 | jobs: 24 | - name: "add-script" 25 | type: script 26 | parameters: 27 | action: add 28 | type: standalone 29 | file: /zap/wrk/juice-shop-score.js 30 | - parameters: 31 | numberOfBrowsers: 10 32 | name: "spiderAjax" 33 | type: "spiderAjax" 34 | - name: "run-script" 35 | type: script 36 | parameters: 37 | action: run 38 | type: standalone 39 | name: juice-shop-score.js 40 | -------------------------------------------------------------------------------- /scans/ssti/ssti-score-main.js: -------------------------------------------------------------------------------- 1 | // This script will _not_ run on its own - it needs a set of fields prepended to it 2 | var YAML_FILE = "/zap/wrk/all.yml"; 3 | var RULES = [40012, 40026, 90019, 90025, 90035, 90036]; 4 | var target = 'http://localhost:' + PORT + '/'; 5 | 6 | var FileWriter = Java.type('java.io.FileWriter'); 7 | var PrintWriter = Java.type('java.io.PrintWriter'); 8 | 9 | var fw = new FileWriter(YAML_FILE, true); 10 | var pw = new PrintWriter(fw); 11 | 12 | function nodeHasAlert(node, pluginId) { 13 | var alerts = node.getAlerts(); 14 | for (var a in alerts) { 15 | if (pluginId == alerts.get(a).getPluginId()) { 16 | return true; 17 | } 18 | } 19 | return false; 20 | } 21 | 22 | function hasAlert(node, pluginId) { 23 | var j; 24 | for (j = 0; j < node.getChildCount(); j++) { 25 | var child = node.getChildAt(j); 26 | if (child.getChildCount() == 0) { 27 | if (nodeHasAlert(child, pluginId)) { 28 | return true; 29 | } 30 | } else { 31 | if (hasAlert(child, pluginId)) { 32 | return true; 33 | } 34 | } 35 | } 36 | return false; 37 | } 38 | 39 | var root = org.parosproxy.paros.model.Model.getSingleton(). 40 | getSession().getSiteTree().getRoot(); 41 | var any = 'FAIL'; 42 | 43 | pw.println('- title: \'' + TITLE + '\''); 44 | 45 | for (var i in RULES) { 46 | var pluginId = RULES[i]; 47 | if (hasAlert(root, pluginId)) { 48 | pw.println(' rule_' + pluginId + ': Pass'); 49 | any = 'Pass'; 50 | } else { 51 | pw.println(' rule_' + pluginId + ': FAIL'); 52 | } 53 | } 54 | pw.println(' any: ' + any); 55 | pw.close(); 56 | 57 | print('Done'); 58 | -------------------------------------------------------------------------------- /scans/ssti/ssti.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | declare -a targets=( 3 | [5000]="Jinja2 - Python" 4 | [5001]="Mako - Python" 5 | [5002]="Tornado - Python" 6 | [5002]="Django - Python" 7 | [5002]="(Code eval) - Python" 8 | [5005]="(Code exec) - Python" 9 | [5020]="Smarty - PHP" 10 | [5021]="Smarty (secure mode) - PHP" 11 | [5022]="Twig - PHP" 12 | [5023]="(Code eval) - PHP" 13 | [5051]="FreeMarker - Java" 14 | [5052]="Velocity - Java" 15 | [5053]="Thymeleaf - Java " 16 | [5061]="Jade - Nodejs" 17 | [5062]="Nunjucks - JavaScript" 18 | [5063]="doT - JavaScript" 19 | [5065]="Dust - JavaScript" 20 | [5066]="EJS - JavaScript" 21 | [5067]="(Code eval) - JavaScript" 22 | [5068]="VueJs - JavaScript" 23 | [5080]="Slim - Ruby" 24 | [5081]="ERB - Ruby" 25 | [5082]="(Code eval) - Ruby" 26 | [5090]="go - go" 27 | [6001]="Input rendered in other location" 28 | [6002]="Rendering result not visible to attacker" 29 | [6003]="Input inserted in the middle of template code math operations" 30 | [6005]="Input inserted in the middle of template code text" 31 | [6004]="Non Vulnerable" 32 | [6010]="\{ \} Python Eval" 33 | [6011]="$\{ \} Python Eval" 34 | [6012]="\{\{ \}\} Python Eval" 35 | [6013]="<%= %> Python Eval ERB" 36 | [6014]="#\{ \} Python Eval" 37 | [6015]="\{\{= \}\} Python Eval" 38 | [6020]="\{ \} Ruby Eval" 39 | [6021]="$\{ \} Ruby Eval" 40 | [6022]="\{\{ \}\} Ruby Eval YBNE Nunjucks" 41 | [6023]="<%= %> Ruby Eval Erb" 42 | [6024]="#\{ \} Ruby Eval" 43 | [6025]="\{\{= \}\} Ruby Eval" 44 | ) 45 | 46 | cd /zap/wrk/ 47 | 48 | export file=/zap/wrk/all.yml 49 | 50 | /zap/zap.sh -silent -addoninstall ascanrulesAlpha -cmd 51 | 52 | echo "section: All URLs" > $file 53 | echo "details:" >> $file 54 | 55 | for i in "${!targets[@]}"; do 56 | echo "var PORT = $i;" > ssti-score.js 57 | echo "var TITLE = \"${targets[$i]}\";" >> ssti-score.js 58 | cat ssti-score-main.js >> ssti-score.js 59 | echo "$i -> ${targets[$i]}"; 60 | export port=$i 61 | pwd 62 | /zap/zap.sh -silent -autorun /zap/wrk/ssti.yaml -cmd 63 | cat $file 64 | sleep 5 65 | done 66 | 67 | pass=`grep -c "any: Pass" $file` 68 | fail=`grep -c "any: FAIL" $file` 69 | 70 | let "score = ($pass * 100) / ($pass + $fail)" 71 | 72 | echo "score: $score%" >> $file 73 | 74 | for rule in rule_40012 rule_40026 rule_90019 rule_90025 rule_90035 rule_90036 any; do 75 | rulescore=`grep -c "$rule: Pass" $file` 76 | echo "${rule}_score: $rulescore" >> $file 77 | done 78 | 79 | echo Pass: $pass 80 | echo Fail: $fail 81 | echo Score: $score% 82 | -------------------------------------------------------------------------------- /scans/ssti/ssti.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | contexts: 4 | - name: "SSTI" 5 | urls: 6 | - "http://localhost:${port}/" 7 | includePaths: [] 8 | excludePaths: [] 9 | parameters: 10 | failOnError: true 11 | failOnWarning: false 12 | progressToStdout: true 13 | vars: {} 14 | jobs: 15 | - name: "add-script" 16 | type: script 17 | parameters: 18 | action: add 19 | type: standalone 20 | file: /zap/wrk/ssti-score.js 21 | - parameters: 22 | updateAddOns: false 23 | install: [] 24 | uninstall: [] 25 | name: "addOns" 26 | type: "addOns" 27 | - parameters: 28 | scanOnlyInScope: true 29 | enableTags: false 30 | rules: [] 31 | name: "passiveScan-config" 32 | type: "passiveScan-config" 33 | - parameters: {} 34 | name: "spider" 35 | type: "spider" 36 | tests: 37 | - onFail: "INFO" 38 | statistic: "automation.spider.urls.added" 39 | site: "" 40 | operator: ">=" 41 | value: 1 42 | name: "At least 1 URLs found" 43 | type: "stats" 44 | - parameters: {} 45 | name: "passiveScan-wait" 46 | type: "passiveScan-wait" 47 | - parameters: 48 | context: "" 49 | user: "" 50 | policy: "" 51 | maxRuleDurationInMins: 0 52 | maxScanDurationInMins: 0 53 | policyDefinition: 54 | defaultStrength: "medium" 55 | defaultThreshold: "off" 56 | rules: 57 | - id: 40012 58 | name: "Cross Site Scripting (Reflected)" 59 | threshold: "medium" 60 | strength: "default" 61 | - id: 40026 62 | name: "Cross Site Scripting (DOM Based)" 63 | threshold: "medium" 64 | strength: "high" 65 | - id: 90019 66 | name: "Server Side Code Injection" 67 | threshold: "medium" 68 | strength: "default" 69 | - id: 90025 70 | name: "Expression Language Injection" 71 | threshold: "medium" 72 | strength: "default" 73 | - id: 90035 74 | name: "Expression Language Injection" 75 | threshold: "medium" 76 | strength: "default" 77 | - id: 90036 78 | name: "Expression Language Injection" 79 | threshold: "medium" 80 | strength: "default" 81 | name: "activeScan" 82 | type: "activeScan" 83 | - name: "run-script" 84 | type: script 85 | parameters: 86 | action: run 87 | type: standalone 88 | name: ssti-score.js 89 | -------------------------------------------------------------------------------- /scans/webseclab/ScoreWebSecLab.js: -------------------------------------------------------------------------------- 1 | var TARGET = "xss/reflect"; 2 | var RULES = [40012]; 3 | var MIN_LEVEL = 1; 4 | var IGNORE_PATHS = ['', 'write', 'write_hash', 'write_hash_urlstyle', 'node_hash', 'node_hash_unencoded', 'node_hash_urlstyle', 5 | '/post1', '/post1_splash', '/raw1', '/raw1_fp', '/full_cookies1', '/full_headers1', '/full_useragent1', 6 | '/xyz', '/xyz/*http:', '/xyz//example.com', 'lab_refer.html(