msteigerwalt

Ghetto Geolocation
(Featuring Soft Porn!)

Update: This is an XSS security example. I wrote this way back in 2008, and even then it wasn’t exactly best practices.

Rob wanted geolocation without actually having to pay for it, so he asked me if there was a way to extract the user’s location from Adult Friend Finder’s ad banner script without allowing the banner to actually be displayed.

The ads are made of of nude (or practically nude) photos of women in the user’s local area who, the ad claims, are looking for casual sex. These pictures are definitely not work-safe.

Clearly, actually showing this banner would be a bad idea. We could hide it with CSS, but that’s riskier than never adding the HTML to our page at all.

What We Have to Work With

The ad script uses document.write to inject HTML into the page with a list of ‘friends’ in the area, along with the name of the area. We want to be able to get the name of the area inside the document.write text without having to show the user a list of friends.

We can’t manipulate the content through a backend script, since AFF’s geolocation works based on IP address, which would match the current location to wherever the server is.

Thinking Outside of the Non-JS Box

At first glance, it seems like it’d be impossible to get any information out of a document.write before loading the page, unless you use some crazy XSS to process the script’s content as a raw string.

But that’s only if you’re thinking in terms of standard languages. In JavaScript, you can freaking overload anything. Including native functions.

So here’s the magical line of code we’re going to be using:

document.write = function(txt) { window.outputBuffer = txt; };

Next, we include the <script> tag for the ad. I won’t post the URL for that here because it’s probably subject to change.

<script type="text/javascript"
    src="http://banners.adsite.com/not/the/real/url.js"></script>

After the ad content has been included (and intercepted by our document.write rewrite), we can access the location data like so:

var loc = window.outputBuffer.match(/<span class="location">(.*)<\/span>/)[1];

It’s also a great way to detect if your user is using an adblocker!

You can see it in action here.

Learning From AFF’s Mistakes

Honestly, I wish it were a bit more complicated. Right now, we’re only getting the user’s location, but imagine if the user was logged into the site and the ad were utilizing personal data.

This is the sort of thing developers should always consider when creating dynamic scripts which display critical data about a user.

The simplest way to get around something like this if you find yourself in AFF’s situation is to use an iframe. They’re subjected to cross-domain security policies which can’t be circumvented so easily.