CVE-2016-9457 (PHP, published 2017-03-28T02:59Z)
Description: value: Revive Adserver before 3.2.3 suffers from Reflected XSS. `www/admin/stats.php` is vulnerable to reflected XSS attacks via multiple parameters that are not properly sanitised or escaped when displayed, such as setPerPage, pageId, bannerid, period_start, period_end, and possibly others.
Severity: LOW (CVSS v3 base score: 5.4)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/revive-adserver/revive-adserver
Files changed:
lib/max/other/html.php
lib/templates/admin/layout/links-container.html
www/admin/stats-conversions.php
Commit message: Fix h1 report 107879

Reflected XSS
-------------

Johan Caluwe has reported via HackerOne that www/admin/stats.php was
vulnerable to reflected XSS attacks via multiple parameters that were not
properly sanitised or escaped when displayed, such as "setPerPage", "pageId",
"bannerid", "pereiod_start", "period_end" and possibly others.

A CVE-ID has been requested, but not assigned yet.

CWE: CWE-79
CVSSv2: 5.6 (AV:N/AC:H/Au:S/C:C/I:P/A:N)


Vulnerable code:
    $entity = _getEntityString($entityIds);
    return $showColumn ? "<b><a href='$pageName?{$entity}listorder=$name'>$title</a>$str</b>" : '';
            $entityArr[] = "$entityId=$entityValue";
        $entity = implode('&',$entityArr) . '&';
            			<a href='{$aLinks[linkLoop].url}' {if $aLinks[linkLoop].iconClass}class='inlineIcon {$aLinks[linkLoop].iconClass}'{/if} {if $aLinks[linkLoop].accesskey}accesskey='{$aLinks[linkLoop].accesskey}'{/if} {$aLinks[linkLoop].extraAttr}>{$aLinks[linkLoop].title}</a>
$clientId       = MAX_getValue('clientid');
$campaignId     = MAX_getValue('campaignid');
$bannerId       = MAX_getValue('bannerid');

$affiliateId    = MAX_getValue('affiliateid');
$zoneId         = MAX_getValue('zoneid');

if (OA_Permission::isAccount(OA_ACCOUNT_ADVERTISER)) {
    $clientId = $clientid = OA_Permission::getEntityId();
} elseif (OA_Permission::isAccount(OA_ACCOUNT_TRAFFICKER)) {
    $affiliateId = $affiliateid = OA_Permission::getEntityId();
    'campaignid'  => $campaignId,
    'bannerid'    => $bannerId,
    'affiliateid' => $affiliateId,
    'zoneid'      => $zoneId,
$addUrl = "entity=conversions&clientid=$clientId&campaignid=$campaignId&bannerid=$bannerId&affiliateid=$affiliateId&zoneid=$zoneId&setPerPage=$setPerPage&pageID=$pageID";
    $addUrl .= "&day={$day}&hour={$hour}&howLong={$howLong}";
    $addUrl .= "&period_preset={$period_preset}&period_start={$period_start}&period_end={$period_end}";
    'clientid' => $clientId,
    'campaignid' => $campaignId,
    'bannerid' => $bannerId,
    'affiliateid' => $affiliateId,
    'zoneid' => $zoneId,
$aParams['clientid']    = $clientId;
$aParams['campaignid']  = $campaignId;
$aParams['bannerid']    = $bannerId;
if (empty($zoneId) && !empty($affiliateId)) {
    $aZonesIds = Admin_DA::fromCache('getZonesIdsByAffiliateId', $affiliateId);
if(!empty($zoneId)) {
    $aZonesIds = array($zoneId);
        echo "<input type='hidden' name='clientid' value='$clientId'>"."\n";
        echo "<input type='hidden' name='campaignid' value='$campaignId'>"."\n";
        echo "<input type='hidden' name='bannerid' value='$bannerId'>"."\n";
        echo "<input type='hidden' name='affiliateid' value='$affiliateId'>"."\n";
        echo "<input type='hidden' name='zoneid' value='$zoneId'>"."\n";
        echo "<input type='hidden' name='day' value='$day'>"."\n";
        echo "<input type='hidden' name='hour' value='$hour'>"."\n";
        echo "<input type='hidden' name='howLong' value='$howLong'>"."\n";
        echo "<input type='hidden' name='period_preset' value='$period_preset'>"."\n";
            echo "<input type='hidden' name='period_start' value='$period_start'>"."\n";
            echo "<input type='hidden' name='period_end' value='$period_end'>"."\n";
        echo "<input type='hidden' name='setPerPage' value='$setPerPage'>"."\n";
        echo "<input type='hidden' name='pageID' value='$pageID'>"."\n";
                echo "&nbsp;<a href='$pageName?collapse=a$conversionId&$addUrl'><img src='" . OX::assetPath() . "/images/triangle-d.gif' align='absmiddle' border='0'></a>&nbsp;";
                echo "&nbsp;<a href='$pageName?expand=a$conversionId&$addUrl'><img src='" . OX::assetPath() . "/images/$phpAds_TextDirection/triangle-l.gif' align='absmiddle' border='0'></a>&nbsp;";
            <td colspan='2' align='$phpAds_TextAlignRight' nowrap><img src='" . OX::assetPath() . "/images/triangle-d.gif' align='absmiddle' border='0'>&nbsp;<a href='$pageName?$addUrl&amp;expand=all' accesskey='$keyExpandAll'>$strExpandAll</a>&nbsp;&nbsp;|&nbsp;&nbsp;<img src='" . OX::assetPath() . "/images/$phpAds_TextDirection/triangle-l.gif' align='absmiddle' border='0'>&nbsp;<a href='$pageName?$addUrl&amp;expand=none' accesskey='$keyCollapseAll'>$strCollapseAll</a>&nbsp;&nbsp;</td>
    echo "<form id='setPager' method='get' action='stats.php?".htmlentities($_SERVER['QUERY_STRING'])."'>";

Fixed code:
    $entity = htmlspecialchars(_getEntityString($entityIds), ENT_QUOTES);
    $pageName = htmlspecialchars($pageName, ENT_QUOTES);
    return $showColumn ? "<b><a href='$pageName?{$entity}listorder=".urlencode($name)."'>$title</a>$str</b>" : '';
            $entityArr[] = "$entityId=".urlencode($entityValue);
        $entity = implode('&', $entityArr) . '&';
                        <a href='{$aLinks[linkLoop].url|escape}' {if $aLinks[linkLoop].iconClass}class='inlineIcon {$aLinks[linkLoop].iconClass}'{/if} {if $aLinks[linkLoop].accesskey}accesskey='{$aLinks[linkLoop].accesskey}'{/if} {$aLinks[linkLoop].extraAttr}>{$aLinks[linkLoop].title}</a>
if ($clientid) {
    OA_Permission::enforceAccessToObject('clients', $clientid);
}
if ($campaignid) {
    OA_Permission::enforceAccessToObject('campaigns', $campaignid);
}
if ($bannerid) {
    OA_Permission::enforceAccessToObject('banners', $bannerid);
}
if ($affiliateid) {
    OA_Permission::enforceAccessToObject('affiliates', $clientid);
}
if ($zoneid) {
    OA_Permission::enforceAccessToObject('zones', $zoneid);
    'campaignid'  => $campaignid,
    'bannerid'    => $bannerid,
    'affiliateid' => $affiliateid,
    'zoneid'      => $zoneid,
$addUrl = "entity=conversions&clientid=$clientid&campaignid=$campaignid&bannerid=$bannerid&affiliateid=$affiliateid&zoneid=$zoneid&setPerPage=$setPerPage&pageID=$pageID";
    $addUrl .= "&day=".urlencode($day)."&hour=".urlencode($hour)."&howLong=".urlencode($howLong);
    $addUrl .= "&period_preset=".urlencode($period_preset)."&period_start=".urlencode($period_start)."&period_end=".urlencode($period_end);
    'clientid' => $clientid,
    'campaignid' => $campaignid,
    'bannerid' => $bannerid,
    'affiliateid' => $affiliateid,
    'zoneid' => $zoneid,
$aParams['clientid']    = $clientid;
$aParams['campaignid']  = $campaignid;
$aParams['bannerid']    = $bannerid;
if (empty($zoneid) && !empty($affiliateid)) {
    $aZonesIds = Admin_DA::fromCache('getZonesIdsByAffiliateId', $affiliateid);
if(!empty($zoneid)) {
    $aZonesIds = array($zoneid);
        echo "<input type='hidden' name='clientid' value='$clientid'>"."\n";
        echo "<input type='hidden' name='campaignid' value='$campaignid'>"."\n";
        echo "<input type='hidden' name='bannerid' value='$bannerid'>"."\n";
        echo "<input type='hidden' name='affiliateid' value='$affiliateid'>"."\n";
        echo "<input type='hidden' name='zoneid' value='$zoneid'>"."\n";
        echo "<input type='hidden' name='day' value='".htmlspecialchars($day, ENT_QUOTES)."'>"."\n";
        echo "<input type='hidden' name='hour' value='".htmlspecialchars($hour, ENT_QUOTES)."'>"."\n";
        echo "<input type='hidden' name='howLong' value='".htmlspecialchars($howLong, ENT_QUOTES)."'>"."\n";
        echo "<input type='hidden' name='period_preset' value='".htmlspecialchars($period_preset, ENT_QUOTES)."'>"."\n";
            echo "<input type='hidden' name='period_start' value='".htmlspecialchars($period_start, ENT_QUOTES)."'>"."\n";
            echo "<input type='hidden' name='period_end' value='".htmlspecialchars($period_end, ENT_QUOTES)."'>"."\n";
        echo "<input type='hidden' name='setPerPage' value='".htmlspecialchars($setPerPage, ENT_QUOTES)."'>"."\n";
        echo "<input type='hidden' name='pageID' value='".htmlspecialchars($pageID, ENT_QUOTES)."'>"."\n";
                echo "&nbsp;<a href='".htmlspecialchars("$pageName?collapse=a$conversionId&$addUrl", ENT_QUOTES)."'><img src='" . OX::assetPath() . "/images/triangle-d.gif' align='absmiddle' border='0'></a>&nbsp;";
                echo "&nbsp;<a href='".htmlspecialchars("$pageName?expand=a$conversionId&$addUrl", ENT_QUOTES)."'><img src='" . OX::assetPath() . "/images/$phpAds_TextDirection/triangle-l.gif' align='absmiddle' border='0'></a>&nbsp;";
            <td colspan='2' align='$phpAds_TextAlignRight' nowrap><img src='" . OX::assetPath() . "/images/triangle-d.gif' align='absmiddle' border='0'>&nbsp;<a href='".htmlspecialchars("$pageName?$addUrl&expand=all", ENT_QUOTES)."' accesskey='$keyExpandAll'>$strExpandAll</a>&nbsp;&nbsp;|&nbsp;&nbsp;<img src='" . OX::assetPath() . "/images/$phpAds_TextDirection/triangle-l.gif' align='absmiddle' border='0'>&nbsp;<a href='$pageName?$addUrl&amp;expand=none' accesskey='$keyCollapseAll'>$strCollapseAll</a>&nbsp;&nbsp;</td>
    echo "<form id='setPager' method='get' action='stats.php?".htmlspecialchars($_SERVER['QUERY_STRING'], ENT_QUOTES)."'>";