/** * Added compatibility for hosts that do not have inet_pton. * * @param $ip * @return bool|string */ public static function _inet_pton($ip) { // IPv4 if (preg_match('/^(?:\\d{1,3}(?:\\.|$)){4}/', $ip)) { $octets = explode('.', $ip); $bin = chr($octets[0]) . chr($octets[1]) . chr($octets[2]) . chr($octets[3]); return $bin; } // IPv6 if (preg_match('/^((?:[\\da-f]{1,4}(?::|)){0,8})(::)?((?:[\\da-f]{1,4}(?::|)){0,8})$/i', $ip)) { if ($ip === '::') { return ""; } $colon_count = wfWAFUtils::substr_count($ip, ':'); $dbl_colon_pos = wfWAFUtils::strpos($ip, '::'); if ($dbl_colon_pos !== false) { $ip = str_replace('::', str_repeat(':0000', ($dbl_colon_pos === 0 || $dbl_colon_pos === wfWAFUtils::strlen($ip) - 2 ? 9 : 8) - $colon_count) . ':', $ip); $ip = trim($ip, ':'); } $ip_groups = explode(':', $ip); $ipv6_bin = ''; foreach ($ip_groups as $ip_group) { $ipv6_bin .= pack('H*', str_pad($ip_group, 4, '0', STR_PAD_LEFT)); } return wfWAFUtils::strlen($ipv6_bin) === 16 ? $ipv6_bin : false; } // IPv4 mapped IPv6 if (preg_match('/^((?:0{1,4}(?::|)){0,5})(::)?ffff:((?:\\d{1,3}(?:\\.|$)){4})$/i', $ip, $matches)) { $octets = explode('.', $matches[3]); return "ÿÿ" . chr($octets[0]) . chr($octets[1]) . chr($octets[2]) . chr($octets[3]); } return false; }
public function getGlobal($global) { if (wfWAFUtils::strpos($global, '.') === false) { return null; } list($prefix, $_global) = explode('.', $global); switch ($prefix) { case 'request': $method = "get" . ucfirst($_global); if (method_exists('wfWAFRequestInterface', $method)) { return call_user_func(array($this->getRequest(), $method)); } break; case 'server': $key = wfWAFUtils::strtoupper($_global); if (isset($_SERVER) && array_key_exists($key, $_SERVER)) { return $_SERVER[$key]; } break; } return null; }
/** * @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; }
public function contains($subject) { if (is_array($this->getExpected())) { return in_array($this->getExpected(), $subject); } return wfWAFUtils::strpos((string) $subject, (string) $this->getExpected()) !== false; }
/** * @param string $regex * @return mixed */ public function check($regex) { $remaining = $this->getRemainingString(); if ($this->regexMatch($regex, $remaining, $matches)) { $matchLen = wfWAFUtils::strlen($matches[0]); if ($matchLen > 0 && wfWAFUtils::strpos($remaining, $matches[0]) === 0) { return $this->setState($matches); } } return $this->setState(); }
/** * @todo Implement wfWAFHTTPTransportStreams::send. * @param wfWAFHTTP $request * @return mixed * @throws wfWAFHTTPTransportException */ public function send($request) { $timeout = 5; $url = $request->getUrl(); if ($queryString = $request->getQueryString()) { if (is_array($queryString)) { $queryString = http_build_query($queryString); } $url .= (wfWAFUtils::strpos($url, '?') !== false ? '&' : '?') . $queryString; } $urlParsed = parse_url($request->getUrl()); $headers = "Host: {$urlParsed['host']}\r\n"; if ($auth = $request->getAuth()) { $headers .= 'Authorization: Basic ' . base64_encode($auth['user'] . ':' . $auth['password']) . "\r\n"; } if ($cookies = $request->getCookies()) { if (is_array($cookies)) { $cookies = self::buildCookieString($cookies); } $headers .= "Cookie: {$cookies}\r\n"; } $hasUA = false; if ($_headers = $request->getHeaders()) { if (is_array($_headers)) { foreach ($_headers as $header => $value) { if (trim(wfWAFUtils::strtolower($header)) === 'user-agent') { $hasUA = true; } $headers .= $header . ': ' . $value . "\r\n"; } } } if (!$hasUA) { $headers .= "User-Agent: Wordfence Streams UA\r\n"; } $httpOptions = array('method' => $request->getMethod(), 'ignore_errors' => true, 'timeout' => $timeout, 'follow_location' => 1, 'max_redirects' => 5); if (wfWAFUtils::strlen($request->getBody()) > 0) { $httpOptions['content'] = $request->getBody(); $headers .= 'Content-Length: ' . wfWAFUtils::strlen($httpOptions['content']) . "\r\n"; } $httpOptions['header'] = $headers; $options = array(wfWAFUtils::strtolower($urlParsed['scheme']) => $httpOptions); $context = stream_context_create($options); $stream = fopen($request->getUrl(), 'r', false, $context); if (!is_resource($stream)) { return false; } $metaData = stream_get_meta_data($stream); // Get the HTTP response code $httpResponse = array_shift($metaData['wrapper_data']); if (preg_match_all('/(\\w+\\/\\d\\.\\d) (\\d{3})/', $httpResponse, $matches) !== false) { // $protocol = $matches[1][0]; $status = (int) $matches[2][0]; } else { // $protocol = null; $status = null; } $responseObj = new wfWAFHTTPResponse(); $responseObj->setHeaders(join("\r\n", $metaData['wrapper_data'])); $responseObj->setBody(stream_get_contents($stream)); $responseObj->setStatusCode($status); // Close the stream after use fclose($stream); return $responseObj; }