

Hacking the &lt;a&gt; tag in 100 characters - bilawal
http://bilaw.al/2013/03/17/hacking-the-a-tag-in-100-characters.html

======
Cushman
I thought this was sensationalist the last time it came up, and I still do.

This is an attack which targets people who are carefully checking the link URL
before clicking, but who then ignore the actual content of their URL bar. That
has to be a pretty limited group, right? And this is far from the only way to
spoof a link in JavaScript, so to really make this impossible would mean
disabling swaths of functionality used widely across the web, i.e. not gonna
happen.[0]

And it's counterproductive. Since the birth of the web we've been trying to
drill into people's skulls not to trust _anything_ except what it says in your
URL bar after "https:". We need to avoid anything that would give users any
other impression.

That said, there is a useful message here, not "this is a problem with
JavaScript" but "this is another reason you must personally validate the
domain name before entering any personal information."

[0] On a large scale, that is. Obviously some people here are comfortable with
disabling swaths of JavaScript across the web.

~~~
cjc1083
The danger of this, is not (IMO) people inserting personal data or financial
data on the end page (which would be avoided by paying attention to the URL
bar), but in targeted attacks where the page serves up a IE/Flash/Java exploit
compromising the users machine. At this point it doesn't matter what the end
result is, as the damage is done. Also, an attacker can simply redirect to to
the orig page/target after exploitation in such a way that the majority of
casual users wouldn't notice, as there is no user interaction at the end.

Example a link to an article or PDF report of interest is Hijacked via this
method (where the hover is correct but actual target is malicious) the user
quickly hits the exploit site and is compromised/malware dropped while the
exploit site displays a splash page of some sort briefly, it then forwards to
the orig. destination.

I don't see the majority of non paranoid users detecting this, even if they
are in the right mindset, as they end up at the proper site with nothing more
than quick, and now ubiquitous, splash/ad page in between.

EDIT: I'm not necessarily advocating any change, this behavior can be tracked
and blocked in a properly secured infrastructure, but this is where I see the
potential for harm.

~~~
cheald
The point remains that this kind of thing is entirely possible via
"legitimate" methods, too.

If the bad guys can inject Javascript into your page, it's game over, period.
The attack vector is meaningless; there are tons of them. If I can inject my
Javascript into your page to hijack your clicks, why would I bother with that
rather than just putting an invisible iframe into the page that delivers the
payload without any user interaction required? It's going to get me far better
results, doesn't rely on undocumented behavior, and isn't contingent on a user
failing to notice a splash screen.

~~~
bilawal
Maybe there's a side to it that I'm not aware, but as far as I know, it's
become very difficult to run exploitable JS in an iframe.

~~~
cheald
cjc1083's proposed attack vector is an interstitial page which drops a
Java/Flash 0-day on you and forwards you to your original target site, leaving
you compromised and none the wiser. My point is that if you can even do the
redirect in the first place, it's much simpler to just iframe in the attack
page and do the drop directly rather than waiting on user input to do it in a
manner that they might notice.

------
lukifer
While this should probably be fixed as prescribed by the author, it's
relatively easy for a no-goodnik to accomplish the same goal without touch the
href:

    
    
      $("a").click(function(e){
        e.preventDefault();
        document.location="http://evilsite.paypa1.com";
      });
    

In either case, a right-click to open or copy/paste sidesteps, though that's
just a kludge.

~~~
devinblais
I think this is an important point. The fact that you can change the href
after the click is irrelevant because there are other (just as easy) ways to
change where the link will be taking the user. If malicious javascript is
being run on your page, THAT is your problem, not the href switch.

------
batiste
This is not a hack it's basic Javascript.

If a malicious hacker can insert some script in a trusted page, security is
pretty much completly broken and you have other worries. The fact that you can
make links in this page point to other malicious pages seems like a small
problems as most people won't even check the domain before clicking the link.

I would think that some users are most likely to check the address bar after
clicking the link. But my dad would probably woudn't see anything.

~~~
bilawal
With relative ease, you can build websites with a cheap $10 SSL that can
impose to be a PayPal page. JavaScript can provide phishing and accessing
cookies, but beyond that, I'm not really sure what else it can offer.

It may be simple code, but I think the title of the post explained that.

~~~
homakov
> JavaScript can provide phishing and accessing cookies, but beyond that, I'm
> not really sure what else it can offer

if you had success putting your JS payload on target website you can do
anything. Period. From from stealing user's passwords
([http://homakov.blogspot.com/2012/11/xss-save-your-
password-p...](http://homakov.blogspot.com/2012/11/xss-save-your-password-
pwned.html)) to executing any authorized request POST /send_money. The last
thing attacker will do is to "phish" you.

------
karolisd
I eagerly awaiting your blog post when you discover preventDefault()

~~~
bilawal
Ha. I'm very much aware of preventDefault(), but to add that in my article
won't make any difference to my point.

------
johnjansen
I work on the IE team at Microsoft, and I really don't think this is an
exploit. If you can control the script for the click event, then you already
have control of the page and can do worse (think: cross-site scripting). In
this case, if you browse to my site and I'm a bad guy and want to send you to
evil.com, I'd just craft a page that makes you think the whole page is
honorable, rather than hope you click on a link. In other words, anyone who
can hack the click event already owns you.

I'm very happy to reassess if you have an example where you do not control the
content of the page, but somehow still control the content of the click. That
would be really serious and worth fixing.

-John Jansen Principal Test Lead Internet Explorer

------
homakov
you kidding right? while we have real world problems (URL detections, cookies
etc check homakov.blogspot.com) you ask w3c to do what? To deny redirecting to
other websites and changing href after click? I can tell you more horror JS
tricks, but they are not fixed yet.

------
mojuba
I use this trick to mask email addresses in mailto: links, i.e. something
like:

    
    
        <a onClick="this.href=
            ['mailto',[['john','doe'].join('.'),
                ['gmail','com'].join('.')].join('@')].join(':')"
    		href=#click-to-email>
    

I don't know how good my solution is in protecting from spammers' scrapers but
I'd be happy to hear about any alternatives.

~~~
SmartWebPerson
Your logic is flawed for bots that parse and render the pages. I have ran a
small blog that I hand wrote from scratch and in the process found that around
4 years ago any phishing/spamming/harvesting bot worth it's salt will render
the pages leaving these types of clever fix hacks useless.

~~~
mojuba
The email address is "rendered" only on mouse click in my scheme, and
something suggests bots don't go as far as clicking around on each page.

------
enigmango
Firefox 21 (Aurora), I got sent to PayPal - just realized that I had NoScript
on, though. Allowed scripts for bilaw.al, tried again, and I got sent to the
dummy page.

I got sent to the dummy page on Opera 12.13 and Chrome 25. Just updated to
Opera 12.14 and I still got sent to the dummy page. Running Windows 7.

------
jvatic
In addition to countless other oversights, setTimeout would not work as you
suggested in the post as the page would be unloaded before it ever executed.
And, as others have already mentioned, there are numerous other ways to
accomplish the exact same effect with 'more legitimate' methods (e.g.
event.preventDefault(); window.location = ...).

Various browsers such as Chrome will warn/block you from visiting known
malicious sites, but it comes down to being aware of where you are before
entering personal information.

I think a better proposal might be getting browsers to warn users if the url
they are visiting is sufficiently different from the original href attribute
(i.e. different host). Something like this could easily be done with a browser
extension (and could handle more cases such as preventDefault +
window.location = ...).

------
burgerguyg
You can set up a span with a style that has a link-like look (color,
underline), use "cursor:pointer" in the style to make the pointer turn to a
hand over it. Use a mouseover/out event catcher to trigger a tooltip that
mimics the mouseover behavior on links, then capture the click event on the
span to send the user to another page.

You can use JavaScript to swap out all the links for spans like these.

If you're on a site that's using intentionally deceptive JavaScript or getting
malicious JavaScript injected, whether or not links go where you think they
will is the least of your problems.

------
DPLeo
I just tried clicking your "Paypal" link in Chrome 25, Firefox 19, and IE9.
All of them allowed the href to change and went to what could have been the
phishing site. Then I went back and tried right-clicking the "Paypal" link and
open in a new tab. All 3 browsers went to Paypal.

I like your suggestion to have behavior changed so the browsers don't allow
the href to be changed to another domain without warning the user. Until that
happens, maybe opening links in a new tab (or window) is a good practice.

Enjoy!

------
Xeno22
The reason for onclick is exactly the mentioned "problem". I use <a> tags to
show them as links, but without reference, only with onclick events to load
the actual request. So if any browser manufacturer tries to kill this
behaviour (like x-site scripting bullshit) the world will go oom...

So, if you do not like the javascript events -> disable javascript interpreter
in your browser!

It would make more sense to kill IE, ActiveX, Flash and Java-Plugins...

------
cthackers
So did you just discovered DOM manipulation with JavaScript ? What would a
browser fix be like in your opinion ? Disallow JavaScript to add event
listeners and/or modify Node properties ?

Google Analytics hooks on links to track clicks and exit pages and so on.
Would you really enjoy an alert every time you click on something ? I am
amazed how you people come up with crap like this.

Enjoy your 5 minutes of traffic while they last

------
dougaitken
right click open in new tab takes you to the original link. So this must be
done in session or something and the alt-open in next tab take the plain link
URL?

~~~
vitobcn
By doing right-click and "Open link in new tab", there's no actual onclick
event, as what you're actually doing is opening the original link in a new
tab. Therefore, his href replacing code wouldn't get executed.

------
Tichy
I dislike loggin in to sites that I have been referred to by other sites in
general. Not sure if there is a solution for paypal? Like getting an
transaction id from a shop, then logging on to PayPal and paying that
transaction id?

Might be something worthwhile to provide a solution for (possibly even a valid
use case for QR codes - pay with phone on a web site)? But then, not many
people will care, I suspect :-/

------
bjazmoore
I noticed that at least one other person suggested opening the link in a new
tab. This seems to defeat this hack in Chrome and IE 9. It probably defeates
it in all browsers, since the new tab is in a different context than where the
javascript is being executed and therefore can not be redirected by the
javascript.

~~~
bilawal
Correct. No browsers execute onclick when you open under new tab.

------
Tarlach
Fun fact: On Chrome, Opening the link in a new tab does not redirect to the
phishing site. However, normal clicking does. Context changing seems to make
this work, as chrome delegates the href to a new process, and does not execute
the JS embed.

------
imack
Chrome 25, I got sent to Paypal.

~~~
bpicolo
Chrome 25 mac, didn't get sent to paypal.

Do you have scripts disabled? Because it wouldn't work in that case.

~~~
chm
I got sent to paypal with scripts enabled using the same configuration.
Without scripts, it obviously doesn't work.

------
arjeezyboom
This may be the dumbest blog post I've ever read. The fact that this is
possible (and necessary) speaks more to the general glacial nature of the HTML
standards and JS to provide the functionality we expect of our web apps.

------
adamzr86
Right clicking the link and choosing "Open in new tab" with Chrome does not
execute the JavaScript. This is good and bad. Good because it solves your
problem, bad because it makes the link unpredictable.

------
skram
So many sites use this for various reasons like appending tracking codes (my
former employer did this for Omniture tracking).. I just don't see this
suggestion to disable the functionality catching on.

~~~
bilawal
Websites don't need to use this, that's my point. Whilst it looks nicer to use
it, it's not worth opening a easy door for fraudsters.

~~~
cheald
You can call `document.location=<http://badsite.com>; e.preventDefault();` in
a click (mousedown, mouseup, mouseclick) handler, too. You aren't going to
ever prevent this kind of thing from being possible without killing the modern
web as we know it.

Instead of making a big deal out of it (phishing 2.0? really?), why not focus
on phishing detection and prevention instead? I do it by using LastPass with
randomly generated passwords that I don't actually know. I have to go to
LastPass for my login information, and it provides information filtered by the
domain I'm on. If I'm on badsite.com rather than paypal.com, LastPass won't
offer my PayPal information to fill. Problem solved.

~~~
bilawal
Okay, Phishing 2.0 may have gone a bit too far. I hold my hand up there. As
for LastPass, I use that and it's great -- but this poses a problem for those
who don't use LastPass, etc. or those who use mobile.

~~~
cheald
LastPass works just fine on my Android phone. :)

Phishing is an everpresent problem, and does require vigilance from both
browser vendors and users, but I really don't think that this contributes to
the problem in any significant way, simply because there are completely
legitimate browser features that can be used to exactly the same effect, and
for which the differences between "benign" and "hostile" use is entirely
subjective and undetectable by software. Fixing this would have exactly no
impact on the bad guys' ability to conduct a blind redirection.

------
unimpressive
Before I turned off noscript, I was very confused about how bilawal came into
possession of paypal.com.

It took me a few seconds before I realized how stupid that entire line of
thought was.

------
xyzzyb
"If someone has control of the DOM the game is already over"

<http://www.frameloss.org/2012/10/28/hover-fail/>

------
thebezet
Don't want to sound rude, but I've known about this for literally years.

I think anyone who makes single page web apps uses this "hack" on an everyday
basis.

------
Rodorm
Firefox 19.0.2 on Linux shows the JS Pishing link on mouseover, Firefox 19.0.2
on Windows 7 doesn't! So, Firefox 19.0.2 on Linux is the only safe browser.

------
gaaah
Offline web apps saved to the home screen in iOS must do this for internal
links: otherwise you end up opening safari for every link you click on

------
bilawal
I've updated the pledge - I'm now asking major browsers to warn users if a
link is changed to another domain from what it originally was.

------
sgoel

      var links = document.links
    

is a more efficient way to get an array of all of the links on a page.

------
switz
I believe your code is incorrect:

    
    
        for(var i=0; i < links.length; j++){ // j++ => i++

~~~
bilawal
I've updated it. I went backwards from the compressed version, and missed it
completely. Thanks.

------
GraphWhit3
Firefox Nightly loads Paypal page fine without any issue. So I think it is
already fixed in upcoming Firefox versions.

~~~
GraphWhit3
My mistake I took it with middle click... Which leads it to open in New tab
perfectly fine.

------
rihananew
hmmm nice though and this is the mainly reason of Phishing page because when
we make a Phishing page then we have to use this step to change the URL when
victim click on that.... that's why phishing is happening ...

so read this news carefully and be aware for futue...

------
curiousmonkey
Question - can the script be modified to act upon a middle click or 'Open in
new tab' function?

------
claudius
It doesn’t appear to work in Opera version 12.14, I get sent to PayPal :)

~~~
rmk2
Doesn't work with Chromium 27, either...

------
andrew_isidoro
Interesting that it doesn't effect "Open in new tab" links in Chrome...

~~~
markjaquith
Seems entirely expected. When you open in a new tab, you're just taking the
(existing) href and opening it in a new tab. No JS executes because you've
opened a new tab, completely unrelated to the previous context.

------
accurrent
If you click open in new tab in chrome it does not work :)

------
Cloop
right-click open in new tab and windows in firefox open the paypal link
opposed to fishing page- funny enough the paypal link is a redirect via paypal

------
evilpie
Why ECMA? Sounds more like something for w3c or whatwg.

~~~
bilawal
W3C only do web standards: HTML, XML, CSS, XSL, etc. According to ECMA
International, they maintain JS. But I'm not sure, each browser does it's own
thing.

~~~
quarterto
JavaScript ≠ DOM. ECMA take care of JavaScript, the language, but have nothing
whatsoever to do with its implementation in and bindings to browsers.

~~~
bilawal
I've updated it. Sorry about that.

------
apaantuh
google will disagree with your proposal...

~~~
bilawal
There's always workarounds, especially with what they're doing with search
results. Google can live.

------
rassar
please, even shorter! for(i in
o=document.links){o[i].onclick=function(){this.href='//j.mp/141nisR'}}

------
orbital303
This is incorrect. Once you get to see the url in the bar, it's too late if
you've been redirected to a site with malware. This is an extremely serious
security flaw and downplaying it is not going to help anyone.

There is no use for this security hole other than to deceive people. Period.

~~~
batiste
If your only goal is to send the user to a malicious page with a payload then
you don't need any user action.

Just do: document.location.href = "<http://malware.com>;

And you are done.

~~~
bilawal
Heck, if you're going to do that.. you don't even need JavaScript.

<meta http-equiv="refresh" content="0; url=<http://malware.com> />

