The Dark Arts – Remote File Inclusion

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 into the URL bar, you type in something like

If you get the Hackaday web page, then is susceptible to an RFI attack. What you’ve done is run 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 

<h1>I Love Arduino</h1>
click here for <a href="/index.php?page=uno">Uno</a>
click here for <a href="/index.php?page=mega">Mega</a>
click here for <a href="/index.php?page=due">Due</a>
<? } ?>

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

Automatic Tools

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.

Source via Imperva

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

28 thoughts on “The Dark Arts – Remote File Inclusion

      1. It’s quite common practice for enterprises to flow millions of dollars from code even worse than the example. No one cares until something blows up or it stops making money.

  1. What the hell, people actually do/did that? Even back when I was doing mostly hobby web dev some 15+ years ago you would do something like “if($_GET[‘page’] == ‘index’){include(‘/pages/index.php’)}” (or more commonly a switch()) to protect against that type of stuff.

    1. I used to work with a guy who liked to do:

      foreach ($_REQUEST as $key => $value)
      $$key = $value;

      Then he proceeded to use $some_form_input_name_here in later parts of the code.

      He even did this BEFORE sanitizing or parsing the request in any way. Pure madness.

      1. I’ve always just went with ./

        For SQLi I go with PDO prepared statements if I have to use PHP which I usually do cause I usually do popular CMS plugin code when I do anything with web-dev.

    1. It’s called “Off Line Testing”, and all quality shops do this protocol. (Unless the “Bean Counters” say no.)
      Ive had an “In house” network for 10 years, just for the type of testing referenced here.

        1. Me and a mate once fired a photographing rocket up next to Menwith Hill, just to see how they like it. Just a 50 quid Estes thing with the old film-based camera. Got some great shots of the empty sky over a major international eavesdropping facility.

  2. The PHP documentation was it’s own worst enemy. For years the documentation included “examples” off how to use features that were straight up security vulnerabilities (a good example was how to send an email which was vulnerable to injection turning your site into a spam gateway). Thanks to the low bar to entry these examples were copy/pasted into hundreds of sites.

    1. PHP was (is?) a goddamn mess for years. I spent months securing both a Perl and PHP based website for my department only to have the admin kill the whole server when another departments website was hacked and went rogue tromping on every other server on our network.

      I got flak for several days because I hid a watchdog suicide routine to kill our wbsite if PHP went rogue and the moronic admin found it after shutting everything down. Placed the blame squarely on me until I pressured our asshole bosses to do an internal investigation by a 3rd party.

      I was absolved but the damage was done. I was reprimanded and eventually taken off the the dev team. I quit and six months later another watchdog I wrote clamped down on the internal file server because some ass downloaded a Trojan.

      I have no sympathy for PHP or their users. Some of the worst code ever written was written in PHP.

  3. This was a big problem many years ago – when there was only allow_url_fopen and not the extra allow_url_include option. (Think it came with PHP 5.0 – but I’m not sure)

  4. Security rule number is – never trust anything that comes from a browser.

    So things like $_GET, $_POST, $_REQUEST, QUERY_STRING, REQUEST_URI and REQUEST_URL need to be sanitized.

  5. Those running histograms, like the plot, are much less useful than a running cumulative sum. It shows trends in the small day-to-day as well as the peaks. You might consider recontriving your information into that format.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s