FIX CVE-2019-11201

This commit is contained in:
Laurent Destailleur 2019-04-25 23:21:25 +02:00
parent 01075081cb
commit 63c0ab93fb
3 changed files with 65 additions and 3 deletions

View File

@ -31,7 +31,7 @@
* @param string $content Content to replace
* @param int $removephppart 0=Replace PHP sections with a PHP badge. 1=Remove completely PHP sections.
* @return boolean True if OK
* @see dolWebsiteOutput for function used to replace content in a web server context
* @see dolWebsiteOutput() for function used to replace content in a web server context
*/
function dolWebsiteReplacementOfLinks($website, $content, $removephppart=0)
{
@ -101,6 +101,7 @@ function dolWebsiteReplacementOfLinks($website, $content, $removephppart=0)
* @param string $str String to clean
* @param string $replacewith String to use as replacement
* @return string Result string without php code
* @see dolKeepOnlyPhpCode()
*/
function dolStripPhpCode($str, $replacewith='')
{
@ -133,6 +134,44 @@ function dolStripPhpCode($str, $replacewith='')
return $newstr;
}
/**
* Keep only PHP code part from a HTML string page.
*
* @param string $str String to clean
* @return string Result string with php code only
* @see dolStripPhpCode()
*/
function dolKeepOnlyPhpCode($str)
{
$newstr = '';
//split on each opening tag
$parts = explode('<?php',$str);
if (!empty($parts))
{
$i=0;
foreach($parts as $part)
{
if ($i == 0) // The first part is never php code
{
$i++;
continue;
}
$newstr.='<?php';
//split on closing tag
$partlings = explode('?>', $part, 2);
if (!empty($partlings))
{
$newstr .= $partlings[0].'?>';
}
else
{
$newstr .= $part.'?>';
}
}
}
return $newstr;
}
/**
* Render a string of an HTML content and output it.
@ -140,7 +179,7 @@ function dolStripPhpCode($str, $replacewith='')
*
* @param string $content Content string
* @return void
* @see dolWebsiteReplacementOfLinks for function used to replace content in the backoffice context when USEDOLIBARREDITOR is not on
* @see dolWebsiteReplacementOfLinks() for function used to replace content in the backoffice context when USEDOLIBARREDITOR is not on
*/
function dolWebsiteOutput($content)
{

View File

@ -95,4 +95,5 @@ InternalURLOfPage=Internal URL of page
ThisPageIsTranslationOf=This page/container is translation of
ThisPageHasTranslationPages=This page/container has translation
NoWebSiteCreateOneFirst=No website created yet. Create on first.
GoTo=Go to
GoTo=Go to
DynamicPHPCodeContainsAForbiddenInstruction=You add dynamic PHP code that contains the PHP instruction '<strong>%s</strong>' that is forbidden by default as dynamic content (see hidden options WEBSITE_PHP_ALLOW_xxx to increase list of allowed commands).

View File

@ -1453,6 +1453,26 @@ if (($action == 'updatesource' || $action == 'updatecontent' || $action == 'conf
$objectpage->content = GETPOST('PAGE_CONTENT','none');
// Security analysis
$phpfullcodestring = dolKeepOnlyPhpCode($objectpage->content);
//print dol_escape_htmltag($phpfullcodestring);exit;
$forbiddenphpcommands=array("exec", "passthru", "system", "shell_exec", "proc_open");
if (empty($conf->global->WEBSITE_PHP_ALLOW_WRITE)) // If option is not on, we disallow functions to write files
{
$forbiddenphpcommands=array_merge($forbiddenphpcommands, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "unlink", "mkdir", "rmdir", "symlink", "touch", "umask"));
}
foreach($forbiddenphpcommands as $forbiddenphpcommand)
{
if (preg_match('/'.$forbiddenphpcommand.'\s*\(/ms', $phpfullcodestring))
{
$error++;
setEventMessages($langs->trans("DynamicPHPCodeContainsAForbiddenInstruction", $forbiddenphpcommand), null, 'errors');
if ($action == 'updatesource') $action = 'editsource';
if ($action == 'updatecontent') $action = 'editcontent';
}
}
// Clean data. We remove all the head section.
$objectpage->content = preg_replace('/<head>.*<\/head>/ims', '', $objectpage->content);
/* $objectpage->content = preg_replace('/<base\s+href=[\'"][^\'"]+[\'"]\s/?>/s', '', $objectpage->content); */
@ -1463,6 +1483,8 @@ if (($action == 'updatesource' || $action == 'updatecontent' || $action == 'conf
{
$error++;
setEventMessages($objectpage->error, $objectpage->errors, 'errors');
if ($action == 'updatesource') $action = 'editsource';
if ($action == 'updatecontent') $action = 'editcontent';
}
if (! $error)