Skip to content

Commit

Permalink
Fixed issue #8564: CSRF vulnerability in KCFinder
Browse files Browse the repository at this point in the history
  • Loading branch information
c-schmitz committed Jan 23, 2014
1 parent 21a0cbc commit 9efe85b
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 22 deletions.
26 changes: 18 additions & 8 deletions application/helpers/admin/htmleditor_helper.php
Expand Up @@ -79,29 +79,38 @@ function initKcfinder()
}
}
}

}

function sTranslateLangCode2CK($sLanguageCode){

$aTranslationTable=array('de-informal'=>'de',
'nl-formal'=>'nl');
$aTranslationTable=array(
'ca-valencia'=>'ca',
'de-informal'=>'de',
'es-AR-informal'=>'es',
'es-AR'=>'es',
'es-CL'=>'es',
'es-MX'=>'es',
'it-informal'=>'it',
'nl-informal'=>'nl',
'zh-Hans'=>'zh-cn',
'zh-Hant-HK'=>'zh',
'zh-Hant-TW'=>'zh'
);
if (isset($aTranslationTable[$sLanguageCode])) {
$sResultCode=$aTranslationTable[$sLanguageCode];
}
else
{
$sResultCode=$sLanguageCode;
$sResultCode=strtolower($sLanguageCode);
}
return $sResultCode;

}


function PrepareEditorScript($load=false, $controller = null)
{
$clang = Yii::app()->lang;
$data['clang'] = $clang;
$data['sKCFinderCSRFToken'] = $_SESSION['kcfinder_csrftoken']=randomChars(128);
App()->getClientScript()->registerCoreScript('ckeditor');
if ($controller == null)
{
Expand Down Expand Up @@ -197,7 +206,7 @@ function getPopupEditor($fieldtype,$fieldname,$fieldtext, $surveyID=null,$gID=nu
}

function getInlineEditor($fieldtype,$fieldname,$fieldtext, $surveyID=null,$gID=null,$qID=null,$action=null)
{
{
$htmlcode = '';
$imgopts = '';
$toolbarname = 'inline';
Expand Down Expand Up @@ -248,7 +257,8 @@ function getInlineEditor($fieldtype,$fieldname,$fieldtext, $surveyID=null,$gID=n

$htmlcode .= ""
. "<script type=\"text/javascript\">\n"
. "$(document).ready(function(){ var $oCKeditorVarName = CKEDITOR.replace('$fieldname', {
. "$(document).ready(
function(){ var $oCKeditorVarName = CKEDITOR.replace('$fieldname', {
customConfig : \"".Yii::app()->getConfig('adminscripts')."ckeditor-config.js\"
,LimeReplacementFieldsType : \"".$fieldtype."\"
,LimeReplacementFieldsSID : \"".$surveyID."\"
Expand Down
39 changes: 27 additions & 12 deletions application/views/admin/survey/prepareEditorScript_view.php
@@ -1,6 +1,21 @@
<script type="text/javascript" src="<?php echo Yii::app()->getConfig('sCKEditorURL'); ?>/ckeditor.js"></script>
<script type='text/javascript'>
<!--
CKEDITOR.on('dialogDefinition', function (ev) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if (dialogName == 'image') {

var infoTab = dialogDefinition.getContents( 'Upload' );

// Add a text field to the "info" tab.
infoTab.add( {
type : 'html',
html : "<script type='javascript'>$(\"<input type='hidden' name='kcfinder_csrftoken' id='kcfinder_csrftoken' value='<?php echo $sKCFinderCSRFToken; ?>'>\").insertAfter(\"[name='upload']\",this.contentWindow.document||this.contentDocument);</script>"
});
}
});

var sReplacementFieldTitle = '<?php $clang->eT('LimeSurvey replacement field properties','js');?>';
var sReplacementFieldButton = '<?php $clang->eT('Insert/edit LimeSurvey replacement field','js');?>';
var editorwindowsHash = new Object();
Expand Down Expand Up @@ -66,18 +81,18 @@ function start_popup_editor(fieldname, fieldtext, sid, gid, qid, fieldtype, acti

function updateCKeditor(fieldname,value)
{
var mypopup= editorwindowsHash[fieldname];
if (mypopup)
{
var oMyEditor = mypopup.CKEDITOR.instances['MyTextarea'];
if (oMyEditor) {oMyEditor.setData(value);}
mypopup.focus();
}
else
{
var oMyEditor = CKEDITOR.instances[fieldname];
oMyEditor.setData(value);
}
var mypopup= editorwindowsHash[fieldname];
if (mypopup)
{
var oMyEditor = mypopup.CKEDITOR.instances['MyTextarea'];
if (oMyEditor) {oMyEditor.setData(value);}
mypopup.focus();
}
else
{
var oMyEditor = CKEDITOR.instances[fieldname];
oMyEditor.setData(value);
}
}

-->
Expand Down
33 changes: 32 additions & 1 deletion third_party/kcfinder/core/uploader.php
Expand Up @@ -274,7 +274,6 @@ public function upload() {
$config = &$this->config;
$file = &$this->file;
$url = $message = "";

if ($config['disabled'] || !$config['access']['files']['upload']) {
if (isset($file['tmp_name'])) @unlink($file['tmp_name']);
$message = $this->label("You don't have permissions to upload files.");
Expand Down Expand Up @@ -368,6 +367,11 @@ protected function checkUploadedFile(array $aFile=null) {

if (!is_array($file) || !isset($file['name']))
return $this->label("Unknown error");

if (!isset($this->post['kcfinder_csrftoken']) || (isset($this->post['kcfinder_csrftoken']) && $this->post['kcfinder_csrftoken']!=$this->session['kcfinder_csrf_token']))
{
return $this->label("CSRF upload error");
}

if (is_array($file['name'])) {
foreach ($file['name'] as $i => $name) {
Expand Down Expand Up @@ -494,6 +498,33 @@ protected function getTypeFromPath($path) {
? $patt[1] : $path;
}

protected function getCSRFToken() {
if (function_exists("hash_algos") and in_array("sha512",hash_algos()))
{
$token=hash("sha512",mt_rand(0,mt_getrandmax()));
}
else
{
$token=' ';
for ($i=0;$i<128;++$i)
{
$r=mt_rand(0,35);
if ($r<26)
{
$c=chr(ord('a')+$r);
}
else
{
$c=chr(ord('0')+$r-26);
}
$token.=$c;
}
}
$this->session['kcfinder_csrf_token']=$token;
return $token;
}


protected function removeTypeFromPath($path) {
return preg_match('/^[^\/]*\/(.*)$/', $path, $patt)
? $patt[1] : "";
Expand Down
1 change: 1 addition & 0 deletions third_party/kcfinder/js/browser/toolbar.js
Expand Up @@ -123,6 +123,7 @@ browser.initUploadButton = function() {
'<form enctype="multipart/form-data" method="post" target="uploadResponse" action="' + browser.baseGetData('upload') + '">' +
'<input type="file" name="upload[]" onchange="browser.uploadFile(this.form)" style="height:' + height + 'px" multiple="multiple" />' +
'<input type="hidden" name="dir" value="" />' +
'<input type="hidden" id="" name="kcfinder_csrftoken" value="'+browser.csrftoken+'" />' +
'</form>' +
'</div>');
$('#upload input').css('margin-left', "-" + ($('#upload input').outerWidth() - width) + 'px');
Expand Down
4 changes: 3 additions & 1 deletion third_party/kcfinder/tpl/tpl_javascript.php
Expand Up @@ -4,7 +4,8 @@
<script src="js/helper.js" type="text/javascript"></script>
<script src="js/browser/joiner.php" type="text/javascript"></script>
<script src="js_localize.php?lng=<?php echo $this->lang ?>" type="text/javascript"></script>
<?php IF (isset($this->opener['TinyMCE']) && $this->opener['TinyMCE']): ?>
<?php
IF (isset($this->opener['TinyMCE']) && $this->opener['TinyMCE']): ?>
<script src="<?php echo $this->config['_tinyMCEPath'] ?>/tiny_mce_popup.js" type="text/javascript"></script>
<?php ENDIF ?>
<?php IF (file_exists("themes/{$this->config['theme']}/init.js")): ?>
Expand All @@ -22,6 +23,7 @@
browser.dir = "<?php echo text::jsValue($this->session['dir']) ?>";
browser.uploadURL = "<?php echo text::jsValue($this->config['uploadURL']) ?>";
browser.thumbsURL = browser.uploadURL + "/<?php echo text::jsValue($this->config['thumbsDir']) ?>";
browser.csrftoken = "<?php echo $this->getCSRFToken();?>";
<?php IF (isset($this->get['opener']) && strlen($this->get['opener'])): ?>
browser.opener.name = "<?php echo text::jsValue($this->get['opener']) ?>";
<?php ENDIF ?>
Expand Down

1 comment on commit 9efe85b

@Shnoulle
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great ! \o/

Please sign in to comment.