Posts (page 32 of 43)

  • BayThreat held its 2012 conference this December in Sunnyvale, CA. Yes, I was sorely disappointed it wasn’t actually in Sunnydale (with a ‘d’).

    My colleagues, @sshekyan and @tukharian, and I gave an overview on the security of WebSockets. The presentation slides are available now.

    Reading slides is always a hazardous approach to understanding a presentation. You may be completely lost because you don’t have the benefit of background given during the talk, miss key points conveyed orally, or misunderstand comments. When a recording is available I’ll add a link to it.

    In the meantime, here’s a rough script for the introduction of the topic. (Usually I try to just jot down a handful of notes, but this post needed some more words. Keep in mind the intro is supposed to clock well under 10 minutes. It’s brief by intent.)

    1 Hello, BayThreat. Hello, WebSockets.

    2 The length of time we have to cover WebSockets is about the same as a saturday morning cartoon from the 80s. So, we’ll skip the commercial breaks and, kind of like Voltron, bring together a bunch of ideas and observations about this cool, new protocol.

    3 In the past, web apps have found many legitimate use cases for persistent connections and two-way communication. HTTP doesn’t support this in any efficient or optimal way for continuous traffic. Trying to get this done with long polling, XHR, or DOM tricks are all workarounds, and like the plans of a cartoon villain (Skeletor, Hordak, Cobra Commander), they never seem to work like you want them to. (Mumra)

    4 That doesn’t mean there aren’t good techniques for two-way communication, they just aren’t as good as they could be in terms of bandwidth or handling non-text data.

    HTML5 introduced Server-Sent Events to accommodate most long-polling scenarios in which the browser just needs to wait for incoming data. For example, stock quotes, tweets, or some other data for which the browser is a passive observer rather than an active participant.

    5 Which brings us to RFC 6455, WebSockets. It’s a way to encapsulate almost any protocol on top of RFC 2616 (HTTP) without being as messy as RFC 1149.

    6 There are two major components to WebSockets. The communication protocol, which is designed to have low overhead and low complexity. And the JavaScript API, which is designed to be a simple interface for the browser. Send with the send() method, receive with the onmessage() method, and then just an open(), close(), and onerror() method to round out the object.

    7 So, let’s take at look at how the browser sets up a WebSocket connection. First, it goes through a challenge-response handshake. The challenge is 128 random bits (that’s a 16d8 for any role-players out there – about 2 1/2 flamestrikes for you 1st ed. AD&D clerics).

    8 Next, the server responds. The response is a hash of the client’s challenge plus a GUID defined by the RFC. The response also includes a “Connection: Upgrade” header so the two end points know to stop talking HTTP and start talking WebSockets. A while ago Carnegie Mellon & Google did a study with Chrome users and discovered that many proxies would strip that Connection header – thus killing the handshake process. However, wss: connections (that is, WebSockets over SSL/TLS) were mostly immune to interference from proxies. So, not only will you create a more secure connection, you’ll be more likely to create the connection in the first place.

    9 An important thing to understand about the handshake is that it proves the server speaks the protocol. That’s it. It’s not a cryptographic handshake to prove identity or trust. And another point, the handshake isn’t supposed to start within mixed content. Also, the browser is supposed to limit pending connections to one per origin in order to prevent connection floods.

    10 Once the browser and server complete the handshake, they switch from HTTP to sending WebSocket data frames. A data frame’s overhead can be as low as two bytes – flags and a length. The maximum overhead is 14 bytes, so we’re still talking an order of magnitude improvement over something like XHR or vanilla HTTP.

    Two notable parts of a data frame are the variable length fields and the mask.

    11 The length of a payload is indicated by 7, 16, or 64 bit values. A length is supposed to be represented by its shortest form. However, if you think of similar situations like overlong UTF-8 encoding you can imagine how variable-length fields might be a source of problems in terms of bypassing detection mechanisms or sneaking across security boundaries. And, of course, you have the potential for buffer abuse. You could submit a data frame that declares a few gigs of payload but only carries a few bytes. If you have a server that pre-allocates memory based on payload lengths alone (without, for example, even validating the frame), then it’d be an easy DoS. In other instances the server might experience a buffer over- or under-run.

    12 Data masking is an aspect of WebSockets that’s transparent to the user. It’s intended to prevent WebSockets from being a vector for cross-protocol attacks. For example, you wouldn’t want WebSocket data to corrupt a proxy cache by impersonating HTML content, nor would you want a WebSocket to start spitting out EHLO commands to an SMTP server in order to spam the internet. (By the way, the handshake is also a countermeasure.)

    The browser applies a mask to all outgoing WebSocket frames. It’s not encryption. The 32-bit “key” for the mask is included in the data frame. In other words, you’re essentially sending the “decryption” key along with the message. The user isn’t able to influence or access the mask from the JavaScript API.

    (As and aside, I created this figure with a dozen or so lines of a Scapy script; which speaks to how simple the protocol is to parse.)

    13 The browser controls a few other things that are kept out of view from the JavaScript API. It handles “ping” and “pong” frames for connection keep-alives. It’s also supposed to limit the verbosity of error reporting to prevent WebSockets from being a better host or port “scanner” than previous techniques like using XHR or src attributes of img or iframe tags.

    14 Finally, remember that upgrading a connection from HTTP to WebSockets loses a certain amount of security context. The handshake itself carries information like Authentication headers, cookies, CORS, and the Origin header. However, you have to be careful about how you track and maintain this context after switching protocols. Imagine a simple chat application. It’s one thing to have a session cookie identify a user’s HTTP connection. But if your chat protocol relies solely on strings or JSON structures to identify the sender and recipient of messages, then it’s probably a short step to spoofing messages unless you remember to enforce server-side controls on the user’s state and chat interactions.

    With that groundwork out of the way, let’s turn the channel to more educational programs on the security of WebSockets.

    … end part I …

    And with that we’ve exhausted the article. Keep an eye on this site for more updates on WebSocket security.

  • HIQR for the SPQR Dec 5, 2012

    Friends, Romans, coding devs, lend me your eyes. I’ve created an HTML Injection Quick Reference (HIQR). More details here.

    British Museum roman coin

    It’s not in iambic pentameter, but there’s a certain rhythm to the placement of quotation marks, less-than signs, and alert functions.

    For those unfamiliar with HTML injection (or cross-site scripting in the Latin Vulgate), it’s a vuln that can be exploited to modify a web page in a way that changes the DOM or executes arbitrary JavaScript. In the worst cases, the app delivers malicious content to anyone who visits the infected page. Insecure string concatenation is the most common programming error that leads to this flaw.

    Imagine an app that allows users to include <img> tags in comments, perhaps to show off cute pictures of spiders. Thus, the app expects image elements whose src attribute points anywhere on the web. For example:

    <img src="https://web.site/image.png">
    

    If users were limited to nicely formed https links, all would be well in the world. (Sort of, there’d still be an issue of what content that link pointed to, whether obscene, copyrighted, malware, multi-GB images that would DoS browsers or sites they’re sourced from, and so on. But those are threat models for a different day.)

    There’s already trouble brewing in the form of javascript: schemes. For example, an attacker could inject arbitrary JavaScript into the page – a dangerous situation considering it would be executing within the page’s Same Origin Policy.

    <img src="javascript:alert(9)">
    

    Then there’s the trouble with attributes. Even if the site restricted schemes to https: an uncreative hacker could simply add an inline event handler. For example:

    <img src="https://&" onerror="alert(9)">
    

    Now the attacker has two ways of executing JavaScript in their victim’s browsers – javascript: schemes and event handlers.

    There’s more.

    Suppose the app writes anything the user submits into the web page. We’ll even imagine that the app’s developers have decided to enforce an https: scheme and the tag may only contain a src value. In an attempt to be more secure, the app writes the user’s src value into an <img> element with no event handlers. This is where string concatenation rears its ugly, insecure head. For example, the hacker submits the following src attribute:

    https:">alert(9)
    

    The app drops this value into the src attribute and, presto!, a new element appears. Notice the two characters at the end of the line, ">, these were the intended end of the src attribute and <img> tag, which the attacker’s payload subverted:

    <img src="https:">alert(9)>">
    

    A few more tweaks to the payload, such as creating some <script> tags, and the page is fully compromised.

    HTML injection attacks become increasingly complex depending on the context of where the payload is rendered, whether characters are affected by validation filters, whether regexes are used to deny malicious payloads, and how payloads are encoded before being placed on the page.

    SPQR (Senātus Populusque Rōmānus) was the Latin abbreviation used to refer to the collective citizens of the Roman empire. Read up on HTML injection and you’ll become SPQH (Senātus Populusque Haxxor) soon enough.

    SPQR

  • Here are the slides for my presentation, Mitigating JavaScript Mistakes Using HTML5, at this year’s RSA Europe.

    The goal is to show that the move towards more complex web apps demands more complex JavaScript, which in turn creates more potential for security bugs. Yet rather than audit every line of deployed JavaScript, we can apply controls like Cross-Origin Request Sharing, HTML5 sandboxes, and Content Security Policy headers to improve the security of apps within the browser. These countermeasures don’t fix server-side code, but they do help reduce the impact to users when hackers try to exploit vulns within a web site.

    I’ll continue to post more articles here that expand and explain the slides. For example, the references to BeEF are intended to show the relation of variable scope, objects, prototypes, and hijacking content within JavaScript in a sort of hack-the-hacker approach. Since BeEF relies heavily on JavaScript, it’s a nice way to explore concepts with a real-life scenario that could attack any site, rather than show the concepts against some fake sites.

    And thanks in advance to all who attended.