Unverified Commit b73ad519 authored by Cédric Anne's avatar Cédric Anne Committed by GitHub
Browse files

Allow iframes in rich text only when allowed by config (#8659)

parent fbcac3b0
......@@ -19,7 +19,7 @@
"DB", "DBSlave",
"// GLPI base constants (they are not detected as they are dynamically declared)",
"GLPI_AJAX_DASHBOARD", "GLPI_CALDAV_IMPORT_STATE", "GLPI_CACHE_DIR", "GLPI_CRON_DIR", "GLPI_CSRF_EXPIRES", "GLPI_CSRF_MAX_TOKENS", "GLPI_USE_IDOR_CHECK", "GLPI_IDOR_EXPIRES", "GLPI_DEMO_MODE", "GLPI_DOC_DIR", "GLPI_DUMP_DIR", "GLPI_FORCE_EMPTY_SQL_MODE", "GLPI_GRAPH_DIR", "GLPI_INSTALL_MODE", "GLPI_LOCAL_I18N_DIR", "GLPI_LOCK_DIR", "GLPI_LOG_DIR", "GLPI_MARKETPLACE_DIR", "GLPI_MARKETPLACE_PLUGINS_API_URI", "GLPI_MARKETPLACE_PRERELEASES", "GLPI_NETWORK_REGISTRATION_API_URL", "GLPI_NETWORK_MAIL", "GLPI_NETWORK_SERVICES", "GLPI_PICTURE_DIR", "GLPI_PLUGIN_DOC_DIR", "GLPI_RSS_DIR", "GLPI_SESSION_DIR", "GLPI_TELEMETRY_URI", "GLPI_TMP_DIR", "GLPI_UPLOAD_DIR", "GLPI_USE_CSRF_CHECK", "GLPI_USER_AGENT_EXTRA_COMMENTS",
"GLPI_AJAX_DASHBOARD", "GLPI_ALLOW_IFRAME_IN_RICH_TEXT", "GLPI_CALDAV_IMPORT_STATE", "GLPI_CACHE_DIR", "GLPI_CRON_DIR", "GLPI_CSRF_EXPIRES", "GLPI_CSRF_MAX_TOKENS", "GLPI_USE_IDOR_CHECK", "GLPI_IDOR_EXPIRES", "GLPI_DEMO_MODE", "GLPI_DOC_DIR", "GLPI_DUMP_DIR", "GLPI_FORCE_EMPTY_SQL_MODE", "GLPI_GRAPH_DIR", "GLPI_INSTALL_MODE", "GLPI_LOCAL_I18N_DIR", "GLPI_LOCK_DIR", "GLPI_LOG_DIR", "GLPI_MARKETPLACE_DIR", "GLPI_MARKETPLACE_PLUGINS_API_URI", "GLPI_MARKETPLACE_PRERELEASES", "GLPI_NETWORK_REGISTRATION_API_URL", "GLPI_NETWORK_MAIL", "GLPI_NETWORK_SERVICES", "GLPI_PICTURE_DIR", "GLPI_PLUGIN_DOC_DIR", "GLPI_RSS_DIR", "GLPI_SESSION_DIR", "GLPI_TELEMETRY_URI", "GLPI_TMP_DIR", "GLPI_UPLOAD_DIR", "GLPI_USE_CSRF_CHECK", "GLPI_USER_AGENT_EXTRA_COMMENTS",
"// GLPI optionnal constants",
"GLPI_FORCE_MAIL", "GLPI_LOG_LVL",
......
......@@ -72,11 +72,12 @@ include_once (GLPI_ROOT . "/inc/autoload.function.php");
'GLPI_UPLOAD_DIR' => '{GLPI_VAR_DIR}/_uploads', // Path for upload storage
// Security constants
'GLPI_USE_CSRF_CHECK' => '1',
'GLPI_CSRF_EXPIRES' => '7200',
'GLPI_CSRF_MAX_TOKENS' => '100',
'GLPI_USE_IDOR_CHECK' => '1',
'GLPI_IDOR_EXPIRES' => '7200',
'GLPI_USE_CSRF_CHECK' => '1',
'GLPI_CSRF_EXPIRES' => '7200',
'GLPI_CSRF_MAX_TOKENS' => '100',
'GLPI_USE_IDOR_CHECK' => '1',
'GLPI_IDOR_EXPIRES' => '7200',
'GLPI_ALLOW_IFRAME_IN_RICH_TEXT' => false,
// Constants related to GLPI Project / GLPI Network external services
'GLPI_TELEMETRY_URI' => 'https://telemetry.glpi-project.org', // Telemetry project URL
......
......@@ -88,18 +88,13 @@ class Html {
// Neutralize not well formatted html tags
$value = preg_replace("/(<)([^>]*<)/", "&lt;$2", $value);
$value = htmLawed(
$value,
[
'elements' => ($striptags) ? 'none' : '',
'deny_attribute' => 'on*',
'keep_bad' => $keep_bad, // 1: neutralize tag and content, 2 : remove tag and neutralize content
'comment' => 1, // 1: remove
'cdata' => 1, // 1: remove
'direct_list_nest' => 1, // 1: Allow usage of ul/ol tags nested in other ul/ol tags
'schemes' => '*: aim, app, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, tel, telnet'
]
);
$config = Toolbox::getHtmLawedSafeConfig();
$config['keep_bad'] = $keep_bad; // 1: neutralize tag and content, 2 : remove tag and neutralize content
if ($striptags) {
$config['elements'] = 'none';
}
$value = htmLawed($value, $config);
// Special case : remove the 'denied:' for base64 img in case the base64 have characters
// combinaison introduce false positive
......
......@@ -429,11 +429,7 @@ class Toolbox {
$value = str_replace($complete, $cleancomplete, $value);
}
$config = ['safe'=>1];
$config["elements"] = "*+iframe+audio+video";
$config["direct_list_nest"] = 1;
$value = htmLawed($value, $config);
$value = htmLawed($value, self::getHtmLawedSafeConfig());
// Special case : remove the 'denied:' for base64 img in case the base64 have characters
// combinaison introduce false positive
......@@ -446,6 +442,29 @@ class Toolbox {
return $value;
}
/**
* Returns a safe configuration for htmLawed.
*
* @return array
*
* @since 9.5.4
*/
public static function getHtmLawedSafeConfig(): array {
$config = [
'elements' => '* -applet -canvas -embed -object -script',
'deny_attribute' => 'on*',
'comment' => 1, // 1: remove HTML comments (and do not display their contents)
'cdata' => 1, // 1: remove CDATA sections (and do not display their contents)
'direct_list_nest' => 1, // 1: Allow usage of ul/ol tags nested in other ul/ol tags
'schemes' => '*: aim, app, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, tel, telnet'
];
if (!GLPI_ALLOW_IFRAME_IN_RICH_TEXT) {
$config['elements'] .= '-iframe';
}
return $config;
}
/**
* Log in 'php-errors' all args
*
......
......@@ -158,7 +158,19 @@ class Html extends \GLPITestCase {
public function providerClean() {
return [
['<p>Hello<script type="text/javascript">alert("Damn!");</script></p>', 'Hello', '<p>Hello</p>'],
// script is not allowed
['<p>Hello<script type="text/javascript">alert("Damn!");</script></p>', 'Hello', '<p>Hello</p>'],
// nested list should be preserved
['<ul><li>one<ul><li>nested</li></ul></li><li>two</li></ul>', 'onenestedtwo', '<ul><li>one<ul><li>nested</li></ul></li><li>two</li></ul>'],
// on* attributes are not allowed
['<img src="test.png" onerror="javascript:alert(document.cookie);" alt="test image" />', '', '<img src="test.png" alt="test image" />'],
['<img src="test.png" onload="javascript:alert(document.cookie);" alt="test image" />', '', '<img src="test.png" alt="test image" />'],
// iframes should not be preserved by default
['Here is an iframe: <iframe src="http://glpi-project.org/"></iframe>', 'Here is an iframe:', 'Here is an iframe:'],
// HTML comments should be removed
['<p>Legit<!-- This is an HTML comment --> text</p>', 'Legit text', '<p>Legit text</p>'],
// CDATA should be removed
['<p><![CDATA[Some CDATA]]>Legit text</p>', 'Legit text', '<p>Legit text</p>'],
];
}
......
......@@ -499,10 +499,34 @@ class Toolbox extends \GLPITestCase {
protected function cleanHtmlProvider() {
$dataset = $this->cleanProvider();
// nested list should be preserved
$dataset[] = [
'<div>Here a list example: <ul><li>one, with nested<ul><li>nested list</li></ul></li><li>two</li></ul></div>',
'&lt;div&gt;Here a list example: &lt;ul&gt;&lt;li&gt;one, with nested&lt;ul&gt;&lt;li&gt;nested list&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;two&lt;/li&gt;&lt;/ul&gt;'
];
// on* attributes are not allowed
$dataset[] = [
'<img src="test.png" alt="test image" />',
'&lt;img src="test.png" alt="test image" onerror="javascript:alert(document.cookie);" /&gt;'
];
$dataset[] = [
'<img src="test.png" alt="test image" />',
'&lt;img src="test.png" alt="test image" onload="javascript:alert(document.cookie);" /&gt;'
];
// iframes should not be preserved by default
$dataset[] = [
'Here is an iframe: ', 'Here is an iframe: &lt;iframe src="http://glpi-project.org/"&gt;&lt;/iframe&gt;'
];
// HTML comments should be removed
$dataset[] = [
['<div>Here a list example: <pre>&lt;ul&gt;&lt;li&gt;one&lt;/li&gt;&lt;li&gt;two&lt;/li&gt;&lt;/ul&gt;</pre></div>'],
['&lt;div&gt;Here a list example: &lt;pre&gt;&lt;ul&gt;&lt;li&gt;one&lt;/li&gt;&lt;li&gt;two&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;']
'<p>Legit text</p>', '&lt;p&gt;Legit&lt;!-- This is an HTML comment --&gt; text&lt;/p&gt;'
];
// CDATA should be removed
$dataset[] = [
'<p>Legit text</p>', '&lt;p&gt;Legit&lt;![CDATA[Some CDATA]]&gt; text&lt;/p&gt;'
];
return $dataset;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment