Breaking Code

January 11, 2010

Having fun with URL shorteners

Filed under: Tools, Web applications — Tags: , , , , — Mario Vilas @ 2:14 am

I’ve taken some interest in URL shorteners recently. URL shorteners are the latest fad in web services – everybody wants to have their own, even if it’s not yet entirely clear how to profit from it, at least not for us mere mortals. They were born out of Twitter users need to compress their microblogging posts (some links are actually longer than 160 characters, believe it or not) and it’s spread everywhere on the Internet. Major web sites like Facebook, Google and Youtube are into it and -some say- it’s one step closer to destroying the Web as we know it.

Of course, this can also be used for evil purposes. 🙂

So I made myself a Python module to toy with these things. It can be used as a command line tool as well as a module to be imported in projects of your own, and contains no non-standard dependencies. You can download it from here: shorturl.py.

For example, this is how you convert a long URL into a short one (the shortest possible choice is automatically selected):

    $ ./shorturl.py http://www.example.com/
    http://u.nu/63e

And it’s reverse, converting that short URL back into the long one:

    $ ./shorturl.py -l http://u.nu/63e
    http://www.example.com/

You can also choose a specific URL shortener service. Let’s try Twitter’s new favorite, bit.ly:

    $ ./shorturl.py http://www.example.com/ -u bit.ly
    http://bit.ly/3hDSUb

Now, the fun stuff 🙂 what would happen if we try to shorten, say, a javascript: link? We can find out with the -t switch (output edited for brevity):

    $ python shorturl.py -t "javascript:alert('Pwn3d');"
    Testing bit.ly:
    RuntimeError: No data returned by URL shortener API
    Testing cru.ms:
    RuntimeError: <h3>URL has wrong format! Forgot 'http://'?</h3>
    Testing easyuri.com:
            Short [1]: http://easyuri.com/657ae
            Long  [0]: http://javascript:alert('Pwn3d');
    Testing tinyurl.com:
            Short [1]: http://tinyurl.com/yhabhth
            Long  [0]: javascript:alert('Pwn3d');
    Testing xrl.us:
            Short [1]: http://xrl.us/bgsge5
            Long  [0]: http://xrl.usjavascript:alert('Pwn3d');

Most services either report an error condition or simply don’t return anything at all. Two services return a garbage response (easyuri.com and xrl.us). But to my surprise TinyURL, the second largest URL shortener service is vulnerable to this! True, this is probably not news to many of you, and blocking this kind of links doesn’t provide that much of an advantage (clicking on a link with an unknown target is pretty much game over anyway) but I still fail to see the reason to support it in the first place. I can’t think of any legitimate reasons to shorten a javascript link.

Example of TinyURL's poor handling of javascript links

As a matter of fact, TinyURL seems to accept anything you send it, may it look like a valid URL or not. This has lead some people to build a rogue filesystem called TinyDisk, world readable, yet very hard (if not impossible) to trace back to it’s creator. The download link seems to be down but the Slashdot article is still there. I also found this article explaining how such a filesystem would work.

Back on the matter, the way people react to URL shorteners make them perfect for an attacker to hide the true target of his/her exploits, or bypass spam filters as it’s being done in the wild for quite some time now. There are some countermeasures. Many URL shorteners (including TinyURL) have a preview feature to let you examine the URL target before going there (for example, http://preview.tinyurl.com/yhabhth shows the sample javascript code we used above). The Echofon plugin for Firefox is a Twitter client that makes heavy use of URL shorteners, and among other things it automatically expands short URLs when the mouse hovers over them. The longurl.com service offers URL expansion as well, both from the web and as a Firefox plugin.

But… how well do they behave when you shorten the URL multiple times? First, let’s try shortening a link with TinyURL three successive times:

    $ ./shorturl.py -c 3 -u tinyurl.com http://www.example.com/
    http://tinyurl.com/ya3k2yy

The preview feature only seems to work for the first redirection (see for yourself). Now let’s try shortening our example URL three times, using random providers:

    $ ./shorturl.py http://www.example.com -v -c 3
    Service: thurly.net
    Service: ito.mx
    Service: cru.ms
    http://cru.ms/53c14

I found the Echofon plugin fails to expand this short URL. However the longurl.com service works like a charm – it even told me how many redirections I used! Click here to see it for yourself.

Example of Echofon expanding a short URL

Just for fun, how about an infinite recursion? First, we create a link to a shortened URL that doesn’t yet exist.

    $ python shorturl.py -v -c 5 http://tinyurl.com/thisisaninfiniteloop
    Service: ito.mx
    Service: migre.me
    Service: thurly.net
    Service: is.gd
    Service: xrl.us
    Service: onodot.com
    http://onodot.com/xeaw

Now let’s go to the TinyURL webpage and create the link manually. Voila! We have an infinite redirection. The longurl.com service seems to break now (see for yourself) but this is of no consequence – the link doesn’t really take you anywhere. Other apps like wget get stuck in an infinite loop however. This is probably of no real use to an attacker but I thought it was fun to try it out. 🙂

As a final note: while writing this I came across this article describing even more risks inherent to URL shorteners: information disclosure. A dedicated attacker could dump randomly chosen shortened URLs to retrieve information like corporate intranet links, user IDs and even passwords. I liked the idea, so I whipped out a small script to test it out:

    from random import randint
    from shorturl import longurl, is_short_url

    characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
    while 1:
        token = ''.join([ characters[ randint(0, len(characters) - 1) ] for i in xrange(6) ])
        try:
            url = longurl('http://bit.ly/%s' % token)
        except Exception:
            print token
            continue
        if not is_short_url(url):
            print "%s => %s" % (token, url)

But the results of bruceforcing didn’t seem so great. Then again, one could also wonder how random this short URLs really are… maybe there’s a way to predict them, or at least reduce the number of URLs one has to try. One could also try a dictionary based approach for services like bit.ly, which provide the users the ability to pick custom short URLs. Update: Those TinyURL links weren’t so random after all 😉 here’s an interesting project on URL scraping.

Read Part 2: parasitic storage

Download

shorturl.py

bitlybf.py

Source code

You can get the source code at Github.

Advertisements

21 Comments »

  1. Gueno! refreshing! enjoy your free time!

    Comment by internetchoter — January 11, 2010 @ 4:48 am

  2. Thank you for this beautiful Topic
    http://www.gmz2.com

    Comment by GMZ2 — January 11, 2010 @ 6:31 am

  3. nice post!

    apparently the tinyurl bug has been exploited at least since 2006 using “data:” instead of “javascript:”, what is the difference? :O

    http://michaeldaw.org/news/news-221206

    Comment by thermo — January 11, 2010 @ 6:20 pm

  4. Hi thermo, there is no difference to the “data:” exploit, in fact this is being exploited in the wild. It just surprised me to see that TinyURL was still vulnerable to this kind of attack, whereas other smaller services were not (in fact TinyURL was the *only* vulnerable service I could find in my tests).

    Comment by Mario Vilas — January 11, 2010 @ 6:55 pm

  5. Social comments and analytics for this post…

    This post was mentioned on Identica by nemo: URL shorteners suck: https://breakingcode.wordpress.com/2010/01/11/having-fun-with-url-shorteners/

    Trackback by uberVU - social comments — January 12, 2010 @ 9:19 am

  6. […] ver un vídeo. Por supuesto, esta actualización contendrá el malware que nos infectará. Esto se agrava con el acortamiento de URLs, que también sirve para enmascararlas. La vulnerabilidad clickjacking tambien hizo uso de este […]

    Pingback by 10 usos fraudulentos de twitter | Shadow Security — January 12, 2010 @ 6:16 pm

  7. […] ver un vídeo. Por supuesto, esta actualización contendrá el malware que nos infectará. Esto se agrava con el acortamiento de URLs, que también sirve para enmascararlas. La vulnerabilidad clickjacking tambien hizo uso de este […]

    Pingback by 10 usos fraudulentos de twitter | Flix Web — January 16, 2010 @ 5:46 pm

  8. […] ver un vídeo. Por supuesto, esta actualización contendrá el malware que nos infectará. Esto se agrava con el acortamiento de URLs, que también sirve para enmascararlas. La vulnerabilidad clickjacking tambien hizo uso de este […]

    Pingback by Qrko » Blog Archive » 10 usos fraudulentos de twitter — January 16, 2010 @ 6:55 pm

  9. Funny how I got pingbacks from three different blogs, all with the exact same text (and presumably different adsense accounts?).

    Comment by Mario Vilas — January 17, 2010 @ 10:23 pm

  10. Hey, thanks for the ‘for fun’ tip.
    Been a long time since I didn’t program in Python.

    Comment by Tu sais que — January 22, 2010 @ 8:52 pm

  11. […] ver un vídeo. Por supuesto, esta actualización contendrá el malware que nos infectará. Esto se agrava con el acortamiento de URLs, que también sirve para enmascararlas. La vulnerabilidad clickjacking tambien hizo uso de este […]

    Pingback by 10 usos fraudulentos de Twitter « Informatica Legal Blog — January 29, 2010 @ 6:43 pm

  12. great info, thanks for sharing.

    Comment by clark — March 10, 2010 @ 11:14 pm

  13. Hey thats very nice …URL shortener..I had a great benefits of it

    Comment by IT Outsourcing — March 29, 2010 @ 7:04 am

  14. Hi

    Thanks for this nice tutorial, it can be very effective to make short URL’s.

    Best regards
    Dan
    The Independent Antivirus Community

    Comment by Dan — May 13, 2010 @ 10:21 am

  15. Hey, check out fun.ly, The Fun URL Shortener!

    Comment by fun.ly — August 29, 2010 @ 6:56 am

  16. What an intersting look. Seems like url shorteners are more vulnerable than everybody thinks.

    Comment by Mark — October 2, 2010 @ 1:03 am

  17. characters[ randint(0, len(characters) - 1) ] should be written as random.choice(characters)

    Comment by bob — December 15, 2010 @ 8:55 am

  18. […] оказалось, что идее уже много лет, и многие вполне успешно её реализовали. Нашлись и другие […]

    Pingback by GEEKS’ TRICKS | Altsoph The Honest — July 3, 2012 @ 6:52 am

  19. http://hpstr.ly is particularly humorous – it appends three random hipster terms.

    Comment by Jeff — November 24, 2012 @ 7:09 am

  20. A motivating ddiscussion is worth comment. I believe that you
    should publish more on this issue, itt might not
    bee a taboo matter but generally eople don’t discuss such subjects.
    To the next! Best wishes!!

    Comment by Mellisa — June 16, 2015 @ 12:30 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: