At work last week we were discussing the security implications of url shortening services, such as tinyURL, biy.ly and goo.gl not only the fact that they can be used to hide malicious URLs for use in phishing attacks but the problem’s we’re having are:
- Users in more restrictive access groups not being able to click links from these services
- But worse, some users are using this service to shorten intranet links
Now that second point is an issue for me; if a shortening service were hacked our server names could be leaked to the world.
The two obvious solutions were ban all users from using such services or run our own internal service
My instinct told me that one shouldn’t be to hard to build.
So Here it is in less than 50 lines
from SimpleHTTPServer import SimpleHTTPRequestHandler import StringIO,os,BaseHTTPServer,sqlite3 if "urls.db" in os.listdir("."): con = sqlite3.connect("urls.db") c=con.cursor() else: con = sqlite3.connect("urls.db") c=con.cursor() c.execute("create table shorts (id integer primary key, url varchar unique)") server = BaseHTTPServer.HTTPServer server_address = ("", 8000) class MyHandler(SimpleHTTPRequestHandler): def send_head(self): body,response = " ",200 if self.path=="""/""":pass elif self.path.endswith("+"): c.execute('SELECT url FROM shorts WHERE id=(?)', (self.path[1:-1].decode("base64"),)) s=c.fetchone() boady = s[0] elif r"/add?" not in self.path: response=301 c.execute('SELECT url FROM shorts WHERE id=?', (self.path[1:].decode("base64"),)) s=c.fetchone() else: x=self.path.split("?",1)[-1].replace(r"http://","") try: c.execute("insert into shorts(url) values (?)", (x,)) con.commit() except sqlite3.IntegrityError:pass c.execute('SELECT id FROM shorts WHERE url=(?)', (x,)) s=c.fetchone() body = "ok. " + str(s[0]).encode("base64") self.send_response(response) self.send_header("Content-type", "text/html; charset=utf-8") self.send_header("Content-Length", str(len(body))) if response==301: self.send_header("Location","http://"+s[0]) self.end_headers() return StringIO.StringIO(body) httpd = server(server_address, MyHandler) print "Starting server..." try: httpd.serve_forever() except KeyboardInterrupt: httpd.socket.close()