コード例 #1
0
ファイル: file.php プロジェクト: ashenkar/sanga
 /**
  * @param string $binary
  * @return wfWAFAttackDataStorageFileEngineRow
  */
 public static function unpack($binary)
 {
     $attackLogTime = wfWAFAttackDataStorageFileEngine::unpackMicrotime(wfWAFUtils::substr($binary, 0, 8));
     $data = wfWAFAttackDataStorageFileEngine::decompress(wfWAFUtils::substr($binary, 8));
     return new self($attackLogTime, $data);
 }
コード例 #2
0
ファイル: request.php プロジェクト: ashenkar/sanga
 /**
  * @param array $matches
  * @return string
  */
 private function highlightParam($matches)
 {
     $value = '';
     if (is_array($this->highlightMatches)) {
         // preg_match_all
         if (is_array($this->highlightMatches[0])) {
             $value = $matches[3];
             $replace = array();
             foreach ($this->highlightMatches[0] as $key => $match) {
                 $this->highlightMatches[0][$key] = $this->callHighlightMatchFilter($match);
                 $replace[] = sprintf($this->highlightMatchFormat, $this->callHighlightMatchFilter($match));
             }
             if ($replace) {
                 $value = str_replace($this->highlightMatches[0], $replace, $value);
             }
         } else {
             // preg_match
             $param = $this->callHighlightMatchFilter($this->highlightMatches[0]);
             $value = str_replace($param, sprintf($this->highlightMatchFormat, $param), $matches[3]);
         }
     }
     if (wfWAFUtils::strlen($value) === 0) {
         $value = sprintf($this->highlightMatchFormat, $value);
     }
     return $matches[1] . sprintf($this->highlightParamFormat, $matches[2] . '=' . $value) . $matches[4];
 }
コード例 #3
0
 public static function requestDetectProxyCallback($timeout = 0.01, $blocking = false)
 {
     $nonce = bin2hex(wfWAFUtils::random_bytes(32));
     $callback = self::getSiteBaseURL() . '?_wfsf=detectProxy';
     wfConfig::set('detectProxyNonce', $nonce, wfConfig::DONT_AUTOLOAD);
     wfConfig::set('detectProxyRecommendation', '', wfConfig::DONT_AUTOLOAD);
     $payload = array('nonce' => $nonce, 'callback' => $callback);
     $siteurl = '';
     if (function_exists('get_bloginfo')) {
         if (is_multisite()) {
             $siteurl = network_home_url();
             $siteurl = rtrim($siteurl, '/');
             //Because previously we used get_bloginfo and it returns http://example.com without a '/' char.
         } else {
             $siteurl = home_url();
         }
     }
     wp_remote_post(WFWAF_API_URL_SEC . "?" . http_build_query(array('action' => 'detect_proxy', 'k' => wfConfig::get('apiKey'), 's' => $siteurl, 't' => microtime(true)), null, '&'), array('body' => json_encode($payload), 'headers' => array('Content-Type' => 'application/json'), 'timeout' => $timeout, 'blocking' => $blocking));
     //Asynchronous so we don't care about a response at this point.
 }
コード例 #4
0
ファイル: waf.php プロジェクト: VizualAbstract/Marilyn
 public function fire()
 {
     $waf = $this->getWaf();
     if (!$waf) {
         return;
     }
     $guessSiteURL = sprintf('%s://%s/', $waf->getRequest()->getProtocol(), $waf->getRequest()->getHost());
     try {
         $this->response = wfWAFHTTP::get(WFWAF_API_URL_SEC . "?" . http_build_query(array('action' => 'get_waf_rules', 'k' => $waf->getStorageEngine()->getConfig('apiKey'), 's' => $waf->getStorageEngine()->getConfig('siteURL') ? $waf->getStorageEngine()->getConfig('siteURL') : $guessSiteURL, 'h' => $waf->getStorageEngine()->getConfig('homeURL') ? $waf->getStorageEngine()->getConfig('homeURL') : $guessSiteURL, 'openssl' => $waf->hasOpenSSL() ? 1 : 0, 'betaFeed' => (int) $waf->getStorageEngine()->getConfig('betaThreatDefenseFeed')), null, '&'));
         if ($this->response) {
             $jsonData = wfWAFUtils::json_decode($this->response->getBody(), true);
             if (is_array($jsonData)) {
                 if ($waf->hasOpenSSL() && isset($jsonData['data']['signature']) && isset($jsonData['data']['rules']) && $waf->verifySignedRequest(base64_decode($jsonData['data']['signature']), $jsonData['data']['rules'])) {
                     $waf->updateRuleSet(base64_decode($jsonData['data']['rules']), isset($jsonData['data']['timestamp']) ? $jsonData['data']['timestamp'] : true);
                     if (array_key_exists('premiumCount', $jsonData['data'])) {
                         $waf->getStorageEngine()->setConfig('premiumCount', $jsonData['data']['premiumCount']);
                     }
                 } else {
                     if (!$waf->hasOpenSSL() && isset($jsonData['data']['hash']) && isset($jsonData['data']['rules']) && $waf->verifyHashedRequest($jsonData['data']['hash'], $jsonData['data']['rules'])) {
                         $waf->updateRuleSet(base64_decode($jsonData['data']['rules']), isset($jsonData['data']['timestamp']) ? $jsonData['data']['timestamp'] : true);
                         if (array_key_exists('premiumCount', $jsonData['data'])) {
                             $waf->getStorageEngine()->setConfig('premiumCount', $jsonData['data']['premiumCount']);
                         }
                     }
                 }
             }
         }
     } catch (wfWAFHTTPTransportException $e) {
         error_log($e->getMessage());
     } catch (wfWAFBuildRulesException $e) {
         error_log($e->getMessage());
     }
 }
コード例 #5
0
ファイル: 403-roadblock.php プロジェクト: ashenkar/sanga
<p>A potentially unsafe operation has been detected in your request to this site, and has been blocked by Wordfence.</p>

<?php 
if ($urlParamsToWhitelist) {
    ?>
	<p>If you are an administrator and you are certain this is a false positive, you can automatically whitelist this
		request and repeat the same action.</p>

	<form id="whitelist-form" action="<?php 
    echo htmlentities($waf->getRequest()->getPath(), ENT_QUOTES, 'utf-8');
    ?>
"
	      method="post">
		<input type="hidden" name="wfwaf-false-positive-params"
		       value="<?php 
    echo htmlentities(wfWAFUtils::json_encode($urlParamsToWhitelist), ENT_QUOTES, 'utf-8');
    ?>
">
		<input type="hidden" name="wfwaf-false-positive-nonce"
		       value="<?php 
    echo htmlentities($waf->getAuthCookieValue('nonce', ''), ENT_QUOTES, 'utf-8');
    ?>
">

		<div id="whitelist-actions">
			<p>
				<label>
					<input id="verified-false-positive-checkbox" type="checkbox" name="wfwaf-false-positive-verified"
					       value="1">
					<em>I am certain this is a false positive.</em>
				</label>
コード例 #6
0
 function geoip_name_by_addr_v6($gi, $addr)
 {
     if ($addr == NULL) {
         return 0;
     }
     $ipnum = wfWAFUtils::inet_pton($addr);
     return _get_org_v6($gi, $ipnum);
 }
コード例 #7
0
ファイル: sqli.php プロジェクト: ashenkar/sanga
 /**
  * @return bool|wfWAFLexerToken
  * @throws wfWAFParserSyntaxError
  */
 public function nextToken()
 {
     if (!$this->scanner->eos()) {
         /** @var wfWAFLexerTokenMatcher $tokenMatcher */
         foreach ($this->tokenMatchers as $tokenMatcher) {
             $this->scanner->skip('/^\\s+/s');
             if ($this->scanner->eos()) {
                 return false;
             }
             if (($this->flags & self::FLAG_TOKENIZE_MYSQL_PORTABLE_COMMENTS) === 0 && ($tokenMatcher->getTokenID() === self::MYSQL_PORTABLE_COMMENT_START || $tokenMatcher->getTokenID() === self::MYSQL_PORTABLE_COMMENT_END)) {
                 continue;
             }
             if (!$this->hasPortableCommentStart && $tokenMatcher->getTokenID() === self::MYSQL_PORTABLE_COMMENT_END) {
                 continue;
             }
             if ($tokenMatcher->useMaximalMunch() && ($match = $this->scanner->check($tokenMatcher->getMatch())) !== null) {
                 $biggestToken = $this->createToken($tokenMatcher->getTokenID(), $match);
                 /** @var wfWAFLexerTokenMatcher $tokenMatcher2 */
                 foreach ($this->tokenMatchers as $tokenMatcher2) {
                     if ($tokenMatcher === $tokenMatcher2) {
                         continue;
                     }
                     if (($match2 = $this->scanner->check($tokenMatcher2->getMatch())) !== null) {
                         $biggestToken2 = $this->createToken($tokenMatcher2->getTokenID(), $match2);
                         if (wfWAFUtils::strlen($biggestToken2->getValue()) > wfWAFUtils::strlen($biggestToken->getValue())) {
                             $biggestToken = $biggestToken2;
                         }
                     }
                 }
                 $this->scanner->advancePointer(wfWAFUtils::strlen($biggestToken->getValue()));
                 return $biggestToken;
             } else {
                 if (($match = $this->scanner->scan($tokenMatcher->getMatch())) !== null) {
                     $token = $this->createToken($tokenMatcher->getTokenID(), $match);
                     if ($tokenMatcher->getTokenID() === self::MYSQL_PORTABLE_COMMENT_START) {
                         $this->hasPortableCommentStart = true;
                     } else {
                         if ($tokenMatcher->getTokenID() === self::MYSQL_PORTABLE_COMMENT_END) {
                             $this->hasPortableCommentStart = false;
                         }
                     }
                     return $token;
                 }
             }
         }
         $char = $this->scanner->scanChar();
         $e = new wfWAFParserSyntaxError(sprintf('Invalid character "%s" (\\x%02x) found on line %d, column %d', $char, ord($char), $this->scanner->getLine(), $this->scanner->getColumn()));
         $e->setParseLine($this->scanner->getLine());
         $e->setParseColumn($this->scanner->getColumn());
         throw $e;
     }
     return false;
 }
コード例 #8
0
ファイル: lexer.php プロジェクト: ashenkar/sanga
 /**
  * @param string $string
  * @throws InvalidArgumentException
  */
 public function setString($string)
 {
     if (!is_string($string)) {
         throw new InvalidArgumentException(sprintf('String expected, got [%s]', gettype($string)));
     }
     $this->setLength(wfWAFUtils::strlen($string));
     $this->string = $string;
     $this->reset();
 }
コード例 #9
0
 public function filePatternsMatch($subject)
 {
     $request = $this->getWAF()->getRequest();
     $files = $request->getFiles();
     $patterns = $this->getWAF()->getMalwareSignatures();
     if (!is_array($patterns) || !is_array($files)) {
         return false;
     }
     foreach ($files as $file) {
         if ($file['name'] == (string) $subject) {
             $fh = @fopen($file['tmp_name'], 'r');
             if (!$fh) {
                 return false;
             }
             $totalRead = 0;
             $readsize = max(min(10 * 1024 * 1024, wfWAFUtils::iniSizeToBytes(ini_get('upload_max_filesize'))), 1 * 1024 * 1024);
             while (!feof($fh)) {
                 $data = fread($fh, $readsize);
                 $totalRead += strlen($data);
                 if ($totalRead < 1) {
                     return false;
                 }
                 foreach ($patterns as $rule) {
                     if (preg_match('/(' . $rule . ')/i', $data, $matches)) {
                         return true;
                     }
                 }
             }
         }
     }
     return false;
 }
コード例 #10
0
 /**
  * Return a set of where clauses to use in MySQL.
  *
  * @param string $column
  * @return false|null|string
  */
 public function toSQL($column = 'ip')
 {
     /** @var wpdb $wpdb */
     global $wpdb;
     $ip_string = $this->getIPString();
     if (strpos($ip_string, '.') !== false && preg_match('/\\[\\d+\\-\\d+\\]/', $ip_string)) {
         $whiteParts = explode('.', $ip_string);
         $sql = "(SUBSTR({$column}, 1, 12) = LPAD(CHAR(0xff, 0xff), 12, CHAR(0)) AND ";
         for ($i = 0, $j = 24; $i <= 3; $i++, $j -= 8) {
             // MySQL can only perform bitwise operations on integers
             $conv = sprintf('CAST(CONV(HEX(SUBSTR(%s, 13, 8)), 16, 10) as UNSIGNED INTEGER)', $column);
             if (preg_match('/^\\[(\\d+)\\-(\\d+)\\]$/', $whiteParts[$i], $m)) {
                 $sql .= $wpdb->prepare("{$conv} >> {$j} & 0xFF BETWEEN %d AND %d", $m[1], $m[2]);
             } else {
                 $sql .= $wpdb->prepare("{$conv} >> {$j} & 0xFF = %d", $whiteParts[$i]);
             }
             $sql .= ' AND ';
         }
         $sql = substr($sql, 0, -5) . ')';
         return $sql;
     } else {
         if (strpos($ip_string, ':') !== false) {
             $ip_string = strtolower(self::expandIPv6Range($ip_string));
             if (preg_match('/\\[[a-f0-9]+\\-[a-f0-9]+\\]/i', $ip_string)) {
                 $whiteParts = explode(':', $ip_string);
                 $sql = '(';
                 for ($i = 0; $i <= 7; $i++) {
                     // MySQL can only perform bitwise operations on integers
                     $conv = sprintf('CAST(CONV(HEX(SUBSTR(%s, %d, 8)), 16, 10) as UNSIGNED INTEGER)', $column, $i < 4 ? 1 : 9);
                     $j = 16 * (3 - $i % 4);
                     if (preg_match('/^\\[([a-f0-9]+)\\-([a-f0-9]+)\\]$/i', $whiteParts[$i], $m)) {
                         $sql .= $wpdb->prepare("{$conv} >> {$j} & 0xFFFF BETWEEN 0x%x AND 0x%x", hexdec($m[1]), hexdec($m[2]));
                     } else {
                         $sql .= $wpdb->prepare("{$conv} >> {$j} & 0xFFFF = 0x%x", hexdec($whiteParts[$i]));
                     }
                     $sql .= ' AND ';
                 }
                 $sql = substr($sql, 0, -5) . ')';
                 return $sql;
             }
         }
     }
     return $wpdb->prepare("({$column} = %s)", wfWAFUtils::inet_pton($ip_string));
 }
コード例 #11
0
ファイル: http.php プロジェクト: ashenkar/sanga
 /**
  * @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;
 }
コード例 #12
0
ファイル: parser.php プロジェクト: ashenkar/sanga
 /**
  * @return mixed|string
  * @throws wfWAFRuleParserSyntaxError
  */
 private function expectLiteral()
 {
     $expectedToken = $this->expectNextToken();
     $this->expectTokenTypeInArray($expectedToken, array(wfWAFRuleLexer::T_SINGLE_STRING_LITERAL, wfWAFRuleLexer::T_DOUBLE_STRING_LITERAL, wfWAFRuleLexer::T_IDENTIFIER, wfWAFRuleLexer::T_NUMBER_LITERAL, wfWAFRuleLexer::T_OPEN_BRACKET));
     if ($expectedToken->getType() === wfWAFRuleLexer::T_SINGLE_STRING_LITERAL) {
         // Remove quotes, strip slashes
         $value = wfWAFUtils::substr($expectedToken->getValue(), 1, -1);
         $value = str_replace("\\'", "'", $value);
     } else {
         if ($expectedToken->getType() === wfWAFRuleLexer::T_DOUBLE_STRING_LITERAL) {
             // Remove quotes, strip slashes
             $value = wfWAFUtils::substr($expectedToken->getValue(), 1, -1);
             $value = str_replace('\\"', '"', $value);
         } else {
             if ($expectedToken->getType() === wfWAFRuleLexer::T_IDENTIFIER) {
                 // Remove quotes, strip slashes
                 $value = new wfWAFRuleVariable($this->getWAF(), $expectedToken->getValue());
             } else {
                 if ($expectedToken->getType() === wfWAFRuleLexer::T_OPEN_BRACKET) {
                     $value = array();
                     while (true) {
                         $nextToken = $this->expectNextToken();
                         if ($nextToken->getType() === wfWAFRuleLexer::T_CLOSE_BRACKET) {
                             break;
                         }
                         if ($nextToken->getType() === wfWAFRuleLexer::T_COMMA) {
                             continue;
                         }
                         $this->index--;
                         $value[] = $this->expectLiteral();
                     }
                 } else {
                     $value = $expectedToken->getValue();
                 }
             }
         }
     }
     return $value;
 }
コード例 #13
0
 public function lengthLessThan($subject)
 {
     return wfWAFUtils::strlen(is_array($subject) ? join('', $subject) : (string) $subject) < $this->getExpected();
 }
コード例 #14
0
ファイル: waf.php プロジェクト: Jerram-Marketing/Gummer-Co
 public function fire()
 {
     $waf = $this->getWaf();
     if (!$waf) {
         return;
     }
     $guessSiteURL = sprintf('%s://%s/', $waf->getRequest()->getProtocol(), $waf->getRequest()->getHost());
     try {
         $request = new wfWAFHTTP();
         $request->setHeaders(array('Content-Type' => 'application/json'));
         $response = wfWAFHTTP::post(WFWAF_API_URL_SEC . "?" . http_build_query(array('action' => 'send_waf_attack_data', 'k' => $waf->getStorageEngine()->getConfig('apiKey'), 's' => $waf->getStorageEngine()->getConfig('siteURL') ? $waf->getStorageEngine()->getConfig('siteURL') : $guessSiteURL, 't' => microtime(true)), null, '&'), '[]', $request);
         if ($response instanceof wfWAFHTTPResponse && $response->getBody()) {
             $jsonData = wfWAFUtils::json_decode($response->getBody(), true);
             if (array_key_exists('data', $jsonData) && array_key_exists('watchedIPList', $jsonData['data'])) {
                 $waf->getStorageEngine()->setConfig('watchedIPs', $jsonData['data']['watchedIPList']);
             }
         }
     } catch (wfWAFHTTPTransportException $e) {
         error_log($e->getMessage());
     }
 }
コード例 #15
0
 public static function authenticateFilter($authUser, $username, $passwd)
 {
     wfConfig::inc('totalLoginHits');
     //The total hits to wp-login.php including logins, logouts and just hits.
     $IP = wfUtils::getIP();
     $secEnabled = wfConfig::get('loginSecurityEnabled');
     $twoFactorUsers = wfConfig::get_ser('twoFactorUsers', array());
     $userDat = isset($_POST['wordfence_userDat']) ? $_POST['wordfence_userDat'] : false;
     $checkTwoFactor = $secEnabled && !self::getLog()->isWhitelisted($IP) && wfConfig::get('isPaid') && isset($twoFactorUsers) && is_array($twoFactorUsers) && sizeof($twoFactorUsers) > 0 && is_object($userDat) && get_class($userDat) == 'WP_User';
     if ($checkTwoFactor) {
         $twoFactorRecord = false;
         $hasActivatedTwoFactorUser = false;
         foreach ($twoFactorUsers as &$t) {
             if ($t[3] == 'activated') {
                 $userID = $t[0];
                 $testUser = get_user_by('ID', $userID);
                 if (is_object($testUser) && wfUtils::isAdmin($testUser)) {
                     $hasActivatedTwoFactorUser = true;
                 }
                 if ($userID == $userDat->ID) {
                     $twoFactorRecord =& $t;
                 }
             }
         }
         if (isset($_POST['wordfence_authFactor']) && $_POST['wordfence_authFactor'] && $twoFactorRecord) {
             //User authenticated with name and password, 2FA code ready to check
             $userID = $userDat->ID;
             if (get_class($authUser) == 'WP_User' && $authUser->ID == $userID) {
                 //Do nothing. This is the code path the old method of including the code in the password field will take -- since we already have a valid $authUser, skip the nonce verification portion
             } else {
                 if (isset($_POST['wordfence_twoFactorNonce'])) {
                     $twoFactorNonce = preg_replace('/[^a-f0-9]/i', '', $_POST['wordfence_twoFactorNonce']);
                     if (!self::verifyTwoFactorIntermediateValues($userID, $twoFactorNonce)) {
                         self::$authError = new WP_Error('twofactor_required', __('<strong>VERIFICATION FAILED</strong>: Two factor authentication verification failed. Please try again.'));
                         return self::processBruteForceAttempt(self::$authError, $username, $passwd);
                     }
                 } else {
                     //Code path for old method, invalid password the second time
                     self::$authError = $authUser;
                     if (is_wp_error(self::$authError) && (self::$authError->get_error_code() == 'invalid_username' || $authUser->get_error_code() == 'invalid_email' || self::$authError->get_error_code() == 'incorrect_password' || $authUser->get_error_code() == 'authentication_failed') && wfConfig::get('loginSec_maskLoginErrors')) {
                         self::$authError = new WP_Error('incorrect_password', sprintf(__('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%2$s" title="Password Lost and Found">Lost your password</a>?'), $username, wp_lostpassword_url()));
                     }
                     return self::processBruteForceAttempt(self::$authError, $username, $passwd);
                 }
             }
             if (isset($twoFactorRecord[5])) {
                 //New method TOTP
                 $mode = $twoFactorRecord[5];
                 $code = preg_replace('/[^a-f0-9]/i', '', $_POST['wordfence_authFactor']);
                 $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
                 try {
                     $codeResult = $api->call('twoFactorTOTP_verify', array(), array('totpid' => $twoFactorRecord[6], 'code' => $code, 'mode' => $mode));
                     if (isset($codeResult['notPaid']) && $codeResult['notPaid']) {
                         //No longer a paid key, let them sign in without two factor
                     } else {
                         if (isset($codeResult['ok']) && $codeResult['ok']) {
                             //Everything's good, let the sign in continue
                         } else {
                             if (get_class($authUser) == 'WP_User' && $authUser->ID == $userID) {
                                 //Using the old method of appending the code to the password
                                 if ($mode == 'authenticator') {
                                     self::$authError = new WP_Error('twofactor_invalid', __('<strong>INVALID CODE</strong>: Please sign in again and add a space, the letters <code>wf</code>, and the code from your authenticator app to the end of your password (e.g., <code>wf123456</code>).'));
                                 } else {
                                     self::$authError = new WP_Error('twofactor_invalid', __('<strong>INVALID CODE</strong>: Please sign in again and add a space, the letters <code>wf</code>, and the code sent to your phone to the end of your password (e.g., <code>wf123456</code>).'));
                                 }
                             } else {
                                 $loginNonce = wfWAFUtils::random_bytes(20);
                                 if ($loginNonce === false) {
                                     //Should never happen but is technically possible
                                     self::$authError = new WP_Error('twofactor_required', __('<strong>AUTHENTICATION FAILURE</strong>: A temporary failure was encountered while trying to log in. Please try again.'));
                                     return self::$authError;
                                 }
                                 $loginNonce = bin2hex($loginNonce);
                                 update_user_meta($userDat->ID, '_wf_twoFactorNonce', $loginNonce);
                                 update_user_meta($userDat->ID, '_wf_twoFactorNonceTime', time());
                                 if ($mode == 'authenticator') {
                                     self::$authError = new WP_Error('twofactor_invalid', __('<strong>INVALID CODE</strong>: You need to enter the code generated by your authenticator app. The code should be a six digit number (e.g., 123456).') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                 } else {
                                     self::$authError = new WP_Error('twofactor_invalid', __('<strong>INVALID CODE</strong>: You need to enter the code generated sent to your phone. The code should be a six digit number (e.g., 123456).') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                 }
                             }
                             return self::processBruteForceAttempt(self::$authError, $username, $passwd);
                         }
                     }
                 } catch (Exception $e) {
                     if (self::isDebugOn()) {
                         error_log('TOTP validation error: ' . $e->getMessage());
                     }
                 }
                 // Couldn't connect to noc1, let them sign in since the password was correct.
             } else {
                 //Old method phone authentication
                 $authFactor = $_POST['wordfence_authFactor'];
                 if (strlen($authFactor) == 4) {
                     $authFactor = 'wf' . $authFactor;
                 }
                 if ($authFactor == $twoFactorRecord[2] && $twoFactorRecord[4] > time()) {
                     // Set this 2FA code to expire in 30 seconds (for other plugins hooking into the auth process)
                     $twoFactorRecord[4] = time() + 30;
                     wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
                 } else {
                     if ($authFactor == $twoFactorRecord[2]) {
                         $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
                         try {
                             $codeResult = $api->call('twoFactor_verification', array(), array('phone' => $twoFactorRecord[1]));
                             if (isset($codeResult['notPaid']) && $codeResult['notPaid']) {
                                 //No longer a paid key, let them sign in without two factor
                             } else {
                                 if (isset($codeResult['ok']) && $codeResult['ok']) {
                                     $twoFactorRecord[2] = $codeResult['code'];
                                     $twoFactorRecord[4] = time() + 1800;
                                     //30 minutes until code expires
                                     wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
                                     //save the code the user needs to enter and return an error.
                                     $loginNonce = wfWAFUtils::random_bytes(20);
                                     if ($loginNonce === false) {
                                         //Should never happen but is technically possible
                                         self::$authError = new WP_Error('twofactor_required', __('<strong>AUTHENTICATION FAILURE</strong>: A temporary failure was encountered while trying to log in. Please try again.'));
                                         return self::$authError;
                                     }
                                     $loginNonce = bin2hex($loginNonce);
                                     update_user_meta($userDat->ID, '_wf_twoFactorNonce', $loginNonce);
                                     update_user_meta($userDat->ID, '_wf_twoFactorNonceTime', time());
                                     self::$authError = new WP_Error('twofactor_required', __('<strong>CODE EXPIRED. CHECK YOUR PHONE:</strong> The code you entered has expired. Codes are only valid for 30 minutes for security reasons. We have sent you a new code. Please sign in using your username, password, and the new code we sent you.') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                     return self::$authError;
                                 }
                             }
                             //else: No new code was received. Let them sign in with the expired code.
                         } catch (Exception $e) {
                             // Couldn't connect to noc1, let them sign in since the password was correct.
                         }
                     } else {
                         //Bad code, so cancel the login and return an error to user.
                         $loginNonce = wfWAFUtils::random_bytes(20);
                         if ($loginNonce === false) {
                             //Should never happen but is technically possible
                             self::$authError = new WP_Error('twofactor_required', __('<strong>AUTHENTICATION FAILURE</strong>: A temporary failure was encountered while trying to log in. Please try again.'));
                             return self::$authError;
                         }
                         $loginNonce = bin2hex($loginNonce);
                         update_user_meta($userDat->ID, '_wf_twoFactorNonce', $loginNonce);
                         update_user_meta($userDat->ID, '_wf_twoFactorNonceTime', time());
                         self::$authError = new WP_Error('twofactor_invalid', __('<strong>INVALID CODE</strong>: You need to enter your password and the code we sent to your phone. The code should start with \'wf\' and should be four characters (e.g., wfAB12).') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                         return self::processBruteForceAttempt(self::$authError, $username, $passwd);
                     }
                 }
             }
             delete_user_meta($userDat->ID, '_wf_twoFactorNonce');
             delete_user_meta($userDat->ID, '_wf_twoFactorNonceTime');
             $authUser = $userDat;
             //Log in as the user we saved in the wp_authenticate action
         } else {
             if (get_class($authUser) == 'WP_User') {
                 //User authenticated with name and password, prompt for the 2FA code
                 //Verify at least one administrator has 2FA enabled
                 $requireAdminTwoFactor = $hasActivatedTwoFactorUser && wfConfig::get('loginSec_requireAdminTwoFactor');
                 if ($twoFactorRecord) {
                     if ($twoFactorRecord[0] == $userDat->ID && $twoFactorRecord[3] == 'activated') {
                         //Yup, enabled, so require the code
                         $loginNonce = wfWAFUtils::random_bytes(20);
                         if ($loginNonce === false) {
                             //Should never happen but is technically possible, allow login
                             $requireAdminTwoFactor = false;
                         } else {
                             $loginNonce = bin2hex($loginNonce);
                             update_user_meta($userDat->ID, '_wf_twoFactorNonce', $loginNonce);
                             update_user_meta($userDat->ID, '_wf_twoFactorNonceTime', time());
                             if (isset($twoFactorRecord[5])) {
                                 //New method TOTP authentication
                                 if ($twoFactorRecord[5] == 'authenticator') {
                                     if (self::hasGDLimitLoginsMUPlugin() && function_exists('limit_login_get_address')) {
                                         $retries = get_option('limit_login_retries', array());
                                         $ip = limit_login_get_address();
                                         if (!is_array($retries)) {
                                             $retries = array();
                                         }
                                         if (isset($retries[$ip]) && is_int($retries[$ip])) {
                                             $retries[$ip]--;
                                         } else {
                                             $retries[$ip] = 0;
                                         }
                                         update_option('limit_login_retries', $retries);
                                     }
                                     $allowSeparatePrompt = ini_get('output_buffering') > 0;
                                     if (wfConfig::get('loginSec_enableSeparateTwoFactor') && $allowSeparatePrompt) {
                                         self::$authError = new WP_Error('twofactor_required', __('<strong>CODE REQUIRED</strong>: Please check your authenticator app for the current code. Enter it below to sign in.') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                         return self::$authError;
                                     } else {
                                         self::$authError = new WP_Error('twofactor_required', __('<strong>CODE REQUIRED</strong>: Please check your authenticator app for the current code. Please sign in again and add a space, the letters <code>wf</code>, and the code to the end of your password (e.g., <code>wf123456</code>).'));
                                         return self::$authError;
                                     }
                                 } else {
                                     //Phone TOTP
                                     $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
                                     try {
                                         $codeResult = $api->call('twoFactorTOTP_sms', array(), array('totpid' => $twoFactorRecord[6]));
                                         if (isset($codeResult['notPaid']) && $codeResult['notPaid']) {
                                             $requireAdminTwoFactor = false;
                                             //Let them sign in without two factor if their API key has expired or they're not paid and for some reason they have this set up.
                                         } else {
                                             if (isset($codeResult['ok']) && $codeResult['ok']) {
                                                 if (self::hasGDLimitLoginsMUPlugin() && function_exists('limit_login_get_address')) {
                                                     $retries = get_option('limit_login_retries', array());
                                                     $ip = limit_login_get_address();
                                                     if (!is_array($retries)) {
                                                         $retries = array();
                                                     }
                                                     if (isset($retries[$ip]) && is_int($retries[$ip])) {
                                                         $retries[$ip]--;
                                                     } else {
                                                         $retries[$ip] = 0;
                                                     }
                                                     update_option('limit_login_retries', $retries);
                                                 }
                                                 $allowSeparatePrompt = ini_get('output_buffering') > 0;
                                                 if (wfConfig::get('loginSec_enableSeparateTwoFactor') && $allowSeparatePrompt) {
                                                     self::$authError = new WP_Error('twofactor_required', __('<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Enter it below to sign in.') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                                     return self::$authError;
                                                 } else {
                                                     self::$authError = new WP_Error('twofactor_required', __('<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Please sign in again and add a space, the letters <code>wf</code>, and the code to the end of your password (e.g., <code>wf123456</code>).'));
                                                     return self::$authError;
                                                 }
                                             } else {
                                                 //oops, our API returned an error.
                                                 $requireAdminTwoFactor = false;
                                                 //Let them sign in without two factor because the API is broken and we don't want to lock users out of their own systems.
                                             }
                                         }
                                     } catch (Exception $e) {
                                         if (self::isDebugOn()) {
                                             error_log('TOTP SMS error: ' . $e->getMessage());
                                         }
                                         $requireAdminTwoFactor = false;
                                         // Couldn't connect to noc1, let them sign in since the password was correct.
                                     }
                                 }
                             } else {
                                 //Old method phone authentication
                                 $api = new wfAPI(wfConfig::get('apiKey'), wfUtils::getWPVersion());
                                 try {
                                     $codeResult = $api->call('twoFactor_verification', array(), array('phone' => $twoFactorRecord[1]));
                                     if (isset($codeResult['notPaid']) && $codeResult['notPaid']) {
                                         $requireAdminTwoFactor = false;
                                         //Let them sign in without two factor if their API key has expired or they're not paid and for some reason they have this set up.
                                     } else {
                                         if (isset($codeResult['ok']) && $codeResult['ok']) {
                                             $twoFactorRecord[2] = $codeResult['code'];
                                             $twoFactorRecord[4] = time() + 1800;
                                             //30 minutes until code expires
                                             wfConfig::set_ser('twoFactorUsers', $twoFactorUsers);
                                             //save the code the user needs to enter and return an error.
                                             if (self::hasGDLimitLoginsMUPlugin() && function_exists('limit_login_get_address')) {
                                                 $retries = get_option('limit_login_retries', array());
                                                 $ip = limit_login_get_address();
                                                 if (!is_array($retries)) {
                                                     $retries = array();
                                                 }
                                                 if (isset($retries[$ip]) && is_int($retries[$ip])) {
                                                     $retries[$ip]--;
                                                 } else {
                                                     $retries[$ip] = 0;
                                                 }
                                                 update_option('limit_login_retries', $retries);
                                             }
                                             $allowSeparatePrompt = ini_get('output_buffering') > 0;
                                             if (wfConfig::get('loginSec_enableSeparateTwoFactor') && $allowSeparatePrompt) {
                                                 self::$authError = new WP_Error('twofactor_required', __('<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Enter it below to sign in.') . '<!-- wftwofactornonce:' . $userDat->ID . '/' . $loginNonce . ' -->');
                                                 return self::$authError;
                                             } else {
                                                 self::$authError = new WP_Error('twofactor_required', __('<strong>CHECK YOUR PHONE</strong>: A code has been sent to your phone and will arrive within 30 seconds. Please sign in again and add a space and the code to the end of your password (e.g., <code>wfABCD</code>).'));
                                                 return self::$authError;
                                             }
                                         } else {
                                             //oops, our API returned an error.
                                             $requireAdminTwoFactor = false;
                                             //Let them sign in without two factor because the API is broken and we don't want to lock users out of their own systems.
                                         }
                                     }
                                 } catch (Exception $e) {
                                     $requireAdminTwoFactor = false;
                                     // Couldn't connect to noc1, let them sign in since the password was correct.
                                 }
                             }
                             //end: Old method phone authentication
                         }
                     }
                 }
                 if ($requireAdminTwoFactor && wfUtils::isAdmin($authUser)) {
                     $username = $authUser->user_login;
                     self::getLog()->logLogin('loginFailValidUsername', 1, $username);
                     wordfence::alert("Admin Login Blocked", "A user with username \"{$username}\" who has administrator access tried to sign in to your WordPress site. Access was denied because all administrator accounts are required to have Cellphone Sign-in enabled but this account does not.", wfUtils::getIP());
                     self::$authError = new WP_Error('twofactor_disabled_required', __('<strong>Cellphone Sign-in Required</strong>: Cellphone Sign-in is required for all administrator accounts. Please contact the site administrator to enable it for your account.'));
                     return self::$authError;
                 }
                 //User is not configured for two factor. Sign in without two factor.
             }
         }
     }
     //End: if ($checkTwoFactor)
     return self::processBruteForceAttempt($authUser, $username, $passwd);
 }
コード例 #16
0
 /**
  * @param mixed $subject
  * @return array|string
  */
 public static function stripMagicQuotes($subject)
 {
     $sybase = ini_get('magic_quotes_sybase');
     $sybaseEnabled = is_numeric($sybase) && $sybase || is_string($sybase) && $sybase && !in_array(wfWAFUtils::strtolower($sybase), array('off', 'false'));
     if (function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc() || $sybaseEnabled) {
         return self::stripslashes_deep($subject);
     }
     return $subject;
 }
コード例 #17
0
 /**
  * @param string $addr Should be in dot or colon notation (127.0.0.1 or ::1)
  * @return bool
  */
 private function _isPrivateIP($ip)
 {
     // Run this through the preset list for IPv4 addresses.
     if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
         $wordfenceLib = realpath(dirname(__FILE__) . '/../lib');
         include $wordfenceLib . '/wfIPWhitelist.php';
         // defines $wfIPWhitelist
         $private = $wfIPWhitelist['private'];
         foreach ($private as $a) {
             if (wfWAFUtils::subnetContainsIP($a, $ip)) {
                 return true;
             }
         }
     }
     return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6) !== false && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false;
 }
コード例 #18
0
 protected function checkForWhitelisted($ip)
 {
     $wordfenceLib = realpath(dirname(__FILE__) . '/../lib');
     include $wordfenceLib . '/wfIPWhitelist.php';
     // defines $wfIPWhitelist
     foreach ($wfIPWhitelist as $group) {
         foreach ($group as $subnet) {
             if ($subnet instanceof wfWAFUserIPRange) {
                 //Not currently reached
                 if ($subnet->isIPInRange($ip)) {
                     return true;
                 }
             } elseif (wfWAFUtils::subnetContainsIP($subnet, $ip)) {
                 return true;
             }
         }
     }
     return false;
 }