Search code examples
phpjavascripttrackingforwardingreferrer

Trackingpixel should load external website through a referring page - but it doesn't work


I have a problem with a trackingpixel. The trackingpixel is included on the main page like that:

<img src="tracking.gif" alt="" />

The tracking.gif contains the following:

<?php
header("Location: http://www.mydomain.com/referrer.php?url=http%3A%2F%2Fwww.external.com")
?>

The referrer.php looks like that:

<?php
$url = $_GET['url'];
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Referring...</title>
        <link rel="stylesheet" type="text/css" href="css.css" />
        <meta http-equiv="refresh" content="0.3; URL=<?php echo $url ?>" />
        <script type="text/javascript">
                    window.setTimeout(function() {
                        location.href = '<?php echo $url ?>';
                    }, 300);
        </script>
    </head>
    <body>
        Some text.
    </body>
</html>

Unfortunately the redirect to the external website doesn't work. Only the referrer.php gets loaded. Why is that? The code works if I replace the referrer-url in the tracking.gif by the url of the external website.

More Info: If I call the referrer.php directly, it's working. And I set the server via htaccess that it shoud handle the tracking.gif as a php-file.

Thanks for your help in advance!


Solution

  • The answer to your question lies in how browsers handle assets of different types, and what assets are allowed to actually do.

    Your first piece of code:

    <img src="tracking.gif" alt="" />
    

    Tells the browser to load and display an image from some location. In order to do that, it's going to make an HTTP request for the image. This is why your second piece of code:

    <?php header("Location: ....") ?>
    

    actually works. The browser sends an HTTP request for tracking.gif, and the response directs the browser to another location. This is all fine (although you should also be setting the response status to 302 for completeness) and the browser goes off to your new URL in search of image data.

    Here's we we hit the problem. When we follow the redirect to our new page, we don't get an image back- we get some HTML. The browser can't interpret this as an image. It appears to be nonsense. And so it is discarded. The browser certainly isn't going to check for, or execute, code embedded in the nonsense image data. It's simply going to hand the data to the pipeline responsible for drawing images, which will then say "I don't understand this" and move on to the next task.

    This is why your referrer.php page actually works when you load it directly in the browser - because the browser is expecting HTML and Javascript. When the same data is received by the browser is expecting an image, the result is failure.

    It appears that you're trying to cause the browser to go to a different URL when an image loads, which isn't permitted by the security model - image files cannot inject behaviour into pages that include them. Can you unpack what you're actually trying to achieve in a little more detail?