Back to Learn

Capture POST Requests on a Web Server | NOC.org

Why Capture POST Requests?

HTTP POST requests carry data from clients to servers — form submissions, API calls, file uploads, login credentials, and payment information. Capturing these requests is essential for debugging application issues, investigating security incidents, detecting brute force attacks, identifying data exfiltration, and analyzing credit card skimmer behavior.

Standard web server access logs record the URL and status code of POST requests but not the request body. To see what data was actually sent, you need additional tools and configuration.

Using tcpdump for HTTP POST Capture

The most direct way to capture POST data is with tcpdump, which intercepts network traffic at the packet level:

# Capture HTTP traffic on port 80
sudo tcpdump -i any -s 0 -A 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' | grep -A 10 "POST"

Breaking down this command:

  • -s 0 — Capture the entire packet (no truncation).
  • -A — Print packet content in ASCII.
  • tcp port 80 — Filter for HTTP traffic.
  • The remaining filter selects only packets with a TCP payload (ignoring SYN/ACK/FIN packets).
  • grep -A 10 "POST" — Show POST lines plus 10 lines of context (the request body).

For HTTPS traffic (port 443), tcpdump cannot read the encrypted payload. You need to capture at the application level instead (see Apache and Nginx methods below), or use a tool like ssldump with the server's private key.

Saving POST Traffic to a File

# Save raw capture for later analysis
sudo tcpdump -i any -s 0 -w /tmp/http-capture.pcap 'tcp port 80'

# Read and filter for POST requests
tcpdump -r /tmp/http-capture.pcap -A | grep -A 20 "^POST"

Using ngrep for Cleaner Output

ngrep (network grep) provides a more readable way to filter network traffic by content:

# Capture all POST requests
sudo ngrep -q -W byline 'POST' 'tcp port 80'

# Capture POST requests to a specific URL
sudo ngrep -q -W byline 'POST /wp-login.php' 'tcp port 80'

# Capture POST requests containing specific form fields
sudo ngrep -q -W byline 'username=|password=' 'tcp port 80'

The -W byline option formats output line by line, making HTTP headers and body easy to read. Install ngrep on Ubuntu with sudo apt install ngrep.

Apache mod_dumpio

Apache's mod_dumpio module logs all input and output data at the application layer, after SSL decryption. This works for both HTTP and HTTPS traffic:

# Enable the module
sudo a2enmod dump_io
sudo systemctl restart apache2

Configure it in your virtual host or Apache configuration:

# Log all input (request headers and body)
DumpIOInput On

# Log all output (response headers and body) - usually not needed
# DumpIOOutput On

# Set log level to trace7 for the dumpio module
LogLevel dumpio:trace7

POST request bodies will appear in the Apache error log (/var/log/apache2/error.log):

[Wed Feb 24 14:30:00.123456 2026] [dumpio:trace7] [pid 12345]
mod_dumpio.c(103): [client 192.168.1.100:45678]
mod_dumpio_in (data-HEAP): username=admin&password=secret123

Warning: mod_dumpio generates massive amounts of log data and significantly impacts performance. Only enable it temporarily for debugging or investigation, and disable it immediately afterward.

Nginx Request Body Logging

Nginx does not have a direct equivalent to mod_dumpio, but you can log the request body using the $request_body variable in your log format:

# Define a custom log format that includes the request body
log_format postdata '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    'body: "$request_body"';

# Apply it to a specific location
server {
    listen 443 ssl;
    server_name example.com;

    # Log POST requests to a separate file
    location /api/ {
        access_log /var/log/nginx/post-data.log postdata;

        # Important: Nginx only populates $request_body when it reads the body
        # This happens with proxy_pass, fastcgi_pass, etc.
        proxy_pass http://backend;
    }
}

Note that $request_body is only populated when Nginx actually reads the request body, which happens when it proxies the request to a backend. For static file serving, the body is not read and will not appear in logs.

Conditional Logging for POST Only

# Only log POST requests
map $request_method $log_post {
    POST    1;
    default 0;
}

server {
    access_log /var/log/nginx/post-data.log postdata if=$log_post;
    # ...
}

PHP-Level Logging

For PHP applications, you can log POST data directly in your application code. This works regardless of the web server:

<?php
// Log all POST requests
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $logEntry = [
        'timestamp' => date('Y-m-d H:i:s'),
        'ip'        => $_SERVER['REMOTE_ADDR'],
        'uri'       => $_SERVER['REQUEST_URI'],
        'user_agent'=> $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
        'post_data' => $_POST,
        'raw_body'  => file_get_contents('php://input')
    ];

    file_put_contents(
        '/var/log/php-post-requests.log',
        json_encode($logEntry) . "\n",
        FILE_APPEND | LOCK_EX
    );
}
?>

For a more targeted approach, log only specific endpoints like login pages or contact forms. You can use a PHP auto_prepend_file to inject logging across all PHP files:

# php.ini or pool config
auto_prepend_file = /opt/scripts/log-post.php

Security Considerations

Capturing POST requests means capturing sensitive data. You must handle this responsibly:

  • Passwords and credentials: POST data often contains plaintext passwords submitted through login forms. Never store these in long-term logs. Mask or redact password fields.
  • Payment card data: If your site processes credit card payments, logging POST data that contains card numbers violates PCI DSS. Use extreme caution on payment pages.
  • Personal information: Names, email addresses, phone numbers, and other PII in POST data may be subject to GDPR, CCPA, or other privacy regulations.
  • Log file permissions: Ensure log files containing POST data have restrictive permissions (600 or 640) and are accessible only to authorized personnel.
  • Retention: Delete POST data logs as soon as the investigation or debugging session is complete. Do not archive them indefinitely.
  • Encryption at rest: If you must store POST data temporarily, ensure the storage volume is encrypted.

Forensic Use Cases

Detecting Data Exfiltration

Attackers who have compromised a server may use POST requests to exfiltrate data to an external server. Look for:

  • POST requests to unexpected external URLs from your server
  • Large POST bodies being sent to unfamiliar domains
  • POST requests originating from cron jobs or background processes
# Monitor outbound POST requests from the server
sudo tcpdump -i any -s 0 -A 'tcp dst port 80 or tcp dst port 443' | grep -B 2 "^POST"

Detecting Form Abuse and Spam

Contact forms and comment forms are common targets for spam bots. Capture POST data to identify patterns:

# Count POST requests per source IP
sudo tcpdump -i any dst port 80 -nn -c 10000 2>/dev/null | \
  grep "POST" | awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head -20

Investigating Credit Card Skimmers

Credit card skimmers injected into compromised websites intercept form submissions and POST the stolen data to attacker-controlled servers. Capturing POST traffic from your web server can reveal these exfiltration attempts by showing unexpected outbound POST requests containing card-like data patterns.

Summary

Capturing POST requests is a powerful technique for debugging, security investigation, and forensic analysis. Use tcpdump or ngrep for quick network-level captures, Apache mod_dumpio for decrypted HTTPS traffic, Nginx custom log formats for application-layer logging, or PHP-level code for targeted endpoint monitoring. Always handle captured data with care — POST bodies contain sensitive information that must be protected, retained only as long as needed, and securely deleted afterward. For comprehensive web application protection, consider deploying a WAF that can inspect and filter malicious POST requests in real time.

Improve Your Websites Speed and Security

14 days free trial. No credit card required.