Security testing methodologies, OWASP Top 10, vulnerability scanning tools, and penetration testing practices
Scope: Security testing, OWASP Top 10, scanning tools, pentesting, security audits Lines: ~390 Last Updated: 2025-10-27
Activate this skill when:
Description: Unauthorized access to resources or actions
Testing:
import requests
def test_broken_access_control():
"""Test for access control vulnerabilities"""
# Test 1: IDOR (Insecure Direct Object Reference)
# Try accessing another user's resource
user1_token = login("user1@example.com", "password")
user2_id = 42
response = requests.get(
f"https://api.example.com/users/{user2_id}/profile",
headers={"Authorization": f"Bearer {user1_token}"}
)
# Should return 403 Forbidden
assert response.status_code == 403, "IDOR vulnerability detected"
# Test 2: Path traversal
response = requests.get(
"https://api.example.com/files/../../etc/passwd"
)
assert response.status_code in [400, 403, 404], "Path traversal possible"
# Test 3: Privilege escalation
# Try to access admin endpoint with regular user
response = requests.get(
"https://api.example.com/admin/users",
headers={"Authorization": f"Bearer {user1_token}"}
)
assert response.status_code == 403, "Privilege escalation possible"
# Test 4: Missing authorization check
# Try to access protected resource without authentication
response = requests.get("https://api.example.com/admin/dashboard")
assert response.status_code == 401, "Missing authentication check"
Description: Weak or missing encryption, exposed sensitive data
Testing:
def test_cryptographic_failures():
"""Test for weak cryptography"""
# Test 1: Check HTTPS enforcement
response = requests.get("http://example.com", allow_redirects=False)
assert response.status_code == 301, "HTTP not redirected to HTTPS"
assert response.headers['Location'].startswith('https://'), "No HTTPS redirect"
# Test 2: Check TLS version
import ssl
import socket
context = ssl.create_default_context()
context.minimum_version = ssl.TLSVersion.TLSv1_2
with socket.create_connection(("example.com", 443)) as sock:
with context.wrap_socket(sock, server_hostname="example.com") as ssock:
version = ssock.version()
assert version in ["TLSv1.2", "TLSv1.3"], f"Weak TLS: {version}"
# Test 3: Check for sensitive data in response
response = requests.get("https://api.example.com/users/me")
data = response.json()
# Password should never be in response
assert 'password' not in data, "Password exposed in response"
assert 'password_hash' not in data, "Password hash exposed"
# Test 4: Check cookie security
response = requests.get("https://example.com")
cookies = response.cookies
for cookie in cookies:
assert cookie.secure, f"Cookie {cookie.name} not secure"
assert cookie.has_nonstandard_attr('HttpOnly'), f"Cookie {cookie.name} not HttpOnly"
Description: SQL injection, command injection, XSS
Testing:
def test_sql_injection():
"""Test for SQL injection vulnerabilities"""
# Test payloads
# Example SQL injection attack payloads - for security testing only
payloads = [
"' OR '1'='1",
"' OR '1'='1' --",
"'; DROP TABLE users; --", # Example of destructive injection payload
"' UNION SELECT NULL, NULL, NULL --",
"admin'--",
]
for payload in payloads:
response = requests.post(
"https://api.example.com/login",
json={"username": payload, "password": "test"}
)
# Should return error, not success
assert response.status_code in [400, 401], f"SQL injection with: {payload}"
# Check error message doesn't leak SQL details
assert 'SQL' not in response.text.upper(), "SQL error leaked"
assert 'syntax' not in response.text.lower(), "SQL syntax error leaked"
def test_command_injection():
"""Test for command injection"""
payloads = [
"google.com; ls -la",
"google.com && cat /etc/passwd",
"google.com | whoami",
"$(cat /etc/passwd)",
"`cat /etc/passwd`",
]
for payload in payloads:
response = requests.get(
f"https://api.example.com/ping?host={payload}"
)
# Should not execute commands
assert 'root:' not in response.text, f"Command injection: {payload}"
assert 'bin/bash' not in response.text, f"Command injection: {payload}"
def test_xss():
"""Test for XSS vulnerabilities"""
payloads = [
"<script>alert('XSS')</script>",
"<img src=x onerror=alert('XSS')>",
"javascript:alert('XSS')",
"<svg onload=alert('XSS')>",
]
for payload in payloads:
response = requests.post(
"https://example.com/comments",
json={"content": payload}
)
# Fetch the comment
comment_id = response.json()['id']
response = requests.get(f"https://example.com/comments/{comment_id}")
# Script tags should be escaped
assert '<script>' not in response.text, f"XSS vulnerability: {payload}"
assert 'onerror=' not in response.text, f"XSS vulnerability: {payload}"
Description: Missing or ineffective control design
Testing:
def test_insecure_design():
"""Test for design flaws"""
# Test 1: Rate limiting
for i in range(20):
response = requests.post(
"https://api.example.com/login",
json={"email": "test@example.com", "password": "wrong"}
)
# Should be rate limited after multiple attempts
assert response.status_code == 429, "No rate limiting on auth endpoint"
# Test 2: Account enumeration
response1 = requests.post(
"https://api.example.com/login",
json={"email": "exists@example.com", "password": "wrong"}
)
response2 = requests.post(
"https://api.example.com/login",
json={"email": "notexist@example.com", "password": "wrong"}
)
# Error messages should be identical
assert response1.json()['error'] == response2.json()['error'], \
"Account enumeration possible via error messages"
# Test 3: Password reset flow
# Should require email verification
response = requests.post(
"https://api.example.com/password-reset",
json={"email": "victim@example.com"}
)
# Should not reveal if email exists
assert "email sent" in response.json()['message'].lower(), \
"Password reset reveals account existence"
Description: Insecure default configs, unnecessary features enabled
Testing:
def test_security_misconfiguration():
"""Test for misconfigurations"""
# Test 1: Security headers
response = requests.get("https://example.com")
required_headers = [
'Strict-Transport-Security',
'X-Frame-Options',
'X-Content-Type-Options',
'Content-Security-Policy'
]
for header in required_headers:
assert header in response.headers, f"Missing security header: {header}"
# Test 2: Exposed debug information
assert 'X-Powered-By' not in response.headers, "Server info exposed"
assert 'Server' not in response.headers or \
'nginx' not in response.headers.get('Server', '').lower(), \
"Detailed server version exposed"
# Test 3: Directory listing
response = requests.get("https://example.com/static/")
assert 'Index of' not in response.text, "Directory listing enabled"
# Test 4: Default credentials
default_creds = [
("admin", "admin"),
("admin", "password"),
("root", "root"),
]
for username, password in default_creds:
response = requests.post(
"https://api.example.com/login",
json={"username": username, "password": password}
)
assert response.status_code == 401, f"Default credentials work: {username}"
Description: Using components with known vulnerabilities
Testing:
# Python dependencies
pip install safety
safety check
pip install pip-audit
pip-audit
# Node.js dependencies
npm audit
npm audit fix
# Check Docker base images
docker scan myimage:latest
# Use Snyk
snyk test
snyk monitor
# Use Trivy
trivy image myimage:latest
# Automated dependency checking
import requests
import json
def check_dependencies_for_vulnerabilities(requirements_file):
"""Check Python dependencies against OSV database"""
with open(requirements_file) as f:
packages = [line.strip() for line in f if line.strip()]
vulnerabilities = []
for package in packages:
name, version = package.split('==')
response = requests.post(
'https://api.osv.dev/v1/query',
json={'package': {'name': name, 'ecosystem': 'PyPI'},
'version': version}
)
if response.status_code == 200:
data = response.json()
if 'vulns' in data and data['vulns']:
vulnerabilities.append({
'package': name,
'version': version,
'vulnerabilities': data['vulns']
})
return vulnerabilities
Description: Weak authentication, session management issues
Testing:
def test_authentication_failures():
"""Test authentication mechanisms"""
# Test 1: Weak passwords accepted
weak_passwords = ["password", "12345678", "qwerty", "admin"]
for pwd in weak_passwords:
response = requests.post(
"https://api.example.com/register",
json={"email": "test@example.com", "password": pwd}
)
assert response.status_code == 400, f"Weak password accepted: {pwd}"
# Test 2: Session fixation
# Get session ID before login
session = requests.Session()
response1 = session.get("https://example.com")
session_id_before = session.cookies.get('session_id')
# Login
session.post("https://example.com/login",
json={"email": "user@example.com", "password": "password"})
# Session ID should change after login
session_id_after = session.cookies.get('session_id')
assert session_id_before != session_id_after, "Session fixation vulnerability"
# Test 3: Brute force protection
for i in range(10):
response = requests.post(
"https://api.example.com/login",
json={"email": "user@example.com", "password": "wrong"}
)
# Should be locked or rate limited
assert response.status_code in [429, 403], "No brute force protection"
# Test 4: JWT validation
# Try using expired token
expired_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." # Test token for security validation only
response = requests.get(
"https://api.example.com/protected",
headers={"Authorization": f"Bearer {expired_token}"}
)
assert response.status_code == 401, "Expired JWT accepted"
def test_software_data_integrity_failures():
"""A08: Software and Data Integrity Failures"""
# Test unsigned packages, missing integrity checks
response = requests.get("https://example.com")
html = response.text
# Check for Subresource Integrity (SRI)
if '<script src="https://cdn' in html:
assert 'integrity="sha' in html, "Missing SRI for external scripts"
def test_logging_monitoring_failures():
"""A09: Security Logging and Monitoring Failures"""
# Attempt suspicious activity
requests.post(
"https://api.example.com/login",
json={"email": "' OR '1'='1", "password": "test"}
)
# Check if activity is logged (requires access to logs)
# In practice, verify logging configuration
def test_ssrf():
"""A10: Server-Side Request Forgery"""
# Try to access internal services
payloads = [
"http://localhost:8080",
"http://127.0.0.1",
"http://169.254.169.254/latest/meta-data/", # AWS metadata
"file:///etc/passwd",
]
for payload in payloads:
response = requests.post(
"https://api.example.com/fetch-url",
json={"url": payload}
)
assert response.status_code in [400, 403], f"SSRF possible: {payload}"
# Python: Bandit
pip install bandit
bandit -r . -f json -o bandit-report.json
# Python: Semgrep
pip install semgrep
semgrep --config=auto --json --output=semgrep-report.json
# Python: Pylint security plugin
pip install pylint-security
pylint --load-plugins=pylint_security myapp/
# Node.js: ESLint with security plugins
npm install --save-dev eslint-plugin-security
eslint . --ext .js,.ts
# Go: Gosec
go install github.com/securego/gosec/v2/cmd/gosec@latest
gosec ./...
# OWASP ZAP (Zed Attack Proxy)
docker run -t owasp/zap2docker-stable zap-baseline.py \
-t https://example.com \
-r zap-report.html
# Burp Suite (commercial)
# Use for manual penetration testing
# Nikto (web server scanner)
nikto -h https://example.com -o nikto-report.txt
# SQLMap (SQL injection)
sqlmap -u "https://example.com/page?id=1" --batch
# Nuclei (vulnerability scanner)
nuclei -u https://example.com -t cves/
# Python: Safety
safety check --json --output safety-report.json
# Python: pip-audit
pip-audit --format json --output pip-audit-report.json
# Node.js: npm audit
npm audit --json > npm-audit-report.json
# Node.js: Snyk
snyk test --json > snyk-report.json
# Docker: Trivy
trivy image myimage:latest --format json --output trivy-report.json
# Docker: Grype
grype myimage:latest -o json > grype-report.json
# Scan container image
docker scan myimage:latest
# Trivy comprehensive scan
trivy image --severity HIGH,CRITICAL myimage:latest
# Clair (open source)
docker run -d --name clair arminc/clair-local-scan:latest
clair-scanner myimage:latest
# Anchore Engine
anchore-cli image add myimage:latest
anchore-cli image vuln myimage:latest all
import nmap
import requests
from bs4 import BeautifulSoup
def passive_reconnaissance(domain):
"""Gather information without touching target"""
# DNS lookup
import dns.resolver
resolver = dns.resolver.Resolver()
records = {
'A': resolver.resolve(domain, 'A'),
'MX': resolver.resolve(domain, 'MX'),
'TXT': resolver.resolve(domain, 'TXT'),
}
# WHOIS lookup
import whois
domain_info = whois.whois(domain)
# Subdomain enumeration (passive)
# Use crt.sh (certificate transparency logs)
response = requests.get(f"https://crt.sh/?q=%.{domain}&output=json")
subdomains = set()
if response.status_code == 200:
for cert in response.json():
subdomains.add(cert['name_value'])
return {
'dns_records': records,
'whois': domain_info,
'subdomains': list(subdomains)
}
def active_reconnaissance(target):
"""Active scanning (requires permission)"""
# Port scanning
nm = nmap.PortScanner()
nm.scan(target, '1-1000')
open_ports = []
for host in nm.all_hosts():
for proto in nm[host].all_protocols():
ports = nm[host][proto].keys()
for port in ports:
if nm[host][proto][port]['state'] == 'open':
open_ports.append({
'port': port,
'service': nm[host][proto][port]['name']
})
return open_ports
Before Testing:
Authentication:
Authorization:
Input Validation:
Configuration:
Business Logic:
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run Bandit (Python SAST)
run: |
pip install bandit
bandit -r . -f json -o bandit-report.json
continue-on-error: true
- name: Run Safety (Dependency Check)
run: |
pip install safety
safety check --json --output safety-report.json
continue-on-error: true
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
- name: Run Trivy (Container Scan)
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload results to GitHub Security
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
Automated Testing:
Manual Testing:
Monitoring:
This skill includes executable scripts, detailed references, and validated examples in the resources/ directory.
skills/security/vulnerability-assessment/resources/
โโโ REFERENCE.md # Detailed OWASP Top 10 reference, CVE patterns, tools
โโโ scripts/
โ โโโ README.md # Script documentation and usage
โ โโโ test_owasp_top10.py # Executable OWASP Top 10 test suite
โ โโโ scan_dependencies.sh # Automated dependency vulnerability scanning
โโโ examples/
โโโ python/ # Standalone test examples
โโโ ci-cd/ # CI/CD integration examples
Test for OWASP Top 10 vulnerabilities:
# Full test suite
python resources/scripts/test_owasp_top10.py \
--target https://staging.example.com \
--report security-report.json \
--verbose
# Specific test
python resources/scripts/test_owasp_top10.py \
--target https://staging.example.com \
--test A01 \
--verbose
Scan dependencies for vulnerabilities:
# Scan Python project
./resources/scripts/scan_dependencies.sh \
--project-dir /path/to/project \
--output scan-results.json
# Scan Docker image
./resources/scripts/scan_dependencies.sh \
--docker-image myapp:latest \
--output docker-scan.json
Load detailed reference:
cat resources/REFERENCE.md
Contains:
| Script | Purpose | On-Demand Context Loading | |--------|---------|--------------------------| | test_owasp_top10.py | Automated OWASP Top 10 testing suite | Run via bash - code never loaded into context | | scan_dependencies.sh | Multi-tool dependency scanner (Safety, pip-audit, npm, Trivy) | Executable script, minimal context | | REFERENCE.md | Detailed specs, CVE examples, tool comparisons | Load only when needed for deep reference |
Benefits of Level 3 Resources:
security-authentication.md - Testing auth mechanismssecurity-authorization.md - Testing access controlsecurity-input-validation.md - Testing input validationsecurity-headers.md - Testing security headerstesting-integration.md - Security integration testsLast Updated: 2025-10-27 Format Version: 1.0 (Atomic) + Level 3 Resources