Enumerating URL shorteners

Thats a nice looking pattern youve got there..

Wed, 11 Jan 2017


I was at work when I almost dropped a URL into goo.gl, you know because short URLs are awesome. However I stopped right before I dropped it in because Google was kind enough to tell me that all URLs shortened are public. Then it occured to me that just haphazardly dropping links in is of course an OPSec issue. With billions of shortened URLs in existence is it really though?

Where we start

We need to start with our plan of attack. Most goo.gl URLs look like this, https://goo.gl/QE6V6o Alright, so six character. We need to calculate all possible combinations with a length of six characters, encompassing all uppercase and lowercase characters, as well as 0-9. It comes out to 10 numbers + 52 letters(Upper&Lower) = 62. 62 ^ 6(length of our string) = about 57 billion unique values. This could take a while to enumerate through, and also presents a challenge.

Being the person I am, I opted to go the path of least resistance. While I could spend forever writing a program to perfectly generate all 57 billion strings, I could also throw together a random generator way faster.


import string
import random
import requests
import signal
import sys

op = open("output.txt", "a")
#Thank you string library for helping make this simple
def generator(size=6, chars=string.ascii_uppercase + string.digits + string.ascii_lowercase):
	rndStr = ''.join(random.choice(chars) for _ in range(size))
	return 'https://goo.gl/' + rndStr
#Thank you stack overflow for helping me make sense of requests. (We are checking the header URL here)
def testURL(url):
	return requests.head(url, timeout=100.0 , headers={'Accept-Encoding': 'identity'}).headers.get('location', url)
#A clean break with Ctrl+C is hit
def signalHandler(signal, frame):
	print 'Stopping logging \n'

#Generate URL-> Request URL -> Check for redirect -> Log redirect
def main(*args):

	for i in range(0,int(sys.argv[1])):
		url = generator()
		test = testURL(url)
		print 'Original url: ' + url + ' Resultant url ' + test
		if url != test: 
			stuff = url + ' Redirects to ' + test + '\n' + '\n'
			print 'Logging redirect: ' + stuff

if __name__ == '__main__':

Alright so we have our script, but what about the results?

I didnt want to blow Google out of the water with requests, not that I could but courtesy you know, so I made sure I could pass an arg setting my loop to run a fininte number of times.

Sometimes we got long stretches of nothing, other times we hit the jackpot.

Overall I probably ran about 7,000 requests and received about 300 results. Considering my effort was minimal, I’d say its a neat return for the work.

I’m going to just drop all of the results pictures beneath this with captions pointing out potentially interesting finds.

Overall I think the pictures will sort of make the case that one shouldnt just drop anything into a URL shortener.

-think the pictures will sort of make the case that one shouldnt just drop anything into a URL shortener.

Nothing so far… URL Enumeration

Around here is where we start seeing some odd stuff.

Odd findings

Questionable findings

Heres a screen cap of us finding some potentially juicy things. We can see a facebook, a jetblue boarding pass, what looks like an online order confirmation, and someones dropbox user content. Not sure I’d just want to share those URLs with just anyone.

I’m sure you’re tired of all of that green font so lets just look at the output file.

Stuff Found

Alright lets just pick out things that catch our eye. A request looking like it belongs to some dev environment, a google drive, a secure checkout from a shopping basket url, a facebook share, and a healthcare site with a lovely encoded url.

Theres plenty more in the file, I didnt think it would be necessary to really post the whole thing to hammer the point home.


As a final conclusion its obvious that you shouldn’t put anything potentially sensitive into a url shortener. Which they tell you not to do on the page but sometimes people gloss over these sorts of things.

Anthony Laiuppa

If you have any feedback feel free to @ me on twitter, Im always looking to learn. -AL