RapiDAST provides a framework for continuous, proactive and fully automated dynamic scanning against web apps/API.
Its core engine is OWASP ZAP Proxy (https://owasp.org/www-project-zap/). Taking advantage of the ZAP container, this project provides value as follows:
- Easy automation(via fully working in CLI with yaml configuration) of API scanning based on OAS definition
- Ability to run the automated API scanning on Kubernetes (or Red Hat OpenShift)
- Ability to create custom rules via yaml files
- HTML, JSON report generation (XML is also possible)
- podman or docker is required.
- podman-compose or docker-compose is required.
If you're wanting to run on kubernetes or OpenShift cluster you can also install using OLM or helm, see more information on this README.md
- Create config.yaml, place it in config/ and set the config values for your API. You can use config/config-template-local.yaml as an example
- Get OAS3/Swagger definition files (either URL or in the directory specified in config[openapi][directory] in the config.yaml file)
- Set the target URL in config.yaml
- Create an .env file in the project root and set the API_KEY and other variables as necessary in it
# This file will set environment variables inside zaproxy container
# API KEY should be set to ensure that public instances of ZAP can only be
# accessed by the intended clients
API_KEY=[GENERATE_RANDOM_STRING]
# oauth2 refresh_token used in authMethod: 'scriptBasedAuthentication' in config.yaml
#RTOKEN=[oauth_refresh_token]
# set this to handle basic auth when authMethod: null in config.yaml
# ZAP_AUTH_HEADER_VALUE=Basic [base64_encoded_creds]
Define authentication method for the context. Possible values are: "null", "scriptBasedAuthentication"
if set to null basic auth can be handled by setting the ZAP_AUTH_HEADER_VALUE=Basic [base64_encoded_creds] enviromental variable in /.env file
authMethod: null
There are 2 parts to script based auth: oauth access token that needs to be refreshed on expiration. This auth method will work on OAuth2 workflows only if offline_token is available
authMethod: 'scriptBasedAuthentication'
scriptAuth:
authScriptName: 'offline-token'
authScriptEngine: 'Oracle Nashorn'
authScriptFilePath: 'scripts/offline-token.js'
authScriptDescription: 'will automatically fetch the new access token for every unauthorized request'
authTokenEndpoint: [oauth_realm_token_endpoint]
authClientID: [oauth_client_id]
authCreateUser: True
To use Logged out authIndicatorRegex authIsLoggedInIndicator: False
regex expression that indicates the user is logged out and triggers the token refresh process authIndicatorRegex: '\QHTTP/1.1 401 Unauthorized\E'
Another authentication type is using HTTP sender script with a bearer token. These variables and script adds the bearer token header auth to each request
authMethod: null
useHttpSenderScript: True
HttpSenderScriptName: 'add-bearer-token'
HttpSenderScriptEngine: 'Oracle Nashorn'
HttpSenderScriptFilePath: 'scripts/add-bearer-token.js'
HttpSenderScriptDescription: 'add bearer token to each HTTP request'
HTTPParams: {} Any parameters you want to use in your authentication script, use in script with key, values that change at runtime
For OpenShift Authentication you will need the cookie name and value passed to the HTTPParams using scripts/add-token-cookie-param.js
example.) HTTPParams: {"cookieName": 'openshift-session-token', "cookieVal": 'sha256~**'}
See example of how to obtain these values in script
zaproxy container must be running (either runenv.sh or runenv-ui.sh)
- Get a URL for the OAS3 definition file
- Get a URL for the target API
- Create config.yaml with the URLs and place it in config/
- Set the API_KEY value in .env file
- zaproxy container must be running (either runenv.sh or runenv-ui.sh)
$ ./podman-wrapper.sh
For docker
$ ./runenv-docker.sh
- Launch a scan in the project root directory,
$ test/scan-example-with-podman.sh <dir_to_store_results>
OR
$ test/scan-example-with-docker.sh <dir_to_store_results>
When a scan is completed, its report will be generated in the results/<dir_to_store_results>
$ test/scan-example-with-podman.sh testrun
Deleting previously generated scripts
Loading the script to ZAP
Templating script Rule_Gen_05eec230-5ba0-4bf5-b1d0-43268b8542d2
Loading script Rule_Gen_05eec230-5ba0-4bf5-b1d0-43268b8542d2 in ZAP from /tmp/Rule_Gen_05eec230-5ba0-4bf5-b1d0-43268b8542d25k5s0yj7.js
Enabling script Rule_Gen_05eec230-5ba0-4bf5-b1d0-43268b8542d2 in ZAP
Script Rule_Gen_05eec230-5ba0-4bf5-b1d0-43268b8542d2 successfully loaded and enabled
Creating session in: /zap/results/testrun/sessions/20211210-041924/session1
Excluded URLs: ^(?:(?!http://192.168.109.202:9000).*).$
Include URL in context: http://192.168.109.202:9000/api/.*
Exclude URL from context:
Importing API: /zap/config/oas/openapi.json
>> Target Url: http://192.168.109.202:9000
Start Active scan. Scan ID equals 0
Scan Policies: ['API-minimal-example']
Active Scan progress: 0%
Active Scan completed
Waiting for Passive Scan to complete
Passive Scan completed
JSON report saved in: /zap/results/testrun/demo1-report-20220722-033427.json
HTML report saved in: /zap/results/testrun/demo1-report-20220722-033427.html
$ ./podman-wrapper.sh
OR
$ docker-compose zaproxy up
$ podman exec zaproxy python /zap/scripts/apis_scan.py <dirname_to_be_created_under_results_dir>
$ ./podman-wrapper.sh -s
OR
$ docker-compose down
This is taking advantage of ZAP's webswing feature. See https://www.zaproxy.org/docs/docker/webswing/. Note that any commercial organization that uses Webswing for non-evaluation purposes needs to have a valid commercial license of Webswing. See https://www.webswing.org/licensing for licensing information.
$ ./podman-wrapper.sh -w
OR
$ docker-compose zaproxy_ui up
After the step, it is necessary to navigate to the GUI via http://127.0.0.1:8081/zap to start an actual ZAP instance.
$ podman exec zaproxy python /zap/scripts/apis_scan.py <dirname_to_be_created_under_results_dir>
OR
$ docker exec zaproxy python /zap/scripts/apis_scan.py <dirname_to_be_created_under_results_dir>
$ ./podman-wrapper.sh -sw
(note: s
stands for stop, w
for WebUI)
OR
$ docker-compose down
It is possible to create a custom rule yaml file and apply to the ZAP instance. Refer to a few examples of the yaml rule files in the scripts/gen_zap_script/rules directory.
Apply custom rules to the running ZAP instance before launching a scan.
$ podman exec zaproxy python scripts/gen_zap_script/cli.py --from-yaml scripts/gen_zap_script/rules/software_version_revealed.yaml --rapidast-config=<config-file> --load-and-enable
$ docker exec zaproxy python scripts/gen_zap_script/cli.py --from-yaml scripts/gen_zap_script/rules/software_version_revealed.yaml --rapidast-config=<config-file> --load-and-enable
$ podman exec zaproxy python scripts/gen_zap_script/cli.py --rapidast-config=<config-file> --delete
OR
$ docker exec zaproxy python scripts/gen_zap_script/cli.py --rapidast-config=<config-file> --delete
You can find an example of an action in .github/workflows/rapidast-scan.yml. This action will run using docker. To config this follow this steps:
- Follow the "Prerequisites" section
- Set GitHub secret named "AUTH_CRED" with the base64 basic authentication credentials for the API to scan. For example:
dGVzdC11c2VyOnRlc3QtcGFzc3dvcmQ=
IMPORTANT: this action will upload the scan results as action artifacts. This contains info about the intercepted HTTP requests by ZAP which will contain your AUTH_CRED secret value in the Authorization header
See this for more information.
Contribution to the project is more than welcome.
See CONTRIBUTING.md