Пример #1
0
    /**
     * @param array $failedParams
     * @param string $highlightParamFormat
     * @param string $highlightMatchFormat
     * @return string
     */
    public function highlightFailedParams($failedParams = array(), $highlightParamFormat = '[param]%s[/param]', $highlightMatchFormat = '[match]%s[/match]')
    {
        $highlights = array();
        // Cap at 50kb
        $maxRequestLen = 1024 * 50;
        $this->highlightParamFormat = $highlightParamFormat;
        $this->highlightMatchFormat = $highlightMatchFormat;
        if (is_array($failedParams)) {
            foreach ($failedParams as $paramKey => $categories) {
                foreach ($categories as $categoryKey => $failedRules) {
                    foreach ($failedRules as $failedRule) {
                        $rule = $failedRule['rule'];
                        /** @var wfWAFRuleComparisonFailure $failedComparison */
                        $failedComparison = $failedRule['failedComparison'];
                        $action = $failedRule['action'];
                        $paramKey = $failedComparison->getParamKey();
                        if (preg_match('/request\\.([a-z0-9]+)(?:\\[(.*?)\\](.*?))?$/i', $paramKey, $matches)) {
                            $global = $matches[1];
                            if (method_exists('wfWAFRequestInterface', "get" . ucfirst($global))) {
                                $highlight = array('match' => $failedComparison->getMatches());
                                if (isset($matches[2])) {
                                    $highlight['param'] = "{$matches['2']}{$matches['3']}";
                                }
                                $highlights[$global][] = $highlight;
                            }
                        }
                    }
                }
            }
        }
        $uri = $this->getURI();
        $queryStringPos = wfWAFUtils::strpos($uri, '?');
        if ($queryStringPos !== false) {
            $uri = wfWAFUtils::substr($uri, 0, $queryStringPos);
        }
        $queryString = $this->getQueryString();
        if ($queryString) {
            $uri .= '?' . http_build_query($queryString);
        }
        if (!empty($highlights['queryString'])) {
            foreach ($highlights['queryString'] as $matches) {
                if (!empty($matches['param'])) {
                    $this->highlightMatches = $matches['match'];
                    $uri = preg_replace_callback('/(&|\\?|^)(' . preg_quote(urlencode($matches['param']), '/') . ')=(.*?)(&|$)/', array($this, 'highlightParam'), $uri);
                }
            }
        }
        if (!empty($highlights['uri'])) {
            foreach ($highlights['uri'] as $matches) {
                if ($matches) {
                }
            }
            $uri = sprintf($highlightParamFormat, $uri);
        }
        $request = "{$this->getMethod()} {$uri} HTTP/1.1\n";
        $hasAuth = false;
        $auth = $this->getAuth();
        if (is_array($this->getHeaders())) {
            foreach ($this->getHeaders() as $header => $value) {
                switch (wfWAFUtils::strtolower($header)) {
                    case 'cookie':
                        // TODO: Hook up highlights to cookies
                        $cookies = '';
                        foreach ($this->getCookies() as $cookieName => $cookieValue) {
                            $cookies .= $cookieName . '=' . urlencode($cookieValue) . '; ';
                        }
                        $request .= 'Cookie: ' . trim($cookies) . "\n";
                        break;
                    case 'host':
                        $request .= 'Host: ' . $this->getHost() . "\n";
                        break;
                    case 'authorization':
                        $hasAuth = true;
                        if ($auth) {
                            $request .= 'Authorization: Basic ' . base64_encode($auth['user'] . ':' . $auth['password']) . "\n";
                        }
                        break;
                    default:
                        $request .= $header . ': ' . $value . "\n";
                        break;
                }
            }
        }
        if (!$hasAuth && $auth) {
            $request .= 'Authorization: Basic ' . base64_encode($auth['user'] . ':' . $auth['password']) . "\n";
        }
        $body = $this->getBody();
        $contentType = $this->getHeaders('Content-Type');
        if (is_array($body)) {
            if (wfWAFUtils::stripos($contentType, 'application/x-www-form-urlencoded') === 0) {
                $body = http_build_query($body);
                if (!empty($highlights['body'])) {
                    foreach ($highlights['body'] as $matches) {
                        if (!empty($matches['param'])) {
                            $this->highlightMatches = $matches['match'];
                            $body = preg_replace_callback('/(&|^)(' . preg_quote(urlencode($matches['param']), '/') . ')=(.*?)(&|$)/', array($this, 'highlightParam'), $body);
                        }
                    }
                }
            } else {
                if (preg_match('/^multipart\\/form\\-data; boundary=(.*?)$/i', $contentType, $boundaryMatches)) {
                    $boundary = $boundaryMatches[1];
                    $bodyArray = array();
                    foreach ($body as $key => $value) {
                        $bodyArray = array_merge($bodyArray, $this->reduceBodyParameter($key, $value));
                    }
                    $body = '';
                    foreach ($bodyArray as $param => $value) {
                        if (!empty($highlights['body'])) {
                            foreach ($highlights['body'] as $matches) {
                                if (!empty($matches['param']) && $matches['param'] === $param) {
                                    $value = sprintf($this->highlightParamFormat, $value);
                                    if (is_array($matches['match'][0])) {
                                        $replace = array();
                                        foreach ($matches['match'][0] as $key => $match) {
                                            $replace[$match] = sprintf($this->highlightMatchFormat, $match);
                                        }
                                        if ($replace) {
                                            $value = str_replace(array_keys($replace), $replace, $value);
                                        }
                                    } else {
                                        // preg_match
                                        $value = str_replace($matches['match'][0], sprintf($this->highlightMatchFormat, $matches['match'][0]), $value);
                                    }
                                    break;
                                }
                            }
                        }
                        $body .= <<<FORM
--{$boundary}
Content-Disposition: form-data; name="{$param}"

{$value}

FORM;
                    }
                    foreach ($this->getFiles() as $param => $file) {
                        $name = array_key_exists('name', $file) ? $file['name'] : '';
                        if (is_array($name)) {
                            continue;
                            // TODO: implement files as arrays
                        }
                        $mime = array_key_exists('type', $file) ? $file['type'] : '';
                        $value = '';
                        $lenToRead = $maxRequestLen - (wfWAFUtils::strlen($request) + wfWAFUtils::strlen($body) + 1);
                        if (array_key_exists('content', $file)) {
                            $value = $file['content'];
                        } else {
                            if ($lenToRead > 0 && file_exists($file['tmp_name'])) {
                                $handle = fopen($file['tmp_name'], 'r');
                                $value = fread($handle, $lenToRead);
                                fclose($handle);
                            }
                        }
                        if (!empty($highlights['fileNames'])) {
                            foreach ($highlights['fileNames'] as $matches) {
                                if (!empty($matches['param']) && $matches['param'] === $param) {
                                    $name = sprintf($this->highlightParamFormat, $name);
                                    $name = str_replace($matches['match'][0], sprintf($this->highlightMatchFormat, $matches['match'][0]), $name);
                                    break;
                                }
                            }
                        }
                        $body .= <<<FORM
--{$boundary}
Content-Disposition: form-data; name="{$param}"; filename="{$name}"
Content-Type: {$mime}
Expires: 0

{$value}

FORM;
                    }
                    if ($body) {
                        $body .= "--{$boundary}--\n";
                    }
                }
            }
        }
        if (!is_string($body)) {
            $body = '';
        }
        $request .= "\n" . $body;
        if (wfWAFUtils::strlen($request) > $maxRequestLen) {
            $request = wfWAFUtils::substr($request, 0, $maxRequestLen);
        }
        return $request;
    }