Security/Reviews/Firefox4/HTML5 Parser Security Review

From MozillaWiki
Jump to: navigation, search

Overview

Describe the goals and objectives of the feature here.

  1. Make HTML parsing well-defined commodity functionality that everyone does the same way instead of having product-specific magic.
  2. Enable the use of SVG and MathML in text/html.
  3. Replace Gecko's HTML parser with something better understood and more maintainable.
  4. Move HTML parsing off the main thread in the hope of improving responsiveness.
Background links

Security and Privacy

  • Is this feature a security feature? If it is, what security issues is it intended to resolve?

The HTML5 parser is not a security feature. However, the HTML5 parsing algorithm attempts to have these defense-in-depth security features:

  1. U+0000 is not ignored where script or style sheet data can occur. (It is turned into U+FFFD instead.) This way, if a security gatekeeper is blacklist-based (which they shouldn't be; everyone should use whitelist-based gatekeepers), if the attacker tries to fool the gatekeeper by injecting U+0000 into blacklisted identifiers, the browser doesn't treat the parsed identifiers as those dangerous identifiers, because U+0000 has been turned into U+FFFD instead of getting dropped.
  2. Forcing a premature end of file doesn't change the executability of a given piece of the page compared to the situation where a premature end of file hasn't been forced. This is achieved by not retokenizing in a different mode if the EOF is seen inside [R]CDATA text or inside a comment.
  3. If the EOF occurs within a token, the incomplete token is discarded. This way, a premature EOF can't truncate the code in event handler attributes.
  • What potential security issues in your feature have you already considered and addressed?

I have considered the security issues that the spec itself addresses (see immediately above).

Gecko's layout system runs algorithms that are recursive along the depth of the DOM tree. This means that deep trees lead to an overflow of the runtime stack, especially on Windows. The HTML5 parser limits the depth of the tree it creates to 200. This works against DoS-by-incompetence but not against DoS-by-malice (since deep trees can be created by other means).

The Adoption Agency Agency algorithm has two loops one inside another, which means that the work done by the parser can grow more than linearly as a function of the length of the input. There are hard limits on the number of iterations; see bug 596180. Stricter limits are pending review; see bug 605466.

  • Is system or subsystem security compromised in any way if your project's configuration files / prefs are corrupt or missing?

No.

  • Include a thorough description of the security assumptions, capabilities and any potential risks (possible attack points) being introduced by your project.

When the tag <isindex> is parsed, a string that depends on the UI localization of the browser is inserted into the resulting DOM. An untrusted JavaScript program can use this string to obtain configuration-dependent entropy for fingerprinting or can infer the UI locale of the user. However, Gecko already leaks this data elsewhere.

Reconstructing active formatting elements can make the DOM grow more than linearly as a function of the length of the input. This makes DoS attacks by resource exhaustion easy. Mitigations for DoS-by-author-incompetence are pending review; see bug 605466. The safeguard against author incompetence won't protect against deliberate attacks, though.

RAM can be exhausted by sending a lot of data to the HTML5 parser. For example, element and attribute names and attribute values get buffered until they've been completely seen, so a server-side script can serve an infinitely long attribute value to exhaust RAM on the client. This is not an attack point _introduced_ by the HTML5 parser, since the old parser had this attack point as well. However, the HTML5 parser's reliance on "infallible" malloc might make RAM exhaustion lead to a crash more often. As a mitigating factor on desktops, the rate at which the network can feed the parser is low enough relative to the available memory that the user can stop the load of pages that consume excessive RAM due to being large for non-malicious reasons. However, a malicious attacker could use gzip bombs to work around the rate at which the network can feed the parser. A previous attempt to use an arbitrary limit failed; see bug 554513.

  • How are transitions in/out of Private Browsing mode handled?

They are not handled.

Exported APIs

  • Please provide a table of exported interfaces (APIs, ABIs, protocols, UI, etc.)

nsHtml5Module.h provides a way for other parts of Gecko to obtain HTML5 parser instances.

Other parts of Gecko see the HTML5 parser as an nsIParser instance.

The HTML5 parser can be invoked by Web content by loading a URL in a browsing context, by assigning to innerHTML or by calling Range.createContextualFragment.

  • Does it interoperate with a web service? How will it do so?

No.

  • Explain the significant file formats, names, syntax, and semantics.

The significant file format is HTML.

  • Are the externally visible interfaces documented clearly enough for a non-Mozilla developer to use them successfully?

innerHTML is documented in the HTML5 spec. createContextualFragment is documented on DevMo but not profoundly.

  • Does it change any existing interfaces?

Yes. There are new members on nsIParser, nsIScriptElement and nsIDocument. (See lines blamed to hsivonen.)

Module interactions

  • What other modules are used (REQUIRES in the makefile, interfaces)?

The HTML5 parser uses various interfaces from the content module. The HTML5 parser implements the usual interfaces for consuming a Necko stream. Various XPCOM facilities are used.

Data

  • What data is read or parsed by this feature?

The HTML5 parser parses full HTML documents from a network stream or from document.write() and HTML fragments from innerHTML or createContextualFragment.

  • What is the output of this feature?

A DOM tree or subtree.

  • What storage formats are used?

The HTML5 parser doesn't store data.

Reliability

  • What failure modes or decision points are presented to the user?

No decision points are presented to the user (outside about:config). When a speculation fails or when a call to document.write is ignored, a message is shown in the error console.

  • Can its files be corrupted by failures? Does it clean up any locks/files after crashes?

The HTML5 parser doesn't manage any files or file system locks.

Configuration

  • Can the end user configure settings, via a UI or about:config? Hidden prefs? Environment variables?

Yes. The end user can configure settings via about:config.

The pref html5.enable can be used to disable the HTML5 parser, in which case the old parser is used instead. This pref will become obsolete once the old parser is removed (after Firefox 4). Flipping this pref has the security-sensitive effect of using another HTML parser and its bugs instead of the bugs of the HTML5 parser.

The pref html5.offmainthread can be used to make the HTML5 parser run all its tasks on the main thread. The purpose of this setting is debugging.

There are various performance/responsiveness tunables: html5.flushtimer.initialdelay, html5.flushtimer.subsequentdelay, content.notify.interval, content.sink.interactive_deflect_count, content.sink.perf_deflect_count, content.sink.pending_event_mode, content.sink.event_probe_rate, content.sink.interactive_parse_time, content.sink.perf_parse_time, content.sink.interactive_time, content.sink.initial_perf_time, content.sink.enable_perf_mode, content.interrupt.parsing. I believe tuning these prefs doesn't have security consequences beyond a potential self-inflicted DoS.

  • Are there build options for developers? [#ifdefs, ac_add_options, etc.]

Beyond #ifdef DEBUG, if SVG is disabled in Gecko build options, the HTML5 parser doesn't dispatch the SVG load event.

The define DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH controls printf dumping of some performance statistics.

  • What ranges for the tunable are appropriate? How are they determined?

For the tunables that aren't booleans, it's not clear what the appropriate ranges are. The default values for the performance tunables are based on experimentation and/or guesswork.

  • What are its on-going maintenance requirements (e.g. Web links, perishable data files)?

The configuration options don't need on-going maintanance.

Relationships to other projects

Are there related projects in the community?

  • If so, what is the proposal's relationship to their work? Do you depend on others' work, or vice-versa?

The HTML5 parser is related to SVG and MathML support. The HTML5 parser enables in text/html what was already possible in XML.

  • Are you updating, copying or changing functional areas maintained by other groups? How are you coordinating and communicating with them? Do they "approve" of what you propose?

The main non-parser area updated as part of the HTML5 parser work has been script execution (nsIScriptElement/nsScriptLoader). Also, the way the SVG load event works was changed. These changes were reviewed by the usual reviewers for those areas.

Review comments

  • current testing
    • real world use in nightlies
    • Jesse has been fuzzing through innerHTML
      • sicking: should add a dom->html->dom roundtripping tests. File bug xxxx
    • need to add MangleMe and IExploder fuzzing bug xxxxx
  • mostly used infallible malloc, but nsTArray is not currently infallible
    • making nsTArray optionally infallible is blocker bug 550611
    • after fixing that need to use it in bug 585943
    • if nsTArray is not fixed we need to check for allocation failures in the parser (probably can still use bug 585943 for that since it'll be an alternate fix for those crashes)