November 2013 - Posts

Ways you haven’t stopped my XSS–Number 1, JavaScript Strings

I saw this again today. I tried smiling, but could only manage a weak grin.

You think you’ve defeated my XSS attack. How did you do that?

Encoding or back-slash quoting the back-slash and quote characters in JavaScript strings

Sure, I can no longer turn this:

<script>
s_prop0="[user-input here]";
</script>

into this, by providing user input that consists of ";nefarious();// :

<script>
s_prop0="";nefarious();//";
</script>

Instead, I get this:

<script>
s_prop0="\";nefarious();//";
</script>

But, and this surprises many web developers, if that’s all you’ve done, I can still close that script tag.

INSIDE THE STRING

Yes, that’s bold, italic and underlined, because developers see this, and think “I have no idea how to parse this”:

<script>
s_prop0="</script><script>nefarious();</script>";
</script>

Fortunately, your browser does.

First it parses it as HTML.

This is important.

The HTML parser knows nothing about your JavaScript, it uses HTML rules to parse HTML bodies, and to figure out where scripts start and end.

So, when the HTML parser sees “<script>”, it creates a buffer. It starts filling that buffer with the first character after the tag, and it ends it with whatever character precedes the very next “</script>” tag it sees.

This means the HTML above gets interpreted as:

1. a block of script that won’t run, because it’s not complete code and generates a syntax error.

s_prop="

2. a block of script that will run, because it parses properly.

nefarious();

3. a double-quote character, a semi-colon, and an unnecessary end tag that it discards

Obviously, your code is more complex than mine, so this kind of injection has all kinds of nasty effects – but it’s possible for an attacker to hide those (not that the attacker needs to!)

So then, the fix is … what?

If you truly have to insert data from users into a JavaScript string, remember what it’s embedded in – HTML.

There are three approaches:

  1. Validate.
    If at all possible, discard characters willy-nilly. Does the user really need to input anything other than alphanumeric characters and spaces? Maybe you can just reject all those other characters.
  2. Encode.
    Yeah, you fell afoul of encoding, but let’s think about it scientifically this time.
    What are you embedded in? A JavaScript string embedded in HTML. You can’t HTML-encode your JavaScript content (try it and you’ll see it doesn’t work that way), so you have to JavaScript-string-encode anything that might make sense either to the HTML parser OR the JavaScript parser.
    You know I don’t like blacklists, but in this case, the only characters you actually need to encode are the double-quote, the back-slash (because otherwise you can’t uniquely reverse the encoding), and either the less-than or forward-slash.
    But, since I don’t like blacklists, I’d rather you chose to encode everything other than alphanumeric and spaces – it doesn’t cost that much.
  3. Span / Div.
    OK, this is a weird idea, but if you care to follow me, how about putting the user-supplied data into a hidden <span> or <div> element?
    Give it an id, and the JavaScript can reference it by that id. This means you only have to protect the user-supplied data in one place, and it won’t appear a dozen times throughout the document.

A note on why I don’t like the blacklists

OK, aside from last weekend’s post, where I demonstrated how a weak blacklist is no defence, it’s important to remember that the web changes day by day. Not every browser is standard, and they each try to differentiate themselves from the other browsers by introducing “killer features” that the other browsers don’t have for a few weeks.

As a result, you can’t really rely on the HTML standard as the one true documentation of all things a browser may do to your code.

Tags change, who knows if tomorrow a <script> tag might not be “pausable” by a <pause>Some piece of text</pause> tag? Ludicrous, maybe, until someone decides it’s a good idea. Or something else.

As a result, if you want to be a robust developer who produces robust code, you need to think less in terms of “what’s the minimum I have to encode?”, and more in terms of “what’s the cost of encoding, and what’s the cost of failure if I don’t encode something that needs it?”

Posted by Alun Jones | with no comments
Filed under: ,

There is no such thing as “small sample code”

Every few months, something encourages me to make the tweet that:

There is no such thing as “small sample code”, every sample you publish is an SDK of its own

OK, so the choice of calling these “SDKs” is rooted in my Microsoft dev background, where “sample code” didn’t need documentation or bug tracking, whereas an SDK does. You can adjust the terminology to suit.

The basic point here is to remind you that you do not get to abrogate all responsibility by saying “this is sample code, you will need to add error checking and security”, even if you do say it in the article – even if you say it in the comments of the sample!

Why do I care so much? It’s only three lines of code!

Simply stated, I’ve seen too many cases where people have included three lines of code (or five, or twenty, the count doesn’t matter) into a program, and they’ve stepped away and shipped that code.

“It wasn’t my fault,” they say, when the incident happens, “I copied that code from a sample online.”

This is the point at which the re-education machine is engaged – because, of course, it totally is your fault, if you include code in your development without treating it with the same rigour as if you had written every line of it yourself. You will get punished – usually by having to stay late and fix it.

It’s also the sample writer’s fault.

He gave you the mini-SDK that you imported blindly into your application, without testing it, without checking errors in it, without appropriate security measures, and he brushed you off with “well, of course, you should add your own error checks and security magic to it”.

Here’s an example of what I’m talking about, courtesy of Troy Hunt linking to an ASP forum.

No, if you’re providing sample code on the Internet, it’s important to make sure it doesn’t embody BAD design; this is code that will be taken up by people by definition less keen, less eager, less smart and less motivated to do things right than you are – after all, rather than figuring out how to write this code for themselves, they are allowing you to do it for them, to teach them how it’s done. If you then teach them how it’s done badly, that’s how they will learn to do it – badly. And they will teach others.

So, instead, make your three line samples five lines, and add enough error checking that unexpected issues or other bad things will break the sample’s execution.

Oh yeah, and what about updates, when you find a horrendous bug – how do you distribute those?

Posted by Alun Jones | with no comments

A reminder of who I am, and what I do

Looking at my recent posts, I’ve noticed a few things – not only have I been posting very sporadically and randomly, but also I’ve been avoiding talking about a number of aspects of myself that are key to why I maintain this blog.

In an effort to improve on that, I’m going to start with a quick recap of my biography – not a chronological approach, but a few details to let newcomers know who I am, and old-timers remember my motivations.

1. Family - a father and husband

This always comes first. I work to support my family. I’ve been married nearly twenty years to a fantastically understanding wife, and with her I have a wonderful seventeen-year-old son who is fast becoming the sort of adult whom I’d want to be friends with, if we weren’t already related.

2. Technical interests – general

What makes me prime MVP material, as well as informs the rest of my work, is that I am fascinated with all aspects of technology, from nanotech to 3d printing, quantum computing, cryptography, physics, mathematics – even if it’s unrelated to my own work, or requires tools I can’t afford to use, I’m fascinated by, and try to remain informed about, as much technology as possible.

Sadly, the human brain and attention span can only gather so much information, so there’s always topics I want to know more about. I think this is the eternal frustration of the technologically inclined.

3. Technical background – developer

I’m also a software developer – practically my first job out of college was to develop for Unix platforms, initially, maintaining and porting Fortran code to that platform. Moved from there to Windows, largely out of cussidness (trying to prove to the world that Windows could run a reliable server), and languages like C++, C#, and a few other languages as time and interest allowed.

4. Interest & Current job – security guy

Over time, though, it became clear that my code was getting hacked. So was everyone else’s, but I was unusual in noticing it and wanting to do something about it.

So I became an expert in security. Mostly I did this by reading other people’s books, blogs and articles, and then answering other people’s security questions, to demonstrate that I understood and could explain.

Then, because I didn’t have a career background in security, I had to build one to match my expertise. So I worked my way up “through the ranks”, albeit a little quicker than was expected. Hopefully, that didn’t result in too much missed instruction.

As a result, I’m now a Senior Security Engineer at a large online site. I won’t name them, not because they’re not proud of me, or I’m not proud of them, but because they’ve made it very clear that my blogging is not a part of my job, and my job is not to be a part of my blog.

That means, of course, that nothing I say here is to be construed as an indication of my employer’s position (unless I specifically say it is), and that the stories here and on my twitter feed are pulled from general experience, conversations with others in my field, and general places I have worked, rather than my current employer. I have worked at enough places to tell that developers are, on average, the same no matter where you go. So the stories are the same.

The main area I’m interested in is that of Application Security – how you can build applications that offer functionality while remaining resilient under attack. But I’m still also interested in network security, social engineering (for good and fighting its use for ill), spam fighting, and a number of other topics. I occasionally tell people their web sites are broken.

5. Side work – WFTPD, 2ndAuth, Texas Imperial Software

At various times I’ve also been self-employed, and created Texas Imperial Software as the outlet for my frustrated software development side. Usually, it’s because I’ve seen a need (or had that need myself!) that isn’t being fulfilled by existing software.

“How hard can that be?” is usually the phrase that gets me into trouble.

So I find out how hard it can be. In this manner, I’ve produced:

WFTPD Server / WFTPD Server Pro – FTP servers for Windows. These have been selling for twenty years now, less solidly lately than in the past, when WFTPD was my full time job. But the income is enough to keep up the absolutely minimal support expenditure this software takes.

2ndAuth – an auditing solution for shared accounts in Windows client and server systems. When you try to log on to a Windows system using an account marked as “shared”, you are prompted in addition for your real username and password. In turn, your verified username is logged in the Windows Event Log as a user of this shared account. Sure, shared accounts are against policy, but there are some times they can’t be avoided. In those times, 2ndAuth is a compensating control that allows you to finally answer the question “I know SQLAdmin brought down the server – so which operator do I kick / re-train / fire?”

iFetch – I love BBC Radio and TV, and wrote an app that fetches radio (or TV, if you’re in the UK) shows from the iPlayer, so that you can sync them to your mobile devices that aren’t supported by iPlayer apps.

6. Survivor – cancer

This is a pretty amazing achievement, thinking back on it – but I feel like all the work was done by other people – my wife, who made important surgical decisions while I was under general anaesthesis, and has been a great strength ever since, my surgeon and the doctors who handled the follow-up work, and my son who suffered through many nights of chicken and rice which was all I had the stomach for after radiotherapy. All I did was live through it.

This is why I cringe whenever I hear people talking about “brave” cancer patients. What I did was not brave, it was survival. Running from a bear that you’ve just noticed is eating you is not brave. It’s normal, it’s natural – it’s hard, for sure, but it isn’t brave. Brave is running towards the bear to beat him off.

Oh, and the type of cancer was testicular. The outside world considers that a bad word – and while conversations about breast cancer are plenty, you won’t find a testicular cancer awareness month. [The medical profession, by comparison, thinks cancer is a bad word, and listed my condition everywhere as “testicular C.”]

Men between the ages of 15 and 35 are most likely to be hit by testicular cancer – and there’s good news, and bad news. The good news is, it’s the most easily treated form of cancer (partly because it’s mostly outside the body already). The bad news – it’s fast acting, so delaying seeking treatment leads to many men literally dying because of embarrassment.

7. Microsoft MVP – Enterprise Security

This is an award that I’m constantly proud to have received, and which I think is thoroughly worth having. I’ll be sadder when I finally lose my MVP status (hopefully many years away still) than I was when I lost my CISSP. The network of other smart people is wonderful – and being in a category that has no closely-defined product means that I can continue to give more generally-appropriate advice, rather than specific instruction on an individual product. [It also means we don’t get the exciting swag, but hey, that’s not what I’m in the program for]

There’s an MVP Summit starting on November 17, it’s kind of a Microsoft-centric conference (think TechEd), but at a faster pace, greater depth, and with some material that isn’t public yet. We’ve each signed an NDA, and there are things I know are coming that are really exciting to me, but that I can’t talk about – yet.

8. Hobbies – juggling, unicycling

And occasionally I will draw on my hobbies of juggling and unicycling. This is how I get my exercise, some of the time, passing clubs with my son or riding unicycles around the school gym. I’m not very good, but then I don’t have to be.

In which a coffee store learns not to blacklist

I’ve been playing a lot lately with cross-site scripting (XSS) – you can tell that from my previous blog entries, and from the comments my colleagues make about me at work.

Somehow, I have managed to gain a reputation for never leaving a search box without injecting code into it.

And to a certain extent, that’s deserved.

But I always report what I find, and I don’t blog about it until I’m sure the company has fixed the issue.

So, coffee store, we’re talking Starbucks, right?

Right, and having known a few people who’ve worked in the Starbucks security team, I was surprised that I could find anything at all.

Yet it practically shouted at me, as soon as I started to inject script:

0-oops

Well, there’s pretty much a hint that Starbucks have something in place to prevent script.

But it’s not the only thing preventing script, as I found with a different search:

1-prompt

So, one search takes me to an “oops” page, another takes me to a page telling me that nothing happened – but without either one executing the script.

The oops page doesn’t include any of my script, so I don’t like that page – it doesn’t help my injection at all.

The search results page, however, that includes some of my script, so if I can just make that work for me, I’ll be happy.

Viewing source is pretty helpful, so here’s what I get from that, plus searching for my injected script:

2-social

So, while my intended JavaScript, “"-prompt(1)-"”, is not executed, and indeed is in the wrong context to be executed, every character has successfully made it into the source sent back to the user’s browser.

At this point, I figure that I need to find some execution that is appropriate for this context.

Maybe the XSS fish will help, so I search for that:

3-XSSFish

Looks promising – no “oops”, let’s check the source:

4-XSSFishSrc

This is definitely working. At this point, I know the site has XSS, I just have to demonstrate it. If I was a security engineer at Starbucks, this would be enough to cause me to go beat some heads about.

I think I should stress that. If you ever reach this point, you should fix your code.

This is enough evidence that a site has XSS issues to make a developer do some work on fixing it. I have escaped the containing quotes, I have terminated/escaped the HTML tag I was in, and I have started something like a new tag. I have injected into your page, and now all we’re debating about is how much I can do now that I’ve broken in.

And yet, I must go on.

I have to go on at this point, because I’m an external researcher to this company. I have to deliver to them a definite breach, or they’ll probably dismiss me as a waste of time.

The obvious thing to inject here is “"><script>prompt(1)</script>” – but we saw earlier that produced an “oops” page. We’ve seen that “prompt(1)” isn’t rejected, and the angle-brackets (chevrons, less-than / greater-than signs, etc, whatever you want to call them) aren’t rejected, so it must be the word “script”.

That, right there, is enough to tell me that instead of encoding the output (which would turn those angle-brackets into “&lt;” and “&gt;” in the source code, while still looking like angle-brackets in the display), this site is using a blacklist of “bad words to search for”.

Why is a blacklist wrong?

That’s a really good question – and the basic answer is because you just can’t make most blacklists complete. Only if you have a very limited character set, and a good reason to believe that your blacklist can be complete.

A blacklist that might work is to say that you surround every HTML tag’s attributes with double quotes, and so your blacklist is double quotes, which you encode, as well as the characters used to encode, which you also encode.

I say it “might work”, because in the wonderful world of Unicode and developing HTML standards, there might be another character to escape the encoding, or a set of multiple code points in Unicode that are treated as the encoding character or double quote by the browser.

Easier by far, to use a whitelist – only these few characters are safe,and ALL the rest get encoded.

You might have an incomplete whitelist, but that’s easily fixed later, and at its worst is no more than a slight inefficiency. If you have an incomplete blacklist, you have a security vulnerability.

Back to the story

OK, so having determined that I can’t use the script tag, maybe I can add an event handler to the tag I’m in the middle of displaying, whether it’s a link or an input. Perhaps I can get that event handler to work.

Ever faithful is the “onmouseover” event handler. So I try that.

You don’t need to see the “oops” page again. But I did.

The weirdest thing, though, is that the “onmooseover” event worked just fine.

Except I didn’t have a moose handy to demonstrate it executing.

5-mooseover

So, that means that they had a blacklist of events, and onmouseover was on the list, but onmooseover wasn’t.

Similarly, “onfocus” triggered the “oops” page, but “onficus” didn’t. Again, sadly I didn’t have a ficus with me.

You’re just inventing event names.

Sure, but then so is the community of browser manufacturers. There’s a range of  “ontouch” events that weren’t on the blacklist, but are supported by a browser or two – and then you have to wonder if Google, maker of the Chrome browser and the Glass voice-controlled eyewear, might not introduce an event or two for eyeball tracking. Maybe a Kinect-powered browser will introduce “onwaveat”. Again, the blacklist isn’t future-proof. If someone invents a new event, you have to hope you find out about it before the attackers try to use it.

Again, back to the story…

Then I tried adding characters to the beginning of the event name. Curious – that works.

6-query

And, yes, the source view showed me the event was being injected. Of course, the browser wasn’t executing it, because of course, “?onmouseover” can’t be executed. The HTML spec just doesn’t allow for it.

Eventually, I made my way through the ASCII table to the forward-slash character.

7-slash

Magic!

Yes, that’s it, that executes. There’s the prompt.

Weirdly, if I used “alert” instead of “prompt”, I get the “oops” page. Clearly, “alert” is on the blacklist, “prompt” is not.

I still want to make this a ‘hotter’ report before I send it off to Starbucks, though.

How “hotter”?

Well, it’d be nice if it didn’t require the user to find and wave their mouse over the page element that you’ve found the flaw in.

Fortunately, I’d also recently found a behaviour in Internet Explorer that allows a URL to set focus to an element on the page by its ID or name. And there’s an “onfocus” event I can trigger with “/onfocus”.

8-focused

So, there we are – automated execution of my chosen code.

Anything else to make it more sexy?

Sure – how about something an attacker might try – a redirect to a site of their choosing. [But since I’m not an attacker, we’ll do it to somewhere acceptable]

I tried to inject “onfocus=’document.location=”//google.com”’” – but apparently, “document” and “location” are also on the banned list.

“ownerDocu”, “ment”, “loca” and “tion” aren’t on the blacklist, so I can do “this["ownerDocu"+"ment"]["loca"+"tion"]=” …

Very quickly, this URL took the visitor away from the Starbucks search page and on to the Google page.

Now it’s ready to report.

Hard part over, right?

Well, no, not really. This took me a couple of months to get reported. I tried “security@starbucks.com”, which is the default address for reporting security issues.

An auto-reply comes my way, informing me this is for Starbucks staff to report [physical] security issues.

I try the webmaster@ address, and that gets me nowhere.

The “Contact Us” link takes me to a customer service representative, and an entertaining exchange that results in them telling me that they’ve passed my email around everyone who’s interested, and the general consensus is that I should go ahead and publish my findings.

So you publish, right?

No, I’m not interested in self-publicising at the cost of someone else’s security. I do this so that things get more secure, not less.

So, I reach out to anyone I know who works for Starbucks, or has ever worked for Starbucks, and finally get to someone in the Information Security team.

This is where things get far easier – and where Starbucks does the right things.

The Information Security team works with me, politely, quickly, calmly, and addresses the problem quickly and completely. The blacklist is still there, and still takes you to the “oops” page – but it’s no longer the only protection in place.

My “onmooseover” and “onficus” events no longer work, because the correct characters are quoted and encoded.

The world is made safer and more secure, and a half a year later, I post this article, so that others can learn from this experience, too.

By withholding publishing until well after the site is fixed, I ensure that I’m not making enemies of people who might be in a position to help me later. By fixing the site quickly and quietly, Starbucks ensure that they protect their customers. And I, after all, am a customer.

The Starbucks Information Security team have also promised that there is now a route from security@ to their inbox, as well as better training for the customer service team to redirect security reports their way, rather than insisting on publishing. I think they were horrified that anyone suggested that. I know I was.

And did I ever tell you about the time I got onto Google’s hall of fame?

Posted by Alun Jones | with no comments
Filed under: ,

Why don’t we do that?

Reading a story on the consequences of the theft of Adobe’s source code by hackers, I come across this startling phrase:

The hackers seem to be targeting vulnerabilities they find within the stolen code. The prediction is that they’re sifting through the code, attempting to find widespread weaknesses, intending to exploit them with maximum effect by using zero-day attacks.

What I’d love to know is why we aren’t seeing a flood of developers crying out to be educated in how they, too, can learn to sift through their own code, attempt to find widespread weaknesses, so they can shore them up and prevent their code from being exploited.

An example of the sort of comments we are seeing can be found here, and they are fairly predictable – “does this mean Open Source is flawed, if having access to the source code is a security risk”, schadenfreude at Adobe’s misfortune, all manner of assertions that Adobe weren’t a very secure company anyway, etc.

Something that’s missing is an acknowledgement that we are all subject to the same pool of developers.

And attackers.

So, if you’re in the business of developing software – whether to sell, licence, give away, or simply to use in your own endeavours, you’re essentially in the same boat as Adobe prior to the hackers breaching their defences. Possibly the same boat as Adobe after the breach, but prior to the discovery.

Unless you are doing something different to what Adobe did, you are setting yourself up to be the next Adobe.

Obviously, Adobe isn’t giving us entire details of their own security program, and what’s gone right or wrong with it, but previous stories (as early as mid-2009) indicated that they were working closely with Microsoft to create an SDL (Security Development Lifecycle) for Adobe’s development.

So, instead of being all kinds of smug that Adobe got hacked, and you didn’t, maybe you should spend your time wondering if you can improve your processes to even reach the level Adobe was at when they got hacked.

And, to bring the topic back to what started the discussion – are you even doing to your software what these unidentified attackers are doing to Adobe’s code?

Are you poring over your own source code to find flaws?

How long are you spending to do that, and what tools are you using to do so?