Support » Fixing WordPress » post.php unecessarily relies on HTTP_REFERER

  • I am pretty new to WP and PHP and wasn’t sure where to post this message. Please feel free to move it to a more appropriate forum.
    I couldn’t find a reference to this problem on the forums. I did find part of the problem here.
    Baiscally, the problem is that HTTP_REFERER is not a dependable system variable. Counting on it is not a good idea. Firewalls, browsers, proxies, and advanced users may block this variable. Fortunately, there is already a hidden variable named ‘referredby’ which returns the full referrer. Assuming someone has not removed it, it will give a correct referrer more reliably than HTTP_REFERER.
    The symptons are on the blog edit form (/wp/wp-admin/post.php). When HTTP_REFERER is not valid, updating, adding, or deleting a meta field or clicking ‘Save and Continue Editing’ button behave the same as the ‘Save’ button. Depositting the user in a new form instead of the current draft. This does not occur on systems where HTTP_REFERER is working correctly. The article above mentions the problem when using a popular proxy Proximitron.
    WP version 1.2 uses the following relevant code. It’s a lot simpler, but does not use the hidden field ‘referredby’ at all.


    if ($_POST['save']) {
    $location = $_SERVER['HTTP_REFERER'];
    } elseif ($_POST['updatemeta']) {
    $location = $_SERVER['HTTP_REFERER'] . '&message=2#postcustom';
    } elseif ($_POST['deletemeta']) {
    $location = $_SERVER['HTTP_REFERER'] . '&message=3#postcustom';
    } else {
    $location = 'post.php';
    }

    The latest nightly build (7/7/04) uses the following relevant code (lines 331 – 341). Unless someone is using an option other than ‘save’, ‘updatemeta’, or ‘deletemeta’ (which shouldn’t happen) the hidden field ‘referredby’ is not used. Even though that field is more reliable than the system referrer ‘HTTP_REFERER’.


    if ($_POST['save']) {
    $location = $_SERVER['HTTP_REFERER'];
    } elseif ($_POST['updatemeta']) {
    $location = $_SERVER['HTTP_REFERER'] . '&message=2#postcustom';
    } elseif ($_POST['deletemeta']) {
    $location = $_SERVER['HTTP_REFERER'] . '&message=3#postcustom';
    } elseif (isset($_POST['referredby']) && $_POST['referredby'] != $_SERVER['HTTP_REFERER']) {
    $location = $_POST['referredby'];
    } else {
    $location = 'post.php';
    }

    Below is my solution. It also defaults the location to ‘post.php’. Unfortunately, I can’t seem to find the right code tag combination to stop the special character conversion in the code. I really hate smart editing. You can go here to view accurate code.


    // Set default.
    // This $location is used if all else fails.
    $location = 'post.php';
    // $_POST['referredby'] is preferred
    if ( isset( $_POST['referredby'] ) ) {
    // Remove the old 'message=' block(s) from the url.
    $location = preg_replace( "/&message=\d/", '', $_POST['referredby'] );
    // $_SERVER['HTTP_REFERER'] is used only if present and
    // $_POST['referredby'] is missing.
    } elseif ( isset( $_SERVER['HTTP_REFERER'] ) ) {
    // Remove the old 'message=' block(s) from the url.
    $location = preg_replace( "/&message=\d/", '', $_SERVER['HTTP_REFERER'] );
    }
    // We are in "case 'editpost':"
    //
    // The only options should be limited to
    // 'save', 'updatemeta', and 'deletemeta'
    // Anything else will revert to the default
    // for $location (see above).
    // 'Save and Continue Editing'
    if ( $_POST['save'] ) {
    // Here in case a message is added later.
    // 'Add Custom Field' and 'Update'
    } elseif ( $_POST['updatemeta'] ) {
    $location .= '&message=2#postcustom';
    // 'Delete'
    } elseif ( $_POST['deletemeta'] ) {
    $location .= '&message=3#postcustom';
    }

    Could someone please verify that this works in their installation? It seems to work fine for me, but I don’t have multiple installations to try it on.
    HTH,
    Charles

Viewing 3 replies - 1 through 3 (of 3 total)
  • Thanks for the long note. I am sure some developer will take a look at this.
    Thanks, again 🙂

    You must have referrers enabled to use WordPress. There are a lot of reasons for this, not the least of which is security.

    Would you mind elaborating on the reasons for requiring referrers, especially related to security?
    The only security risk I can think of is that a malicious web site will include a URL or some other tag that causes my browser to GET a URL like “https://mysite/wordpress/wp-admin/post.php?action=delete&post=5”. If I’ve previously logged in and am caching cookies, this can cause me to unknowingly delete an entry.
    Could that kind of attack be mitigated by requiring a POST instead of a GET for actions like that? Or is it just as easy to write javascript code that will perform the POST?
    Otherwise, I can’t think of any attack that doesn’t also require capturing the username/password or the authentication cookies that couldn’t also fake the “Referer” header.
    I have commented out the check_admin_referer function becaue I’d rather turn of referers in FireFox and be open to this attack than to turn them on just to use WordPress.
    Cheers,
    Jason

Viewing 3 replies - 1 through 3 (of 3 total)
  • The topic ‘post.php unecessarily relies on HTTP_REFERER’ is closed to new replies.