/** * Build rewrite rules. * * @since 4.0 * * @param mixed $input options to build rules from * * @return array rules to write */ public static function build_rewrite_rules($input = null) { $server_type = ITSEC_Lib::get_server(); //Get the server type to build the right rules //Get the rules from the database if input wasn't sent if ($input === null) { $input = get_site_option('itsec_tweaks'); } $rules = ''; //initialize all rules to blank string //Process Protect Files Rules if ($input['protect_files'] === true) { if ($server_type === 'nginx') { //NGINX rules $rules .= "\t# " . __('Rules to block access to WordPress specific files and wp-includes', 'it-l10n-ithemes-security-pro') . PHP_EOL . "\tlocation ~ /\\.ht { deny all; }" . PHP_EOL . "\tlocation ~ wp-config.php { deny all; }" . PHP_EOL . "\tlocation ~ readme.html { deny all; }" . PHP_EOL . "\tlocation ~ readme.txt { deny all; }" . PHP_EOL . "\tlocation ~ /install.php { deny all; }" . PHP_EOL . "\tlocation ^wp-includes/(.*).php { deny all; }" . PHP_EOL . "\tlocation ^/wp-admin/includes(.*)\$ { deny all; }" . PHP_EOL; } else { //rules for all other servers $rules .= "# " . __('Rules to block access to WordPress specific files', 'it-l10n-ithemes-security-pro') . PHP_EOL . "<files .htaccess>" . PHP_EOL . "\tOrder allow,deny" . PHP_EOL . "\tDeny from all" . PHP_EOL . "</files>" . PHP_EOL . "<files readme.html>" . PHP_EOL . "\tOrder allow,deny" . PHP_EOL . "\tDeny from all" . PHP_EOL . "</files>" . PHP_EOL . "<files readme.txt>" . PHP_EOL . "\tOrder allow,deny" . PHP_EOL . "\tDeny from all" . PHP_EOL . "</files>" . PHP_EOL . "<files install.php>" . PHP_EOL . "\tOrder allow,deny" . PHP_EOL . "\tDeny from all" . PHP_EOL . "</files>" . PHP_EOL . "<files wp-config.php>" . PHP_EOL . "\tOrder allow,deny" . PHP_EOL . "\tDeny from all" . PHP_EOL . "</files>" . PHP_EOL; } } //Rules to disanle XMLRPC if ($input['disable_xmlrpc'] == 2) { if (strlen($rules) > 1) { $rules .= PHP_EOL; } $rules .= "# " . __('Rules to disable XML-RPC', 'it-l10n-ithemes-security-pro') . PHP_EOL; if ($server_type === 'nginx') { //NGINX rules $rules .= "\tlocation ~ xmlrpc.php { deny all; }" . PHP_EOL; } else { //rules for all other servers $rules .= "<files xmlrpc.php>" . PHP_EOL . "\tOrder allow,deny" . PHP_EOL . "\tDeny from all" . PHP_EOL . "</files>" . PHP_EOL; } } //Primary Rules for Directory Browsing if ($input['directory_browsing'] == true) { if (strlen($rules) > 1) { $rules .= PHP_EOL; } $rules .= "# " . __('Rules to disable directory browsing', 'it-l10n-ithemes-security-pro') . PHP_EOL; if ($server_type !== 'nginx') { //Don't use this on NGINX $rules .= "Options -Indexes" . PHP_EOL; } } //Apache rewrite rules (and related NGINX rules) if ($input['protect_files'] == true || $input['uploads_php'] == true || $input['request_methods'] == true || $input['suspicious_query_strings'] == true || $input['non_english_characters'] == true || $input['comment_spam'] == true) { if (strlen($rules) > 1) { $rules .= PHP_EOL; } //Open Apache rewrite rules if ($server_type !== 'nginx') { $rules .= "<IfModule mod_rewrite.c>" . PHP_EOL . "\tRewriteEngine On" . PHP_EOL; } //Rewrite Rules for Protect Files if ($input['protect_files'] == true && $server_type !== 'nginx') { $rules .= PHP_EOL . "\t# " . __('Rules to protect wp-includes', 'it-l10n-ithemes-security-pro') . PHP_EOL; $rules .= "\tRewriteRule ^wp-admin/includes/ - [F]" . PHP_EOL . "\tRewriteRule !^wp-includes/ - [S=3]" . PHP_EOL . "\tRewriteCond %{SCRIPT_FILENAME} !^(.*)wp-includes/ms-files.php" . PHP_EOL . "\tRewriteRule ^wp-includes/[^/]+\\.php\$ - [F]" . PHP_EOL . "\tRewriteRule ^wp-includes/js/tinymce/langs/.+\\.php - [F]" . PHP_EOL . "\tRewriteRule ^wp-includes/theme-compat/ - [F]" . PHP_EOL; } //Rewrite Rules for Disable PHP in Uploads if ($input['uploads_php'] === true) { $rules .= PHP_EOL . "\t# " . __('Rules to prevent php execution in uploads', 'it-l10n-ithemes-security-pro') . PHP_EOL; if ($server_type !== 'nginx') { $rules .= "\tRewriteRule ^(.*)/uploads/(.*).php(.?) - [F]" . PHP_EOL; } else { //rules for all other servers $rules .= "\tlocation ^(.*)/uploads/(.*).php(.?){ deny all; }" . PHP_EOL; } } //Apache rewrite rules for disable http methods if ($input['request_methods'] == true) { $rules .= PHP_EOL . "\t# " . __('Rules to block unneeded HTTP methods', 'it-l10n-ithemes-security-pro') . PHP_EOL; if ($server_type === 'nginx') { //NGINX rules $rules .= "\tif (\$request_method ~* \"^(TRACE|DELETE|TRACK)\"){ return 403; }" . PHP_EOL; } else { //rules for all other servers $rules .= "\tRewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC]" . PHP_EOL . "\tRewriteRule ^(.*)\$ - [F]" . PHP_EOL; } } //Process suspicious query rules if ($input['suspicious_query_strings'] == true) { $rules .= PHP_EOL . "\t# " . __('Rules to block suspicious URIs', 'it-l10n-ithemes-security-pro') . PHP_EOL; if ($server_type === 'nginx') { //NGINX rules $rules .= "\tset \$susquery 0;" . PHP_EOL . "\tif (\$args ~* \"\\.\\./\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"\\.(bash|git|hg|log|svn|swp|cvs)\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"etc/passwd\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"boot.ini\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"ftp:\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"http:\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"https:\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"(<|%3C).*script.*(>|%3E)\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"mosConfig_[a-zA-Z_]{1,21}(=|%3D)\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"base64_encode\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"(%24&x)\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"(127.0)\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"(globals|encode|localhost|loopback)\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args ~* \"(request|insert|concat|union|declare)\") { set \$susquery 1; }" . PHP_EOL . "\tif (\$args !~ \"^loggedout=true\"){ set \$susquery 0; }" . PHP_EOL . "\tif (\$args !~ \"^action=jetpack-sso\"){ set \$susquery 0; }" . PHP_EOL . "\tif (\$args !~ \"^action=rp\"){ set \$susquery 0; }" . PHP_EOL . "\tif (\$http_cookie !~ \"^.*wordpress_logged_in_.*\$\"){ set \$susquery 0; }" . PHP_EOL . "\tif (\$http_referer !~ \"^http://maps.googleapis.com(.*)\$\"){ set \$susquery 0; }" . PHP_EOL . "\tif (\$susquery = 1) { return 403; } " . PHP_EOL; } else { //rules for all other servers $rules .= "\tRewriteCond %{QUERY_STRING} \\.\\.\\/ [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} ^.*\\.(bash|git|hg|log|svn|swp|cvs) [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} etc/passwd [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} boot\\.ini [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} ftp\\: [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} http\\: [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} https\\: [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} (\\<|%3C).*script.*(\\>|%3E) [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} base64_encode.*\\(.*\\) [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} ^.*(%24&x).* [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} ^.*(127\\.0).* [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} ^.*(request|concat|insert|union|declare).* [NC]" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} !^loggedout=true" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} !^action=jetpack-sso" . PHP_EOL . "\tRewriteCond %{QUERY_STRING} !^action=rp" . PHP_EOL . "\tRewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in_.*\$" . PHP_EOL . "\tRewriteCond %{HTTP_REFERER} !^http://maps\\.googleapis\\.com(.*)\$" . PHP_EOL . "\tRewriteRule ^(.*)\$ - [F]" . PHP_EOL; } } //Process filtering of foreign characters if ($input['non_english_characters'] == true) { $rules .= PHP_EOL . "\t# " . __('Rules to block foreign characters in URLs', 'it-l10n-ithemes-security-pro') . PHP_EOL; if ($server_type === 'nginx') { //NGINX rules $rules .= "\tif (\$args ~* \"(%0|%A|%B|%C|%D|%E|%F)\") { return 403; }" . PHP_EOL; } else { //rules for all other servers $rules .= "\tRewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F).* [NC]" . PHP_EOL . "\tRewriteRule ^(.*)\$ - [F]" . PHP_EOL; } } //Process Comment spam rules if ($input['comment_spam'] == true) { $rules .= PHP_EOL . "\t# " . __('Rules to help reduce spam', 'it-l10n-ithemes-security-pro') . PHP_EOL; if ($server_type === 'nginx') { //NGINX rules $rules .= "\tlocation /wp-comments-post.php {" . PHP_EOL . "\t\tvalid_referers jetpack.wordpress.com/jetpack-comment/ " . ITSEC_Lib::get_domain(get_site_url(), false) . ";" . PHP_EOL . "\t\tset \$rule_0 0;" . PHP_EOL . "\t\tif (\$request_method ~ \"POST\"){ set \$rule_0 1\$rule_0; }" . PHP_EOL . "\t\tif (\$invalid_referer) { set \$rule_0 2\$rule_0; }" . PHP_EOL . "\t\tif (\$http_user_agent ~ \"^\$\"){ set \$rule_0 3\$rule_0; }" . PHP_EOL . "\t\tif (\$rule_0 = \"3210\") { return 403; }" . PHP_EOL . "\t}"; } else { //rules for all other servers $rules .= "\tRewriteCond %{REQUEST_METHOD} POST" . PHP_EOL . "\tRewriteCond %{REQUEST_URI} ^(.*)wp-comments-post\\.php*" . PHP_EOL . "\tRewriteCond %{HTTP_REFERER} !^" . ITSEC_Lib::get_domain(get_site_url()) . ".* " . PHP_EOL . "\tRewriteCond %{HTTP_REFERER} !^http://jetpack\\.wordpress\\.com/jetpack-comment/ [OR]" . PHP_EOL . "\tRewriteCond %{HTTP_USER_AGENT} ^\$" . PHP_EOL . "\tRewriteRule ^(.*)\$ - [F]" . PHP_EOL; } } //Close Apache Rewrite rules if ($server_type !== 'nginx') { //non NGINX rules $rules .= "</IfModule>"; } } if (strlen($rules) > 0) { $rules = explode(PHP_EOL, $rules); } else { $rules = false; } //create a proper array for writing return array('type' => 'htaccess', 'priority' => 10, 'name' => 'Tweaks', 'rules' => $rules); }
protected function get_valid_referers( $server_type ) { $valid_referers = array(); if ( 'apache' === $server_type ) { $domain = ITSEC_Lib::get_domain( get_site_url() ); if ( '*' == $domain ) { $valid_referers[] = $domain; } else { $valid_referers[] = "*.$domain"; } } else if ( 'nginx' === $server_type ) { $valid_referers[] = 'server_names'; } else { return array(); } $valid_referers[] = 'jetpack.wordpress.com/jetpack-comment/'; $valid_referers = apply_filters( 'itsec_filter_valid_comment_referers', $valid_referers, $server_type ); if ( is_string( $valid_referers ) ) { $valid_referers = array( $valid_referers ); } else if ( ! is_array( $valid_referers ) ) { $valid_referers = array(); } foreach ( $valid_referers as $index => $referer ) { $valid_referers[$index] = preg_replace( '|^https?://|', '', $referer ); } return $valid_referers; }
/** * Sanitize and update user options. * * Sanitizes and updates user options when a user saves two-factor settings * on their own profile. * * @since 1.2.0 * * @param int $user_id user id * * @return void */ public function personal_options_update( $user_id ) { $enabled = 'off'; $enabled_input = isset( $_POST['itsec_two_factor_enabled'] ) ? sanitize_text_field( $_POST['itsec_two_factor_enabled'] ) : 'off'; $description = isset( $_POST['itsec_two_factor_description'] ) ? sanitize_text_field( $_POST['itsec_two_factor_description'] ) : ITSEC_Lib::get_domain( get_site_url(), false, false ); $key = isset( $_POST['itsec_two_factor_key'] ) ? sanitize_text_field( $_POST['itsec_two_factor_key'] ) : ITSEC_Lib::get_random( 16, true ); $use_app = isset( $_POST['itsec_two_factor_use_app'] ) ? sanitize_text_field( $_POST['itsec_two_factor_use_app'] ) : 'off'; $app_passes = array(); if ( isset( $_POST['itsec_app_pass'] ) ) { $saved_passes = get_user_option( 'itsec_two_factor_app_pass', $user_id ); if ( false === $saved_passes ) { $saved_passes = array(); } elseif ( ! is_array( $saved_passes ) ) { $app_passes = array( __( 'unknown', 'it-l10n-ithemes-security-pro' ) => $saved_passes, ); } //Prevent duplicates or changing password to all hashes foreach ( $_POST['itsec_app_pass'] as $app_pass ) { $name = sanitize_text_field( trim( $app_pass['name'] ) ); if ( ! isset( $saved_passes[ $name ] ) ) { $pass = wp_hash_password( strtoupper( str_replace( ' ', '', sanitize_text_field( trim( $app_pass['pass'] ) ) ) ) ); $app_passes[ $name ] = $pass; } else { $app_passes[ $name ] = $saved_passes[ $name ]; } } } $time = floor( time() / 30 ); //time to check if ( ( 'off' === get_user_option( 'itsec_two_factor_enabled', $user_id ) && 'on' === $enabled_input ) || ( $key !== get_user_option( 'itsec_two_factor_key', $user_id ) ) ) { if ( isset( $_POST['itsec_two_factor_confirm'] ) ) { $code = sanitize_text_field( trim( $_POST['itsec_two_factor_confirm'] ) ); } else { $code = false; } if ( false !== $code && 0 < strlen( $code ) ) { $good_code = false; $offset = isset( $this->settings['offset'] ) ? intval( $this->settings['offset'] ) : 1; //Check both sides of the time for ( $i = - $offset; $i <= $offset; $i ++ ) { $log_time = $time + $i; if ( $this->get_code( $key, $log_time ) === $code ) { $enabled = $enabled_input; $good_code = true; } } } else { $good_code = false; } if ( false === $good_code ) { add_action( 'user_profile_update_errors', array( $this, 'user_profile_update_errors' ), 10, 3 ); } } else { $enabled = $enabled_input; } update_user_option( $user_id, 'itsec_two_factor_enabled', $enabled, true ); update_user_option( $user_id, 'itsec_two_factor_description', $description, true ); update_user_option( $user_id, 'itsec_two_factor_key', $key, true ); if ( 'off' !== $use_app ) { if ( 1 > sizeof( $app_passes ) ) { $use_app = 'off'; delete_user_option( $user_id, 'itsec_two_factor_app_pass', true ); } else { update_user_option( $user_id, 'itsec_two_factor_app_pass', $app_passes, true ); } } update_user_option( $user_id, 'itsec_two_factor_use_app', $use_app, true ); }