This article was originally written by Julien Cretel on the Honeybadger Developer Blog.
Links! They're the very fabric of the Web. Browsing simply wouldn't be possible without them. Creating and following links feels so natural that you probably don't stop very often to wonder about the risks associated with them. In this post, I want to cover three vulnerabilities involving links: broken-link hijacking, open redirects, and reverse tabnabbing.
You probably share useful resources in your blog posts, on your social networks, etc. By linking to some third-party website and inviting your readers, though, you're implicitly establishing some kind of contract with them. You're essentially saying:
Hey! We believe that the resource accessible at the end of this link could be of interest to you, and we vouch for the trustworthiness of the site that hosts it. :)
However, can you guarantee that the resource will remain accessible and unaltered forever? Not if the resource is outside of your control. After all, the Web is in a constant state of flux, and link rot is real because, for example, websites restructure their content, companies rebrand or are acquired, and domains expire.
Broken-link hijacking is an attack whereby a facetious (if not malicious) actor notices a dead link in your content and manages to take control of what lies at the end of that link.
What could a broken-link hijacker do, in practice? Here is a funny example.
In April 2011, Donald Trump posted a tweet in which he announced he would attend the 2012 National Achievers Congress; he also shared the URL of the congress's website (
www.nac2012.com) in his tweet. At some later stage, the congress organizers let the
nac2012.com domain lapse, which then caused the link in Trump's tweet to break. After noticing that the domain was available for purchase, Belgian ethical hacker Inti de Ceukelaire bought the domain and playfully redirected it to a Youtube video lampooning Trump. From then on, any unsuspecting person viewing Trump's tweet would be led to believe that Trump himself willingly tweeted a video in which he is the object of satire!
Tweets can't be edited, only deleted; nonetheless, the tweet has endured ever since. The most likely explanation for its longevity is that nobody on Trump's team ever noticed Inti's prank.
You may think this hijacked tweet is an isolated example, but it's not. A few years later, a hacker then known as @MisterCh0c defaced multiple tweets by celebrities, such as Shakira and Katy Perry. These examples may cause you to chuckle, but broken-link hijacking is widespread and can have more dramatic consequences on organizations.
A couple of months ago, I noticed that the Facebook social link on a multimillion-dollar company's website was pointing to a non-existent Facebook profile. As I knew the company was running a bug-bounty program, I claimed the Facebook account for myself, personalized "my" status (as a proof of concept), and reported the vulnerability to their security team, who promptly fixed it.
A happy ending, but imagine how a malicious broken-link hijacker could have taken advantage of the situation. The link to the hijacker-controlled Facebook profile on the company's website would have indeed lent the hijacker enough legitimacy to impersonate the company on the social network. The hijacker could have
- posted offensive content meant to harm the company's reputation,
- elicited sensitive information from distressed customers, or
- distributed malware,
all the while pretending to be a legitimate representative of the company. Incidentally, the company recognized the potential impact of such a vulnerability and decided to reward me with a 3-digit bounty. Not bad for a ten-minute job. 😛
There is no easy defense against broken-link hijacking. The best thing you can do is to regularly scrape your own website, tweets, etc., inspect broken links, and audit all outbound links. Consider outsourcing this task by setting up a bug-bounty program and reward reports of broken-link hijacking (among other vulnerabilities, of course).
You've probably come across endpoints in the form of
that accept a URL and redirect visitors to that location, with little to no preliminary validation. Such endpoints are known as open redirects; variations in terminology abound, but let's not linger on that here.
Because tampering with the
url query parameter is straightforward
and because sharing URLs is trivial, open redirects can easily be
weaponized against you and your users. Unfortunately, open redirects are widespread on the Web: many organizations simply dismiss them as inconsequential. However, let's examine why you may not want to have open redirects on your main domain.
The sad truth is that the presence of open redirects on your domain
opens the door to all kinds of abuse.
Before long, search engines may start referencing pages that are
seemingly hosted on your website, but whose content you're not responsible for and with which you most likely don't want to be associated! For instance, think of a few lewd or offensive terms, stick them at the end of the following Google dork, and run the search.
You'll quickly get a sense of how many respectable universities unwittingly appear to host questionable content on their websites. Of course, they're not. Rather, most of the offending results stem from the presence of open redirects on the universities' domains that some nasty sites are taking advantage of to generate inbound traffic.
Open redirects are also valuable for phishing purposes because
they allow malicious links to look safe by "hiding" behind a reputable domain name. Most security-conscious people probably wouldn't click on a link like
because the hostname betrays its maliciousness, but what about this one?
Or this one (in which I've to obfuscated the query parameter by percent-encoding it)?
Whether even tech-savvy people would smell a rat here is doubtful.
If you're still unconvinced that open redirects are bad, be aware that they often play a crucial role in exploit chains. When combined with other vulnerabilities, they may, for example, enable attackers to bypass protection (e.g., against server-side request forgery) or steal auth tokens. In fact, seasoned ethical hackers know better than to immediately report open redirects to organizations that happen to run a bug-bounty program. Such hackers would rather keep an open redirect close to their chest and bide their time until they figure out how to chain it with other vulnerabilities to achieve greater impact. By doing so, they'll be able to collect a larger bounty.
In many cases, you could and should only accept a finite number of trusted URLs and reject all others. In other cases, some functionalities demand that all URLs be accepted, such as on sites that allow user-generated content and funnel all outbound traffic through one of their endpoints (for analytics purposes, presumably).
Such sites should consider either
- hosting the endpoint on a distinct, dedicated domain, or
- presenting an interstitial page to their users when they leave the site.
Slack, for instance, follows the first approach. Every time you click on a link rendered as
https://example.org within Slack,
you're sent to
which then redirects you to
https://example.org. Note that this open redirect is hosted on a dedicated domain (
to avoid compromising Slack's main domain (
HackerOne follows the second approach and shows users an interstitial page when they're about to navigate to an untrusted third-party site. Such a page is essentially meant as a warning:
You may not have realized it, but you're about to leave our site.
We cannot vouch for your safety beyond this point.
Be careful; here be dragons!
For more guidance about remediating open redirects, check out
OWASP's cheat sheet on the topic.
_blank as the value of the anchor element's
target attribute will do the trick:
<a href="https://eff.org" target="_blank">Click me!</a>
will cause the linked document to open in a new tab:
Because the browser runs the new window in the same process as the first window, it allows for a modicum of interaction between the two, regardless of the respective origins of the two windows. In particular, the first window can change the location of the second one. Here is an example:
What's perhaps more surprising is that the opposite is possible!
By default, the second window holds, through its
a reference to the window that opened it (i.e., the first window);
unless some precautions are taken by the document in the first tab,
the second tab can simply change the location of the first tab!
A kind of spooky action at a distance, if you will.
Here is an example. If you click on an innocent link, such as this one:
<a href="https://tabnabbing-attack.jub0bs.com" target="_blank"> Click me! </a>
and the linked document consists of the following code:
<h1>Not Found</h1> <p>The requested URL was not found on this server.</p> <hr /> <address> Apache/2.2.15 (Red Hat) Server at tabnabbing-attack.jub0bs.com on Port 443 </address> <script> const url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"; window.opener.location.replace(url); </script>
then, the linked document (masquerading as a fake Apache error page)
will open in a new tab but immediately set the location of the first tab to the Rick Astley video! Try it for yourself here.
This subterfuge—a window altering its opener's location—is known as reverse tabnabbing, and it is considered a security issue. Why? Well, being rick-rolled can be amusing or, perhaps, irritating, but is rather innocuous. However, I'm sure you can imagine how malicious actors could be tempted to exploit this reverse tabnabbing for a more insidious kind of evil, namely phishing.
Consider, for example, a banking site that would be vulnerable to reverse tabnabbing:
- You open your browser and navigate to the landing page of your banking site, perhaps to check your balance.
- Before you log in, some link on the landing page catches your eye. You click on it, which causes a third-party site to open in a second tab.
- Unbeknownst to you and your bank, the third-party site is malicious. While you're focused on the new tab, the document therein accesses its opener and redirects the first tab to some phishing site that's meant to look just like your banking site.
- You eventually close the second tab and return to the first tab. You still believe the site you're seeing is your banking site; you didn't notice that the address of the first tab changed because you were too busy looking at the third-party site in the second tab at the time.
- You confidently enter your banking credentials, thereby handing them over to whoever controls the phishing site. You've just been pwned!
This example may suffice to convince you that reverse tabnabbing is no laughing matter.
Fortunately, the remedy to reverse tabnabbing is simple; for each outbound link meant to open in a new tab, prevent the linked document from accessing its opener.
In HTML, specify the
noopener link type in the
of each outbound link's anchor element:
<a href="https://tabnabbing-attack.jub0bs.com" target"_blank" rel="noopener"> Click me! </a>
Doing so will cause the linked document to hold no reference to its opener (its
window.opener property will simply be
null), which will thwart any reverse-tabnabbing attack. Try it for yourself here; inspect the console of the second tab after following the link, and you should see something like
TypeError: window.opener is null
noopener link type enjoys widespread support in modern browsers but isn't supported in any version of Internet Explorer. However, Internet Explorer does support link type
noreferrer, which prevents any referrer information from being communicated to the linked document. Because
noopener in browsers that support the latter,
noreferrer is preferable to
window.open( "https://tabnabbing.jub0bs.com", "window name", // irrelevant, here "noreferrer" );
Although you create and follow links every day, there's more to them than meets the eye, especially in terms of security. Understanding these three vulnerabilities—broken-link hijacking, open redirects, and reverse tabnabbing—is key to reducing your attack surface and effectively keeping your users and yourself safe.