icon_firefox[CVE-2016-1967] Same-origin policy violation using perfomance.getEntries and history navigation with session restore


Same-origin policy violation using perfomance.getEntries and history navigation with session restore


Announced: March 8, 2016
Reporter: Jordi Chancel
Impact: High
Products: Firefox
Fixed in: Firefox 45


Description

Security researcher Jordi Chancel discovered a variant of Mozilla Foundation Security Advisory 2015-136 which was fixed in Firefox 43. In the original bug, it was possible to read cross-origin URLs following a redirect if perfomance.getEntries() was used along with an iframe to host a page. Navigating back in history through script, content was pulled from the browser cache for the redirected location instead of going to the original location.

In the newly reported variant issue, it was found that if a browser session was restored, history navigation would still allow for the same attack as content was restored from the browser cache. This is a same-origin policy violation and could allow for data theft.


Le Patch utilisé pour la précédente vulnérabilité MFSA 2015-136 (découverte par le chercheur en sécurité informatique portant le pseudonyme cgvwzq) avait ajouté des vérifications de sécurité permettant de neutraliser la violation des restrictions Same-Origin Policy par une analyse de sécurité ayant pour objectif la vérification de l’origine exacte de l’URL contenu dans la balise <iframe> qui utilise une redirection ciblant un nom de domaine différent que celle de l’adresse URL utilisée dans l’attribut « src= » contenu dans la balise <iframe> permettant cette redirection et de celle de la page Web contenant la Preuve de Concept.

  • Exemple concernant les différentes adresses URL utilisées :

1. Nom de Domaine contenant la page Web de la Preuve de Concept :
http://www.Malicious-Website.com/

2. Adresse URL ciblé par la redirection utilisant un Nom de Domaine différent :
http://www.cible.com/token.php

3. Adresse URL de redirection utilisée dans l’attribut « src= » de la balise <iframe> :
http://www.Malicious-Website.com/redir.php?url=http://www.cible.com/token.php

4. Adresse URL ciblé par la redirection générant un token de manière automatique :
http://www.cible.com/token.php?secret=90c16200e6c708c415f450c12a2995ae

Codes Modifiés Pour la correction de la vulnérabilité MFSA 2015-136:

« /docshell/base/nsDocShell.cpp »
« /docshell/base/nsDocShell.h »
« /docshell/base/nsDocShellLoadInfo.cpp »
« /docshell/base/nsDocShellLoadInfo.h »
« /docshell/base/nsIDocShell.idl »
« /docshell/base/nsIDocShellLoadInfo.idl »
« /docshell/shistory/nsISHEntry.idl »
« /docshell/shistory/nsSHEntry.cpp »
« /docshell/shistory/nsSHEntry.h »
« /docshell/shistory/nsSHistory.cpp »

Cependant en cas de fermeture de la page contenant la preuve de concept et de réouverture de celle-ci via le Menu Historique et l’option de réouverture d’onglets précédemment fermés ou via le redémarrage de Firefox en cas de crash et la réouverture de la précédente session permettant aussi la réouverture de l’onglet contenant la preuve de concept, les codes suivants utilisés par l’action de restauration de session et d’onglets précédemment fermés:

« /browser/components/sessionstore/SessionHistory.jsm »
« /mobile/android/components/SessionStore.js »

ne permettaient pas les vérifications de sécurité nécessaires pour neutraliser la violation des restrictions Same-Origin Policy mises en place dans le Patch de la vulnérabilité MFSA-2015-136. Ainsi dans le Patch corrigeant la vulnérabilité Mozilla Foundation Security Advisory 2016-29 découverte lors de mes recherches en vulnérabilité sur Mozilla Firefox (code du Patch visible ci-dessous), d’autre contrôles de sécurité ont été ajoutés dans le but de vérifier de l’origine exacte de l’URL contenu dans la balise <iframe> en cas de restauration d’une précédente session et de restauration d’onglets précédemment fermés.
(les codes de sécurité ajoutés permettant de neutraliser la violation des restrictions Same-Origin Policy en cas de restauration de session et d’onglets précédemment fermés sont surlignés en vert)


--- a/browser/components/sessionstore/SessionHistory.jsm
+++ b/browser/components/sessionstore/SessionHistory.jsm
@@ -137,16 +137,20 @@ var SessionHistoryInternal = {

// We will include the property only if it's truthy to save a couple of
// bytes when the resulting object is stringified and saved to disk.
if (shEntry.referrerURI) {
entry.referrer = shEntry.referrerURI.spec;
entry.referrerPolicy = shEntry.referrerPolicy;
}


+ if (shEntry.originalURI) {
+ entry.originalURI = shEntry.originalURI.spec;
+ }
+

if (shEntry.srcdocData)
entry.srcdocData = shEntry.srcdocData;

if (shEntry.isSrcdocEntry)
entry.isSrcdocEntry = shEntry.isSrcdocEntry;

if (shEntry.baseURI)
entry.baseURI = shEntry.baseURI.spec;
@@ -297,16 +301,19 @@ var SessionHistoryInternal = {
shEntry.setIsSubFrame(entry.subframe || false);
shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;
if (entry.contentType)
shEntry.contentType = entry.contentType;
if (entry.referrer) {
shEntry.referrerURI = Utils.makeURI(entry.referrer);
shEntry.referrerPolicy = entry.referrerPolicy;
}

+ if (entry.originalURI) {
+ shEntry.originalURI = Utils.makeURI(entry.originalURI);
+ }

if (entry.isSrcdocEntry)
shEntry.srcdocData = entry.srcdocData;
if (entry.baseURI)
shEntry.baseURI = Utils.makeURI(entry.baseURI);

if (entry.cacheKey) {
var cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].
createInstance(Ci.nsISupportsPRUint32);


--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -747,16 +747,20 @@ SessionStore.prototype = {

entry.ID = aEntry.ID;
entry.docshellID = aEntry.docshellID;

if (aEntry.referrerURI) {
entry.referrer = aEntry.referrerURI.spec;
}

+ if (aEntry.originalURI) {
+ entry.originalURI = aEntry.originalURI.spec;
+ }
+

if (aEntry.contentType) {
entry.contentType = aEntry.contentType;
}

let x = {}, y = {};
aEntry.getScrollPosition(x, y);
if (x.value != 0 || y.value != 0) {
entry.scroll = x.value + "," + y.value;
@@ -827,16 +831,20 @@ SessionStore.prototype = {
shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;
if (aEntry.contentType) {
shEntry.contentType = aEntry.contentType;
}
if (aEntry.referrer) {
shEntry.referrerURI = Services.io.newURI(aEntry.referrer, null, null);
}

+ if (aEntry.originalURI) {
+ shEntry.originalURI = Services.io.newURI(aEntry.originalURI, null, null);
+ }
+

if (aEntry.cacheKey) {
let cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].createInstance(Ci.nsISupportsPRUint32);
cacheKey.data = aEntry.cacheKey;
shEntry.cacheKey = cacheKey;
}

if (aEntry.ID) {
// get a new unique ID for this frame (since the one from the last


Vulnerability demonstration (video):


Comments are closed.