Earlier this week, Sucuri wrote about auto generated iframes in hacked WordPress blogs. The malicious PHP code fetched the iframe URLs from a remote server (hxxp://82 .200 .204 .151/config.inc.php) on-the-fly every time someone loaded infected web pages. This trick helped regularly update the malicious URLs without having to change the code on each hacked site individually. All the URLs had the same format http://<domain-of-a-hacked -site.com>/news/faults-ending.php. For example, hxxp://brewerstire .com/news/faults-ending.php .
This reminded me of another ongoing attack that also rotates iframe URLs in a similar way. However it has some distinguishing features that make it worth it to describe it separately.
Disclaimer: I still haven’t had access to websites affected by this hack and didn’t see the actual malicious code, but I have enough details that I managed to get as an external observer to speculate about what’s going on.
1. This hack affects all sorts of PHP sites. Most of the sites I checked were Joomla and WordPress sites.
2. There is a malicious iframe code at the very top of the HTML code of infected web pages.
<i f r a m e src="hxxp://<malicious URL>" width=1 height=1 style="visibility: hidden"></i f r a m e>
3. The iframe URL changes much more often then in the case described by Sucuri. It changes every minute! Actually this attack rotates a long list of URLs and roughly in two hours you begin to notice repetitions.
4. The iframe URLs conform to patterns that your can easily spot if you see a few URLs. Every few days the pattern changes. The current pattern is: http://<domain-of-a-hacked-site>/templates/system/index.php. For example:
hxxp://www .exileskimboards .com/templates/system/index.php
hxxp://www .granvillesoccer .com .au/templates/system/index.php
hxxp://www .bonabejadid .ir/templates/system/index.php
hxxp://www .dijonpoker .fr/templates/system/index.php
hxxp://rcouncil.rmutr .ac .th/templates/system/index.php
hxxp://www .tvstein .ch/templates/system/index.php
my list of 119 URLs can be found on pastebin.
Before that I saw: http://<domain-of-a-hacked-site>/<7-random-characters>.php.
hxxp://reneks .com .tr/yrdoter.php
hxxp://profiaudio .com .pl/xbiwspk.php
hxxp://web429 .webclient2 .de/uqevulx.php
my incomplete list of 41 URLs can be found on pastebin.
Update (May 23rd, 2013): New list of 105 iframe URLs.
hxxp://www .funfiles .cc/deliveryairport/deliveryairport.php
hxxp://www .svendborgfrivilligraad .dk/themes/Phos/forum/green/green.php
hxxp://www .lt90 .org/upload_files/now/nata/nata.php
hxxp://www .goduk1apt .com/elephantcablegrahamcooper/elephantcablegrahamcooper .php
my short list of 18 URLs can be found on pastebin.
5. The iframe is being injected only if visitors come from search engines and don’t use known IPs of search engine crawlers.
6. The iframe is being injected for all types of requests that contain eligible referrer headers. I.e. not only into web pages (content type text/html) but into any other requested resource: *.js, *.css, *.jpg, *.png, etc. and even “404 Not found” error pages. All the infected responses have the text/html content type, regardless of the type of the resource being requested, their status code is 200 (even for non-existen pages whose content say “404 not found”), and they have the X-Powered-By: PHP headers even for static files.
7. The malicious code seems to be buggy and on some sites it generates the “500 Internal Server Error“.
Now let me speculate about what’s going on.
1. When the iframes are injected into static resources, such as images, we see the extra X-Powered-By: PHP HTTP header. This means that some PHP script is responsible for this iframe injection.
2. Since the iframe HTML code is being injected even into static resources that should not be processed by PHP (e.g. images, CSS, JS ), which is clearly a bug, this means that the malicious PHP code starts working before web server touches any legitimate files. But if requests lacks a search engine referrer, then the same static files are being processed directly (no X-Powered-By: PHP header and correct Content-Type) Therefore, we can suggest that it’s either something that’s working on the server level or something that has changed the site configuration.
3. This is not a server-wide infection. I checked other sites that share the same servers with the infected sites. They didn’t exhibit the same malicious behavior.
4. So it must be some site configuration modification. Since the malicious behavior relies on the Referrer header, I guess it is done using a set of ModRewrite rules in .htaccess file that redirect all incoming requests with eligible referrers (search engines and, maybe, social networks) to some PHP script hidden somewhere on the server, providing it with the originally requested URL as a parameter.
Here’s how such a script can work:
1. Get the URL requested by a visitor (passed as a parameter by the ModRewrite rule) and either fetch it directly, or make a roundtrip to a remote server that will fetch it and return the content (like in the scenario I described in my previous post).
2. Then check the visitors IP. If it is not in a known range of IPs belonging to search engines and security companies, then inject the iframe code at the very top of the fetched “page” content and return it back to user. Otherwise return the unmodified content. If the original URLs are being fetched by a remote server then the iframe code could be injected by that remote server too (and in this case skip the following points about the iframe generation)
So how does the script change the iframe URLs (in case the iframe code is being generated by that script)? I’ve seen other attacks that use the following two tricks that can help accomplish this task:
I normally focus on infected websites and don’t analyze malicious URLs. However in this case the malicious URLs clearly belong to other infected sites and can add some interesting details to this story.
The “/templates/system/index.php” pattern in the malicious iframe URLs suggests that all those sites are powered by Joomla. So they currently use a batch of about 120 URLs that all point to an index.php file in the system template of Joomla. I guess, those sites all had been hacked using a brute force attack on the Joomla login form, followed by malicious code injection into template files using the access to Joomla admin interface. (Many people have been talking about distributed WordPress brute force attacks lately, but you should not forget that similarly massive attacks are being targeted at Joomla too. I constantly come across their traces in logs of Joomla site I work with.)
But wait, if we take a look at other lists of iframe URLs with the “7-random-characters.php” and “subdir/subdir.php” patterns, we’ll see a different picture. You won’t see many Joomla sites there. Sites in those two lists are very heterogeneous: pure html, forums, Drupal, and even ASP.NET sites on IIS servers (although PHP was installed on those IIS servers). In my experience, such lists of hacked sites could be compiled as a result of attacks that steal FTP credentials from computers of their webmasters.
It looks like the gang that injects the iframes simply sells the traffic to another gang that provides them with the lists of URLs, or they manage several different attacks at the same time.
What does those iframes URLs point at? They actually do a 302 redirect to malicious resources that try to attack visitors’ computers using known vulnerabilities in browser plugins. At this point the malware looks for the following exploitable plugins: Adobe Reader, Java, Flash, Quick Time, Real Player, Shockwave, Silverlight, VLC and Windows Media Player. The page with the exploit tracks visitors’ IPs and will return the “404 not found” errors to returning visitors.
The redirect URLs synchronously change for every iframe URL (even for those with older URL patterns that are no longer in use) every minute. This proves that the redirect rules are not something static (like typical .htaccess redirects). They have a dynamic nature and should be handled by the PHP scripts themselves. Most likely they request the redirect URLs on-the-fly from a remote server (maybe the same that provided the iframe URLs).
The redirect URLs have a peculiar format:
While the domain names change several times a day, the query part of the URLs changes every minute. Its numeric part remains the same though. At this point I noticed only two variants: 9840870 and 5186750. Not sure what they mean. Probably some IDs. You can use them to find even more malicious redirect URLs using the urlquery.net‘s search tool: 5186751 and 9840870.
When I got a first few redirect URLs, I thought they also belonged to hacked sites. There was no pattern in domain names, they all were quite meaningful (e.g. underwater-house .com or pizza-recipes .de), they belonged to multiple TDLs (.com, .net, .org, .info, .de) and pointed to multiple different IPs all over the world. However the root levels of those sites were empty, so I decided to take a look at their WHOIS records.
It turns out that all those domains (a couple of hundred) are less than a month old and each of them were registered using the united-domains.de service by a half-dozen “persons” (most likely fake) just hours before the attackers began to use them. Now it’s clear that they were specifically registered for this attack (probably using fake identities and stolen credit card details). I won’t be surprised if they also used the United Domains’ reselling program’s API to automate the process (I’ve blogged about this approach last year).
Then I checked the servers. It appeared they all were dedicated or virtual private servers with a few legitimate sites (usually from one to ten sites). One more detail. The HTTP headers of the malicious content show that it’s being served by Nginx web server. You might also have noticed that many redirect URLs point to port 8000. I checked several servers and figured out that this happens when server owners have Apache working on port 80. In this case hackers install Nginx on port 8000 and serve the malicious content off of it. Thus, the need to specify the port for URLs on such servers. But if Nginx was initially installed and working on port 80, then hackers only needed to configure new virtual hosts for their own domains and didn’t have to add port to their URLs.
The only plausible explanation is that all these servers are hacked at a root level.
Here’s the list of compromised servers (one of them is on the network of Linode, but I’m sure it’s not related to their recent security incident):
At this point I don’t have definite answers to a few questions to complete this investigation. I hope that fellow researchers and webmasters of the hacked site will be able to help me.
Meanwhile, some general advice to webmasters of compromised sites.
Questions and comments are welcome.