Geolocation of IP addresses using GeoIP and Google Maps

People mean totally different things when they use the word “hack”.

To me, hacking is what Dr. Frankenstein did just before he created his monster.

Today’s creation will glue a few parts together to make a web site that will show the geographical location of an IP address on Google Maps.  This script also lets the user look up the geolocation by DNS hostname.

The advantage of my approach over some others on the net is that this method is totally free and requires no API key.  I’ve also made it portable to shared hosting sites, and it will run just as easily on Linux, OSX or Windows web servers.

Screenshot of iplocate.php in action

First, an ingredients list:

  1. A web server or web hosting site that supports PHP.
  2. A copy of the latest version of MaxMind’s GeoIP City database, which provides the mappings from IP to map coordinates in latitude and longitude.  You can download the latest free version here.
  3. The scripts require two PEAR modules:  Net_DNS and Net_GeoIP.  If you are running this on your own server, just use ‘pear install Net_DNS Net_GeoIP’.  If you are on Dreamhost, you can follow the awesome instructions on David Yin’s blog to get Pear installed first.

Once you have everything ready, all you need to do is download this PHP script, and customize it in a few places:

  1. If you are on Dreamhost, and you had to install Pear in your home directory, uncomment the Dreamhost section at the top of the file (and replace the path with the real path to the “php” subdirectory of your Pear installation.  If you followed David Yin’s instructions above, the path will be:
    /home/USERNAME/pear/php
  2. Replace the fake path on this line:
    $geoip = Net_GeoIP::getInstance("/FIX-THIS-PATH/GeoLiteCity.dat");
    with the real path to your GeoIP City database file.
  3. Replace the fake IP addresses on this line:
    $resolver->nameservers = array('YOUR.FIRST.DNS.HERE','YOUR.SECOND.DNS.HERE','YOUR.THIRD.DNS.HERE');
    with the real DNS servers that you want to use for looking up hostnames.
  4. Finally, copy the edited file into the documents folder of your web server (make sure that it has a .php extension) and point your browser at it!

You should now be able to enter an IP address or a hostname and have it pull up a Google Map of the correct coordinates!  If the hostname lookups don’t work off the bat, double-check step 2 above and try uncommenting the two DNS debugging lines in the PHP file.  Remember to give it DNS servers relative to your web server.

At this point, you might be wondering why I’m posting the PHP code instead of simply hosting this page myself. Turns out that Maxmind’s license for the free GeoIP database forbids you from providing a publicly-available interface that allows translating IP addresses into coordinates. The only way to do this (legally) using the free database is to either run this on an internal web server (not accessible to the public) or to password-protect the page using .htaccess files.

Obviously, this could be easily extended to add some stuff like plotting multiple different records from the DNS queries instead of just the first hit. Another idea is to make it spit out KML so that it would just magically work with Google Earth as well. I will leave that to you (or perhaps to some kindly strangers down in the comments).

Also, the hostname lookup feature reveals something interesting when you use it on edge-cached domains or clouds, but I’ll leave that for the home experimenter to explore.

… It lives, my creation LIVES

How To Connect a PS/2 Keyboard to the iPhone

Although I’ve seen many pictures of PS/2 keyboards plugged into iPhones on the Internet, no one has yet published a detailed howto on how to get this working yourself.  Until now, that is.

In this article I will show you how you can make a PS/2 keyboard to iPhone converter, including all hardware and software instructions. As the bugs get worked out, or improvements are made, I’ll update this page. Continue reading “How To Connect a PS/2 Keyboard to the iPhone”

XSS Vulnerability in Internet Explorer HTML Attachment Download

Update: MS fixed this issue in the IE8 6/9/09 security update.  Now IE8 behaves like Firefox (unclear on whether ‘X-Download-Options: noopen’ still exists at all).

I have noticed a Cross-Site Scripting vulnerability in the way Internet Explorer handles the downloading and opening of HTML files when they are downloaded as an attachment, rather than opened normally. This vulnerability exists in all versions of Internet Explorer, including the latest patch level of IE7 as of 12/23/08.

This vulnerability related to sites serving user-submitted HTML files with “Content-Disposition: attachment”.

When directly opening a downloaded HTML file, Internet Explorer violates the Same Origin Policy by allowing any script inside the downloaded file to access the cookies of the site the file was downloaded from. This script should be restricted to running in a local context, not a domain context.

Firefox exhibits better behavior by first downloading the HTML attachment and then opening it with a file:// URL. When scripts in the downloaded HTML file are executed, they are treated as if run from a local file, not as if run from the domain the file was downloaded from, and they cannot access the source domain’s cookies.

This vulnerability would allow an attacker to execute a Cross-Site Scripting attack on a site that allowed uploading file attachments. An HTML file could be uploaded containing malicious script that could steal user credentials or forge user actions on the site (if downloaded and opened by an IE user).

I have created a screencast reproducing the incorrect behavior in Internet Explorer as well as the correct behavior in Firefox. Additionally, I’ve set up a downloadable HTML file that you can use to reproduce the issue yourself!

The screencast and example are available at: https://www.awgh.org/iebug

Microsoft has addressed this issue in IE8, but their solution leaves me with some questions.  The write-up in their development blog is here, skip down to the section titled “MIME-Handling: Force Save”.  This section acknowledges that this is a potential vector for script injection in IE and describes the solution as implemented in IE8.

The solution in IE8:

The web server can set the response header “X-Download-Options” to the value “noopen”.  This will tell Internet Explorer to only offer the option to save the file or cancel.  It simply removes the “Open” option when this option is set.

I see two problems with this solution.  First, call me a pessimist, but I can see someone actually disabling “noopen” simply to bring back the “Open” dialog option.

Second, I doubt that most web server admins are going to be worried enough about this issue to remember to set this header, or even know they should do it.  It’s a bit of an esoteric bug – it only affects sites that serve untrusted HTML with “Content-Disposition: attachment”.  Even if Microsoft web servers set “noopen” by default, I doubt that most LAMP admins will bother adding this to their server options.

Why force the server to fix this problem?  Why not treat the “Open” option the same way Firefox does, by first downloading the file, then opening it with only a local script context?

This method of script injection will continue to work in Internet Explorer 8, as long as the site has not set the “X-Download-Options” header to “noopen”.

So the moral of the story:  If you are the admin of a site that serves untrusted HTML files with “Content-Disposition: attachment” set, please make sure the “X-Download-Options” header is set to “noopen”.