• In January 2003 Jeremiah Grossman disclosed a technique to bypass the HttpOnly1 cookie restriction. He named it Cross-Site Tracing (XST), unwittingly starting a trend to attach “cross-site” to as many web-related vulns as possible.

    Unfortunately, the “XS” in XST evokes similarity to XSS (Cross-Site Scripting) which often leads to a mistaken belief that XST is a method for injecting JavaScript. (Thankfully, character encoding attacks have avoided the term Cross-Site Unicode, XSU.) Although XST attacks rely on JavaScript to exploit the flaw, the underlying problem is not the injection of JavaScript. XST is a technique for accessing headers normally restricted from JavaScript.

    Confused yet?

    First, let’s review XSS and HTML injection. These vulns occur because a web app echoes an attacker’s payload within the HTTP response body – the HTML. This enables the attacker to modify a page’s DOM by injecting characters that affect the HTML’s layout, such as adding spurious characters like brackets (< and >) and quotes (' and ").

    Cross-site tracing relies on HTML injection to craft an exploit within the victim’s browser, but this implies that an attacker already has the capability to execute JavaScript. Thus, XST isn’t about injecting <script> tags into the browser. The attacker must already be able to do that.

    Cross-site tracing takes advantage of the fact that a web server should reflect the client’s HTTP message in its respose.2 The common misunderstanding of an XST attack’s goal is that it uses a TRACE request to cause the server to reflect JavaScript in the HTTP response body that the browser would then execute. In the following example, the reflection of JavaScript isn’t the real vuln – the server is acting according to spec. The green and red text indicates the response body. The request was made with netcat.

    Cross-site tracing

    The reflection of <script> tags is immaterial (the RFC even says the server should reflect the request without modification). The real outcome of an XST attack is that it exposes HTTP headers normally inaccessible to JavaScript.

    To reiterate: XST attacks use the TRACE (or synonymous TRACK) method to read HTTP headers that are otherwise blocked from JavaScript access.

    For example, the HttpOnly attribute of a cookie prevents JavaScript from reading that cookie’s properties. The Authentication header, which for HTTP Basic Auth is simply the Base64-encoded username and password, is not part of the DOM and not directly readable by JavaScript.

    No cookie values or auth headers showed up when we made the example request via netcat because we didn’t include any. Netcat doesn’t have the internal state or default headers that a browser does. For comparison, take a look at the server’s response when a browser’s XHR object makes a TRACE request. This is the snippet of JavaScript:

    var xhr = new XMLHttpRequest();
    xhr.open('TRACE', 'https://test.lab/', false);
    xhr.send(null);
    if(200 == xhr.status)
        alert(xhr.responseText);
    

    The following image shows one possible response. (In this scenario, we’ve imagined a site for which the browser has some prior context, including cookies and a login with HTTP Basic Auth.) Notice the text in red. The browser included the Authorization and Cookie headers to the XHR request, which have been reflected by the server:

    XST headers

    Now we see that both an HTTP Basic Authentication header and a cookie value appear in the response text. A simple JavaScript regex could extract these values, bypassing the normal restrictions imposed on script access to headers and protected cookies. The drawback for attackers is that modern browsers (such as the ones that have moved into this decade) are savvy enough to block TRACE requests through the XMLHttpRequest object, which leaves the attacker to look for alternate vectors like Flash plug-ins (which are also now gone from modern browsers).

    This is the real vuln associated with cross-site tracing – peeking at header values. The exploit would be impossible without the ability to inject JavaScript in the first place3. Therefore, its real impact (or threat, depending on how you define these terms) is exposing sensitive header data. Hence, alternate names for XST could be TRACE disclosure, TRACE header reflection, TRACE method injection (TMI), or TRACE header & cookie (THC) attack.

    We’ll see if any of those actually catch on for the next OWASP Top 10 list.


    1. HttpOnly was introduced by Microsoft in Internet Explorer 6 Service Pack 1, which they released September 9, 2002. It was created to mitigate, not block, XSS exploits that explicitly attacked cookie values. It wasn’t a method for preventing html injection (aka cross-site scripting or XSS) vulns from occurring in the first place. Mozilla magnanimously adopted in it FireFox 2.0.0.5 four and a half years later. 

    2. Section 9.8 of the HTTP/1.1 RFC

    3. Security always has nuance. A request like TRACE /<script>alert(42)</script> HTTP/1.0 might be logged. If a log parsing tool renders requests like this to a web page without encoding it correctly, then HTML injection once again becomes possible. This is often referred to as second order XSS – when a payload is injected via one application, stored, then rendered by a different one. 

    • • •
  • At about this time...

    The Day of the Triffids cover

    When a day that you happen to know is Wednesday starts off by sounding like Sunday, there is something seriously wrong somewhere.

    Bill Masen’s day only worsens as he tries to survive the apocalyptic onslaught of ambling, venomous plants.

    John Wyndham’s The Day of the Triffids doesn’t feel like an outdated menace even though the book was published in 1951.

    It starts as the main character, Bill Masen, awakens in a hospital with his eyes covered in bandages. It’s a great hook that leads to a brief history of the triffids while also establishing an unease from the start. The movie 28 Days Later uses an almost identical method to bring both the character and audience into the action.

    I love these sorts of stories. Where Cormac McCarthy’s The Road focuses on the harshness of personal survival and meaning after an apocalypse, Triffids considers how a society might try to emerge from one.

    The 1981 BBC series stays very close the book’s plot and pacing. Read the book first, as the time-capsule aspect of the mini-series might distract you – 80s hair styles, clunky control panels, and lens flares.

    But if you’re a sci-fi fan who’s been devoted to Doctor Who since the Tom Baker era (or before), you’ll feel right at home in the BBC’s adaptation.

    • • •
  • Here’s a case where a page has one of the simplest types of XSS vulns: A server echoes the querystring verbatim in the HTTP response. The payload shows up inside an HTML comment labeled “Request Query String”. The site’s developers claim the comment prevents XSS because browsers will not execute the JavaScript, as below:

    <!-- _not gonna' happen_ -->
    

    One exploit technique would be to terminate the comment opener with “ –>” (space dash dash >). Use netcat to make the raw HTTP request (for some reason, though likely related to the space, the server doubles the payload1):

    $ echo -e "GET /nexistepas.cgi? --> HTTP/1.0\r\nHost: vuln.site\r\n" | nc vuln.site 80 | tee response.html
    ...
    <!-- === Request URI: /abc/def/error/404.jsp -->
    <!-- === Request Query String: pageType=error&emptyPos=100&isInSecureMode=false& --> --> -->
    <!-- === Include URI: /abc/def/cmsTemplates/def_headerInclude_1_v3.jsp -->
    ...
    

    You can confirm this works by viewing the HTML source in Mozilla to see its syntax highlighting pick up the tags (yes, you could just as easily pop an alert window).

    html injection

    The server is clearly vulnerable to XSS because it renders the exact payload. The HTML comments were a poor countermeasure because they could be easily closed by including a few extra characters in the payload. This also shows why I prefer the term HTML injection since it describes the underlying effect more comprehensively.

    However, there’s a major problem of effective exploitability: The attack uses illegal HTTP syntax.2 Though the payload works when sent with netcat, a browser applies URL encoding to the payload’s important characters, thereby rendering the it ineffective because the payload loses the literal characters necessary to modify the HTML:

    https://vuln.site/nexistepas.cgi? -->
    ...
    <!-- === Request URI: /abc/def/error/404.jsp -->
    <!-- === Request Query String: pageType=error&emptyPos=100&isInSecureMode=false&%20--%3e%3cscript%3e%3c/script%3e -->
    <!-- === Include URI: /abc/def/cmsTemplates/def_headerInclude_1_v3.jsp -->
    ...
    

    I tried Mozilla’s XMLHttpRequest object to see if it might subvert the encoding issue, but didn’t have any luck. Browsers are smart enough to apply URL encoding for all requests, thus defeating this possible trick:

    var req = new XMLHttpRequest();
    req.open('GET', 'https://vuln.site/nexistepas.cgi? --><scri' + 'pt></s' + 'cript>', false);
    req.send(null);
    ...
    

    The developers are correct to claim that HTML comments prevent <script> tags from being executed, but that has nothing to do with protecting this web site. It’s like saying you can escape Daleks by using the stairs; they’ll just level the building.

    Daleks cartoon

    The page’s only protection comes from the fact that browsers will always encode the space character. If the page were to decode percent-encoded characters or there was a way to make the raw request with a space, then the page would be trivially exploited. The real solution for this vuln is to apply HTML encoding or percent encoding to the querystring when it’s written to the page.

    Set aside whether the vuln is exploitable or not. The 404 message in this situation clearly has a bug. Bugs should be fixed.

    The time spent arguing over risks, threats, and feasibility far outweighs the time required to create a patch. If the effort of pushing out a few lines of code cripples your development process, then it’s probably a better idea to put more effort into figuring out why the process is broken.

    Notice that I didn’t mention the timeline for the patch. The release cycle might require a few days or a few weeks to validate the change. On the other hand, if minor changes cause panic about uptime and require months to test and apply, then you don’t have a good development process – and that’s something far more hazardous to the app’s long-term security.


    1. Weird behavior like this is always interesting. Why would the querystring be repeated? What implications does this have for other types of attacks? 

    2. Section 5.1 of RFC 2616 specifies the format of a request line must be as follows (SP indicates whitespace characters): Request-Line = Method SP Request-URI SP HTTP-Version CRLF Including spurious space characters within the request line might elicit errors from the web server and is a worthy test case, but you’ll be hard-pressed to convince a standards-conformant browser to include a space in the URI. 

    • • •