Learn web application penetration testing methodology. Master Burp Suite, OWASP ZAP, SQLMap, and automated security testing for finding vulnerabilities before attackers do.
Web Application Penetration Testing
Testing Methodology (OWASP Testing Guide)
1. Information Gathering
- Fingerprinting (tech stack, versions)
- Directory enumeration
- Subdomain discovery
2. Configuration Management
- Security headers audit
- TLS/SSL analysis
- Error handling
3. Authentication Testing
- Password policies
- Default credentials
- Token predictability
4. Session Management
- Cookie attributes
- Session fixation
- CSRF
5. Input Validation
- XSS
- SQL Injection
- XXE, SSRF
6. Business Logic
- Parameter manipulation
- Race conditions
OWASP ZAP Automated Scanning
from zapv2 import ZAPv2
import time
ZAP_API_KEY = 'your-api-key'
TARGET_URL = 'http://localhost:3000'
zap = ZAPv2(apikey=ZAP_API_KEY, proxies={'http': 'http://127.0.0.1:8080'})
# Spider to discover endpoints
print("[*] Starting spider...")
scan_id = zap.spider.scan(TARGET_URL, apikey=ZAP_API_KEY)
while int(zap.spider.status(scan_id)) < 100:
print(f" Spider: {zap.spider.status(scan_id)}%")
time.sleep(2)
print(f" Spider found {len(zap.spider.results())} URLs")
# Active scan
print("[*] Starting active scan...")
ascan_id = zap.ascan.scan(TARGET_URL, apikey=ZAP_API_KEY)
while int(zap.ascan.status(ascan_id)) < 100:
print(f" Active scan: {zap.ascan.status(ascan_id)}%")
time.sleep(5)
# Get alerts
alerts = zap.core.alerts(baseurl=TARGET_URL)
high = [a for a in alerts if a['risk'] == 'High']
medium = [a for a in alerts if a['risk'] == 'Medium']
print(f"
Results: {len(high)} High, {len(medium)} Medium")
for alert in high:
print(f" HIGH: {alert['name']} at {alert['url']}")
print(f" {alert['description'][:100]}...")
# Generate HTML report
report = zap.core.htmlreport()
with open('zap-report.html', 'w') as f:
f.write(report)
SQLMap Usage
# Basic SQL injection test
sqlmap -u "http://example.com/products?id=1" --dbs
# Test POST request
sqlmap -u "http://example.com/login" --data="username=admin&password=test" --dbs
# With session cookie
sqlmap -u "http://example.com/profile" --cookie="session=abc123" --tables -D users_db
# Extract data
sqlmap -u "http://example.com/products?id=1" -D mydb -T users --dump --batch
# Time-based blind injection
sqlmap -u "http://example.com/products?id=1" --technique=T --dbms=postgresql
Python Security Testing Script
import requests
from bs4 import BeautifulSoup
import re
class BasicSecurityTester:
def __init__(self, base_url: str):
self.base_url = base_url
self.session = requests.Session()
self.findings = []
def check_security_headers(self) -> list:
resp = self.session.get(self.base_url)
required_headers = {
'X-Content-Type-Options': 'nosniff',
'X-Frame-Options': ['DENY', 'SAMEORIGIN'],
'Strict-Transport-Security': None,
'Content-Security-Policy': None,
}
missing = []
for header, expected in required_headers.items():
value = resp.headers.get(header)
if not value:
missing.append({'severity': 'medium', 'header': header, 'issue': 'missing'})
elif expected and (isinstance(expected, str) and value != expected or
isinstance(expected, list) and value not in expected):
missing.append({'severity': 'low', 'header': header, 'issue': f"value is '{value}'"})
return missing
def test_xss_reflection(self, url: str, param: str) -> bool:
"""Test for reflected XSS."""
payload = '<script>alert(1)</script>'
resp = self.session.get(url, params={param: payload})
return payload in resp.text # Check if reflected unencoded
def test_sql_injection(self, url: str, param: str) -> bool:
"""Basic SQL injection test."""
payloads = ["'", "1' OR '1'='1", "1; DROP TABLE users--"]
for payload in payloads:
try:
resp = self.session.get(url, params={param: payload})
# Look for SQL error messages
sql_errors = ['mysql_fetch', 'ORA-', 'PostgreSQL', 'syntax error']
if any(err.lower() in resp.text.lower() for err in sql_errors):
return True
except Exception:
pass
return False
def run_all_checks(self) -> dict:
results = {
'security_headers': self.check_security_headers(),
'findings': self.findings,
}
return results
Continuous Security Testing in CI
# .github/workflows/security-tests.yml
name: Security Tests
on:
push:
branches: [main]
jobs:
security-scan:
runs-on: ubuntu-latest
services:
app:
image: myapp:${{ github.sha }}
ports:
- 3000:3000
steps:
- name: OWASP ZAP Scan
uses: zaproxy/action-baseline@v0.10.0
with:
target: 'http://localhost:3000'
rules_file_name: '.zap/rules.tsv'
fail_action: true
- name: Nuclei scan
run: |
nuclei -target http://localhost:3000 -severity critical,high -o nuclei-report.txt -exit-code 1
Bug Bounty Checklist
| Test |
Tool |
| IDOR |
Manual + Burp |
| SQL Injection |
SQLMap |
| XSS |
XSStrike |
| CSRF |
Burp Suite |
| Auth bypass |
Manual |
| API testing |
Postman + Burp |