More fixes for Trac#446: XSS vulnerabilities with vectors containing double quotes

SVN:trunk[1563]
This commit is contained in:
Denis Flaven
2011-09-08 13:21:32 +00:00
parent 205e80f8a5
commit c4db9cd84e
17 changed files with 54 additions and 37 deletions

View File

@@ -265,7 +265,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
function DoShowGrantSumary($oPage)
{
if ($this->GetName() == "Administrator")
if ($this->GetRawName() == "Administrator")
{
// Looks dirty, but ok that's THE ONE
$oPage->p(Dict::S('UI:UserManagement:AdminProfile+'));

View File

@@ -97,7 +97,7 @@ class URP_Profiles extends UserRightsBaseClass
function DoShowGrantSumary($oPage)
{
if ($this->GetName() == "Administrator")
if ($this->GetRawName() == "Administrator")
{
// Looks dirty, but ok that's THE ONE
$oPage->p(Dict::S('UI:UserManagement:AdminProfile+'));

View File

@@ -163,7 +163,7 @@ class ApplicationContext
$sContext = "";
foreach($this->aValues as $sName => $sValue)
{
$sContext .= "<input type=\"hidden\" name=\"c[$sName]\" value=\"$sValue\" />\n";
$sContext .= "<input type=\"hidden\" name=\"c[$sName]\" value=\"".htmlentities($sValue)."\" />\n";
}
return $sContext;
}

View File

@@ -581,7 +581,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
$oTemplate = new DisplayTemplate($sTemplate);
// Note: to preserve backward compatibility with home-made templates, the placeholder '$pkey$' has been preserved
// but the preferred method is to use '$id$'
$oTemplate->Render($oPage, array('class_name'=> MetaModel::GetName(get_class($this)),'class'=> get_class($this), 'pkey'=> $this->GetKey(), 'id'=> $this->GetKey(), 'name' => $this->Get('friendlyname')));
$oTemplate->Render($oPage, array('class_name'=> MetaModel::GetName(get_class($this)),'class'=> get_class($this), 'pkey'=> $this->GetKey(), 'id'=> $this->GetKey(), 'name' => $this->GetName()));
}
else
{
@@ -1473,14 +1473,14 @@ EOF
$aEventsList[] ='validate';
$aEventsList[] ='keyup';
$aEventsList[] ='change';
$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"12\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iId\"/>&nbsp;{$sValidationField}";
$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"12\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($value)."\" id=\"$iId\"/>&nbsp;{$sValidationField}";
break;
case 'DateTime':
$aEventsList[] ='validate';
$aEventsList[] ='keyup';
$aEventsList[] ='change';
$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"20\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iId\"/>&nbsp;{$sValidationField}";
$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"20\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($value)."\" id=\"$iId\"/>&nbsp;{$sValidationField}";
break;
case 'Duration':
@@ -1495,7 +1495,7 @@ EOF
$sHours = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[h]{$sNameSuffix}\" value=\"{$aVal['hours']}\" id=\"{$iId}_h\"/>";
$sMinutes = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[m]{$sNameSuffix}\" value=\"{$aVal['minutes']}\" id=\"{$iId}_m\"/>";
$sSeconds = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[s]{$sNameSuffix}\" value=\"{$aVal['seconds']}\" id=\"{$iId}_s\"/>";
$sHidden = "<input type=\"hidden\" id=\"{$iId}\" value=\"$value\"/>";
$sHidden = "<input type=\"hidden\" id=\"{$iId}\" value=\"".htmlentities($value)."\"/>";
$sHTMLValue = Dict::Format('UI:DurationForm_Days_Hours_Minutes_Seconds', $sDays, $sHours, $sMinutes, $sSeconds).$sHidden."&nbsp;".$sValidationField;
$oPage->add_ready_script("$('#{$iId}').bind('update', function(evt, sFormId) { return ToggleDurationField('$iId'); });");
break;
@@ -1504,7 +1504,7 @@ EOF
$aEventsList[] ='validate';
$aEventsList[] ='keyup';
$aEventsList[] ='change';
$sHTMLValue = "<input title=\"$sHelpText\" type=\"password\" size=\"30\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iId\"/>&nbsp;{$sValidationField}";
$sHTMLValue = "<input title=\"$sHelpText\" type=\"password\" size=\"30\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($value)."\" id=\"$iId\"/>&nbsp;{$sValidationField}";
break;
case 'Text':
@@ -1528,7 +1528,7 @@ EOF
{
$sStyle = 'style="'.implode('; ', $aStyles).'"';
}
$sHTMLValue = "<table><tr><td><textarea class=\"resizable\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\" $sStyle>$sEditValue</textarea></td><td>{$sValidationField}</td></tr></table>";
$sHTMLValue = "<table><tr><td><textarea class=\"resizable\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\" $sStyle>".htmlentities($sEditValue)."</textarea></td><td>{$sValidationField}</td></tr></table>";
break;
case 'CaseLog':
@@ -1553,7 +1553,7 @@ EOF
$sPreviousLog = is_object($value) ? $value->GetAsHTML() : '';
$iEntriesCount = is_object($value) ? count($value->GetIndex()) : 0;
$sHidden = "<input type=\"hidden\" id=\"{$iId}_count\" value=\"$iEntriesCount\"/>"; // To know how many entries the case log already contains
$sHTMLValue = "<div class=\"caselog\" $sStyle><table style=\"width:100%;\"><tr><td>$sHeader<textarea style=\"border:0;width:100%\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\">$sEditValue</textarea>$sPreviousLog</td><td>{$sValidationField}</td></tr></table>$sHidden</div>";
$sHTMLValue = "<div class=\"caselog\" $sStyle><table style=\"width:100%;\"><tr><td>$sHeader<textarea style=\"border:0;width:100%\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\">".htmlentities($sEditValue)."</textarea>$sPreviousLog</td><td>{$sValidationField}</td></tr></table>$sHidden</div>";
$oPage->add_ready_script("$('#$iId').bind('keyup change validate', function(evt, sFormId) { return ValidateCaseLogField('$iId', $bMandatory, sFormId) } );"); // Custom validation function
break;
@@ -1580,7 +1580,7 @@ EOF
}
$iMaxFileSize = utils::ConvertToBytes(ini_get('upload_max_filesize'));
$sHTMLValue = "<input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"$iMaxFileSize\" />\n";
$sHTMLValue .= "<input name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}[filename]\" type=\"hidden\" id=\"$iId\" \" value=\"$sFileName\"/>\n";
$sHTMLValue .= "<input name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}[filename]\" type=\"hidden\" id=\"$iId\" \" value=\"".htmlentities($sFileName)."\"/>\n";
$sHTMLValue .= "<span id=\"name_$iInputId\">$sFileName</span><br/>\n";
$sHTMLValue .= "<input title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}[fcontents]\" type=\"file\" id=\"file_$iId\" onChange=\"UpdateFileName('$iId', this.value)\"/>&nbsp;{$sValidationField}\n";
break;
@@ -1654,7 +1654,7 @@ EOF
}
else
{
$sHTMLValue = "<input title=\"$sHelpText\" type=\"text\" size=\"30\" maxlength=\"$iFieldSize\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iId\"/>&nbsp;{$sValidationField}";
$sHTMLValue = "<input title=\"$sHelpText\" type=\"text\" size=\"30\" maxlength=\"$iFieldSize\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($value)."\" id=\"$iId\"/>&nbsp;{$sValidationField}";
$aEventsList[] ='keyup';
$aEventsList[] ='change';
}

View File

@@ -1034,7 +1034,7 @@ class HistoryBlock extends DisplayBlock
$aValues = array();
foreach($aChanges as $aChange)
{
$aValues[] = array('date' => $aChange['date'], 'userinfo' => $aChange['userinfo'], 'log' => "<ul><li>".implode('</li><li>', $aChange['log'])."</li></ul>");
$aValues[] = array('date' => $aChange['date'], 'userinfo' => htmlentities($aChange['userinfo']), 'log' => "<ul><li>".implode('</li><li>', $aChange['log'])."</li></ul>");
}
$sHtml .= $oPage->GetTable($aAttribs, $aValues);
return $sHtml;
@@ -1135,7 +1135,7 @@ class MenuBlock extends DisplayBlock
$this->AddMenuSeparator($aActions);
// Static menus: Email this page & CSV Export
$sUrl = ApplicationContext::MakeObjectUrl($sClass, $id);
$aActions['UI:Menu:EMail'] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=".$oObj->GetName()."&body=".urlencode($sUrl));
$aActions['UI:Menu:EMail'] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=".urlencode($oObj->GetRawName())."&body=".urlencode($sUrl));
$aActions['UI:Menu:CSVExport'] = array ('label' => Dict::S('UI:Menu:CSVExport'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=search&filter=$sFilter&format=csv{$sContext}");
}
$this->AddMenuSeparator($aActions);

View File

@@ -141,7 +141,6 @@ EOF
public function DisplayChangePwdForm($bFailedLogin = false)
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthPwd = utils::ReadParam('suggest_pwd', '', false, 'raw_data');
$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_VERSION);
$sInconsistenPwdMsg = Dict::S('UI:Login:RetypePwdDoesNotMatch');

View File

@@ -288,7 +288,7 @@ EOF
{
$aRow = array();
$aRow['key'] = '<a href="./index.php?operation=details&class='.get_class($oObj).'&id='.$oObj->GetKey().'">'.$oObj->Get('friendlyname').'</a>';
$aRow['key'] = '<a href="./index.php?operation=details&class='.get_class($oObj).'&id='.$oObj->GetKey().'">'.$oObj->GetName().'</a>';
$sHilightClass = $oObj->GetHilightClass();
if ($sHilightClass != '')
{

View File

@@ -133,7 +133,7 @@ class UIExtKeyWidget
$aAllowedValues = array();
while($oObj = $oAllowedValues->Fetch())
{
$aAllowedValues[$oObj->GetKey()] = $oObj->Get('friendlyname');
$aAllowedValues[$oObj->GetKey()] = $oObj->GetName();
}
$sHTMLValue = $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", $bMandatory, $bVertical, $sValidationField);
$aEventsList[] ='change';
@@ -159,7 +159,7 @@ class UIExtKeyWidget
while($oObj = $oAllowedValues->Fetch())
{
$key = $oObj->GetKey();
$display_value = $oObj->Get('friendlyname');
$display_value = $oObj->GetName();
if (($oAllowedValues->Count() == 1) && ($bMandatory == 'true') )
{
@@ -326,11 +326,11 @@ EOF
{
throw new Exception('Implementation: null value for allowed values definition');
}
$oValuesSet = new ValueSetObjects($sFilter);
$oValuesSet = new ValueSetObjects($sFilter, 'friendlyname'); // Bypass GetName() to avoid the encoding by htmlentities
$aValues = $oValuesSet->GetValues(array('this' => $oObj), $sContains);
foreach($aValues as $sKey => $sFriendlyName)
{
$oP->add(trim($sFriendlyName)."|".$sKey."\n");
$oP->add(trim($sFriendlyName)."\t".$sKey."\n");
}
}

View File

@@ -85,7 +85,7 @@ class UILinksWizard
$sTargetClass = $oAttDef->GetTargetClass();
$oTargetObj = MetaModel::GetObject($sTargetClass, $this->m_iObjectId);
$oP->set_title("iTop - ".MetaModel::GetName($this->m_sLinkedClass)." objects linked with ".MetaModel::GetName(get_class($oTargetObj)).": ".$oTargetObj->GetName());
$oP->set_title("iTop - ".MetaModel::GetName($this->m_sLinkedClass)." objects linked with ".MetaModel::GetName(get_class($oTargetObj)).": ".$oTargetObj->GetRawName());
$oP->add("<div class=\"wizContainer\">\n");
$oP->add("<form method=\"post\">\n");
$oP->add("<div class=\"page_header\">\n");

View File

@@ -622,7 +622,23 @@ abstract class DBObject
return MetaModel::GetClassIcon(get_class($this), $bImgTag);
}
/**
* Gets the name of an object in a safe manner for displaying inside a web page
* @return string
*/
public function GetName()
{
return htmlentities($this->GetRawName(), ENT_QUOTES, 'UTF-8');
}
/**
* Gets the raw name of an object, this is not safe for displaying inside a web page
* since the " < > characters are not escaped and the name may contain some XSS script
* instructions.
* Use this function only for internal computations or for an output to a non-HTML destination
* @return string
*/
public function GetRawName()
{
return $this->Get('friendlyname');
}

View File

@@ -251,7 +251,7 @@ class ValueSetRelatedObjectsFromLinkSet extends ValueSetDefinition
}
// #@# or AddObjectArray($aObjects) ?
$oSetToCreate = DBObjectSet::FromArray($this->m_sTargetLinkClass, $aLinksToCreate);
$this->m_aValues[$oObject->GetKey()] = $oObject->GetAsHTML($oObject->GetName());
$this->m_aValues[$oObject->GetKey()] = $oObject->GetName();
}
return true;

View File

@@ -354,7 +354,7 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
if (me.bSelectMode)
{
// Add the newly created object to the drop-down list and select it
$('<option/>', { value : data.id }).text(data.name).appendTo('#'+me.id);
$('<option/>', { value : data.id }).html(data.name).appendTo('#'+me.id);
$('#'+me.id+' option[value="'+data.id+'"]').attr('selected', 'selected');
$('#'+me.id).focus();
}

View File

@@ -388,7 +388,7 @@ $.Autocompleter = function(input, options) {
for (var i=0; i < rows.length; i++) {
var row = $.trim(rows[i]);
if (row) {
row = row.split("|");
row = row.split("\t");
parsed[parsed.length] = {
data: row,
value: row[0],
@@ -668,6 +668,8 @@ $.Autocompleter.Select = function (options, input, select, config) {
var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
if ( formatted === false )
continue;
// Escape dangerous characters to prevent XSS vulnerabilities
formatted = formatted.replace('&', '&amp;').replace('"', '&quot;').replace('>', '&gt;').replace('<', '&lt;');
var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
$.data(li, "ac_data", data[i]);
}

View File

@@ -424,7 +424,7 @@ function DisplayDetails($oP, $sClass, $oObj, $id)
{
throw new SecurityException('User not allowed to view this object', array('class' => $sClass, 'id' => $id));
}
$oP->set_title(Dict::Format('UI:DetailsPageTitle', $oObj->GetName(), $sClassLabel));
$oP->set_title(Dict::Format('UI:DetailsPageTitle', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
$oObj->DisplayDetails($oP);
}
@@ -780,7 +780,7 @@ try
throw new SecurityException('User not allowed to modify this object', array('class' => $sClass, 'id' => $id));
}
// Note: code duplicated to the case 'apply_modify' when a data integrity issue has been found
$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetName(), $sClassLabel));
$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
$oP->add("<div class=\"page_header\">\n");
$oP->add("<h1>".$oObj->GetIcon()."&nbsp;".Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $oObj->GetName())."</h1>\n");
$oP->add("</div>\n");
@@ -1226,7 +1226,7 @@ EOF
}
elseif (!utils::IsTransactionValid($sTransactionId, false))
{
$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetName(), $sClassLabel));
$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
$oP->p("<strong>".Dict::S('UI:Error:ObjectAlreadyUpdated')."</strong>\n");
}
else
@@ -1236,7 +1236,7 @@ EOF
if (!$oObj->IsModified())
{
$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetName(), $sClassLabel));
$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
$oP->p(Dict::Format('UI:Class_Object_NotUpdated', MetaModel::GetName(get_class($oObj)), $oObj->GetName()));
}
else
@@ -1244,7 +1244,7 @@ EOF
list($bRes, $aIssues) = $oObj->CheckToWrite();
if ($bRes)
{
$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetName(), $sClassLabel));
$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
$oP->add("<h1>".Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $oObj->GetName())."</h1>\n");
$oMyChange = MetaModel::NewObject("CMDBChange");
@@ -1262,7 +1262,7 @@ EOF
$bDisplayDetails = false;
// Found issues, explain and give the user a second chance
//
$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetName(), $sClassLabel));
$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
$oP->add("<div class=\"page_header\">\n");
$oP->add("<h1>".$oObj->GetIcon()."&nbsp;".Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $oObj->GetName())."</h1>\n");
$oP->add("</div>\n");

View File

@@ -199,7 +199,7 @@ try
while($oAuditRule = $oRulesSet->fetch() )
{
$aRow = array();
$aRow['description'] = $oAuditRule->Get('name');
$aRow['description'] = $oAuditRule->GetName();
if ($iCount == 0)
{
// nothing to check, really !

View File

@@ -77,8 +77,8 @@ function GetRelatedObjectsAsXml(DBObject $oObj, $sRelationName, &$oLinks, &$oXml
$oLinkedNode = $oXmlDoc->CreateElement('node');
$oLinkedNode->SetAttribute('id', $oTargetObj->GetKey());
$oLinkedNode->SetAttribute('obj_class', get_class($oTargetObj));
$oLinkedNode->SetAttribute('obj_class_name', MetaModel::GetName(get_class($oTargetObj)));
$oLinkedNode->SetAttribute('name', $oTargetObj->GetName());
$oLinkedNode->SetAttribute('obj_class_name', htmlspecialchars(MetaModel::GetName(get_class($oTargetObj))));
$oLinkedNode->SetAttribute('name', htmlspecialchars($oTargetObj->GetRawName())); // htmlentities is too much for XML
$oLinkedNode->SetAttribute('icon', BuildIconPath($oTargetObj->GetIcon(false /* No IMG tag */)));
AddNodeDetails($oLinkedNode, $oTargetObj);
$oSubLinks = $oXmlDoc->CreateElement('links');
@@ -158,15 +158,15 @@ try
$oXmlNode = $oXmlDoc->CreateElement('node');
$oXmlNode->SetAttribute('id', $oObj->GetKey());
$oXmlNode->SetAttribute('obj_class', get_class($oObj));
$oXmlNode->SetAttribute('obj_class_name', MetaModel::GetName(get_class($oObj)));
$oXmlNode->SetAttribute('name', $oObj->GetName());
$oXmlNode->SetAttribute('obj_class_name', htmlspecialchars(MetaModel::GetName(get_class($oObj))));
$oXmlNode->SetAttribute('name', htmlspecialchars($oObj->GetRawName()));
$oXmlNode->SetAttribute('icon', BuildIconPath($oObj->GetIcon(false /* No IMG tag */))); // Hard coded for the moment
AddNodeDetails($oXmlNode, $oObj);
$oLinks = $oXmlDoc->CreateElement("links");
$oXmlRoot->SetAttribute('position', 'left');
$oXmlRoot->SetAttribute('title', MetaModel::GetRelationDescription($sRelation).' '.$oObj->GetName());
$oXmlRoot->SetAttribute('title', MetaModel::GetRelationDescription($sRelation).' '. htmlspecialchars($oObj->GetRawName()));
GetRelatedObjectsAsXml($oObj, $sRelation, $oLinks, $oXmlDoc, $oXmlNode);
$oXmlRoot->AppendChild($oXmlNode);

View File

@@ -135,7 +135,7 @@ class WebServiceResult
{
$this->m_aResult[$sLabel] = array(
'id' => $oObject->GetKey(),
'name' => $oObject->GetName(),
'name' => $oObject->GetRawName(),
'url' => $oObject->GetHyperlink(),
);
}