- Security: close cross site scripting vulnerability in draft, compose
authorkink <kink@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Sat, 2 Dec 2006 15:11:09 +0000 (15:11 +0000)
committerkink <kink@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Sat, 2 Dec 2006 15:11:09 +0000 (15:11 +0000)
    and mailto functionality [CVE-2006-6142].
  - Security: work around an issue in Internet Explorer that would guess
    the mime type of a file based on contents, not Content-Type header.

git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@11968 7612ce4b-ef26-0410-bec9-ea0150e637f0

ChangeLog
functions/mime.php
src/compose.php
src/login.php
src/mailto.php
src/redirect.php
src/right_main.php
src/webmail.php

index 9c9b99bc5c395860eb474071a00b2926ba4249c0..070071e40488329baa633f47328413b0c3f1d377 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -159,6 +159,10 @@ Version 1.5.2 - CVS
   - Add support for SpamAssassin's X-Spam-Status header (#1589520).
   - Added plugin on/off switch, which completely disables all plugins
     (optionally for one named user, otherwise for all users).
+  - Security: close cross site scripting vulnerability in draft, compose
+    and mailto functionality [CVE-2006-6142].
+  - Security: work around an issue in Internet Explorer that would guess
+    the mime type of a file based on contents, not Content-Type header.
 
 Version 1.5.1 (branched on 2006-02-12)
 --------------------------------------
index 12c46a3cacbe837a91ab03dba57e6a35c4ceb4c6..2dccda47c6eb4c7ac5fe91ec7f5a709cf9c89093 100644 (file)
@@ -540,7 +540,11 @@ function buildAttachmentArray($message, $exclude_id, $mailbox, $id) {
         if ($where && $what) {
             $defaultlink .= '&amp;where='. urlencode($where).'&amp;what='.urlencode($what);
         }
-
+        // IE does make use of mime content sniffing. Forcing a download
+        // prohibit execution of XSS inside an application/octet-stream attachment
+        if ($type0 == 'application' && $type1 == 'octet-stream') {
+            $defaultlink .= '&amp;absolute_dl=true';
+        }
         /* This executes the attachment hook with a specific MIME-type.
          * If that doesn't have results, it tries if there's a rule
          * for a more generic type. Finally, a hook for ALL attachment
@@ -1695,12 +1699,66 @@ function sq_fixatts($tagname,
 function sq_fixstyle($body, $pos, $message, $id, $mailbox){
     global $view_unsafe_images;
     $me = 'sq_fixstyle';
-    $ret = sq_findnxreg($body, $pos, '</\s*style\s*>');
-    if ($ret == FALSE){
+
+    // workaround for </style> in between comments
+    $iCurrentPos = $pos;
+    $content = '';
+    $sToken = '';
+    $bSucces = false;
+    $bEndTag = false;
+    for ($i=$pos,$iCount=strlen($body);$i<$iCount;++$i) {
+        $char = $body{$i};
+        switch ($char) {
+            case '<':
+                $sToken .= $char;
+                break;
+            case '/':
+                 if ($sToken == '<') {
+                    $sToken .= $char;
+                    $bEndTag = true;
+                 } else {
+                    $content .= $char;
+                 }
+                 break;
+            case '>':
+                 if ($bEndTag) {
+                    $sToken .= $char;
+                    if (preg_match('/\<\/\s*style\s*\>/i',$sToken,$aMatch)) {
+                        $newpos = $i + 1;
+                        $bSucces = true;
+                        break 2;
+                    } else {
+                        $content .= $sToken;
+                    }
+                    $bEndTag = false;
+                 } else {
+                    $content .= $char;
+                 }
+                 break;
+            case '!':
+                if ($sToken == '<') {
+                    // possible comment
+                    if (isset($body{$i+2}) && substr($body,$i,3) == '!--') {
+                        $i = strpos($body,'-->',$i+3);
+                        $sToken = '';
+                    }
+                } else {
+                    $content .= $char;
+                }
+                break;
+            default:
+                if ($bEndTag) {
+                    $sToken .= $char;
+                } else {
+                    $content .= $char;
+                }
+                break;
+        }
+    }
+    if ($bSucces == FALSE){
         return array(FALSE, strlen($body));
     }
-    $newpos = $ret[0] + strlen($ret[2]);
-    $content = $ret[1];
+
     /**
     * First look for general BODY style declaration, which would be
     * like so:
@@ -2389,11 +2447,15 @@ function SendDownloadHeaders($type0, $type1, $filename, $force, $filesize=0) {
 
             // This works for most types, but doesn't work with Word files
             header ("Content-Type: application/download; name=\"$filename\"");
-
+            // This is to prevent IE for MIME sniffing and auto open a file in IE
+            header ("Content-Type: application/force-download; name=\"$filename\"");
             // These are spares, just in case.  :-)
             //header("Content-Type: $type0/$type1; name=\"$filename\"");
             //header("Content-Type: application/x-msdownload; name=\"$filename\"");
             //header("Content-Type: application/octet-stream; name=\"$filename\"");
+        } else if ($isIE) {
+             // This is to prevent IE for MIME sniffing and auto open a file in IE
+             header ("Content-Type: application/force-download; name=\"$filename\"");
         } else {
             // another application/octet-stream forces download for Netscape
             header ("Content-Type: application/octet-stream; name=\"$filename\"");
index 8bc437c8e81e1a561774e9d49f76c95ef561c3cd..93845a4ca6923ca4fb754f258c78b4cb3c4a799b 100644 (file)
@@ -69,7 +69,11 @@ sqgetGlobalVar('draft',$draft);
 sqgetGlobalVar('draft_id',$draft_id);
 sqgetGlobalVar('ent_num',$ent_num);
 sqgetGlobalVar('saved_draft',$saved_draft);
-sqgetGlobalVar('delete_draft',$delete_draft);
+
+if ( sqgetGlobalVar('delete_draft',$delete_draft) ) {
+    $delete_draft = (int)$delete_draft;
+}
+
 if ( sqgetGlobalVar('startMessage',$startMessage) ) {
     $startMessage = (int)$startMessage;
 } else {
@@ -110,6 +114,25 @@ if ( !sqgetGlobalVar('smaction',$action) )
     if ( sqgetGlobalVar('smaction_edit_new',$tmp) )   $action = 'edit_as_new';
 }
 
+/**
+ * Here we decode the data passed in from mailto.php.
+ */
+if ( sqgetGlobalVar('mailtodata', $mailtodata, SQ_GET) ) {
+    $trtable = array('to'       => 'send_to',
+                 'cc'           => 'send_to_cc',
+                 'bcc'          => 'send_to_bcc',
+                 'body'         => 'body',
+                 'subject'      => 'subject');
+    $mtdata = unserialize($mailtodata);
+    
+    foreach ($trtable as $f => $t) {
+        if ( !empty($mtdata[$f]) ) {
+            $$t = $mtdata[$f];
+        }
+    }
+    unset($mailtodata,$mtdata, $trtable);
+}
+
 /* Location (For HTTP 1.1 Header("Location: ...") redirects) */
 $location = get_location();
 /* Identities (fetch only once) */
@@ -333,6 +356,8 @@ if (sqsession_is_registered('session_expired_post')) {
 if (!isset($composesession)) {
     $composesession = 0;
     sqsession_register(0,'composesession');
+} else {
+    $composesession = (int)$composesession;
 }
 
 if (!isset($session) || (isset($newmessage) && $newmessage)) {
index 50efeb3f795f0b104e3b693c78002a38269b453e..14ee6030db501feece1f882179aba081f31d662f 100644 (file)
@@ -148,15 +148,15 @@ if (isset($hide_sm_attributions) && !$hide_sm_attributions) {
                         _("By the SquirrelMail Project Team")."<br />\n";
 }
 
-if(sqgetGlobalVar('mailto', $mailto)) {
-    $rcptaddress = addHidden('mailto', $mailto);
+if(sqgetGlobalVar('mailtodata', $mailtodata)) {
+    $mailtofield = addHidden('mailtodata', $mailtodata);
 } else {
-    $rcptaddress = '';
+    $mailtofield = '';
 }
 
 $password_field = addPwField('secretkey');
 $login_extra = addHidden('js_autodetect_results', SMPREF_JS_OFF).
-               $rcptaddress .
+               $mailtofield .
                addHidden('just_logged_in', '1');
 
 session_write_close();
index 0ad9224fc78221582a25fff4f16f6307e63201ab..b27b1524727252b679f61365256c95aa1cb40df7 100644 (file)
@@ -38,6 +38,8 @@ $trtable = array('cc'           => 'send_to_cc',
                  'subject'      => 'subject');
 $url = '';
 
+$data = array();
+
 if(sqgetGlobalVar('emailaddress', $emailaddress)) {
     $emailaddress = trim($emailaddress);
     if(stristr($emailaddress, 'mailto:')) {
@@ -47,33 +49,33 @@ if(sqgetGlobalVar('emailaddress', $emailaddress)) {
         list($emailaddress, $a) = explode('?', $emailaddress, 2);
         if(strlen(trim($a)) > 0) {
             $a = explode('=', $a, 2);
-            $url .= $trtable[strtolower($a[0])] . '=' . urlencode($a[1]) . '&';
+            $data[strtolower($a[0])] = $a[1];
         }
     }
-    $url = 'send_to=' . urlencode($emailaddress) . '&' . $url;
+    $data['to'] = $emailaddress;
 
     /* CC, BCC, etc could be any case, so we'll fix them here */
     foreach($_GET as $k=>$g) {
         $k = strtolower($k);
         if(isset($trtable[$k])) {
             $k = $trtable[$k];
-            $url .= $k . '=' . urlencode($g) . '&';
+            $data[$k] = $g;
         }
     }
-    $url = substr($url, 0, -1);
 }
+sqsession_is_active();
 
 if($force_login == false && sqsession_is_registered('user_is_logged_in')) {
     if($compose_only == true) {
-        $redirect = 'compose.php?' . $url;
+        $redirect = 'compose.php?mailtodata=' . urlencode(serialize($data));
     } else {
-        $redirect = 'webmail.php?right_frame=compose.php?' . urlencode($url);
+        $redirect = 'webmail.php?mailtodata=' . urlencode(serialize($data));
     }
 } else {
-    $redirect = 'login.php?mailto=' . urlencode($url);
+    $redirect = 'login.php?mailtodata=' . urlencode(serialize($data));
 }
 
 session_write_close();
 header('Location: ' . get_location() . '/' . $redirect);
 
-?>
\ No newline at end of file
+?>
index f48de676470d505576e098158a8006e27be26542..17623d817dd29c54695729986b9df15bf5382fc5 100644 (file)
@@ -35,8 +35,8 @@ sqGetGlobalVar('secretkey', $secretkey);
 if(!sqGetGlobalVar('squirrelmail_language', $squirrelmail_language) || $squirrelmail_language == '') {
     $squirrelmail_language = $squirrelmail_default_language;
 }
-if (!sqgetGlobalVar('mailto', $mailto)) {
-    $mailto = '';
+if (!sqgetGlobalVar('mailtodata', $mailtodata)) {
+    $mailtodata = '';
 }
 
 /* end of get globals */
@@ -161,9 +161,9 @@ if ( sqgetGlobalVar('session_expired_location', $session_expired_location, SQ_SE
     unset($session_expired_location);
 }
 
-if($mailto != '') {
-    $redirect_url  = $location . '/webmail.php?right_frame=compose.php&mailto=';
-    $redirect_url .= urlencode($mailto);
+if($mailtodata != '') {
+    $redirect_url  = $location . '/webmail.php?right_frame=compose.php&mailtodata=';
+    $redirect_url .= urlencode($mailtodata);
 }
 
 /* Write session data and send them off to the appropriate page. */
index 0e33723ec033de420f0c4e9eeb7b0ebd4e17b780..726b41d7d138476927804d549ca849144364c8b5 100644 (file)
@@ -248,7 +248,7 @@ if (isset($aMailbox['FORWARD_SESSION'])) {
         }
         // do not use &amp;, it will break the query string and $session will not be detected!!!
         $comp_uri = SM_PATH . 'src/compose.php?mailbox='. urlencode($mailbox).
-                    '&session='.$aMailbox['FORWARD_SESSION'];
+                    '&session='.urlencode($aMailbox['FORWARD_SESSION']);
         displayPageHeader($color, $mailbox, "comp_in_new('$comp_uri', $compose_width, $compose_height);", '');
     } else {
         $mailbox_cache[$account.'_'.$aMailbox['NAME']] = $aMailbox;
index c8af2939e7ca39334a479b6cdc98874fa787ebb1..8124e562af6d40fe4607dc73c71c848a5727c9d2 100644 (file)
@@ -31,8 +31,10 @@ if (!sqgetGlobalVar('mailbox', $mailbox)) {
 
 sqgetGlobalVar('right_frame', $right_frame, SQ_GET);
 
-if(!sqgetGlobalVar('mailto', $mailto)) {
-    $mailto = '';
+if(!sqgetGlobalVar('mailtodata', $mailtodata)) {
+    $mailtourl = 'mailtodata='.urlencode($mailtodata);
+} else {
+    $mailtourl = '';
 }
 
 // Determine the size of the left frame
@@ -95,7 +97,7 @@ switch($right_frame) {
         $right_frame_url = 'folders.php';
         break;
     case 'compose.php':
-        $right_frame_url = 'compose.php?' . $mailto;
+        $right_frame_url = 'compose.php?' . $mailtourl;
         break;
     case '':
         $right_frame_url = 'right_main.php';
@@ -116,4 +118,4 @@ $oTemplate->assign('right_frame_url', $right_frame_url);
 
 $oTemplate->display('webmail.tpl');
 
-$oTemplate->display('footer.tpl');
\ No newline at end of file
+$oTemplate->display('footer.tpl');