I had a spare hour over the weekend and I wanted to do something fun, so I created a short URL service for securityheaders.io! This is how I did it.


Why?

Honestly, there's no real reason. Sometimes an idea will pop into my head and if it sounds fun, I will just go and do it! Besides, I was pretty sure that I could get it almost for free and it sounded like an interesting project for the afternoon, so here's how to do it!


YOURLS

YOURLS, or Your Own URL Shortener, is a cool (and free!) tool to create your own URL shortening service. You basically have something that closely resembles Bitly for those of you that have used it, except it's fully under your control. It's simple to setup and you get a cool dashboard to control everything. I already use YOURLS for scotthel.me on my blog.


dashboard


You can use the GUI to create links and they will either take the next available, random value for the end of the URL, or you can create a custom one. Another really awesome thing about YOURLS is the stats you can view on each short URL you create.


traffic stats


traffic location


traffic sources


This means you can create different URLs for different social media platforms, to use in email campaigns or however else you may wish to track different click rates. Of course, it's also possible to create short URLs with API calls, which is what I'm doing for securityheaders.io, to create new links. You can do this with your user credentials, or they also support an API token if you don't want to bake your credentials into your code. I use the following call to create short links:


https://schd.io/yourls-api.php?
signature=*snip*
&action=shorturl
&title=short
&format=json
&url=[URL encoded URL]

The signature value can be found in your YOURLS admin section and the rest of the values are pretty straightforward. The action, shorturl here, tells the API we want to create a new short URL, I provide a title so that the API doesn't initiate an outbound request to fetch the page title, the format indicates I want the resulting data to returned as JSON and the URL is the long URL that I want a short URL for! The returned payload looks like this:


{"url":
    {"keyword":"1",
    "url":"https:\/\/scotthelme.co.uk\/",
    "title":"short",
    "date":"2016-07-24 11:08:49",
    "ip":"*snip*"},
"status":"success",
"message":"https:\/\/scotthelme.co.uk\/ added to database",
"title":"short",
"shorturl":"https:\/\/schd.io\/1",
"statusCode":200}

From this you can extract the new shorturl that was created and use that from now on. To avoid duplication of long URLs in the database, YOURLS has an option to return a previously created short URL for the long URL. If you call the API to create a short URL for a long URL that already exists, you get the following back:


{"status":"fail",
"code":"error:url",
"url":
    {"keyword":"1",
    "url":"https:\/\/scotthelme.co.uk\/",
    "title":"short",
    "date":"2016-07-24 11:08:49",
    "ip":"*snip*",
    "clicks":"0"},
"message":"https:\/\/scotthelme.co.uk\/ already exists in database",
"title":"short",
"shorturl":"https:\/\/schd.io\/1",
"statusCode":200}

You still get the shorturl value that we need and it stops a build of duplicates in the database wasting those precious short URLs!


Encryption

Of course, any new service online today should be available over HTTPS, it is 2016 after all. Thanks to Let's Encrypt, the free Certificate Authority, this will also come at no additional financial cost.


Let's Encrypt Logo


If you want to use Let's Encrypt, I have a few articles that should help you out. There's Getting started with Let's Encrypt!, Let's Encrypt Smart Renew and if you want things to be super fast, Testing out ECDSA certificates, which details how to get ECDSA certificates up and running with Let's Encrypt. If you're worried about backwards compatibility for really old clients you should read Hybrid RSA and ECDSA certificates with NginX to avoid any issues.


Using HTTPS does come at a cost though, it's going to make my precious short URLs one character longer! The horror... I'm currently weighing up a 'fix' for this, and it's HSTS Preloading. I have a blog on HSTS and preloading, but in short, they force a browser to use HTTPS to communicate with a site even if the URL says HTTP. This means I could technically provide URLs in their HTTP version and most of the time it would be upgraded to HTTPS by the HSTS policy or at least a cached 301, worst case, the 301 itself. I'm not too keen on that so I'm providing them as HTTPS, but any thoughts on that approach would be great to hear, please drop them in the comments below.


Finding a domain

There are some cool services online like domai.nr that will try and help you find short URLs that you like. I had a look around and whilst I could have gotten one that was a character or two shorter, schd.io seemed like a good fit. The shortening of security headers to schd seemed logical and I'm using a .io domain now so it seemed sensible to stick with that too. Domains are pretty cheap these days but it did represent the first cost to implementing my new short URL service. I guess we can't get everything for free, right?


Making it all work!

With the nameservers and DNS configured for the new domain and YOURLS and Let's Encrypt setup, all that was left to do was to hook it up to the securityheaders.io site. That turned out to be super easy too.


if(!$this->hide) {
    $url = $this->config->item('base_url') . "?q=" . $this->currentUrl;
    if($this->followRedirects) {
        $url .= "&followRedirects=on";
    }
    $apiResponse = file_get_contents("https://schd.io/yourls-api.php?signature=*snip*&action=shorturl&title=short&format=json&url=" . urlencode($url));
    $apiJson = json_decode($apiResponse, true);
    if($apiJson['status'] == "success" || $apiJson['status'] == "fail") {
        $this->shortUrl = $apiJson['shorturl'];
    }
}

The first thing to note is that scans that are hidden on securityheaders.io do not get a short URL to protect them from being easy to enumerate. After this, everything else is fairly self explanatory and all I needed to do was add a new row in the report table. This completes the work and you now get an easy to share short URL for all scans!


short url


Just for comparison purposes, here is the before and after of the URL for the results page.


https://securityheaders.io/?q=https%3A%2F%2Fscotthelme.co.uk&followRedirects=on

https://schd.io/1