Skip to content

Commit

Permalink
[security] Fixed issue #13960: vulnerabilities in file upload functio…
Browse files Browse the repository at this point in the history
…nality
  • Loading branch information
LouisGac committed Aug 16, 2018
1 parent 20fc85e commit 91d1432
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 30 deletions.
16 changes: 10 additions & 6 deletions application/controllers/admin/export.php
Expand Up @@ -348,7 +348,7 @@ public function exportspss()
// Default to 2 (16 and up)
Yii::app()->session['spssversion'] = 2;
}
$spssver = Yii::app()->request->getParam('spssver', Yii::app()->session['spssversion']);
$spssver = Yii::app()->request->getParam('spssver', Yii::app()->session['spssversion']);
Yii::app()->session['spssversion'] = $spssver;

$length_varlabel = '231'; // Set the max text length of Variable Labels
Expand Down Expand Up @@ -1150,7 +1150,7 @@ public function quexml($iSurveyID)


$lang = Yii::app()->request->getPost('save_language');
$tempdir = Yii::app()->getConfig("tempdir");


// Setting the selected language for printout
App()->setLanguage($lang);
Expand All @@ -1169,7 +1169,9 @@ public function quexml($iSurveyID)
//NEED TO GET QID from $quexmlpdf
$qid = intval($quexmlpdf->getQuestionnaireId());

$zipdir = $this->_tempdir($tempdir);
Yii::import('application.helpers.common_helper', true);
$zipdir = createRandomTempDir();


$f1 = "$zipdir/quexf_banding_{$qid}_{$lang}.xml";
$f2 = "$zipdir/quexmlpdf_{$qid}_{$lang}.pdf";
Expand All @@ -1185,7 +1187,7 @@ public function quexml($iSurveyID)


Yii::app()->loadLibrary('admin.pclzip');
$zipfile = "$tempdir/quexmlpdf_{$qid}_{$lang}.zip";
$zipfile = Yii::app()->getConfig("tempdir").DIRECTORY_SEPARATOR."quexmlpdf_{$qid}_{$lang}.zip";
$z = new PclZip($zipfile);
$z->create($zipdir, PCLZIP_OPT_REMOVE_PATH, $zipdir);

Expand Down Expand Up @@ -1222,10 +1224,12 @@ private function _exportPrintableHtmls($iSurveyID, $readFile = true)
$fullAssetsDir = Template::getTemplatePath($oSurvey->template);
$aLanguages = $oSurvey->getAllLanguages();

$tempdir = Yii::app()->getConfig("tempdir");
$zipdir = $this->_tempdir($tempdir);
Yii::import('application.helpers.common_helper', true);
$zipdir = createRandomTempDir();

$fn = "printable_survey_".preg_replace('([^\w\s\d\-_~,;\[\]\(\).])','',$oSurvey->currentLanguageSettings->surveyls_title)."_{$oSurvey->primaryKey}.zip";

$tempdir = Yii::app()->getConfig("tempdir");
$zipfile = "$tempdir/".$fn;

Yii::app()->loadLibrary('admin.pclzip');
Expand Down
3 changes: 2 additions & 1 deletion application/controllers/admin/labels.php
Expand Up @@ -60,7 +60,8 @@ public function importlabelresources()
// Create temporary directory
// If dangerous content is unzipped
// then no one will know the path
$extractdir = $this->_tempdir(Yii::app()->getConfig('tempdir'));
Yii::import('application.helpers.common_helper', true);
$extractdir = createRandomTempDir();
$zipfilename = $_FILES['the_file']['tmp_name'];
$basedestdir = Yii::app()->getConfig('uploaddir')."/labels";
$destdir = $basedestdir."/$lid/";
Expand Down
3 changes: 2 additions & 1 deletion application/controllers/admin/surveyadmin.php
Expand Up @@ -272,7 +272,8 @@ public function importsurveyresources()
// Create temporary directory
// If dangerous content is unzipped
// then no one will know the path
$extractdir = $this->_tempdir(Yii::app()->getConfig('tempdir'));
Yii::import('application.helpers.common_helper', true);
$extractdir = createRandomTempDir();
$zipfilename = $_FILES['the_file']['tmp_name'];
$basedestdir = Yii::app()->getConfig('uploaddir')."/surveys";
$destdir = $basedestdir."/$iSurveyID/";
Expand Down
22 changes: 0 additions & 22 deletions application/core/Survey_Common_Action.php
Expand Up @@ -1234,28 +1234,6 @@ protected function _filterImportedResources($extractdir, $destdir)
return array($aImportedFilesInfo, $aErrorFilesInfo);
}

/**
* Creates a temporary directory
*
* @access protected
* @param string $dir
* @param string $prefix
* @param int $mode
* @return string
*/
protected function _tempdir($dir, $prefix = '', $mode = 0700)
{
if (substr($dir, -1) != DIRECTORY_SEPARATOR) {
$dir .= DIRECTORY_SEPARATOR;
}

do {
$path = $dir.$prefix.mt_rand(0, 9999999);
} while (!mkdir($path, $mode));

return $path;
}

/**
* Get extra menus from plugins that are using event beforeAdminMenuRender
*
Expand Down
68 changes: 68 additions & 0 deletions application/helpers/common_helper.php
Expand Up @@ -4961,6 +4961,74 @@ function isAssociativeArray($array){
return false;
}


/**
* Create a directory in tmp dir using a random string
*
* @param string $dir the temp directory (if empty will use the one from configuration)
* @param string $prefix wanted prefix for the directory
* @param int $mode wanted file mode for this directory
* @return string the path of the created directory
*/
function createRandomTempDir($dir=null, $prefix = '', $mode = 0700)
{

$sDir = (empty($dir)) ? Yii::app()->getConfig('tempdir') : get_absolute_path ($dir);

if (substr($sDir, -1) != DIRECTORY_SEPARATOR) {
$sDir .= DIRECTORY_SEPARATOR;
}

do {
$sRandomString = getRandomString();
$path = $sDir.$prefix.$sRandomString;
}
while (!mkdir($path, $mode));

return $path;
}

/**
* Generate a random string, using openssl if available, else using md5
* @param int $length wanted lenght of the random string (only for openssl mode)
* @return string
*/
function getRandomString($length=32){

if ( function_exists('openssl_random_pseudo_bytes') ) {
$token = "";
$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
$codeAlphabet.= "0123456789";
for($i=0;$i<$length;$i++){
$token .= $codeAlphabet[crypto_rand_secure(0,strlen($codeAlphabet))];
}
}else{
$token = md5(uniqid(rand(), true));
}
return $token;
}

/**
* Get a random number between two values using openssl_random_pseudo_bytes
* @param int $min
* @param int $max
* @return string
*/
function crypto_rand_secure($min, $max) {
$range = $max - $min;
if ($range < 0) return $min; // not so random...
$log = log($range, 2);
$bytes = (int) ($log / 8) + 1; // length in bytes
$bits = (int) $log + 1; // length in bits
$filter = (int) (1 << $bits) - 1; // set all lower bits to 1
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
$rnd = $rnd & $filter; // discard irrelevant bits
} while ($rnd >= $range);
return $min + $rnd;
}

/**
* Test if a given zip file is Zip Bomb
* see comment here : http://php.net/manual/en/function.zip-entry-filesize.php
Expand Down

0 comments on commit 91d1432

Please sign in to comment.