Skip to main content

Security Testing Quick Reference

A lookup page for security checks, safe test inputs, scanner commands and reporting β€” for systems you are authorised to test.

Authorisation first

Everything here assumes written permission and a defined scope, or a legal practice target (Juice Shop, PortSwigger Academy, DVWA, WebGoat). See the cheat sheet's scope section.

How to use this page

New to security testing? Start with the security cheat sheet. For the ordered plan, see the security learning path.

Quick Navigation​

Checklists: OWASP Top 10 Β· Baseline Β· Headers & cookies Β· API security

Testing: Safe test inputs Β· curl recipes Β· JWT

Scanners: Commands Β· CI workflow

Reporting: CVSS Β· Finding template Β· Practice targets


OWASP Top 10 checklist​

Risk (2021)CheckHow
A01 Broken Access ControlChange ids; call admin routes as a user; force-browse pagesLog in as A, request B's ids
A02 Cryptographic FailuresHTTPS everywhere; strong hashing; no secrets in transit/at restCheck TLS, cookie flags, stored data
A03 Injection', ", <>, OS metacharacters in every inputWatch for 500s, SQL errors, script execution
A04 Insecure DesignAbuse the business rulesRefund > payment, skip payment, coupon abuse
A05 Security MisconfigurationVerbose errors, default creds, missing headers, open dirsTrigger errors; check headers
A06 Vulnerable ComponentsKnown CVEs in dependenciesnpm audit, Trivy, Dependency-Check
A07 Auth FailuresRate limit, session expiry, password reset, MFABrute force, reuse old token, reset others'
A08 Integrity FailuresUnsigned updates, unsafe deserializationCheck update signing, CI provenance
A09 Logging FailuresAre attacks logged and alerted?Do failed logins/permission errors appear?
A10 SSRFURL inputs reaching internal addressesGive a URL param an internal/metadata URL

Baseline​

[ ] HTTPS only; HTTP β†’ HTTPS redirect
[ ] Security headers set (below)
[ ] Wrong login β†’ 401, generic message
[ ] Change id in URL/body β†’ can't see others' data
[ ] ' " < > in inputs β†’ no 500, no SQL error, no script run
[ ] Errors generic (no stack trace / SQL / paths)
[ ] No secrets in URL, page source, localStorage
[ ] Cookies: Secure, HttpOnly, SameSite
[ ] Old/expired token rejected; logout ends session

Headers & cookies​

curl -sI https://TARGET/ | grep -iE 'content-security-policy|strict-transport-security|x-frame-options|x-content-type-options|referrer-policy|permissions-policy|set-cookie'
HeaderPurposeGood value
Content-Security-PolicyLimit script/resource sources (anti-XSS)A restrictive policy, no unsafe-inline
Strict-Transport-SecurityForce HTTPSmax-age=31536000; includeSubDomains
X-Frame-Options / CSP frame-ancestorsAnti-clickjackingDENY / SAMEORIGIN
X-Content-Type-OptionsNo MIME sniffingnosniff
Referrer-PolicyLimit referrer leakagestrict-origin-when-cross-origin
CookiesSession protectionSecure; HttpOnly; SameSite=Lax (or Strict)

API security​

[ ] Every endpoint refuses no-token and bad-token requests (401)
[ ] User A can't act on user B's object ids (BOLA/IDOR) β†’ 403/404
[ ] Normal user can't call admin functions (403)
[ ] Sending role/isAdmin/price in the body is ignored (mass assignment)
[ ] Responses contain only fields the caller may see
[ ] Rate limits on login, signup, password reset, OTP
[ ] Old API versions (/v1) removed or equally protected
[ ] Large page sizes / uploads are capped

Full list: API testing cheat sheet.


Safe test inputs​

Use these only on authorised/practice targets. They are proofs, not weapons.

ClassInput to tryA vulnerable app…
SQLi (auth)' OR 1=1--logs you in / errors
SQLi (data)test')--, 1;--returns extra rows / 500 SQL error
XSS (proof)<img src=x onerror=alert(1)>pops an alert / reflects unescaped
Path traversal../../etc/passwdreturns file contents
Command injection; id, `whoami` (in fields that run commands)
SSRFhttp://169.254.169.254/ (cloud metadata)server fetches it
Template injection{{7*7}}, ${7*7}renders 49
Open redirect?next=https://evil.exampleredirects off-site

Always start with the harmless proof (alert(1), 7*7), never a real attack.

curl recipes​

J=http://localhost:3001
# login, capture JWT
TOKEN=$(curl -s -X POST $J/rest/user/login -H 'Content-Type: application/json' \
-d '{"email":"a@b.com","password":"pass"}' | python3 -c "import json,sys;print(json.load(sys.stdin)['authentication']['token'])")
# authenticated request
curl -s "$J/rest/basket/1" -H "Authorization: Bearer $TOKEN"
# BOLA sweep: try many ids
for id in $(seq 1 10); do curl -s -o /dev/null -w "$id %{http_code}\n" "$J/rest/basket/$id" -H "Authorization: Bearer $TOKEN"; done
# check a header quickly
curl -sI $J/ | grep -i content-security-policy || echo "CSP missing"
# time a request (auth brute-force throttling)
for i in $(seq 1 5); do curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" -X POST $J/rest/user/login -H 'Content-Type: application/json' -d '{"email":"a@b.com","password":"wrong"}'; done

JWT​

echo "<JWT>" | cut -d. -f1 | base64 -d 2>/dev/null; echo   # header (alg)
echo "<JWT>" | cut -d. -f2 | base64 -d 2>/dev/null; echo # payload (claims, exp)

Check: alg is not none; signature is verified server-side; exp is set and short; no sensitive data in the payload (it's only base64, not encrypted).


Scanner commands​

# DAST β€” OWASP ZAP baseline (passive, safe)
docker run --rm ghcr.io/zaproxy/zaproxy zap-baseline.py -t https://TARGET
# DAST β€” ZAP full scan (ACTIVE β€” non-prod, with permission only)
docker run --rm ghcr.io/zaproxy/zaproxy zap-full-scan.py -t https://TARGET

# SAST β€” Semgrep
docker run --rm -v "$PWD:/src" semgrep/semgrep semgrep scan --config auto /src

# Dependencies + secrets + images β€” Trivy
docker run --rm -v "$PWD:/src" aquasec/trivy fs --scanners vuln,secret --severity HIGH,CRITICAL /src
docker run --rm -v "$PWD:/src" aquasec/trivy config /src # IaC misconfig

# Secrets in git history β€” Gitleaks
docker run --rm -v "$PWD:/repo" zricethezav/gitleaks detect --source=/repo

# Dependencies by ecosystem
npm audit --audit-level=high
pip-audit

CI workflow​

# .github/workflows/security.yml (excerpt)
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: SAST
run: docker run --rm -v "$PWD:/src" semgrep/semgrep semgrep scan --config auto --error /src
- name: Dependencies & secrets
run: docker run --rm -v "$PWD:/src" aquasec/trivy fs --scanners vuln,secret --severity HIGH,CRITICAL --exit-code 1 /src
- name: DAST baseline (passive) against staging
run: docker run --rm ghcr.io/zaproxy/zaproxy zap-baseline.py -t https://staging.example.com

Gate on new HIGH/CRITICAL only; baseline existing issues while you fix them.


CVSS​

ScoreRatingFix urgency
9.0–10.0CriticalNow / hotfix
7.0–8.9HighThis release
4.0–6.9MediumPlanned
0.1–3.9LowBacklog
0None / InfoNote it

Use the FIRST CVSS calculator for a base score; adjust for your data sensitivity and exposure.

Finding template​

ID / Title:   SEC-01 β€” <one-line what and where>
Severity: <Critical/High/Medium/Low> (CVSS <score> <vector>)
Affected: <method + path / component>, <build / environment>
Steps: <exact curl / request an engineer can run>
Result: <actual response / proof, e.g. 200 logged in as admin>
Impact: <what an attacker gains>
Fix: <concrete change: parameterised queries, ownership check, header…>
Reference: <OWASP id, CWE>

Practice targets​

TargetFormat
OWASP Juice ShopDocker, full app with a scoreboard
PortSwigger Web Security AcademyFree online labs, per-topic
OWASP WebGoatDocker, guided lessons
DVWADocker, adjustable difficulty
Hack The Box / TryHackMeOnline, gamified
VulnHubDownloadable vulnerable VMs

Need more detail? Cheat sheet Β· Best practices Β· Learning path Β· Full guide