CVE-2018-1000658: Unrestricted Upload of File with Dangerous Type (CWE-434)
value: LimeSurvey version prior to 3.14.4 contains a file upload vulnerability in upload functionality that can result in an attacker gaining code execution via webshell. This attack appear to be exploitable via an authenticated user uploading a zip archive which can contains malicious php files that can be called under certain circumstances. This vulnerability appears to have been fixed in after commit 91d143230eb357260a19c8424b3005deb49a47f7 / version 3.14.4.
CWE description: The product allows the upload or transfer of dangerous file types that are automatically processed within its environment.
CVSS v3 base score: 8.8
Published: 2018-09-06T17:29Z
Repository: https://github.com/LimeSurvey/LimeSurvey
Language: PHP
Files changed: application/helpers/common_helper.php, application/third_party/pclzip/pclzip.lib.php
Commit date: 2018-08-16 11:51:02 +0200
Commit message: [security] Fixed issue #13960: vulnerabilities in file upload functionality


Diff: diff --git a/application/helpers/common_helper.php b/application/helpers/common_helper.php
index d16c2b77d44..c7849ef4710 100644
--- a/application/helpers/common_helper.php
+++ b/application/helpers/common_helper.php
@@ -4958,5 +4958,42 @@ function isAssociativeArray($array){
             return true;
         }
     }
     return false;
 }
+
+/**
+ * Test if a given zip file is Zip Bomb
+ * see comment here : http://php.net/manual/en/function.zip-entry-filesize.php
+ * @param string $zip_filename
+ * @return int
+ */
+function isZipBomb($zip_filename)
+{
+    return ( get_zip_originalsize($zip_filename) >  getMaximumFileUploadSize() );
+}
+
+/**
+ * Get the original size of a zip archive to prevent Zip Bombing
+ * see comment here : http://php.net/manual/en/function.zip-entry-filesize.php
+ * @param string $filename
+ * @return int
+ */
+function get_zip_originalsize($filename) {
+
+    if ( function_exists ('zip_entry_filesize') ){
+        $size = 0;
+        $resource = zip_open($filename);
+        while ($dir_resource = zip_read($resource)) {
+            $size += zip_entry_filesize($dir_resource);
+        }
+        zip_close($resource);
+
+        return $size;
+    }else{
+        if ( YII_DEBUG ){
+            Yii::app()->setFlashMessage(gT("Warning! php zip extension is not installed on your server. You're not protected from Zip Bomb attaacks."), 'error');
+        }
+    }
+
+    return -1;
+}
diff --git a/application/third_party/pclzip/pclzip.lib.php b/application/third_party/pclzip/pclzip.lib.php
index 8c7cbc79395..1db8f983060 100644
--- a/application/third_party/pclzip/pclzip.lib.php
+++ b/application/third_party/pclzip/pclzip.lib.php
@@ -219,10 +219,17 @@
     if (!function_exists('gzopen'))
     {
       die('Abort '.basename(__FILE__).' : Missing zlib extensions');
     }
 
+
+    // Added by LS Team to prevent Zip Bombing
+    if (isZipBomb($p_zipname)){
+        die('Abort '.basename(__FILE__).' : Unzipped file is superior to upload_max_filesize or to post_max_size');
+    }
+
+
     // ----- Set the attributes
     $this->zipname = $p_zipname;
     $this->zip_fd = 0;
     $this->magic_quotes_status = -1;
 
@@ -3668,11 +3675,11 @@
 
       }
     }
 
     // Added by LS Team to check for invalid paths
-    $p_entry['filename'] = get_absolute_path($p_entry['filename']);    
+    $p_entry['filename'] = get_absolute_path($p_entry['filename']);
 
     // ----- Add the path
     if ($p_path != '') {
       $p_entry['filename'] = $p_path."/".$p_entry['filename'];
     }

Vulnerable code:     $p_entry['filename'] = get_absolute_path($p_entry['filename']);    
Fixed code: 
/**
 * Test if a given zip file is Zip Bomb
 * see comment here : http://php.net/manual/en/function.zip-entry-filesize.php
 * @param string $zip_filename
 * @return int
 */
function isZipBomb($zip_filename)
{
    return ( get_zip_originalsize($zip_filename) >  getMaximumFileUploadSize() );
}

/**
 * Get the original size of a zip archive to prevent Zip Bombing
 * see comment here : http://php.net/manual/en/function.zip-entry-filesize.php
 * @param string $filename
 * @return int
 */
function get_zip_originalsize($filename) {

    if ( function_exists ('zip_entry_filesize') ){
        $size = 0;
        $resource = zip_open($filename);
        while ($dir_resource = zip_read($resource)) {
            $size += zip_entry_filesize($dir_resource);
        }
        zip_close($resource);

        return $size;
    }else{
        if ( YII_DEBUG ){
            Yii::app()->setFlashMessage(gT("Warning! php zip extension is not installed on your server. You're not protected from Zip Bomb attaacks."), 'error');
        }
    }

    return -1;
}

    // Added by LS Team to prevent Zip Bombing
    if (isZipBomb($p_zipname)){
        die('Abort '.basename(__FILE__).' : Unzipped file is superior to upload_max_filesize or to post_max_size');
    }


    $p_entry['filename'] = get_absolute_path($p_entry['filename']);