Co-authored-by: Tao Sun <168447269+fengju0213@users.noreply.github.com>
6.8 KiB
Vulnerability Patterns Reference
Detailed patterns for identifying security vulnerabilities across languages and frameworks.
Table of Contents
- Injection Vulnerabilities
- Authentication and Session Issues
- Cryptographic Weaknesses
- Insecure Deserialization
- Server-Side Request Forgery
- File Operations
- Framework-Specific Patterns
Injection Vulnerabilities
SQL Injection
Vulnerable patterns (string concatenation or f-strings in queries):
# Python
execute(f"...{var}...")
execute("..." + var + "...")
execute("...%s..." % var)
# JavaScript
query(`...${var}...`)
query("..." + var + "...")
# Go
db.Query("..." + var + "...")
fmt.Sprintf("SELECT ... %s", var) passed to Query()
# Java
statement.execute("..." + var + "...")
Safe alternatives: Parameterized queries, prepared statements, ORM query builders.
NoSQL Injection
Vulnerable patterns:
// MongoDB: user input directly in query object
db.collection.find({ user: req.body.user, pass: req.body.pass })
// Attacker sends: { "pass": { "$gt": "" } }
Safe alternative: Validate input types, use $eq explicitly, sanitize with libraries like mongo-sanitize.
Command Injection
Vulnerable functions by language:
Python: os.system(), os.popen(), subprocess.call(shell=True), subprocess.Popen(shell=True)
Node.js: child_process.exec(), child_process.execSync()
Go: exec.Command("sh", "-c", userInput)
Java: Runtime.exec(userInput)
PHP: exec(), system(), passthru(), shell_exec(), backticks
Ruby: system(), exec(), backticks, %x{}
Safe alternative: Use subprocess with list arguments (no shell), validate and allowlist input values.
LDAP Injection
Vulnerable pattern:
ldap.search_s(base, scope, f"(uid={username})")
Safe alternative: Escape special characters ()*\ and null bytes in user input.
XSS (Cross-Site Scripting)
Vulnerable sinks:
JavaScript: innerHTML, outerHTML, document.write(), eval(), v-html, dangerouslySetInnerHTML
Template: |safe, {% autoescape off %}, !=, !{}, {!! !!}
Safe alternatives: Use textContent, template auto-escaping, CSP headers, DOMPurify for required HTML.
Authentication and Session Issues
Weak Password Storage
Vulnerable:
# Plaintext or weak hashing
hashlib.md5(password.encode()).hexdigest()
hashlib.sha256(password.encode()).hexdigest()
Safe:
# Use adaptive hashing with salt
import bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
JWT Vulnerabilities
Common issues:
- Accepting
alg: "none" - Using symmetric algorithms (HS256) with public keys
- Not validating expiry (
exp) or issuer (iss) - Storing sensitive data in payload (JWT is base64, not encrypted)
Verification checklist:
# Ensure algorithm is explicitly specified
jwt.decode(token, key, algorithms=["RS256"]) # explicit algorithm
jwt.decode(token, key) # VULNERABLE: accepts any algorithm
Session Management
Issues to flag:
- Session IDs in URLs
- Missing
HttpOnly,Secure,SameSiteflags on session cookies - No session timeout or rotation after authentication
- Predictable session identifiers
Cryptographic Weaknesses
Insecure Algorithms
Deprecated/broken (flag if found):
Hash: MD5, SHA1 (for security purposes)
Cipher: DES, 3DES, RC4, Blowfish
Mode: ECB mode for any block cipher
RSA: Key size < 2048 bits
Acceptable:
Hash: SHA-256, SHA-384, SHA-512, BLAKE2
Cipher: AES-128/256-GCM, ChaCha20-Poly1305
RSA: 2048+ bits with OAEP padding
ECDSA: P-256 or P-384 curves
Hardcoded Cryptographic Material
Flag if found in source:
- Encryption keys, IV/nonce values
- Private keys (RSA, ECDSA, Ed25519)
- Salt values for password hashing
Insecure Deserialization
Vulnerable functions by language:
Python: pickle.loads(), yaml.load() (without SafeLoader), marshal.loads()
Java: ObjectInputStream.readObject(), XMLDecoder
PHP: unserialize()
Ruby: Marshal.load(), YAML.load()
Node.js: node-serialize, js-yaml.load() (with dangerous schema)
Safe alternatives: Use JSON for data exchange, use safe loaders (yaml.safe_load()), validate and type-check deserialized data.
Server-Side Request Forgery
Vulnerable pattern:
# User controls the URL
requests.get(user_provided_url)
urllib.request.urlopen(user_provided_url)
Mitigations:
- Validate URLs against an allowlist of domains/IPs
- Block requests to internal/private IP ranges (10.x, 172.16-31.x, 192.168.x, 127.x, 169.254.x)
- Disable redirects or validate redirect targets
- Use a network-level firewall for outbound requests
File Operations
Path Traversal
Vulnerable pattern:
# User controls filename
open(os.path.join(base_dir, user_filename))
Safe pattern:
import pathlib
base = pathlib.Path(base_dir).resolve()
target = (base / user_filename).resolve()
if not str(target).startswith(str(base)):
raise ValueError("Path traversal detected")
Unrestricted File Upload
Checklist:
- Validate file type by content (magic bytes), not just extension
- Enforce maximum file size limits
- Store uploads outside the web root
- Generate random filenames, do not use user-supplied names
- Scan uploads for malware when possible
Framework-Specific Patterns
Django
# Dangerous: raw SQL
Model.objects.raw(f"SELECT * FROM t WHERE id = {user_id}")
# Safe: ORM or parameterized raw
Model.objects.filter(id=user_id)
Model.objects.raw("SELECT * FROM t WHERE id = %s", [user_id])
# Check settings.py
DEBUG = True # Must be False in production
ALLOWED_HOSTS = ['*'] # Must be restricted
CSRF_COOKIE_SECURE = False # Must be True with HTTPS
SESSION_COOKIE_SECURE = False # Must be True with HTTPS
Flask
# Dangerous: XSS via Markup
from markupsafe import Markup
return Markup(f"<p>{user_input}</p>")
# Safe: Use templates with auto-escaping
return render_template("page.html", data=user_input)
# Check for debug mode
app.run(debug=True) # Must be False in production
Express.js
// Missing security headers - use helmet
const helmet = require('helmet');
app.use(helmet());
// Missing CSRF protection on state-changing routes
// Missing rate limiting on auth endpoints
// Missing input validation (use express-validator or zod)
Spring Boot
// Dangerous: SpEL injection
parser.parseExpression(userInput).getValue();
// Check application.properties
server.error.include-stacktrace=always // Leaks internals
management.endpoints.web.exposure.include=* // Exposes actuator