Fix cleaning html tags with trans and with GETPOST.

This commit is contained in:
Laurent Destailleur
2020-12-06 17:30:27 +01:00
parent 1f83e22aea
commit de61a7cfd3
7 changed files with 42 additions and 22 deletions

View File

@@ -1032,21 +1032,19 @@ class Contrat extends CommonObject
}
// Insert business contacts ('SALESREPFOLL','contrat')
if (!$error)
{
if (!$error) {
$result = $this->add_contact($this->commercial_suivi_id, 'SALESREPFOLL', 'internal');
if ($result < 0) $error++;
}
if (!$error)
{
if (!$error) {
if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) // To use new linkedObjectsIds instead of old linked_objects
{
$this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds
}
// Add object linked
if (!$error && $this->id && is_array($this->linked_objects) && !empty($this->linked_objects))
if (!$error && $this->id && !empty($this->linked_objects) && is_array($this->linked_objects))
{
foreach ($this->linked_objects as $origin => $tmp_origin_id)
{
@@ -1144,10 +1142,10 @@ class Contrat extends CommonObject
/**
* Supprime l'objet de la base
* Delete object
*
* @param User $user Utilisateur qui supprime
* @return int < 0 si erreur, > 0 si ok
* @param User $user User that deletes
* @return int < 0 if KO, > 0 if OK
*/
public function delete($user)
{

View File

@@ -1,5 +1,5 @@
<?php
/* Copyright (C) 2011-2015 Laurent Destailleur <eldy@users.sourceforge.net>
/* Copyright (C) 2011-2020 Laurent Destailleur <eldy@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -356,6 +356,9 @@ if ($action == 'update')
$visibility = GETPOST('list', 'alpha');
if ($type == 'separate') $visibility = 3;
// Example: is_object($object) ? ($object->id < 10 ? round($object->id / 2, 2) : (2 * $user->id) * (int) substr($mysoc->zip, 1, 2)) : 'objnotdefined'
$computedvalue = GETPOST('computed_value', 'nohtml');
$result = $extrafields->update(
GETPOST('attrname', 'aZ09'),
GETPOST('label', 'alpha'),
@@ -371,7 +374,7 @@ if ($action == 'update')
$visibility,
GETPOST('help', 'alpha'),
GETPOST('default_value', 'alpha'),
GETPOST('computed_value', 'alpha'),
$computedvalue,
(GETPOST('entitycurrentorall', 'alpha') ? 0 : ''),
GETPOST('langfile'),
GETPOST('enabled', 'alpha'),

View File

@@ -624,7 +624,7 @@ class Translate
// we want to keep '"' '<b>' '</b>' '<strong' '</strong>' '<a ' '</a>' '<br>' '< ' '<span' '</span>' that are reliable HTML tags inside translation strings.
$str = str_replace(
array('"', '<b>', '</b>', '<u>', '</u>', '<i>', '</i>', '<center>', '</center>', '<strong>', '</strong>', '<a ', '</a>', '<br>', '<span', '</span>', '< ', '>'), // We accept '< ' but not '<'. We can accept however '>'
array('__quot__', '__tagb__', '__tagbend__', '__tagu__', '__taguend__', '__tagi__', '__tagiend__', '__tagcenter__', '__tagcenterend__', '__tagb__', '__tagbend__', '__taga__', '__tagaend__', '__tagbr__', '__tagspan__', '__tagspanend__', '__lt__', '__gt__'),
array('__quot__', '__tagb__', '__tagbend__', '__tagu__', '__taguend__', '__tagi__', '__tagiend__', '__tagcenter__', '__tagcenterend__', '__tagb__', '__tagbend__', '__taga__', '__tagaend__', '__tagbr__', '__tagspan__', '__tagspanend__', '__ltspace__', '__gt__'),
$str
);
@@ -638,8 +638,8 @@ class Translate
// Restore reliable HTML tags into original translation string
$str = str_replace(
array('__quot__', '__tagb__', '__tagbend__', '__tagu__', '__taguend__', '__tagi__', '__tagiend__', '__tagcenter__', '__tagcenterend__', '__taga__', '__tagaend__', '__tagbr__', '__tagspan__', '__tagspanend__', '__lt__', '__gt__'),
array('"', '<b>', '</b>', '<u>', '</u>', '<i>', '</i>', '<center>', '</center>', '<a ', '</a>', '<br>', '<span', '</span>', '< ', '> '),
array('__quot__', '__tagb__', '__tagbend__', '__tagu__', '__taguend__', '__tagi__', '__tagiend__', '__tagcenter__', '__tagcenterend__', '__taga__', '__tagaend__', '__tagbr__', '__tagspan__', '__tagspanend__', '__ltspace__', '__gt__'),
array('"', '<b>', '</b>', '<u>', '</u>', '<i>', '</i>', '<center>', '</center>', '<a ', '</a>', '<br>', '<span', '</span>', '< ', '>'),
$str
);

View File

@@ -5701,9 +5701,11 @@ function dol_string_nohtmltag($stringtoclean, $removelinefeed = 1, $pagecodeto =
if ($removelinefeed == 2) $stringtoclean = preg_replace('/<br[^>]*>(\n|\r)+/ims', '<br>', $stringtoclean);
$temp = preg_replace('/<br[^>]*>/i', "\n", $stringtoclean);
// We remove entities BEFORE stripping (in case of a separator char is encoded and not the other, the strip will fails)
// We remove entities BEFORE stripping (in case of an open separator char that is entity encoded and not the closing other, the strip will fails)
$temp = dol_html_entity_decode($temp, ENT_COMPAT | ENT_HTML5, $pagecodeto);
$temp = str_replace('< ', '__ltspace__', $temp);
if ($strip_tags) {
$temp = strip_tags($temp);
} else {
@@ -5727,16 +5729,19 @@ function dol_string_nohtmltag($stringtoclean, $removelinefeed = 1, $pagecodeto =
}
}
$temp = str_replace('__ltspace__', '< ', $temp);
return trim($temp);
}
/**
* Clean a string to keep only desirable HTML tags.
* WARNING: This also clean HTML comments (used to obfuscate tag name).
*
* @param string $stringtoclean String to clean
* @param int $cleanalsosomestyles Remove absolute/fixed positioning from inline styles
* @param int $removeclassattribute Remove the class attribute from tags
* @param int $cleanalsojavascript Remove also occurence of (javascript:'
* @param int $cleanalsojavascript Remove also occurence of 'javascript:'.
* @return string String cleaned
*
* @see dol_escape_htmltag() strip_tags() dol_string_nohtmltag() dol_string_neverthesehtmltags()
@@ -5754,16 +5759,21 @@ function dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles = 1,
$stringtoclean = dol_string_nounprintableascii($stringtoclean, 0);
$stringtoclean = preg_replace('/&colon;/i', ':', $stringtoclean);
$stringtoclean = preg_replace('/<!--[^>]*-->/', '', $stringtoclean);
$stringtoclean = preg_replace('/&#58;|&#0000058|&#x3A/i', '', $stringtoclean); // refused string ':' encoded (no reason to have it encoded) to lock 'javascript:...'
$stringtoclean = preg_replace('/javascript\s*:/i', '', $stringtoclean);
$temp = strip_tags($stringtoclean, $allowed_tags_string);
if ($cleanalsosomestyles) { // Clean for remaining html tags
$stringtoclean = preg_replace('/position\s*:\s*(absolute|fixed)\s*!\s*important/i', '', $temp); // Note: If hacker try to introduce css comment into string to bypass this regex, the string must also be encoded by the dol_htmlentitiesbr during output so it become harmless
$temp = preg_replace('/position\s*:\s*(absolute|fixed)\s*!\s*important/i', '', $temp); // Note: If hacker try to introduce css comment into string to bypass this regex, the string must also be encoded by the dol_htmlentitiesbr during output so it become harmless
}
if ($removeclassattribute) { // Clean for remaining html tags
$stringtoclean = preg_replace('/(<[^>]+)\s+class=((["\']).*?\\3|\\w*)/i', '\\1', $temp);
$temp = preg_replace('/(<[^>]+)\s+class=((["\']).*?\\3|\\w*)/i', '\\1', $temp);
}
// Remove 'javascript:' that we should not find into a text with
// Warning: This is not reliable to fight against obfuscated javascript, there is a lot of other solution to include js into a common html tag (only filtered by the GETPOST).
if ($cleanalsojavascript) {
$temp = preg_replace('/javascript\s*:/i', '', $temp);
}

View File

@@ -1411,7 +1411,7 @@ class Holiday extends CommonObject
// Update each user counter
foreach ($users as $userCounter) {
$nbDaysToAdd = $typeleaves[$userCounter['type']]['newByMonth'];
$nbDaysToAdd = (isset($typeleaves[$userCounter['type']]['newByMonth']) ? $typeleaves[$userCounter['type']]['newByMonth'] : 0);
if (empty($nbDaysToAdd)) continue;
dol_syslog("We update leave type id ".$userCounter['type']." for user id ".$userCounter['rowid'], LOG_DEBUG);

View File

@@ -143,14 +143,14 @@ class FormTest extends PHPUnit\Framework\TestCase
$result=$localobject->select_produits_list('', 'productid', '', 5, 0, '', 1, 2, 1);
$this->assertEquals(count($result), 5);
print __METHOD__." result=".$result."\n";
print __METHOD__." count result=".count($result)."\n";
$conf->global->ENTREPOT_EXTRA_STATUS = 1;
// Exclude stock in warehouseinternal
$result=$localobject->select_produits_list('', 'productid', '', 5, 0, '', 1, 2, 1, 0, '1', 0, '', 0, 'warehouseclosed,warehouseopen');
$this->assertEquals(count($result), 5);
print __METHOD__." result=".$result."\n";
print __METHOD__." count result=".count($result)."\n";
return $result;
}

View File

@@ -285,9 +285,10 @@ class SecurityTest extends PHPUnit\Framework\TestCase
$_POST["param6"]="&quot;&gt;<svg o&#110;load='console.log(&quot;123&quot;)'&gt;";
$_GET["param7"]='"c:\this is a path~1\aaa&#110;" abc<bad>def</bad>';
$_POST["param8"]="Hacker<svg o&#110;load='console.log(&quot;123&quot;)'"; // html tag is not closed so it is not detected as html tag but is still harmfull
$_POST["param9"]='is_object($object) ? ($object->id < 10 ? round($object->id / 2, 2) : (2 * $user->id) * (int) substr($mysoc->zip, 1, 2)) : \'objnotdefined\'';
$_POST["param10"]='is_object($object) ? ($object->id < 10 ? round($object->id / 2, 2) : (2 * $user->id) * (int) substr($mysoc->zip, 1, 2)) : \'<abc>objnotdefined\'';
// Test int
$result=GETPOST('id', 'int'); // Must return nothing
$result=GETPOST('id', 'int'); // Must return nothing
print __METHOD__." result=".$result."\n";
$this->assertEquals($result, '');
@@ -347,6 +348,14 @@ class SecurityTest extends PHPUnit\Framework\TestCase
print __METHOD__." result=".$result."\n";
$this->assertEquals("Hacker<svg onload='console.log(123)'", $result);
$result=GETPOST("param9", 'alphanohtml');
print __METHOD__." result=".$result."\n";
$this->assertEquals($_POST["param9"], $result);
$result=GETPOST("param10", 'alphanohtml');
print __METHOD__." result=".$result."\n";
$this->assertEquals($_POST["param9"], $result, 'We should get param9 after processing param10');
return $result;
}