Wapiti
This image ships Wapiti on Ubuntu 24.04 LTS, ready to scan a running web application you own for vulnerabilities from the first boot of every deployed virtual machine. Wapiti is installed from PyPI, pinned to a known release inside an isolated virtualenv, with a simple wapiti command on the path.
Wapiti is an open source dynamic application security testing (DAST) tool: a black box web vulnerability scanner. Point it at the URL of an application you own or are authorised to test and it crawls the pages and forms, then injects crafted payloads to surface real vulnerabilities: SQL injection, cross site scripting, command and code injection, path traversal, XML external entity, server side request forgery, open redirects, exposed backup files and more, reporting each finding with the exact request that triggered it.
Only scan systems you are authorised to test
Read this first. Wapiti is an offensive security tool: it actively attacks the target you point it at. Running it against a host you do not own or have written permission to test is illegal in most jurisdictions. It also breaches the acceptable use policy of every cloud provider, including Azure.
This image ships safe by default. It scans nothing on its own. There is no default target, and the scheduled scan is empty until you add one. The only scan this guide runs is against a throwaway target that the commands stand up on the machine's own loopback address (127.0.0.1). Add only your own applications, or applications you have explicit authorisation to test, to the scheduled scan.
What this appliance does and does not do
What Wapiti is good at. Wapiti answers one question with authority: does my deployed, running web application expose a vulnerability that an attacker could reach over HTTP? It drives the live application from the outside. That lets it catch issues that appear only in the deployed system, such as a reflected cross-site scripting flaw or an injectable parameter. It complements static code scanning rather than replacing it.
What Wapiti is not. Wapiti is an on-demand, black-box scanner. This image does not include, and Wapiti itself is not:
- A static code scanner. It tests a running application over HTTP and does not read your source code.
- A web application firewall or a runtime protection agent. It finds flaws and does not block attacks.
- A central console, a SIEM or an agent that reports to a server.
- A remediation engine. It reports findings, and the fix to the target application is yours to make.
- A web interface of any kind.
Wapiti tells you that a running application exposes a flaw, and shows you the request that proves it. Fixing the application is your work, and this guide shows you the workflow.
What makes this image different
It is ready to run and has no credential. Wapiti has no user database, no network service and no credential of any kind. There is nothing to rotate and nothing to leak. You administer the machine over SSH with your own key.
The release is pinned in an isolated virtualenv. Wapiti and its Python dependencies are installed into a dedicated virtualenv. They are pinned to a known release and scanned clean of fixable vulnerabilities before the image is sealed. What you run is reproducible rather than whatever floated to the top of an index on build day.
A scheduled scan is already wired, and ships with no target. A systemd timer is ready to scan the targets you authorise and to log its reports. You get continuous coverage of applications you own with almost no configuration. It scans nothing until you add a target.
The image fails closed. The scheduled scan will not run unless first boot has completed and the scanner actually executes. Two independent safeguards enforce that on every run, not only the first.
1. Deploy the virtual machine
Deploy the image from the Azure Marketplace. This guide assumes the following defaults:
- Size:
Standard_B2s(2 vCPU, 4 GB) is sufficient and is what this image is validated on. Wapiti is a command-line tool, so size up only to scan very large applications. - Inbound ports: SSH (22) only. Wapiti opens no network port of its own, so nothing else needs to be open.
- Authentication: your own SSH public key.
2. Connect to the virtual machine
ssh azureuser@<vm-ip>On first boot, the machine verifies the scanner itself and records an instance note. That takes a moment. If you connect before first boot finishes, it is still working. Section 8 shows how to watch it.
3. Confirm Wapiti is installed
wapiti --version sudo test -f /var/lib/sac/data/wapiti-firstboot.done && echo "firstboot sentinel present" systemctl is-active wapiti-firstboot.serviceYou should see the pinned Wapiti version, the first-boot sentinel present, and a first-boot service that is active. Wapiti lives in an isolated virtualenv at /opt/wapiti/venv. The wapiti command on your path is a thin wrapper around it.
4. See the attack modules it loads
Wapiti runs a set of attack modules, each targeting a class of vulnerability. List them to confirm the module set loads:
wapiti --list-modulesYou should see the modules Wapiti can run, including sql (SQL injection), xss (reflected cross-site scripting), exec (command and code execution), xxe (XML external entity), ssrf (server-side request forgery), redirect (open redirect), file (path traversal and file disclosure) and more. A plain scan runs the modules marked as used by default. Select a specific set with -m.
5. Prove it actually detects a vulnerability
Do not take "the scanner ran" as proof that detection works. Prove it. This step stands up a tiny, deliberately vulnerable web page on the machine's own loopback address. The page reflects a URL parameter back without escaping it, which is a textbook reflected cross-site scripting flaw. You then scan it and confirm that Wapiti reports the finding.
cat > /tmp/demo-target.py <<'PY' import sys, html from http.server import BaseHTTPRequestHandler, HTTPServer from urllib.parse import urlparse, parse_qs class H(BaseHTTPRequestHandler): def log_message(self, *a): pass def do_GET(self): q = parse_qs(urlparse(self.path).query); name = q.get("name", [""])[0] body = (f"<html><body><p>Hello {name}</p>" "<form action='/' method='get'><input name='name'></form></body></html>").encode() self.send_response(200); self.send_header("Content-Type", "text/html") self.send_header("Content-Length", str(len(body))); self.end_headers() try: self.wfile.write(body) except Exception: pass HTTPServer(("127.0.0.1", 8231), H).serve_forever() PY python3 /tmp/demo-target.py & SRV=$!; echo "demo target running on 127.0.0.1:8231 (loopback only)" sleep 1 wapiti -u "http://127.0.0.1:8231/?name=demo" -m xss --scope url --flush-session -f json -o /tmp/demo-report.json python3 -c "import json; d=json.load(open('/tmp/demo-report.json')); v={k:x for k,x in d['vulnerabilities'].items() if x}; print('findings:', {k: len(x) for k,x in v.items()}); [print(' ', x[0]['info'], '(parameter:', x[0]['parameter'], ')') for x in v.values()]" kill "$SRV" 2>/dev/null; rm -f /tmp/demo-target.py /tmp/demo-report.jsonYou should see Wapiti report a Reflected Cross Site Scripting finding on the name parameter. That is Wapiti's core job: it found a real flaw in the running application from the outside, over HTTP, and named the parameter that carries it.
6. Scan your own application
To scan an application you own or are authorised to test, point Wapiti at its URL and write a report. A full scan runs the default module set and produces an HTML report that you can open in a browser:
# Replace the URL with YOUR OWN application, or one you are authorised to test. wapiti -u https://your-app.example/ -f html -o ~/wapiti-report.htmlUseful flags:
-m xss,sql,execrestricts the scan to a chosen set of modules.--scope domainlets the crawler follow links across the whole domain rather than a single page.-d 3sets how deep the crawler follows links.--flush-sessionstarts a fresh scan rather than resuming.
Run wapiti --help for the full set. Wapiti keeps its scan session under ~/.wapiti, so you can resume a long scan if it is interrupted.
7. The scheduled scan
A systemd timer can scan a set of target URLs that you configure, and it writes each report to /var/log/wapiti/. This gives you continuous coverage of applications you own. It ships with no target configured, so it scans nothing until you add one.
systemctl is-active wapiti-scan.timer
systemctl list-timers wapiti-scan.timer --no-pager | sed -n '1,3p'
sudo sed -n '1,12p' /etc/wapiti/targets.confTo enable the scheduled scan, add one target URL per line to /etc/wapiti/targets.conf. Use only hosts you own or are authorised to test. The next commands add a target, run the scheduled scan immediately instead of waiting for the timer, and show the tail of its log:
# Add ONLY hosts you are authorised to test, one URL per line.
echo "https://your-app.example/" | sudo tee -a /etc/wapiti/targets.conf
sudo systemctl start wapiti-scan.service
sudo tail -n 20 /var/log/wapiti/scan.log8. First boot and troubleshooting
The wapiti-firstboot.service unit handles first boot. It verifies the scanner on this machine and writes the instance note at /root/wapiti-instance.txt. To check its status and read the note:
systemctl status wapiti-firstboot.service --no-pager | sed -n '1,8p'
sudo sed -n '1,14p' /root/wapiti-instance.txtIf first boot did not complete, for example because the machine lost power part-way through, re-run it:
# Re-run first boot if it did not complete.
sudo systemctl restart wapiti-firstboot.serviceThe scheduled scan refuses to run until first boot has completed and the scanner executes. A machine that has not finished first boot therefore never presents a scan that silently ran nothing.
9. Licensing
Wapiti is licensed under the GNU General Public License, version 2, and is installed unmodified from PyPI (the wapiti3 distribution). The licence text is shipped on the image at /usr/share/doc/sac/WAPITI-LICENSE.txt.
The GPL is a copyleft licence, so the image also ships a written offer for the corresponding source, along with the exact command to fetch it, at /usr/share/doc/sac/WAPITI-GPL-2-WRITTEN-OFFER.txt. The exact resolved dependency set is recorded at /usr/share/doc/sac/wapiti-pip-freeze.txt.
The underlying Ubuntu operating system and its system Python are installed from Ubuntu's public apt archive. They stay patchable through the normal unattended-upgrades path for the life of the release.
Support
Every SecureAnyCloud deployment is backed by 24/7 support. If you have any questions about this image, contact us at sales@secureanycloud.com.
Deploy on Azure
Launch Wapiti on Ubuntu 24.04 LTS by SecureAnyCloud with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
This image runs Wapiti, the open source web application vulnerability scanner. Wapiti is a dynamic application security testing (DAST) tool. Given the URL of a web application you own or are authorised to test, it crawls the application and actively injects payloads to surface real, exploitable vulnerabilities. It then writes a report you can act on.
What you get:
- Black-box scanning. Wapiti does not read your source code. It fuzzes the forms, URLs and parameters it discovers and reports the vulnerability classes it can prove. These include cross-site scripting (XSS), SQL and NoSQL injection, command injection, path traversal, XML external entity (XXE), server-side request forgery (SSRF), open redirects and exposed backup or configuration files.
- A ready-to-use appliance. Wapiti is installed unmodified from PyPI into an isolated virtualenv, with a thin
wapitiwrapper on the system path. When you connect over SSH, the scanner is installed, self-verified and ready to run. - No login and no listening port. There is no web interface, no daemon, no listening port and no login or bootstrap password of any kind. There is nothing to leak and nothing to rotate. You administer the instance over SSH with your own key.
- An SSH-only security group. Wapiti binds no listening socket. It is a client-side scanner that only makes outbound requests to the targets you choose, so the shipped security group opens the SSH port only.
Responsible and authorised use
Wapiti is an offensive security tool. Scanning a web application actively sends attack payloads to it. Doing so against a system you do not own or are not authorised to test is illegal in most jurisdictions.
Scan only systems you own or have explicit written authorisation to test. This appliance makes that the default. It ships with no scan target, and it never scans anything on its own, except for a deliberately vulnerable page it stands up on the loopback interface to verify its own detection engine. You are responsible for ensuring that you have authorisation for every target you scan.
Prerequisites
Before you deploy this image, make sure you have:
- An Amazon Web Services account where you can launch EC2 instances.
- IAM permissions to launch instances, create security groups and subscribe to AWS Marketplace products.
- An EC2 key pair in the target Region for SSH access to the instance.
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network.
- The AWS CLI (version 2) installed locally, if you plan to deploy from the command line.
- A web application you own or are authorised to test, if you intend to run a scan.
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console and open the EC2 service. Select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for Wapiti. Select the SecureAnyCloud listing, choose Select, then choose Continue on the subscription summary.
Pick an instance type of m5.large or larger. Under Key pair (login), choose your EC2 key pair. Under Network settings, select your VPC and subnet, then create or select a security group that opens port 22 from your management network. Leave the root volume at the default size or larger.
Select Launch instance. First-boot initialisation takes a short time after the instance state becomes Running and the status checks pass. During it, the image verifies the scanner on the instance and writes a per-instance welcome note.
Launch the Instance from the AWS CLI
This command launches an instance from the SecureAnyCloud Wapiti Marketplace AMI into an existing subnet and security group. Replace the values in angle brackets as follows:
- <ami-id>: the AMI ID shown on the Marketplace listing.
- <key-name>: your EC2 key pair name.
- <subnet-id>: your subnet ID.
- <security-group-id>: a security group that opens port 22 from your management network.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--metadata-options "HttpTokens=required" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=wapiti}]'When the instance state is Running and both status checks pass, note its public or private IP address for the SSH step.
Connect over SSH
Connect to the instance with your key pair. The login user depends on the operating system variant you launched.
Connect to your instance
On Ubuntu 24.04 LTS, the SSH login user is ubuntu:
ssh -i <key>.pem ubuntu@<public-ip>Read the welcome note
Every instance writes a per-instance welcome note on first boot. It contains no secrets. It confirms the installed version, reminds you of the authorised-use-only policy and shows where the scheduled scan reads its targets.
sudo cat /root/wapiti-instance.txtConfirm the scanner and its attack modules
Confirm the installed Wapiti version and list the loaded attack modules. The module set includes the core web attack modules such as xss, sql, exec, file, xxe, ssrf and redirect.
wapiti --versionwapiti --list-modulesRun your first scan
Point Wapiti at a web application you own or are authorised to test. This example runs the default module set and writes an HTML report into a directory. Wapiti also supports -f json, -f xml and -f txt output formats. Use the -m flag to select specific modules, for example -m xss,sql.
wapiti -u https://your-app.example/ -f html -o wapiti-report/When the scan completes, open the report's index.html in a browser to review the findings. Copy it back with scp, or serve the directory. Each finding includes the vulnerable parameter, the payload that proved it, and the full HTTP request Wapiti sent, so you can reproduce and fix it.
For a reflected cross-site scripting flaw, Wapiti identifies the injectable parameter, such as name. It injects an XSS payload, observes it reflected unescaped in the response, and reports the finding.
The scheduled scan (optional)
The image ships a systemd timer, wapiti-scan.timer. It can run Wapiti daily against a list of authorised targets and write an HTML report for each into /var/log/wapiti/. The timer is enabled and active, but the target list at /etc/wapiti/targets.conf ships empty, so nothing is scanned until you add a target yourself.
systemctl is-active wapiti-scan.timerTo enable scheduled scanning, add one URL per line to the targets file, one for each web application you are authorised to test. Lines beginning with # and blank lines are ignored.
echo "https://staging.your-app.example/" | sudo tee -a /etc/wapiti/targets.confThe scheduled scan is fail-closed. A drop-in requires the first-boot self-verification to have completed. It also re-checks on every run that the scanner resolves and executes, so a broken install can never silently run a no-op scan. Reports accumulate under /var/log/wapiti/. Wire them into your own review workflow to track a web application's security posture over time.
Keeping the image current
The operating system and system Python install from the Ubuntu archive and are covered by unattended-upgrades, so security patches for the base are applied automatically. Wapiti and its Python dependencies are pinned inside the virtualenv for reproducibility. SecureAnyCloud refreshes them by re-cutting the image, which is the standard update model for a Python application appliance. To move to a newer Wapiti, launch a fresh instance from the latest SecureAnyCloud AMI.
Troubleshooting
wapiti: command not found: the wrapper is at/usr/local/bin/wapiti. Make sure/usr/local/binis on yourPATH, or invoke it by full path.- A scan hangs or takes a long time. Large applications take time to crawl and fuzz. Use
--max-scan-time <seconds>to cap a scan,--scope urlto limit it to the given URL, or-m <module>to run only specific modules. - A scan reports no findings. That is a valid result: Wapiti did not prove any vulnerability in the scope it tested. Widen the scope, add modules, or provide authentication for pages behind a login.
- You must scan only authorised targets. If you are unsure whether you are authorised to test a system, do not scan it.
Support
SecureAnyCloud provides 24/7 technical support for this image by email and live chat. Our engineers help with running scans, choosing and tuning attack modules, interpreting reports, configuring the scheduled scan against authorised targets, integrating Wapiti into CI/CD security gates, and upgrade planning. Contact sales@secureanycloud.com with your instance ID, Region, and a description of your question.
Deploy on AWS
Launch Wapiti on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com