W3C home > Mailing lists > Public > public-script-coord@w3.org > January to March 2013

Re: E4H and constructing DOMs

From: Adam Barth <w3c@adambarth.com>
Date: Thu, 7 Mar 2013 14:52:12 -0800
Message-ID: <CAJE5ia8bxKY-c9LvDSa7vnQxCdKn+w+hDjeiTXuSo=4uWPoC3w@mail.gmail.com>
To: Allen Wirfs-Brock <allen@wirfs-brock.com>
Cc: Brendan Eich <brendan@secure.meer.net>, Ian Hickson <ian@hixie.ch>, Rick Waldron <waldron.rick@gmail.com>, Ojan Vafai <ojan@chromium.org>, "rafaelw@chromium.org" <rafaelw@chromium.org>, Adam Klein <adamk@chromium.org>, Anne van Kesteren <annevk@annevk.nl>, Alex Russell <slightlyoff@chromium.org>, "public-script-coord@w3.org" <public-script-coord@w3.org>
On Thu, Mar 7, 2013 at 1:26 PM, Allen Wirfs-Brock <allen@wirfs-brock.com> wrote:
> On Mar 7, 2013, at 12:58 PM, Adam Barth wrote:
>> On Thu, Mar 7, 2013 at 11:23 AM, Brendan Eich <brendan@secure.meer.net> wrote:
>>> I'd like to hear more about the security concerns with template strings. I
>>> couldn't find that at a glance among the three links Ojan footnoted.
>>
>> The general problem with template strings is that they're an XSS risk.
>> Essentially, we're encouraging authors to mix untrusted data into
>> strings that will later be parsed by the HTML parser.  If the attacker
>> is clever in selecting these untrusted strings, he'll be able to cause
>> the remainder of the string to be parsed differently than the author
>> intends.
>>
>> var firstName = [...];
>> var lastName = [...];
>> header.innerHTML = `<h1>Welcome ${ firstName } ${ lastName }!</h1>`;
>>
>> If firstName and lastName are are user-controlled (i.e., untrusted),
>> the above is an XSS vulnerability.  For example, the attacker can set
>> firstName to "<img onerror='alert(/pwned/)'>".
>>
>> We have lots of implementation experience with these sorts of
>> string-based template systems because they're widely used in languages
>> like PHP.  Our broad experience is that they lead to buggy, XSS-prone
>> code.
>>
>> The general anti-pattern to avoid is the following:
>>
>>    template + input -> string -> HTML parser -> DOM
>>
>> A more secure approach is to first parse the template into a DOM and
>> then add the untrusted input into the DOM as text nodes.  In this
>> approach, the attacker's maliciously crafted firstName would simply
>> end up as a text node and would not execute as script.  (You might or
>> might not like other aspects of E4H, but one of its virtues is that it
>> follows this more secure pattern.)
>>
>> I understand that someone (either the author or the browser) could
>> write an HTML tag for template strings that implements the more secure
>> pattern, but most authors will simply use the default mode, which
>> follows the insecure pattern.  As a result, this language feature will
>> lead to many XSS vulnerabilities and general sadness in the world.
>
> So, what's the issue?  We can't force end user's to not use (with string based APIs such as innerHTML)  untagged template strings just like we can't force them to not use regular strings and concatenation to construct strings that they assign to innerHTML.  But we can provide via template strings a more secure mechanism for dynamically constructing such markup (for various embedded languages).
>
> Note the template tags aren't required to return string values.  If you want, you can design the HTML tag to return a special kind of object (for example an encapsulated and signed DOM subtree) and provide new APIs that only accept such objects and reject strings.

It's true that we can't take string concatenation and innerHTML away
from authors, but that doesn't mean we should give authors a shiny new
footgun.  If we are more careful, we should be able to design a
templating mechanism that doesn't suffer from these vulnerabilities.

It might be helpful to think about SQL queries as an analogy.  If
authors use string templates in their default mode, they'll build up
SQL queries that are vulnerable to SQL injection (a la [1]).  However,
if we use an approach more like prepared statements, we'll help
authors to avoid SQL injection (see, for example, [2]).  Prepared
statements use the general approach I advocate for above of first
parsing the template and then adding the untrusted data as leaves in
the abstract syntax tree.

My point is just that string templates, as currently envision, are bad
for security because they follow a known-bad approach to templating
systems.  We should learn from the mistakes of others and provide
ECMAScript authors a templating system that isn't a giant security
footgun.

Adam

[1] http://xkcd.com/327/
[2] http://stackoverflow.com/questions/1582161/how-does-a-preparedstatement-avoid-or-prevent-sql-injection
Received on Thursday, 7 March 2013 22:53:13 UTC

This archive was generated by hypermail 2.3.1 : Wednesday, 8 May 2013 19:30:09 UTC