Ensure init_sec_context endpoint is the document host.
authorMark Donnelly <mark@painless-security.com>
Fri, 31 Jul 2015 19:24:17 +0000 (15:24 -0400)
committerMark Donnelly <mark@painless-security.com>
Fri, 31 Jul 2015 19:24:17 +0000 (15:24 -0400)
* Hook calls to import_name and remember the hostname associated with the result
* Check on calls to init_sec_context that the hostname for the supplied target handle

browsers/common/contentscript.js

index b425ad3..a786197 100644 (file)
@@ -31,8 +31,6 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  */
-console.log("Loading content script #6...");
-
 function addScript(url) {
   var elt = document.createElement("script");
   elt.setAttribute("src", 
@@ -42,6 +40,8 @@ function addScript(url) {
 
 var port;
 var browser;
+var gssHostNames = {};
+var pendingGssHostNames = {};
 
 if ("undefined" != typeof(chrome) &&
     "undefined" != typeof(chrome.extension) &&
@@ -60,14 +60,36 @@ if ("undefined" != typeof(chrome) &&
 addScript( gss_script_name );
 
 sendReplyToWebpage = function(gssReplyJSON) {
-     var appTag = gssReplyJSON.cookies.app_tag;
-     
-     console.log("[" + appTag + "] Extension port listener received message: [" + 
-                  JSON.stringify(gssReplyJSON) + "]"
-               ); 
-     window.postMessage(gssReplyJSON, "*");
+  var appTag = gssReplyJSON.cookies.app_tag;
+  var csTag = gssReplyJSON.cookies.cs_tag;
+
+  gssReplyJSON.cookies.cs_tag = undefined;
+
+  /* Save off the hostnames of any reply to GSSImportName if:
+   * + There is a csTag
+   * + The invoked method was 'gss_import_name'
+   * + The method completed successfully
+   * + There is a hostname wating in the pendingGssHostNames hash
+   *   indexed by csTag
+  */
+  if ( typeof(csTag) != 'undefined' &&
+       gssReplyJSON.method == 'gss_import_name' &&
+       typeof(gssReplyJSON.return_values) != 'undefined' &&
+       gssReplyJSON.return_values.major_status == '0' &&
+       typeof(pendingGssHostNames[csTag]) != 'undefined' )
+  {
+    gssHostNames[gssReplyJSON.return_values.gss_name] =
+      pendingGssHostNames[csTag];
+    delete pendingGssHostNames[csTag];
   }
 
+  console.log("[" + appTag +
+             "] Extension port listener received message: [" + 
+              JSON.stringify(gssReplyJSON) + "]"
+            );
+  window.postMessage(gssReplyJSON, "*");
+}
+
 
 /* When we get a message back from the extension 
  * background script
@@ -94,9 +116,58 @@ window.addEventListener("message", function(event) {
     }
     var appTag = event.data.cookies.app_tag;
     
-    console.log("[" + appTag + "] Window message listener received message: [" +
+    console.log("[" + appTag +
+                "] Window message listener received message: [" +
                JSON.stringify(event.data) + "]"
-               );
+              );
+
+    /*
+     * Deny calls to init_sec_context where we don't know that the
+     * target has the same hostname as the origin.
+     */
+    if(event.data.method == "gss_init_sec_context" &&
+       typeof(event.data.arguments) != 'undefined' &&
+       gssHostNames[event.data.arguments.target_name] !=
+          document.location.hostname)
+    {
+      console.log("[" + appTag + "] Window message listener received " +
+                 "gss_init_sec_context, but the hostname in the " +
+                 "target_name could not be found to match the document " +
+                 "location hostname.");
+      sendReplyToWebpage({
+        'method':'gss_init_sec_context',
+        'return_values': {
+          'major_status': -2,
+          'minor_status': -1,
+          'major_status_message': 'The GSS call cannot be completed',
+          'minor_status_message': 'init_sec_context requires a target ' +
+                                 'that matches your page origin.'
+        },
+        'cookies': event.data.cookies;
+      });
+      return;
+    }
+
+    /* Add a content script tag, csTag */
+    var csTag = navigator.generateNonce();
+    event.data.cookies.cs_tag = csTag;
+
+    /* Save out the hostname from calls to import_name with an
+     * NT hostbased name
+     */
+    if(event.data.method == 'gss_import_name')
+    {
+      if( typeof(event.data.arguments) != 'undefined' &&
+         ( event.data.arguments.input_name_type ==
+             "{1 2 840 113554 1 2 1 4 }" ||
+           event.data.arguments.input_name_type ==
+             "1.2.840.113554.1.2.1.4" ) )
+      {
+       var hostname = /[^@]*$/.exec(event.data.arguments.input_name)[0];
+       pendingGssHostNames[csTag] = hostname;
+      }
+    }
+
     if ("Chrome" == browser)
     {
       port.postMessage(event.data);