In the waning hours of 2010, a hacking group known as Lulzsec ran rampant across the Internet, leaving a path of compromised servers, a trail of defaced home pages, leaked emails, and login information in their wake. They were eventually busted via human error, and the leader of the group becoming an FBI informant. This handful of relatively young hackers had made a huge mess of things. After the digital dust had settled – researches, journalists, and coders began to dissect just how these seemingly harmless group of kids were able to harness so much power and control over the World Wide Web. What they found was not only eye-opening to web masters and coders, but shined a light on just how vulnerable all of our data was for everyone to see. It ushered in an era of renewed focus on security and how to write secure code.
In this Dark Arts series, we have taken a close look at the primary techniques the Luzsec hackers used to gain illegal access to servers. We’ve covered two them – SQL injection (SQLi) and cross-site scripting (XSS). In this article, we’ll go over the final technique called remote file inclusion (RFI).
DISCLAIMER: Fortunately, the surge of security-minded coding practices after the fall of Lulzsec has (for the most part) removed these vulnerabilities from the Internet as a whole. These techniques are very dated and will not work on any server that is maintained and/or behind a decent firewall, and your IP will probably get flagged and logged for trying them out. But feel free to set up a server at home and play around.
PHP, Yeah You Should Know Me Better Than That
RFI attacks are not as well-known as their SQLi and XSS counterparts. However, it’s a very effective way to get malicious code to run on a vulnerable target server. It works by including a remote file in an HTTP request. Its basic form is to append a URL to include a file from a remote server. For instance, say instead of typing
http://www.ilurvmesomearduino.com/ into the URL bar, you type in something like
If you get the Hackaday web page, then
http://www.ilurvmesomearduino.com is susceptible to an RFI attack. What you’ve done is run
http://www.hackaday.com/index.php on the Arduino site server. There is nothing stopping you from doing something like
The most prevalent reason this was possible was because web coders would often structure links to other pages within their site like this:
------| index.php?page=uno.php ------| index.php?page=mega.php ------| index.php?page=due.php
This way, the links in the index.php home page will simply call another .php file. To do this, they would use the include() function to call the sub-pages of uno, mega and due.php. Consider the slightly modified code we found on the web (written in 2011) from a hacker who went by [B.K.]:
<?php if(isset($_GET['page'])) //vulnerable to RFI $page=$_GET['page']; include($page.".php"); else ?> <html> <h1>I Love Arduino</h1> click here for <a href="http://hackaday.com/index.php?page=uno">Uno</a> click here for <a href="http://hackaday.com/index.php?page=mega">Mega</a> click here for <a href="http://hackaday.com/index.php?page=due">Due</a> </html> <? ?>
Can you see where the problem is? When a link in the HTML block is clicked, it gets passed to the
GET variable. The
include() function will then resolve the URL to
http://www.ilurvmesomearduio.com/index.php?page=uno if you click the ‘Uno’ link. There is nothing here to stop someone from including files from outside the domain. Nothing stops you from changing
?page=uno to whatever you want.
And that’s how a basic RFI attack works. There are variations of course. Let us know your favorite in the comments!
As you see, the attack is simple enough to construct a program that can look for pages that are susceptible to RFI, and then run code to extract information from the vulnerable server. And that’s exactly what happened in the early part of the decade. The graph below shows logged RFI attacks in 2010-2011. The spikes were largely do to a single user, suggesting an automated tool was at work.
Preventing RFI Attacks
Fortunately it is relatively trivial to stop RFI attacks. The absolute best way is to go into your
php.ini file and set
allow_url_include to off. They should be off by default if you keep your server updated, but check anyway. Another way is to sanitize the inputs, much in the same you would to prevent SQLi. This can be done by making a whitelist of files that can be run on your server. And there’s always a good firewall that can stop these kind of attacks before they start.
Most importantly, we should always look at code through the eyes of the hacker probing for weaknesses, and of course patch up the holes as quickly as possible when a new one is discovered. With RFI, as with SQLi, the problem is opening up the system to arbitrary user input. This was a lesson the Internet learned the hard way. We hope.