Stop Building HTML on the Server

Many web sites conceptually fit into the Model-View-Controller (MVC) design pattern despite (or often in spite of) the site’s actual code design. The server pieces together user data, state data, and other bits of HTML to send to the browser. One of the biggest frustrations with automating web app testing is dealing with poorly written web applications, especially the “View” — the HTML to be shown in the browser. A brief list of complaints includes: HTML with typos, outright invalid HTML, HTTP headers omitted, headers incorrect, strange state mechanisms, and weird case sensitivity issues.

Blackbox scanning fundamentally interacts only with content (HTML) and transport (HTTP and its accompanying statefulness as created by cookies). A scanner primarily bases its understanding of a web application on the site’s conceptual View. Whitebox testing, e.g. source code scanning, has more insight into the application’s functionality and can therefore more easily find vulns in our conceptually defined Model and Controller components that reside on the server.

HTML injection (a.k.a XSS) is probably the best example of vulnerabilities that arise due to View problems. For those few still unfamiliar with the term: HTML injection occurs when data to be displayed in a web page ends up modifying the page’s underlying structure. The structure is referred to as the Document Object Model (DOM). For example, a text node expecting to hold the user’s first name may unintentionally turn into a script node when the user’s name becomes “<script>alert(0)</script>” instead of “Trudy”.

The DOM also changes when characters like extraneous quotes appear in the syntax of href or input value attributes, for example:

<a href=””onMouseover=alert(0);a=”>Search again</a>

Zip Code:<input name=zip_code value=‘90210‘onMouseover=alert(0);a=’>

In the two previous cases the data, a search string and a zip code, changed the page’s structure by adding an onMouseover attribute (with innocuous payload, yawn) to the anchor and input tags. The data wasn’t even intended to be displayed to the user, yet it is used in a way that pollutes the View.

Ah, so we’ve finally come back to that concept: the View. Now we get to mention frameworks. Specifically, JavaScript-based browser development frameworks like Dojo, Ext JS, Prototype, and YUI. These frameworks help move the uninteresting part of the UI Controller into the browser. In other words, the server doesn’t have to care about the visual effects of dragging and dropping an email message between folders, displaying data in a tree view, sorting a list, or other interactions that take place in the browser.

JavaScript frameworks enable the site’s UI (its View) to be well-separated from the server-side processing. It should follow that the web site can create a simpler, stricter set of functions that operate on well-defined data.

In other words, the server exposes APIs that respond to very small, atomic requests with very small, atomic responses. The server no longer has to deal with writing complete HTML pages for every response. This doesn’t absolve the server from dealing with encoding issues, but it centralizes the problem more cleanly because functions can be better focused on a single purpose. For example, a drag and drop of an email between folders in a browser requires an API call that verifies access to the message, its source and destination, and updates the message’s state. The server can respond as simply as “succeeded” or “failed” and leave the HTML updating to the browser’s JavaScript library.

Design vs. Implementation

Adopting a browser-side framework entails a significant amount of design effort (in terms of both visual style and software). This design effort can have several positive side-effects, including a reduction in the kinds of implementation errors that lead to HTML injection vulnerabilities. For example, the server can concern itself with ensuring a consistent encoding format for all output and the browser can display that output using well-defined, centralized functions. This is a far cry from ad-hoc HTML generation on the server. While software will always suffer from typos and bugs, a framework at least provides the tools to make a web site more secure by default.

There are some other areas where frameworks quite easily improve design security: CSRF and click-jacking countermeasures. Several frameworks have built-in countermeasures for these two types of attacks. Keep in mind that the countermeasures may not provide complete protection, but the defenses they provide are infinitely better than zero if your site current lacks any defense and most likely better than a home-grown countermeasure based on an incomplete understanding of the problem.1 After all, the framework’s countermeasures have been designed and tested by a large group of developers. Some of them even know a thing or two about security.

Right now frameworks largely rely on JavaScript-based tricks to block CSRF and click-jacking rather than more reliable Header-based ones that recent browsers provide. Of course, it’s a bit early to expect the majority of users’ browsers to include the Origin header2 so this still favors frameworks. (The Origin header is a more reliable version of the Referer header and as such can thwart CSRF attacks. And before you write in with nifty counterexamples of all the ways the Origin header can fail and shouldn’t be trusted, make sure your example doesn’t require an HTML injection, a.k.a. XSS, exploit as well — that’s a different problem.) Conversely, web sites can add click-jacking protection by setting the X-Frame-Options header3, but the number of users with browsers that would benefit is still limited.

Frameworks do not always reduce design errors. Obviously, they have no bearing on server-side design or implementation. User impersonation, data access controls, and authorization will not magically improve. A richer UI might introduce more complex interactions between data and user objects, which implies more chances for security failures.

JavaScript frameworks make the automated analysis of sites more difficult. Web application scanners have trouble testing them and even manually-aided tools like Selenium run into problems with dynamically changing DOMs. We’ll cover those issues in more detail in a separate post. Until then, consider introducing a browser development framework into your site in order to better consolidate server-side processing to a discrete set of APIs and leave HTML manipulation to the browser.

1 You could always start with a book.

1 thought on “Stop Building HTML on the Server”

Comments are closed.