diff --git a/LinkShim.dev.js b/LinkShim.dev.js new file mode 100644 index 0000000..a56ece1 --- /dev/null +++ b/LinkShim.dev.js @@ -0,0 +1,41 @@ +var LinkShim = { + + //set options + redirect_url: "http://yoururl.com:8888/r?", + tracker_attr: "data-track", + params: {}, + + //called on mousedown event + changeHref: function(a) { + var $a = $(a); + var params = this.params; + var url = this.redirect_url + $a.attr(this.tracker_attr); + + //build params + params.href = $a.attr('href'); + for (var f in params) { + url += "&" + f + "=" + encodeURIComponent(params[f]); + } + + //change href of click + $a.attr('href', url); + }, + + //manually call to add PageParams + addPageParams: function(new_params) { + if (typeof new_params == 'object') { + for (var f in new_params) { + this.params[f] = new_params[f]; + } + } + }, + + //call to listen to clicks on objects that contain the tracker_attr par + init: function() { + var obj = this; //added b/c 'this' will end up refering to a tag + $("a[" + obj.tracker_attr + "]").bind('mousedown', function(e) { + e.preventDefault(); + obj.changeHref(this); + }); + } +}; \ No newline at end of file diff --git a/LinkShim.min.js b/LinkShim.min.js new file mode 100644 index 0000000..9e931f4 --- /dev/null +++ b/LinkShim.min.js @@ -0,0 +1 @@ +var LinkShim={redirect_url:"http://yoururl.com:8888/r?",tracker_attr:"data-track",params:{},changeHref:function(a){var b=$(a);var c=this.params;var d=this.redirect_url+b.attr(this.tracker_attr);c.href=b.attr("href");for(var e in c){d+="&"+e+"="+encodeURIComponent(c[e])}b.attr("href",d)},addPageParams:function(a){if(typeof a=="object"){for(var b in a){this.params[b]=a[b]}}},init:function(){var a=this;$("a["+a.tracker_attr+"]").bind("mousedown",function(b){b.preventDefault();a.changeHref(this)})}} \ No newline at end of file diff --git a/README.md b/README.md index d07ce04..def13b4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,60 @@ -# LinkShim +Notice: +====== +This is a proof of concept, and not a production-ready script. Use it as a reference. -l.facebook.com clone \ No newline at end of file + +LinkShim +======== + +Replicates Facebook Functionality of their LinkShim + +When you click on a link on Facebook to an external url, they take you to a script on Facebook that redirects you to link you requested. This is an important security feature, for the following reasons: + +### Protects People +Creates opportunity to stop malicious and spammy sites in real-time. + +### Protect Privacy +Websites know where you came from by the referrer attribute in the header. On most pages, this might not be an issue. But if I clicked on a link that was on my profile, the website could glean the fact that my facebook user +name is "iqbalrifaii" because my referrer would be "http://www.facebook.com/iqbalrifaii". But when we use a redirect script, the referrer is simply "http://www.facebook.com/l.php" + +### Gather Analytics +A successful web company should know what's be linked to, shared by who, clicked by who, trends, etc. A redirect script creates that opportunity. + + +### Learn More About Facebook's (& thus this) LinkShim +Matt Jones, an engineer at Facebook, wrote an excellent explanation of their LinkShim +https://www.facebook.com/note.php?note_id=10150492832835766 + +How to Setup +======== +This project is meant to be a framework you can use to quickly set a LinkShim. Thus, it is not comprehensive (for example, there is no user specific logging, which would be necessary in production). Follow these steps to setup: + +### 1. Install Redis & Tornado +LinkShim uses [Redis](http://redis.io), a [NoSQL](http://en.wikipedia.org/wiki/NoSQL) technology, to maintain a spam watchlist, an analytics container, and a set of valid hashes to prevent becoming an [OpenRedirector](https://www.owasp.org/index.php/Open_redirect) + +It also uses the python (Tornado Framework)[http://www.tornadoweb.org/], a scalable, non-blocking web server. I implemented this in python rather than PHP so we can keep settings and database connections open between calls. In redirect engines, speed is of utmost importantance (behind security, of course.) + +### 2. Change Settings +Download these files, place them where you want, and open server.py. Change the `admin_token` to something random/secure, and `listen_on_port` to the port you want to listen to, and templates_dir to the absolute path of your templates. (duh.) + +### 3. Start er' Up. +`python server.py` will work for testing. In production, you'll want to use a daemon. + +### 4. Create some Hashes +Have your frontend guys/gals hit `/hash?admin_token=YOUR_TOKEN&num=10` to create some hashes when they need them. By Default, tokens are valid for 6 hours. This endpoint should really be only avaiable internally for security reasons. It's on the same port for now just for the demo. + +### 5. Include the JS and place the Hashes +Include the JS Script on your page. Place one of the hashes in JS like so: + +```javascript + + + + + +
+This link is outbound, and will be tracked! + + +