Logging post data

Lets say you have a relatively complex php web application, like wordpress. You have it running under apache (which is common.) You have good control of your site via .htaccess (which is common — permalinks and all.) And something happens to your blog (e.g. someone is exploiting some unknown vulnerability to compromise your content), which you want to track down. So you want to log, for instance, HTTP POST data. Your first instinct might be to add some logging code to index.php (mine was) But there are a lot of possible places which might be directly accessed, especially in the admin. So The trick I use (and this is probably the only time I’ve ever condoned this) is to use PHPs auto_prepend_file functionality.

Make a /home/user/postlog/ directory, then a /home/user/postlog/logs/ directory (and chmod a+rw that one.) Next make a simple /home/user/postlog/postlog.php file with the following contents:

<?php 
if ( isset($_POST) && is_array($_POST) && count($_POST) > 0 ) { 
  $log_dir = dirname( __FILE__ ) . '/logs/'; 
  $log_name = "posts-" . $_SERVER['REMOTE_ADDR'] . "-" . date("Y-m-d-H") . ".log"; 
  $log_entry = gmdate('r') . "\t" . $_SERVER['REQUEST_URI'] . "
" . serialize($_POST) . "

"; 
  $fp=fopen( $log_dir . $log_name, 'a' ); 
  fputs($fp, $log_entry); 
  fclose($fp); } 
?>

Finally add this line to the top of your .htaccess file:

php_value auto_prepend_file /home/user/postlog/postlog.php

If all went well this should start logging any request to any php file with any post data into the /home/user/postlog/logs/ direcory (with a unique log per ip per day)

7 thoughts on “Logging post data

  1. Thanks for the quick script. it helped me identify issues with xhr post request headers from android. Oh and I added a function for parsing the headers.

    function parseRequestHeaders() {

    $headers = array();

    foreach($_SERVER as $key => $value) {

    if (substr($key, 0, 5) 'HTTP_') {

    continue;

    }

    $header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));

    $headers[$header] = $value;

    }

    return $headers;

    }

  2. Great script. Exactly what I needed after studying the log files to find dozens of attempted posts to pages in the Joomla core, but not being able to see what the bad guy was trying to post. We're not running mod_php so I wasn't able to use .htaccess. Instead I used the .user.ini file (user-level add-on for php.ini). Once I got all the files in place, it worked great.
    I changed gmdate() to date() to get the log entries in my time zone. Also, for some reason the sample code was urlencoded. I changed it back to simple php <?php instead of &lt;?php , and it worked fine. If there's a reason to actually use the urlencoded version, please advise.

    • apokalyptik says:

      Nope. That was just the blog/me messing up the text when it was entered. Urldecoding it is the proper thing to do (otherwise it wouldn't run.) Glad it helped.

  3. marcgott says:

    Just wanted you to know that this post is still relevant, and (in case you were wondering) still works, Hero!

    I hope I catch this s** of a b****

Leave a Reply to Josh TischerCancel reply