Example #1
0
/**
 * Detects typical XSS attack patterns
 * @param string str String to search for XSS attack vectors
 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
 * @return array Array of matches, empty on clean string
 */
function clean_xss($str, $cleanImg = true)
{
    global $sugar_config;
    if (empty($sugar_config['email_xss'])) {
        $sugar_config['email_xss'] = getDefaultXssTags();
    }
    $arr = unserialize(base64_decode($sugar_config['email_xss']));
    $regex = '';
    foreach ($arr as $v) {
        if (!empty($regex)) {
            $regex .= "|";
        }
        $regex .= $v;
    }
    $tag_regex = "#<({$regex})[^>]*>?#sim";
    // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
    $jsEvents = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
    $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
    $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror|ondragdrop";
    $attribute_regex = "#<.+({$jsEvents})[^=>]*=[^>]*>#sim";
    $javascript_regex = '@<[^/>][^>]+(expression\\(|j\\W*a\\W*v\\W*a|v\\W*b\\W*s\\W*c\\W*r|&#|/\\*|\\*/)[^>]*>@sim';
    $imgsrc_regex = '#<[^>]+src[^=]*=([^>]*?http(s)?://[^>]*)>#sim';
    $css_url = '#url\\(.*\\.\\w+\\)#';
    $str = str_replace("\t", "", $str);
    $matches = array_merge(xss_check_pattern($tag_regex, $str), xss_check_pattern($javascript_regex, $str));
    $jsMatches = xss_check_pattern($attribute_regex, $str);
    if (!empty($jsMatches)) {
        preg_match_all($attribute_regex, $str, $newMatches, PREG_PATTERN_ORDER);
        if (!empty($newMatches[0][0])) {
            $matches2 = array_merge(xss_check_pattern("#({$jsEvents})#sim", $newMatches[0][0]));
            $matches = array_merge($matches, $matches2);
        }
    }
    if ($cleanImg) {
        $matches = array_merge($matches, xss_check_pattern($imgsrc_regex, $str));
    }
    // cn: bug 13498 - custom white-list of allowed domains that vet remote images
    preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
    if (isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
        if (is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
            // normalize whitelist
            foreach ($sugar_config['security_trusted_domains'] as $k => $v) {
                $sugar_config['security_trusted_domains'][$k] = strtolower($v);
            }
            foreach ($cssUrlMatches[0] as $match) {
                $domain = strtolower(substr(strstr($match, "://"), 3));
                $baseUrl = substr($domain, 0, strpos($domain, "/"));
                if (!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
                    $matches[] = $match;
                }
            }
        }
    } else {
        $matches = array_merge($matches, $cssUrlMatches[0]);
    }
    return $matches;
}
Example #2
0
/**
 * Detects typical XSS attack patterns
 * @deprecated
 * @param string str String to search for XSS attack vectors
 * @param bool cleanImg Flag to allow <img> tags to survive - only used by InboundEmail for inline images.
 * @return array Array of matches, empty on clean string
 */
function clean_xss($str, $cleanImg = true)
{
    global $sugar_config;
    if (empty($sugar_config['email_xss'])) {
        $sugar_config['email_xss'] = getDefaultXssTags();
    }
    $xsstags = unserialize(base64_decode($sugar_config['email_xss']));
    // cn: bug 13079 - "on\w" matched too many non-events (cONTact, strONG, etc.)
    $jsEvents = "onblur|onfocus|oncontextmenu|onresize|onscroll|onunload|ondblclick|onclick|";
    $jsEvents .= "onmouseup|onmouseover|onmousedown|onmouseenter|onmouseleave|onmousemove|onload|onchange|";
    $jsEvents .= "onreset|onselect|onsubmit|onkeydown|onkeypress|onkeyup|onabort|onerror|ondragdrop";
    $attribute_regex = "#\\b({$jsEvents})\\s*=\\s*(?|(?!['\"])\\S+|['\"].+?['\"])#sim";
    $javascript_regex = '@<[^/>][^>]+(expression\\(|j\\W*a\\W*v\\W*a|v\\W*b\\W*s\\W*c\\W*r|&#|/\\*|\\*/)[^>]*>@sim';
    $imgsrc_regex = '#<[^>]+src[^=]*=([^>]*?http(s)?://[^>]*)>#sim';
    $css_url = '#url\\(.*\\.\\w+\\)#';
    $tagsrex = '#<\\/?(\\w+)((?:\\s+(?:\\w|\\w[\\w-]*\\w)(?:\\s*=\\s*(?:\\".*?\\"|\'.*?\'|[^\'\\">\\s]+))?)+\\s*|\\s*)\\/?>#im';
    $tagmatches = array();
    $matches = array();
    preg_match_all($tagsrex, $str, $tagmatches, PREG_PATTERN_ORDER);
    foreach ($tagmatches[1] as $no => $tag) {
        if (in_array($tag, $xsstags)) {
            // dangerous tag - take out whole
            $matches[] = $tagmatches[0][$no];
            continue;
        }
        $attrmatch = array();
        preg_match_all($attribute_regex, $tagmatches[2][$no], $attrmatch, PREG_PATTERN_ORDER);
        if (!empty($attrmatch[0])) {
            $matches = array_merge($matches, $attrmatch[0]);
        }
    }
    $matches = array_merge($matches, xss_check_pattern($javascript_regex, $str));
    if ($cleanImg) {
        $matches = array_merge($matches, xss_check_pattern($imgsrc_regex, $str));
    }
    // cn: bug 13498 - custom white-list of allowed domains that vet remote images
    preg_match_all($css_url, $str, $cssUrlMatches, PREG_PATTERN_ORDER);
    if (isset($sugar_config['security_trusted_domains']) && !empty($sugar_config['security_trusted_domains']) && is_array($sugar_config['security_trusted_domains'])) {
        if (is_array($cssUrlMatches) && count($cssUrlMatches) > 0) {
            // normalize whitelist
            foreach ($sugar_config['security_trusted_domains'] as $k => $v) {
                $sugar_config['security_trusted_domains'][$k] = strtolower($v);
            }
            foreach ($cssUrlMatches[0] as $match) {
                $domain = strtolower(substr(strstr($match, "://"), 3));
                $baseUrl = substr($domain, 0, strpos($domain, "/"));
                if (!in_array($baseUrl, $sugar_config['security_trusted_domains'])) {
                    $matches[] = $match;
                }
            }
        }
    } else {
        $matches = array_merge($matches, $cssUrlMatches[0]);
    }
    return $matches;
}