Today I discovered a treasure trove of security resources from OWASP (Open Web Application Security Project) that provide practical guidance for secure development and testing.
OWASP Cheat Sheet Series#
OWASP Cheat Sheets offer concise, actionable security guidance for developers and security professionals.
Key Cheat Sheets:#
Authentication and Session Management:#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// Secure session configuration example
app.use(session({
name: 'sessionId',
secret: process.env.SESSION_SECRET, // Strong, unique secret
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // Prevent XSS access
maxAge: 1800000, // 30 minutes
sameSite: 'strict' // CSRF protection
},
store: new RedisStore({
host: 'localhost',
port: 6379
})
}));
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# Secure input validation patterns
import re
from html import escape
def validate_email(email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email)) and len(email) <= 254
def sanitize_html_input(user_input):
# Escape HTML entities
escaped = escape(user_input)
# Remove potential script tags
cleaned = re.sub(r'<script.*?</script>', '', escaped, flags=re.IGNORECASE)
return cleaned
# Parameterized queries for SQL injection prevention
cursor.execute(
"SELECT * FROM users WHERE email = %s AND status = %s",
(validated_email, 'active')
)
|
Cryptography Guidelines:#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# Secure password hashing
import bcrypt
import secrets
def hash_password(password):
# Generate salt with sufficient rounds
salt = bcrypt.gensalt(rounds=12)
return bcrypt.hashpw(password.encode('utf-8'), salt)
def verify_password(password, hashed):
return bcrypt.checkpw(password.encode('utf-8'), hashed)
# Secure random token generation
def generate_csrf_token():
return secrets.token_urlsafe(32)
|
OWASP Top 10 Web Application Security Risks#
OWASP Top 10 identifies the most critical web application security risks based on industry data and expert consensus.
2021 Top 10 Breakdown:#
A01: Broken Access Control#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// Vulnerable: Direct object reference
app.get('/user/:id/profile', (req, res) => {
const userId = req.params.id;
// No authorization check!
const profile = database.getProfile(userId);
res.json(profile);
});
// Secure: Proper authorization
app.get('/user/:id/profile', authenticate, (req, res) => {
const userId = req.params.id;
const currentUser = req.user;
// Verify user can access this profile
if (currentUser.id !== userId && !currentUser.isAdmin) {
return res.status(403).json({ error: 'Access denied' });
}
const profile = database.getProfile(userId);
res.json(profile);
});
|
A02: Cryptographic Failures#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# Secure data encryption at rest
from cryptography.fernet import Fernet
import os
def encrypt_sensitive_data(data):
# Use environment variable for key
key = os.environ.get('ENCRYPTION_KEY').encode()
cipher_suite = Fernet(key)
encrypted_data = cipher_suite.encrypt(data.encode())
return encrypted_data
def decrypt_sensitive_data(encrypted_data):
key = os.environ.get('ENCRYPTION_KEY').encode()
cipher_suite = Fernet(key)
decrypted_data = cipher_suite.decrypt(encrypted_data)
return decrypted_data.decode()
|
A03: Injection Attacks#
1
2
3
4
5
|
-- Vulnerable: SQL injection
SELECT * FROM users WHERE username = '" + user_input + "'
-- Secure: Parameterized query
SELECT * FROM users WHERE username = ?
|
Risk Assessment Matrix:#
- Broken Access Control: Prevalence: High, Impact: High
- Cryptographic Failures: Prevalence: Medium, Impact: High
- Injection: Prevalence: Medium, Impact: High
- Insecure Design: Prevalence: Medium, Impact: High
- Security Misconfiguration: Prevalence: High, Impact: Medium
OWASP Web Security Testing Guide#
OWASP Web Security Testing Guide provides systematic methodology for testing web application security.
Testing Framework:#
1
2
3
4
5
6
7
8
9
10
11
|
# Subdomain enumeration
subfinder -d example.com -o subdomains.txt
# Technology stack identification
whatweb https://example.com
# Directory and file discovery
dirb https://example.com /usr/share/dirb/wordlists/common.txt
# SSL/TLS configuration testing
sslscan example.com
|
Authentication Testing:#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
# Automated authentication bypass testing
import requests
def test_authentication_bypass(base_url):
test_cases = [
# SQL injection attempts
{"username": "admin' OR '1'='1", "password": "anything"},
{"username": "admin'--", "password": ""},
# Default credentials
{"username": "admin", "password": "admin"},
{"username": "administrator", "password": "password"},
# Empty authentication
{"username": "", "password": ""},
]
for case in test_cases:
response = requests.post(
f"{base_url}/login",
data=case,
allow_redirects=False
)
if response.status_code == 302: # Redirect might indicate success
print(f"Potential bypass: {case}")
|
Session Management Testing:#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
// Session testing checklist
const sessionTests = {
// Test session token entropy
checkTokenRandomness: (tokens) => {
const uniqueTokens = new Set(tokens);
return uniqueTokens.size === tokens.length;
},
// Test session fixation
checkSessionFixation: async (sessionId) => {
const loginResponse = await fetch('/login', {
method: 'POST',
headers: { 'Cookie': `SESSIONID=${sessionId}` },
body: JSON.stringify({ username: 'test', password: 'test' })
});
const newSessionId = extractSessionFromResponse(loginResponse);
return newSessionId !== sessionId; // Should be different
},
// Test session timeout
checkSessionTimeout: async (sessionId) => {
await new Promise(resolve => setTimeout(resolve, 1800000)); // 30 minutes
const response = await fetch('/protected', {
headers: { 'Cookie': `SESSIONID=${sessionId}` }
});
return response.status === 401; // Should be unauthorized
}
};
|
Testing Categories:#
Technical Testing:#
- Input validation: Boundary value analysis, fuzz testing
- Error handling: Information disclosure through error messages
- Cryptography: Weak algorithms, key management issues
- Business logic: Workflow bypasses, race conditions
Infrastructure Testing:#
- Network security: Port scanning, SSL/TLS configuration
- Web server configuration: Default accounts, unnecessary services
- Database security: Privilege escalation, data exposure
These OWASP resources provide a comprehensive foundation for implementing security throughout the software development lifecycle, from secure coding practices to thorough security testing methodologies.