This page looks best with JavaScript enabled

Enumerating URL shorteners

 ·  ☕ 4 min read

Intro

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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/python

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'
	op.close()
	exit(0)

signal.signal(signal.SIGINT,signalHandler)
#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
			op.write(stuff)
		
	op.close()

if __name__ == '__main__':
	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.

Conclusion

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.

Share on

Anthony Laiuppa
WRITTEN BY
Anthony Laiuppa
DevSecOps Engineer