7

edit I got some good responses about Frameworks but the crucial part of this is that it's built into the programming language itself, so it's literally impossible to write an XSS vulnerable or SQL injectable web site even if you wanted to. (Of course you could write a SQL parser that takes a string and converts it to an SQL data type then executes it, or an HTML/JS parser that enables people to submit their own HTML and JS to be embedded in your site.. but no one would write a parser by accident)


Currently, a web server runs a PHP script which outputs a string of text which is interpreted as HTML by a parser.

But if the web server ran a different language lets call it "SPHP" (secure PHP) which outputs an HTML data structure rather than text.. then it gets rendered into a string by the web server and sent to be interpreted as HTML...

(Mathematically this means instead of writing a function php : web request --> string you write sphp : web request --> html and there is a function render : html --> string. The important thing to notice is that the image of the function render only contains strings which can be parsed into valid HTML.)

at first this would just mean you can't ever have a unclosed HTML tag in your output, but then I realized..

You could also completely solve XSS with it: when ever you try to put a piece of text (e.g. from user input) into the HTML data structure it will escape it in exactly the correct way to stop an XSS vulnerability.

In fact the idea can be used "backwards" for SQL: rather than calling mysql("SELECT mytable WHERE name=$user AND password=$pass") you would build an "SQL query data structure" that would have everything escaped correctly as you built it.

It seems like if you programmed a web site using the SPHP language it would be completely free of XSS and SQL injection.. the top 2 OWASP vulnerabilities.. but that can't be right because no one is moving to SPHP despite the amount of hacks that cause so much security damage and stuff.. so what have I overlooked?

6
  • 1
    HTML is just a string. It's just a string with meaning to the computer. The rest of what you put does exist.
    – ewanm89
    Oct 25, 2012 at 18:02
  • 3
    Your solution sounds a lot like how every language except PHP handles web frameworks and SQL.. Oct 25, 2012 at 19:11
  • @BrendanLong You can shoot yourself in the foot with any language. I don't think there's anything wrong with PHP per se, but it is novice-friendly and that shows (see my answer).
    – Null
    Oct 25, 2012 at 19:57
  • 1
    "it's built into the programming language itself" Basically that's not feasible because these languages can do many, many things other than output HTML pages. Even when you do output HTML, you might want some flexibility. It is easier to shoot yourself in the foot in some languages than others though.
    – Null
    Oct 25, 2012 at 20:25
  • 1
    Most web-related vulnerabilities stem from the fact that data and meta-data are combined into single string which uses specific characters for delimiters. Be it SQL, HTML, Javascript, or others. If you could re-engineer the protocols to remove that factor, almost all of the top vulnerabilities would disappear.
    – tylerl
    Oct 26, 2012 at 2:15

3 Answers 3

10

Both of these ideas have already been proposed. From a security perspective, they can be made to work. However, they are not widely adopted because they require too drastic a change to the way that developers write code, and many developers are not willing to do that.

That said, there has been more recent work on better approaches, approaches that achieve similar security properties but without disrupting the way that developers write code nearly as much. So your idea is not without merit.

Early, seminal research. To see your idea worked out in greater detail, look at, e.g., this research paper:

It looks at exactly the idea you proposed for defending against XSS, builds a framework that works in that way, and evaluates it. It turns out you may want to do something a bit more sophisticated than you suggested, to prevent the app from inadvertently adding script tags (while still allowing web pages that are intended to have script tags, to have them), but it's feasible.

The primary shortcoming is that it radically changes the way you write web applications, and it is less convenient for developers. Instead of writing a simple HTML fragment like <DIV><P>Hi <I>John</I>!</P></DIV>, you have to write several lines of code with several DOM operations. As a result, your code gets wordier. This is a barrier that makes it harder to persuade developers to adopt the idea.

Since then, there has been a lot of work on attempting to make this sort of idea more palatable for web developers. Let me outline some of them.

Context-sensitive auto-escaping. Today, the best defense against XSS is to use a web programming framework that supports context-sensitive automatic escaping. The idea is that the web framework automatically identifies what escaping function needs to be used for each variable that is dynamically interpolated (at runtime) into the HTML, and automatically applies that escaping function. This is great, because it provides a framework that is "secure-by-default" and "secure-by-design". There's a lot less opportunity for developer error or developer oversight to lead to a severe vulnerability in the web application.

Context-sensitive auto-escaping is an especially good match for frameworks that are based upon a template engine: i.e., where the framework enforces separation between code and content, and uses HTML templates for the content (with holes that can be dynamically filled in based upon the results of the computation by the code).

However, today only a few web frameworks currently support context-sensitive auto-escaping. Google's ctemplate does.

To learn more about context-sensitive auto-escaping, read the following questions on this site:

and the following research papers:

Interpolique. Interpolique is a proposal by Dan Kaminsky that attempts to defend against these vulnerabilities in a way that is a bit less obtrusive and more familiar for PHP developers. (See also Blueprint, for a predecessor.) You can find a detailed evaluation of Interpolique at this question: Interpolique: transparently preventing SQL Injection and XSS with base64 encoding, what happened?

Prepared statements. Today, the standard defense against SQL injection vulnerabilities is to use prepared statements (strictly speaking, parametrized queries; but many developers know them as prepared statements). This is a "good-enough" defense against SQL injection. It is widely supported by databases and frameworks, well-understood by developers, intuitive and familiar to developers -- and provides "good-enough" security. Therefore, there is little motivation or need to develop or adopt better solutions for SQL injection. Today, the predominant problem is not that people use prepared statements and end up with vulnerable code -- the predominant problem is that too many web applications still use string concatenation rather than prepared statements.

Therefore, SQL injection is largely a solved problem, from a technology standpoint. That's why most of the research focuses on XSS, which is a considerably harder problem.

0
5

Interesting. Both of these solutions sound a lot like Content Security Policy and parametrized quires respectively.

In short, the content security policy allows you to dictate where JavaScript comes from. You can say that JavaScript can only be included in a src= attribute and come from the same domain or some CDN of your choice. Applications can use Backbone and a client-side tempting system like Handelbars with the CSP to build a system that is difficult to exploit via XSS. In this design the server just sends JSON and static html/js and the client takes care of the rest (sexy and fast!). However, this system doesn't prevent DOM Based XSS (and your proposed system doesn't stop DOM based XSS!).

Parametrized queries are about separating data and executable code. MySQL supports a query structure such that the SQL statement and each data element within the query is sent in a partially parsed C-style struct, which is not only secure but also more efficient. MySQLi does this behind the scenes, PDO and ADODB re-builds the query to make sure that mysql_real_escape_string() is used on all data elements and then sends the query as a string to the server. (And yes i have looked at the code of all three of the libraries.)

This is a good strategy for addressing two of a few thousand vulnerabilities that affect modern applications.

3
4

Summary: Frameworks that escape or strip potentially dangerous HTML input already exist. The "SQL query data structure" idea also already exists (parameterized queries).


Currently, a web server runs a PHP script which outputs a string of text which is interpreted as HTML by a parser.

But if the web server ran a different language lets call it "SPHP" (secure PHP) which outputs an HTML data structure rather than text..

HTML is a string of text. Just so it happens it can be understood by a browser and rendered to the end user in some meaningful way. Regardless, you don't need a new server-side language to implement your idea: PHP can do that already (or Python, or Ruby, or even Brainf**k; ie: any Turing complete language).

There are also web frameworks that will automatically escape or strip potentially harmful user input before it creates the HTML output. But I think anyone who has worked with these frameworks can tell you that this also introduces a learning curve and decreases flexibility.

Your idea of creating an HTML data structure (ie: a DOM tree), and then have the server render it into HTML would introduce an even bigger learning curve and further decrease flexibility. This also adds more overhead, without providing much added benefit over the approach above.

Enforcing anything like this at a language level would be even more cumbersome, because most of these are general purpose languages. They do many things other than output HTML pages. Even PHP, which was designed to be a "webby" language can work as a general purpose language.

In fact the idea can be used "backwards" for SQL: rather than calling mysql("SELECT mytable WHERE name=$user AND password=$pass") you would build an "SQL query data structure" that would have everything escaped correctly as you built it.

This also already exists (in a way) in the form of parameterized queries. For PHP specifically:

$sql = 'SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour';

$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':calories' => 150, ':colour' => 'red'));

In this case, both calories and colour will be automatically escaped when the query is executed.

So what have I overlooked?

That these things already exist in one way or another.

The bigger problem is not the technology, but the programmer. Ultimately, it's up to the programmer to properly use their tools. The best way to stop a misinformed programmer from shooting themselves in the foot is to educate them.

Security often comes at the expense of convenience, flexibility and practicality. It is much easier to write bad and unsafe code than it is to write good and safe code, regardless of the language. Novice-friendly languages like PHP* compound this problem.

Finally, regardless of how some technology works, there are ways to exploit it. They're called exploits for a reason: they subvert the system to work in ways it wasn't intended to. If you made every single language force HTML to be built a certain way (an impossible goal), maybe XSS wouldn't be a concern. But certainly something else would.

* Yes, I am singling out PHP due to the inordinate amount of unsafe code I see on Stack Overflow every day, written by obviously novice programmers. This isn't really a dig at the language: novice-friendliness is a double-edged sword.

9
  • "just wouldn't work because of how the web works": Actually, you can make it work. I don't know why you think it isn't workable. I wonder if maybe you've misunderstood the idea, or are unfamiliar with prior work on this subject.
    – D.W.
    Oct 25, 2012 at 18:19
  • P.S. We don't need to invent a new standard called SecHTML: tools like HTMLPurifier demonstrate that there exists a subset of HTML that is (a) consistently parsed by all major browsers, and (b) "safe" (contains no active content). jdoe proposes rendering html to string. That could work, e.g., by rendering to the subset that HTMLPurifier uses, using the same renderer that HTMLPurifier uses -- as a thought experiment. (This might not be exactly how you'd implement in practice, but it is enough to serve as a counterexample to your claim of impossibility.)
    – D.W.
    Oct 25, 2012 at 18:20
  • 1
    I believe you misinterpreted the question. The idea wasn't to send a data structure to the browser, but render first to a data structure, then have the web server render this data structure to an HTML string. Which is what several rendering engines for e.g., Rails already do. Oct 25, 2012 at 18:34
  • @D.W. Perhaps I worded the answer poorly or misunderstood the question. I'm arguing that while a "safe" version of HTML certainly can work, I don't see it being ever implemented. Like I said, you can disable all scripting (and this can be done to an extent by a server stripping all potentially harmful tags). I understood that the OP is a proposing new "version" of HTML, and that just won't work.
    – Null
    Oct 25, 2012 at 18:39
  • @StephenTouset To me, it certainly sounded like the OP wants to send a data structure to the browser: "which outputs an HTML data structure rather than text" and the paragraph in parentheses seems to support my interpretation. Otherwise, like it's been noted, it would something that already exists.
    – Null
    Oct 25, 2012 at 18:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .