• iPhone zombie

    This is how it began. Over two years ago I unwittingly planted the seeds of an undead horde into the pages of my book, Seven Deadliest Web Application Attacks.

    Only recently did I discover the rotted fruit of those seeds festering within the pages of Amazon.

    • Visit the book’s Amazon page.
    • Click on the “Look Inside!” feature.
    • Use the “Search Inside This Book” function to search for zombie.
    • Cower before approaching mass of flesh-hungry brutes. Or just click OK a few times.

    On page 16 of the book there is an example of an HTML element’s syntax that forgoes the typical whitespace used to separate attributes. The element’s name is followed by a valid token separator, albeit one rarely used in hand-written HTML. The printed text contains this line:

    <img/src="."alt=""onerror="alert('zombie')"/>
    

    onerror alert zombie

    The “Search Inside” feature lists the matches for a search term. It makes the search term bold (i.e. adds <b> markup) and includes the context in which the search term was found (hence the surrounding text with the full <img/src="."alt="" /> element). Then it just pops the contextual find into the list, to be treated as any other “text” extracted from the book.

    <img src="." alt="" onerror="alert('<b>zombie</b>')"/>
    

    Finally, the matched term is placed within an anchor so you can click on it to find the relevant page. Notice that the <img> tag hasn’t been inoculated with HTML entities; it’s a classic HTML injection attack.

    <a ... href="javascript:void(0)">
    <span class="sitbReaderSearch-result-page">Page 16 ...t require spaces to
        delimit their attributes.
        **<img src="." alt="" onerror="alert('<b>zombie</b>')"/>** JavaScript
        doesn't have to...
    

    This has actually happened before. In December 2010 a researcher in Germany, Dr. Wetter, reported the same effect via <script> tags when searching for content in different security books. He even found <script> tags whose src attribute pointed to a live host, which made the flaw infinitely more entertaining.

    iPad zombie

    In fact, this was such a clever example of an unexpected vector for HTML injection that I included Dr. Wetter’s findings in the new Hacking Web Apps book (pages 40 and 41, the same <img...onerror> example shows up a little later on page 59). Behold, there’s a different infestation on page 31. Try searching for zombie again. This time the server responds with a JSON payload that contains straight-forward <script> tags. This one was more tedious to track down. The <script> tags don’t appear in the search listing, but they do exist in the excerpt property of the JavaScript object that contains, applies bold tags, etc. for matches:

    {...,"totalResults":2,"results":[[52,"Page 31","... encoded characters with
    their literal values:  <a href=\"http://\"/>**<script>alert('<b>zombie</b>')
    </script>**@some.site/\">search again</a>   Abusing the authority component
    of a ...", ...}
    

    I only discovered this injection flaw when I recently searched the older book for references to the living dead. (Yes, a weird – but true – reason.)

    How did this happen?

    One theory is that an anti-XSS filter relied on a deny list to catch potentially malicious tags. In this case, the <img> tag used a valid, but uncommon, token separator that would have confused any filter expecting whitespace delimiters. One common approach to regexes is to build a pattern based on what we think browsers know. For example, a quick filter to catch <script> tags or opening tags (e.g. <iframe src...> or <img src...>) might look like this:

    <\[\[:alpha:\]\]+(\\s+|>)
    

    A payload like <img/src> bypasses the regex and the browser correctly parses the syntax to create an image element. Of course, the src attribute fails to resolve, thereby triggering the onerror event handler, leading to yet another banal alert() declaring the presence of an HTML injection attack.

    The <script> example is less clear without knowing more about the internals of the site. Perhaps a sequences of stripping quotes and buggy regexes misunderstood the href to actually contain an authority section? Don’t have a good guess for this one.

    This highlights one problem of relying on regexes to parse a grammar like HTML. Yes, it’s possible to create strong, effective regexes. However, a regex does not represent the parsing state machine of browsers, including their quirks, exceptions, and “fix-up” behaviors. Fortunately, HTML5 brings a measure of sanity to this mess by clearly defining rules of interpretation. On the other hand, web history foretells that we’ll be burdened with legacy modes and outdated browsers for years to come. So, be wary of those regexes.

    No. That’s not it.

    How did this really happen?

    Well, I listen to various music while I write. You might argue that it was the demonic influence (or awesome Tony Iommi riffs) of Black Sabbath that ensorcelled the pages or that Judas Priest made me do it. Or that March 30, 2010 – right around the book’s release – was a full moon. Maybe in one of Amazon’s vast, diversely-stocked warehouses an oil drum with military markings spilled over, releasing a toxic gas that infected the books. I think we’ll never know for sure.

    Maybe one day we’ll be safe from this kind of attack. HTML5 and Content Security Policy make more sandboxes and controls available for implementing countermeasures. But I just can’t shake the feeling that somehow, somewhere, there are more lurking about.

    Until then, the most secure solution is to –

    – what’s that noise at the door…?

    They're coming to get you, Barbara.

    • • •
  • In which an exposition of Twelve Web (In)Security Truths begins.

    #1 – Software execution is less secure than software design, but running code has more users.

    A site you send people to visit is infinitely more useable than the one you describe to people. (Value differs from usability. Before social media flamed you could raise $41 million dollars on a slide deck.) Talk all you want, but eventually someone wants you to deliver.

    Sure, you could describe Twitter as a glorified event loop around an echo server. You might even replicate it in a weekend with a few dozen lines of Python or Node.js and an EC2 instance. Just try scaling that napkin design to a few hundred million users while keeping security and privacy controls in place. That’s a testament to implementing a complex design. (Or scaling a simple design if you boil it down to sending and receiving tweets.)

    It’s possible to attain impressive security through careful design. A prominent example in cryptography is the “perfect secrecy”1 of the One-Time Pad (OTP). The first OTP appeared in 1882, designed in an era without the codified information theory or cryptanalysis of Claude Shannon and Alan Turing.2 Never the less, its design understood the threats to confidential communications when telegraphs and Morse code carried secrets instead of fiber optics and TCP/IP. Sadly, good designs are sometimes forgotten or their importance unrecognized. The OTP didn’t gain popular usage until its re-invention in 1917, along with a more rigorous proof of its security.

    But security also suffers when design becomes implementation. The OTP fails miserably should a pad be reused or is insufficiently random. The pad must be as long as the input to be ciphered. So, if you’re able to securely distribute a pad (remember, the pad must be unknown to the attacker), then why not just distribute the original message? Once someone introduces a shortcut in the name of efficiency or cleverness the security breaks. (Remember the Debian OpenSSL debacle?) This is why it’s important to understand the reasons for a design rather than treat it as a logic table to be condensed like the singularity of a black hole. Otherwise, you might as well use two rounds of ROT13.

    Web security has its design successes. Prepared statements are a prime example of a programming pattern that should have relegated SQL injection to the CVE graveyard. Avoiding it is inexcusable. Only devotees of Advanced Persistent Ignorance continue to blithely glue SQL statements together with string concatenation. SQL injection is so well-known (at least by hackers) and studied that a venerable tool like sqlmap has been refining exploitation for over six years. The X-Frame-Options header is another example of design that could dispatch a whole class of vulnerabilities (i.e. clickjacking).

    Oh how the Internet loves to re-invent vulns. Whether or not SQL injection is in its death throes, NoSQL injection promises to reanimate its bloated corpse. Herbet West would be proud.

    Sometimes software repeats the mistakes of other projects without considering or acknowledging the reasons for those mistakes. The Ruby on Rails Mass Assignment feature is reminiscent of PHP’s register_globals issues. Both PHP and Ruby On Rails are Open Source projects with large communities. It’s unfair to label the entire group as ignorant of security. But the question of priorities has to be considered. Do you have a default stance of high or low security? Do you have language features whose behavior changes based on configuration settings outside the developer’s control, or that always have predictable behavior?

    Secure design isn’t always easy. Apache’s reverse proxy/mod_rewrite bug went through a few iterations and several months of discussion before Apache developers arrived at an effective solution. Once again, you might argue that the problem lies with users (i.e. poor rewrite rules that omit a path component) rather than the software. Still, the vuln proved how difficult it is to refine security for complex situations.

    HTML injection is another bugbear of web security. (Which makes SQL injection the owlbear?) There’s no equivalent to prepared statements for building HTML on the fly; developers must create solutions for their programming language and web architecture. That doesn’t mean XSS isn’t preventable, prevention just takes more effort and more attention to the context where user-influenced data shows up in a page. Today’s robust JavaScript frameworks help developers avoid many of the XSS problems that arise from haphazard construction of HTML on the server.

    There’s hope on the horizon for countering HTML injection with design principles that are tied to HTTP Headers rather than a particular programming language or web framework. The Content Security Policy (CSP) has moved from a Mozilla effort to a standard for all browsers. CSP won’t prevent HTML injection from occurring, but it will diminish its exploitability because developers will be able to give browsers directives that prevent script execution, form submission, and more. CSP even has the helpful design feature of a monitor or enforce mode, thereby easing the transition to a possibly complex policy.

    Design is how we send whole groups of vulns to the graveyard. Good security models understand the threats a design counters as well as those it does not. Spend too much time on design and the site will never be implemented. Spend too much time on piecemeal security and you risk blocking obscure exploits rather than fundamental threats.

    As the ancient Fremen saying goes, “Truth suffers from too much analysis.”3 So too does design suffer in the face of scrutiny based on unspecific or unreasonable threats. It’s important to question the reasons behind a design and the security claims it makes. Sure, HSTS relies on the frail security of DNS. Yet HSTS is a significant improvement to HTTPS, which in turn is unquestionably better than HTTP. But if you refuse to implement an imperfect solution in favor of preserving the status quo of HTTP then you haven’t done enough consideration of the benefits of encryption.

    Nor are security checklists absolute. The httponly attribute prevents no vulnerabilities. It only prevents JavaScript from accessing a cookie. Blindly following the mantra that httponly must exist on all cookies ignores useful designs where JavaScript intentionally reads and writes cookie values. If you’ve put sensitive data into a Local Storage object, then an XSS vuln is going to expose all that tasty data to a hacker who cares little for the cookie’s accessibility.

    Design your way to a secure concept, code your way to a secure site. When vulnerabilities arise determine if they’re due to flaws in the design or mistakes in programming. A design that anticipates vulnerabilities (e.g. parameterized queries) should make it easy to fix inevitable bugs. Vulnerabilities that surprise developers should lead to design changes that provide more flexibility for resolving the problem. Inflexibility, whether in design or in code, is dangerous to security. Just like the Bene Gesserit say, “Any road followed precisely to its end leads precisely nowhere.”4


    1. In the sense of Claude Shannon’s “Communication Theory of Secrecy Systems”. 

    2.  As Steven Bellovin notes in his paper, an 1882 codebook contains an amusingly familiar phrase regarding identity questions, “Identity can be established if the party will answer that his or her mother’s maiden name is…“ It seems identity proofs haven’t changed in 130 years! 

    3. Frank Herbert. Dune Messiah. p. 81. 

    4. Frank Herbert. Dune. p. 69. 

    • • •
  • My current writing project has taken time away from adding new content lately. Here’s a brief interlude of The Twelve Web Security Truths I’ve been toying with as a side project. They are modeled on The Twelve Networking Truths from RFC 1925.

    1. Software execution is less secure than software design, but executing code attracts actual users.
    2. The time saved by not using parameterized queries to build SQL statements should be used to read about using parameterized queries.
    3. Same Origin Policy restricts the DOM access and JavaScript behavior of content loaded from multiple origins. Malware only cares about plugin and browser versions.
    4. Content with XSS vulns are affected by the Same Origin Policy, which is nice for XSS attacks that inject into the site’s origin.
    5. CSRF countermeasures like Origin headers mitigate CSRF, not XSS. Just like X-Frame-Options mitigates clickjacking, not XSS.
    6. Making data safe for serialization with JSON does not make the data safe for the site.
    7. There are four HTML injection vulns in your site today. Hackers will find two of them, the security team will find one, the dev team will introduce another one tomorrow.
    8. Deny lists miss the attack payload that works.
    9. A site that secures user data still needs to work on the privacy of user data.
    10. Hashing passwords with 1,000-round PBKDF2 increases the work factor to brute force the login page by a factor of 1. Increasing this to a 10,000-round PBKDF2 scheme provides an additional increase by a factor of 1.
    11. The vulnerabilities in “web 2.0” sites occur against the same HTML and JavaScript capabilities of “web 1.0” sites. HTML5 makes this different in the same way.
    12. A site is secure when a compromise can be detected, defined, and fixed with minimal effort and users are notified about it.
    13. Off-by-one errors only happen in C.
    • • •