mozilla

Revision 315575 of Firefox Security Basics for Developers

  • Revision slug: Security/Firefox_Security_Basics_For_Developers
  • Revision title: Firefox Security Basics for Developers
  • Revision id: 315575
  • Created:
  • Creator: mgoodwin
  • Is current revision? No
  • Comment It was thought the title was a little condescendingSecurity/Firefox_Security_For_Beginners Security/Firefox_Security_Basics_For_Developers
Tags: 

Revision Content

Who should read this document?

Developers, security folk, anyone else who's keen to know about Firefox Security.

Definitions

Content - Something (most commonly script) loaded from an untrusted source (e.g. a web page). In security discussions 'content' can refer to the set of restricted privileges made available to scripts in web content.

Chrome - something pertaining to the browser (as oppsed to web content) - in security discussions, this most commonly refers to a set of privileges which allows code to do everything (unlike web content, which is restricted)

DocShell - an object that hosts documents - a docshell is responsible for initiating loading of content from a uri, creating the content viewer and hooking it up to the incoming content. There is a docshell associated with every window (tab) or frame.

Principal - a security context. On the web, this is typically a combination of scheme, host and port.

Same-Origin Policy - a policy which prevents a document or script loaded from one origin accessing properties of a document from another.

Sandbox - an object that allows you to evaluate JavaScript code with restricted privileges. Code evaluated in a sandbox will have the same permission as if it was running in a 'normal' web page.

Wrappers - Wrappers protect extensions from untrusted content by providing safeguards and enforcing basic security rules such as the Same Origin Policy.

Assumptions

This document assumes some knowledge of security principles, common vulnerabilities and attack techniques.  Where concepts are mentioned, reference will be made to external resources that can provide further information on these concepts rather than outlining them in detail here.

Developers should familiarize themselves with common security pitfalls associated with the technologies they're working with. Web devs should know about XSS and CSRF, if you're writing in C++, you should know about buffer overflows, format string vulnerabilities, etc

Goals

Code which runs in Firefox needs to prevent external code (ie running in a web page) from:

  • Running with Chrome privileges
  • Gaining file system access
  • Stealing credentials
  • Accessing the user's personal data without their permission
  • Spoofing a trusted page (such as a banking site)
  • Crashing Firefox, or causing it to become unusable

Note that we cannot protect the user from native code that they have downloaded and explicitly run.

Front end

Front-end security is, in some ways, analogous to conventional web security: In desktop Firefox, the UI is XUL (similar in some ways to HTML). There is script that has access to sensitive APIs at the backend (Firefox), which also has access to untrusted data either from content (e.g. in documents viewed using the browser) or the user (e.g. user input).
  • Normally, content can't get a reference to chrome objects.
  • XSS from content to chrome is a bad thing; chrome has, essentially, all the privileges of the local user account running Firefox.  This could result in remote attackers executing code, silently installing malware (keyloggers, etc), reading the contents of the password manager, etc.
  • Care is needed around use of untrusted data in XUL and HTML UI elements; It's common to see the use of innerHTML or similar when safer alternatives exist (e.g. createTextNode).
  • One important difference between writing web content and chrome code is that in the latter, iframes have chrome privileges by default. If this is not desirable (and it probably isn't) you'll want to explicitly specify it's for content - e.g. iframe.setAttribute("type", "content")

General

Security checks

Under norrnal circumstances when content is loaded the browser enforces the Same Origin policy, preventing documents from different domains from interfering with each other.

If you are in a situation when you are loading web content from chrome code and you wish to perform similar checks it is recommended, where possible, to use the same mechanisms.  Ensure you consult the documentation on principals and how security checks are performed before attempting to implement your own checks - duplicating this functionality is fraught with danger.  In situations where, for some reason, you must deal with URLs directly there are a number of pitfalls you should be aware of (see the URIs section below).

URIs

Watch out for the following issues when dealing with URIs:

  • If you're performing operations on URIs, ensure you use nsIURI directly rather than ASCII hostnames (e.g from getASCIIHost - which is essentially only intended for display); this is because nsIURI is guaranteed to be canonical (notice nsIPrincipal takes nsIURIs for it's checks) whereas other forms may not be.
  • Check your schemes; only accept URIs with schemes you expect.
  • Watch out for psuedoschemes - in security checks it's the inner URI that's significant (e.g. jar:http://example.com - http://example.com is the relevant part).

Before you load anything:

  • Check you're allowed to; both nsIScriptSecurityManager and nsIPrincipal provide means of checking whether a resource is safe to load - always use these. Also, see ContentPolicy.shouldLoad
  • Set the referer correctly when loading stuff at a web page's request or when following a link, but set no referer when loading a bookmark.
Sandboxes

Sandboxes should be used to evaluate JavaScript in Chrome code unless you explicitly need it to run with Chrome privileges (and completely trust the contents of the script).

To create and use a sandbox:

// create new sandbox instance
var mySandbox = new Components.utils.Sandbox("http://www.example.com/");
mySandbox.y = 5;  // insert property 'y' with value 5 into global scope.
var result = Components.utils.evalInSandbox("x = y + 2; x + 3", mySandbox);
// result is 10, mySandbox.x is now 7

Objects inserted into a sandbox do not carry their privileges into the sandbox.

However any function that comes out of a sandbox will execute with Chrome privileges.

So for the code:

var s = new Components.utils.Sandbox(url);
var x = Components.utils.evalInSandbox(untrusted_code, s);

Any method calls on x are unsafe, including the use of == which when evaluated will call the x.valueOf() method.

Interactions with content DOM

Firefox relies on wrappers to provide 'safe' representations of objects from one context in another (e.g. chrome from content and vice versa).  In simple terms, wrappers can be thought of as filtering proxies which enforce the rules on how content and script from different principals may interact. For example, if a chrome object is exported to web content it will be wrapped in a ChromeObjectWrapper; this ensures that only the properties which are supposed to be exposed to web content (there's a whitelist in the __exposedProps__ property) can be accessed.

Whilst these wrappers provide a good level of protection against accidental problems, there are some things to be aware of. In particular, take care when using wrappedJSObject on content objects from chrome code (for more information on safely accessing content DOM from chrome, refer to this document).

More information on wrappers can be found in this article.

Chrome JS Dangerous functions

Avoid using eval or setTimeout(string, time) and other related functions if at all possible.

Further Reading:

 

Revision Source

<h3 id="Who_should_read_this_document.3F">Who should read this document?</h3>
<p>Developers, security folk, anyone else who's keen to know about Firefox Security.</p>
<h3 id="Definitions">Definitions</h3>
<p>Content - Something (most commonly script) loaded from an untrusted source (e.g. a web page). In security discussions 'content' can refer to the set of restricted privileges made available to scripts in web content.</p>
<p><a class="external-link" href="https://developer.mozilla.org/en/Chrome" rel="nofollow">Chrome</a> - something pertaining to the browser (as oppsed to web content) - in security discussions, this most commonly refers to a set of privileges which allows code to do everything (unlike web content, which is restricted)</p>
<p><a class="external-link" href="https://wiki.mozilla.org/DocShell:Home_Page" rel="nofollow">DocShell</a> - an object that hosts documents - a docshell is responsible for initiating loading of content from a uri, creating the content viewer and hooking it up to the incoming content. There is a docshell associated with every window (tab) or frame.</p>
<p><a class="external-link" href="https://developer.mozilla.org/en/Security_check_basics#Principals" rel="nofollow">Principal</a> - a security context. On the web, this is typically a combination of scheme, host and port.</p>
<p><a class="external-link" href="https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript" rel="nofollow">Same-Origin Policy</a> - a policy which prevents a document or script loaded from one origin accessing properties of a document from another.</p>
<p><a class="external-link" href="https://developer.mozilla.org/en/Components.utils.Sandbox" rel="nofollow">Sandbox</a> - an object that allows you to evaluate JavaScript code with restricted privileges. Code evaluated in a sandbox will have the same permission as if it was running in a 'normal' web page.</p>
<p><a class="external-link" href="https://developer.mozilla.org/en/XPConnect_wrappers" rel="nofollow">Wrappers</a> - Wrappers protect extensions from untrusted content by providing safeguards and enforcing basic security rules such as the Same Origin Policy.</p>
<h3 id="Assumptions">Assumptions</h3>
<p>This document assumes some knowledge of security principles, common vulnerabilities and attack techniques.&nbsp; Where concepts are mentioned, reference will be made to external resources that can provide further information on these concepts rather than outlining them in detail here.</p>
<p>Developers should familiarize themselves with common security pitfalls associated with the technologies they're working with. Web devs should know about XSS and CSRF, if you're writing in C++, you should know about buffer overflows, format string vulnerabilities, etc</p>
<h3 id="Goals">Goals</h3>
<p>Code which runs in Firefox needs to prevent external code (ie running in a web page) from:</p>
<ul>
  <li>Running with Chrome privileges</li>
  <li>Gaining file system access</li>
  <li>Stealing credentials</li>
  <li>Accessing the user's personal data without their permission</li>
  <li>Spoofing a trusted page (such as a banking site)</li>
  <li>Crashing Firefox, or causing it to become unusable</li>
</ul>
<p>Note that we cannot protect the user from native code that they have downloaded and explicitly run.</p>
<h3 id="Front_end">Front end</h3>
<div>
  <span class="author-g-x0vgakwyi95bajxr">Front-end security is, in some ways, analogous to conventional web security: In desktop Firefox, the UI is XUL (similar in some ways to HTML). There is script that has access to sensitive APIs at the backend (Firefox), which also has access to untrusted data either from content (e.g. in documents viewed using the browser) or the user (e.g. user input).</span></div>
<ul>
  <li><span class="author-g-x0vgakwyi95bajxr">Normally, content can't get a reference to chrome objects.</span></li>
  <li><span class="author-g-x0vgakwyi95bajxr">XSS from content to chrome is a bad thing; chrome has, essentially, all the privileges of the local user account running Firefox.&nbsp; This could result in remote attackers executing code, silently installing malware (keyloggers, etc), reading the contents of the password manager, etc.</span></li>
  <li><span class="author-g-x0vgakwyi95bajxr">Care is needed around use of untrusted data in XUL and HTML UI elements; It's common to see the use of innerHTML or similar when safer alternatives exist (e.g. <a class="external-link" href="https://developer.mozilla.org/en-US/docs/DOM/document.createTextNode" rel="nofollow">createTextNode</a>).</span></li>
  <li><span class="author-g-x0vgakwyi95bajxr">One important difference between writing web content and chrome code is that in the latter, iframes have chrome privileges by default. If this is not desirable (and it probably isn't) you'll want to explicitly specify it's for content - e.g. iframe.setAttribute("type", "content")</span></li>
</ul>
<h3 id="General">General</h3>
<h5 id="Security_checks">Security checks</h5>
<p>Under norrnal circumstances when content is loaded the browser enforces the Same Origin policy, preventing documents from different domains from interfering with each other.</p>
<p>If you are in a situation when you are loading web content from chrome code and you wish to perform similar checks it is recommended, where possible, to use the same mechanisms.&nbsp; Ensure you consult the documentation on <a class="external-link" href="https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIPrincipal" rel="nofollow">principals</a> and how <a class="external-link" href="https://developer.mozilla.org/en-US/docs/Security_check_basics" rel="nofollow">security checks are performed</a> before attempting to implement your own checks - duplicating this functionality is fraught with danger.&nbsp; In situations where, for some reason, you must deal with URLs directly there are a number of pitfalls you should be aware of (see the URIs section below).</p>
<h5 id="URIs">URIs</h5>
<p>Watch out for the following issues when dealing with URIs:</p>
<ul>
  <li>If you're performing operations on URIs, ensure you use nsIURI directly rather than ASCII hostnames (e.g from getASCIIHost - which is essentially only intended for display); this is because nsIURI is guaranteed to be canonical (notice nsIPrincipal takes nsIURIs for it's checks) whereas other forms may not be.</li>
  <li>Check your schemes; only accept URIs with schemes you expect.</li>
  <li>Watch out for psuedoschemes - in security checks it's the inner URI that's significant (e.g. jar:http://example.com - http://example.com is the relevant part).</li>
</ul>
<p>Before you load anything:</p>
<ul>
  <li>Check you're allowed to; both <a class="external-link" href="http://doxygen.db48x.net/mozilla/html/interfacensIScriptSecurityManager.html" rel="nofollow">nsIScriptSecurityManager</a> and <a class="external-link" href="http://doxygen.db48x.net/mozilla/html/interfacensIPrincipal.html" rel="nofollow">nsIPrincipal</a> provide means of checking whether a resource is safe to load - always use t<span style="color: rgb(0,0,0);">hese. Also, see ContentPolicy.shouldLoad</span></li>
  <li>Set the referer correctly when loading stuff at a web page's request or when following a link, but set no referer when loading a bookmark.</li>
</ul>
<h5 id="Sandboxes">Sandboxes</h5>
<p>Sandboxes should be used to evaluate JavaScript in Chrome code unless you explicitly need it to run with Chrome privileges (and completely trust the contents of the script).</p>
<p>To create and use a sandbox:</p>
<pre>
// create new sandbox instance
var mySandbox = new Components.utils.Sandbox("<span>http://www.example.com/</span>");
mySandbox.y = 5;  // insert property 'y' with value 5 into global scope.
var result = Components.utils.evalInSandbox("x = y + 2; x + 3", mySandbox);
// result is 10, mySandbox.x is now 7</pre>
<p>Objects inserted into a sandbox do not carry their privileges into the sandbox.</p>
<p>However any function that comes out of a sandbox will execute with Chrome privileges.</p>
<p>So for the code:</p>
<pre class="eval">
var s = new Components.utils.Sandbox(url);
var x = Components.utils.evalInSandbox(untrusted_code, s);</pre>
<p>Any method calls on x are unsafe, including the use of == which when evaluated will call the x.valueOf() method.</p>
<h5 id="Interactions_with_content_DOM">Interactions with content DOM</h5>
<p>Firefox relies on wrappers to provide 'safe' representations of objects from one context in another (e.g. chrome from content and vice versa).&nbsp; In simple terms, wrappers can be thought of as filtering proxies which enforce the rules on how content and script from different principals may interact. For example, if a chrome object is exported to web content it will be wrapped in a ChromeObjectWrapper; this ensures that only the properties which are supposed to be exposed to web content (there's a whitelist in the __exposedProps__ property) can be accessed.</p>
<p>Whilst these wrappers provide a good level of protection against accidental problems, there are some things to be aware of. In particular, take care when using wrappedJSObject on content objects from chrome code (for more information on safely accessing content DOM from chrome, refer to <a class="external-link" href="https://developer.mozilla.org/en-US/docs/Safely_accessing_content_DOM_from_chrome" rel="nofollow">this document</a>).</p>
<p>More information on wrappers can be found in <a class="external-link" href="https://blog.mozilla.org/gabor/2012/04/18/security-wrappers-part-1/" rel="nofollow">this article</a>.</p>
<h5 id="Chrome_JS_Dangerous_functions">Chrome JS Dangerous functions</h5>
<p>Avoid using eval or setTimeout(string, time) and other related functions if at all possible.</p>
<h3 id="Further_Reading.3A">Further Reading:</h3>
<div>
  <div>
    <span class="author-g-x0vgakwyi95bajxr url"><a class="external-link" href="https://developer.mozilla.org/en/Safely_accessing_content_DOM_from_chrome" rel="nofollow">https://developer.mozilla.org/en/Safely_accessing_content_DOM_from_chrome</a></span></div>
  <div>
    <span class="author-g-x0vgakwyi95bajxr url"><a class="external-link" href="https://developer.mozilla.org/en/XPConnect_wrappers" rel="nofollow">https://developer.mozilla.org/en/XPConnect_wrappers</a></span></div>
</div>
<div>
  <span class="author-g-x0vgakwyi95bajxr url"><a class="external-link" href="https://developer.mozilla.org/en/XPConnect_security_membranes" rel="nofollow">https://developer.mozilla.org/en/XPConnect_security_membranes</a></span></div>
<div>
  <span class="author-g-x0vgakwyi95bajxr url"><a class="external-link" href="http://blog.mozilla.org/gabor/2012/04/18/security-wrappers-part-1/" rel="nofollow">http://blog.mozilla.org/gabor/2012/04/18/security-wrappers-part-1/</a></span></div>
<div>
  <div>
    <span class="author-g-qdplz122ziorg21ylwyn">Linked from the above, but worth noting as well:</span></div>
  <div>
    <span class="author-g-qdplz122ziorg21ylwyn url"><a class="external-link" href="http://www.squarefree.com/securitytips/mozilla-developers.html" rel="nofollow">http://www.squarefree.com/securitytips/mozilla-developers.html</a> (* StfMed)</span></div>
  <div>
    <span class="author-g-qdplz122ziorg21ylwyn url"><a class="external-link" href="http://www.mozilla.org/projects/security/components/reviewguide.html" rel="nofollow">http://www.mozilla.org/projects/security/components/reviewguide.html</a></span></div>
  <div>
    <span class="author-g-qdplz122ziorg21ylwyn url"><a class="external-link" href="https://developer.mozilla.org/en-US/docs/Components.utils.evalInSandbox" rel="nofollow">https://developer.mozilla.org/en-US/docs/Components.utils.evalInSandbox</a></span></div>
</div>
<p>&nbsp;</p>
Revert to this revision