Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save asciitohex/ab89ec9c0b0145f5527ebfee336defcd to your computer and use it in GitHub Desktop.
Save asciitohex/ab89ec9c0b0145f5527ebfee336defcd to your computer and use it in GitHub Desktop.

Revisions

  1. @tlongren tlongren revised this gist Oct 9, 2017. 1 changed file with 2 additions and 4 deletions.
    6 changes: 2 additions & 4 deletions wordpress-hardening-techniques.md
    Original file line number Diff line number Diff line change
    @@ -87,8 +87,6 @@ deny from all
    <a name="plugins"></a>
    ## Plugins and Other

    #### 1. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/)
    #### 1. Install [Saltech Functionality Plugin](http://gitlab.saltechsystems.com/tyler.longren/wordpress-saltech-functionality-plugin) to limit login attempts.

    #### 2. Install [Saltech Functionality Plugin](http://gitlab.saltechsystems.com/tyler.longren/wordpress-saltech-functionality-plugin) to limit login attempts.

    #### 3. If you need functionality not already provided above, like blocking known attackers, install [WordFence](https://wordpress.org/plugins/wordfence/)
    #### 2. If you need functionality not already provided above, like blocking known attackers, install [WordFence](https://wordpress.org/plugins/wordfence/)
  2. @tlongren tlongren revised this gist Oct 5, 2017. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion wordpress-hardening-techniques.md
    Original file line number Diff line number Diff line change
    @@ -77,7 +77,8 @@ deny from all
    <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{REQUEST_URI} ^(.*)?wp-login\.php(.*)$ [OR]
    RewriteCond %{REQUEST_URI} ^(.*)?wp-admin(\/)$
    RewriteCond %{REQUEST_URI} ^(.*)?wp-admin(\/)$ [OR]
    RewriteCond %{REQUEST_URI} ^(.*)?wp-admin/$
    RewriteCond %{REMOTE_ADDR} !^63\.224\.182\.124$
    RewriteCond %{REMOTE_ADDR} !^96\.81\.205\.229$
    RewriteRule ^(.*)$ - [R=403,L]
  3. @tlongren tlongren revised this gist Oct 5, 2017. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions wordpress-hardening-techniques.md
    Original file line number Diff line number Diff line change
    @@ -77,8 +77,7 @@ deny from all
    <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{REQUEST_URI} ^(.*)?wp-login\.php(.*)$ [OR]
    RewriteCond %{REQUEST_URI} ^(.*)?wp-admin$ [OR]
    RewriteCond %{REQUEST_URI} ^(.*)?wp-admin/$
    RewriteCond %{REQUEST_URI} ^(.*)?wp-admin(\/)$
    RewriteCond %{REMOTE_ADDR} !^63\.224\.182\.124$
    RewriteCond %{REMOTE_ADDR} !^96\.81\.205\.229$
    RewriteRule ^(.*)$ - [R=403,L]
  4. @tlongren tlongren revised this gist Oct 3, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion wordpress-hardening-techniques.md
    Original file line number Diff line number Diff line change
    @@ -72,7 +72,7 @@ deny from all
    </files>
    ```

    #### 10. Limit Login to Specific IP
    #### 10. Limit Login and Access to `/wp-admin/` to a Specific IP
    ```ApacheConf
    <IfModule mod_rewrite.c>
    RewriteEngine on
  5. @tlongren tlongren revised this gist Oct 3, 2017. No changes.
  6. @tlongren tlongren revised this gist Oct 3, 2017. 1 changed file with 1 addition and 96 deletions.
    97 changes: 1 addition & 96 deletions wordpress-hardening-techniques.md
    Original file line number Diff line number Diff line change
    @@ -89,101 +89,6 @@ deny from all

    #### 1. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/)

    #### 2. Limit login attempts via functionality plugin or `functions.php` theme file
    ```php
    <?php
    /**
    * CLASS LIMIT LOGIN ATTEMPTS
    * Prevent Mass WordPress Login Attacks by setting locking the system when login fail.
    * To be added in functions.php or as an external file.
    */
    if ( ! class_exists( 'Limit_Login_Attempts' ) ) {
    class Limit_Login_Attempts {

    var $transient_name = 'attempted_login';

    public function __construct($attempts = 3, $duration = 1800) {
    $this->failed_login_limit = $attempts;
    $this->lockout_duration = $duration;
    add_filter( 'authenticate', array( $this, 'check_attempted_login' ), 30, 3 );
    add_action( 'wp_login_failed', array( $this, 'login_failed' ), 10, 1 );
    }

    /**
    * Lock login attempts of failed login limit is reached
    */
    public function check_attempted_login( $user, $username, $password ) {
    if ( get_transient( $this->transient_name ) ) {
    $datas = get_transient( $this->transient_name );

    if ( $datas['tried'] >= $this->failed_login_limit ) {
    $until = get_option( '_transient_timeout_' . $this->transient_name );
    $time = $this->when( $until );

    return new WP_Error( 'too_many_attempts', sprintf( __( '<strong>ERROR</strong>: You have reached authentification limit, you will be able to try again in %1$s.' ) , $time ) );
    }
    }

    return $user;
    }


    /**
    * Add transient
    */
    public function login_failed( $username ) {
    if ( get_transient( $this->transient_name ) ) {
    $datas = get_transient( $this->transient_name );
    $datas['tried']++;

    if ( $datas['tried'] <= $this->failed_login_limit )
    set_transient( $this->transient_name, $datas , $this->lockout_duration );
    } else {
    $datas = array(
    'tried' => 1
    );
    set_transient( $this->transient_name, $datas , $this->lockout_duration );
    }
    }


    /**
    * Return difference between 2 given dates
    * @param int $time Date as Unix timestamp
    * @return string Return string
    */
    private function when( $time ) {
    if ( ! $time )
    return;

    $right_now = time();

    $diff = abs( $right_now - $time );

    $second = 1;
    $minute = $second * 60;
    $hour = $minute * 60;
    $day = $hour * 24;

    if ( $diff < $minute )
    return floor( $diff / $second ) . ' seconds';

    if ( $diff < $minute * 2 )
    return "about 1 minute ago";

    if ( $diff < $hour )
    return floor( $diff / $minute ) . ' minutes';

    if ( $diff < $hour * 2 )
    return 'about 1 hour';

    return floor( $diff / $hour ) . ' hours';
    }
    }
    }

    // enable login attempt limiting
    new Limit_Login_Attempts(3,1800);
    ```
    #### 2. Install [Saltech Functionality Plugin](http://gitlab.saltechsystems.com/tyler.longren/wordpress-saltech-functionality-plugin) to limit login attempts.

    #### 3. If you need functionality not already provided above, like blocking known attackers, install [WordFence](https://wordpress.org/plugins/wordfence/)
  7. @tlongren tlongren revised this gist Oct 3, 2017. 1 changed file with 7 additions and 10 deletions.
    17 changes: 7 additions & 10 deletions wordpress-hardening-techniques.md
    Original file line number Diff line number Diff line change
    @@ -74,17 +74,14 @@ deny from all

    #### 10. Limit Login to Specific IP
    ```ApacheConf
    ErrorDocument 401 /index.php?error=404
    ErrorDocument 403 /index.php?error=404
    <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{REQUEST_URI} ^(.*)?wp-login\.php(.*)$ [OR]
    RewriteCond %{REQUEST_URI} ^(.*)?wp-admin$
    RewriteCond %{REMOTE_ADDR} !^IP Address One$
    RewriteCond %{REMOTE_ADDR} !^IP Address Two$
    RewriteCond %{REMOTE_ADDR} !^IP Address Three$
    RewriteRule ^(.*)$ - [R=403,L]
    RewriteEngine on
    RewriteCond %{REQUEST_URI} ^(.*)?wp-login\.php(.*)$ [OR]
    RewriteCond %{REQUEST_URI} ^(.*)?wp-admin$ [OR]
    RewriteCond %{REQUEST_URI} ^(.*)?wp-admin/$
    RewriteCond %{REMOTE_ADDR} !^63\.224\.182\.124$
    RewriteCond %{REMOTE_ADDR} !^96\.81\.205\.229$
    RewriteRule ^(.*)$ - [R=403,L]
    </IfModule>
    ```
    <a name="plugins"></a>
  8. @tlongren tlongren revised this gist Aug 16, 2017. 1 changed file with 16 additions and 0 deletions.
    16 changes: 16 additions & 0 deletions wordpress-hardening-techniques.md
    Original file line number Diff line number Diff line change
    @@ -71,6 +71,22 @@ order allow,deny
    deny from all
    </files>
    ```

    #### 10. Limit Login to Specific IP
    ```ApacheConf
    ErrorDocument 401 /index.php?error=404
    ErrorDocument 403 /index.php?error=404
    <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{REQUEST_URI} ^(.*)?wp-login\.php(.*)$ [OR]
    RewriteCond %{REQUEST_URI} ^(.*)?wp-admin$
    RewriteCond %{REMOTE_ADDR} !^IP Address One$
    RewriteCond %{REMOTE_ADDR} !^IP Address Two$
    RewriteCond %{REMOTE_ADDR} !^IP Address Three$
    RewriteRule ^(.*)$ - [R=403,L]
    </IfModule>
    ```
    <a name="plugins"></a>
    ## Plugins and Other

  9. @tlongren tlongren revised this gist Aug 4, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion wordpress-hardening-techniques.md
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ Securing WordPress using a combination of [configuration changes](#config) and [

    #### 2. Hide `.htaccess` and `wp-config.php`
    ```ApacheConf
    <Files .htaccess>
    <Files .htaccess wp-config.php>
    order allow,deny
    deny from all
    </Files>
  10. @tlongren tlongren renamed this gist Aug 4, 2017. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  11. @tlongren tlongren revised this gist Aug 4, 2017. No changes.
  12. @tlongren tlongren revised this gist Aug 4, 2017. No changes.
  13. @tlongren tlongren revised this gist Aug 4, 2017. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@ Securing WordPress using a combination of [configuration changes](#config) and [
    #### 1. Add [keys](https://api.wordpress.org/secret-key/1.1/salt/) to `wp-config.php`

    #### 2. Hide `.htaccess` and `wp-config.php`
    ```
    ```ApacheConf
    <Files .htaccess>
    order allow,deny
    deny from all
    @@ -27,7 +27,7 @@ define('DISALLOW_FILE_EDIT', true);
    ```

    #### 5. Disable access to `wp-includes/`
    ```
    ```ApacheConf
    # Block wp-includes folder and files
    <IfModule mod_rewrite.c>
    RewriteEngine On
    @@ -41,13 +41,13 @@ RewriteRule ^wp-includes/theme-compat/ - [F,L]
    ```

    #### 6. Prevent username enumeration
    ```
    ```ApacheConf
    RewriteCond %{QUERY_STRING} author=d
    RewriteRule ^ /? [L,R=301]
    ```

    #### 7. Prevent script injection
    ```
    ```ApacheConf
    Options +FollowSymLinks
    RewriteEngine On
    RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
    @@ -57,15 +57,15 @@ RewriteRule ^(.*)$ index.php [F,L]
    ```

    #### 8. Prevent PHP execution using `.htaccess`. This `.htaccess` files goes in `wp-content/uploads/`.
    ```
    ```ApacheConf
    # Kill PHP Execution
    <Files *.php>
    deny from all
    </Files>
    ```

    #### 9. Disable `xml-rpc.php` if not using mobile app for site management
    ```
    ```ApacheConf
    <files xmlrpc.php>
    order allow,deny
    deny from all
    @@ -74,7 +74,7 @@ deny from all
    <a name="plugins"></a>
    ## Plugins and Other

    #### 1. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/
    #### 1. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/)

    #### 2. Limit login attempts via functionality plugin or `functions.php` theme file
    ```php
  14. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -173,4 +173,4 @@ if ( ! class_exists( 'Limit_Login_Attempts' ) ) {
    new Limit_Login_Attempts(3,1800);
    ```

    #### 3. If you need functionality not already provided via config changes, install [WordFence](https://wordpress.org/plugins/wordfence/)
    #### 3. If you need functionality not already provided above, like blocking known attackers, install [WordFence](https://wordpress.org/plugins/wordfence/)
  15. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -74,7 +74,7 @@ deny from all
    <a name="plugins"></a>
    ## Plugins and Other

    #### 1. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/)
    #### 1. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/

    #### 2. Limit login attempts via functionality plugin or `functions.php` theme file
    ```php
    @@ -171,4 +171,6 @@ if ( ! class_exists( 'Limit_Login_Attempts' ) ) {

    // enable login attempt limiting
    new Limit_Login_Attempts(3,1800);
    ```
    ```

    #### 3. If you need functionality not already provided via config changes, install [WordFence](https://wordpress.org/plugins/wordfence/)
  16. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 9 additions and 12 deletions.
    21 changes: 9 additions & 12 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -74,11 +74,9 @@ deny from all
    <a name="plugins"></a>
    ## Plugins and Other

    #### 1. Install [WordFence](https://wordpress.org/plugins/wordfence/)
    #### 1. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/)

    #### 2. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/)

    #### 3. Limit login attempts via functionality plugin or `functions.php` theme file
    #### 2. Limit login attempts via functionality plugin or `functions.php` theme file
    ```php
    <?php
    /**
    @@ -89,11 +87,11 @@ deny from all
    if ( ! class_exists( 'Limit_Login_Attempts' ) ) {
    class Limit_Login_Attempts {

    var $failed_login_limit = 3; //Number of authentification accepted
    var $lockout_duration = 1800; //Stop authentification process for 30 minutes: 60*30 = 1800
    var $transient_name = 'attempted_login'; //Transient used
    var $transient_name = 'attempted_login';

    public function __construct() {
    public function __construct($attempts = 3, $duration = 1800) {
    $this->failed_login_limit = $attempts;
    $this->lockout_duration = $duration;
    add_filter( 'authenticate', array( $this, 'check_attempted_login' ), 30, 3 );
    add_action( 'wp_login_failed', array( $this, 'login_failed' ), 10, 1 );
    }
    @@ -109,7 +107,7 @@ if ( ! class_exists( 'Limit_Login_Attempts' ) ) {
    $until = get_option( '_transient_timeout_' . $this->transient_name );
    $time = $this->when( $until );

    return new WP_Error( 'too_many_tried', sprintf( __( '<strong>ERROR</strong>: You have reached authentification limit, you will be able to try again in %1$s.' ) , $time ) );
    return new WP_Error( 'too_many_attempts', sprintf( __( '<strong>ERROR</strong>: You have reached authentification limit, you will be able to try again in %1$s.' ) , $time ) );
    }
    }

    @@ -171,7 +169,6 @@ if ( ! class_exists( 'Limit_Login_Attempts' ) ) {
    }
    }

    //Enable it:
    new Limit_Login_Attempts();
    ?>
    // enable login attempt limiting
    new Limit_Login_Attempts(3,1800);
    ```
  17. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -155,7 +155,7 @@ if ( ! class_exists( 'Limit_Login_Attempts' ) ) {
    $day = $hour * 24;

    if ( $diff < $minute )
    return floor( $diff / $second ) . ' secondes';
    return floor( $diff / $second ) . ' seconds';

    if ( $diff < $minute * 2 )
    return "about 1 minute ago";
  18. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    # Hardening WordPress
    Securing WordPress installs using a combination of [configuration changes](#config) and [plugins](#plugins).
    Securing WordPress using a combination of [configuration changes](#config) and [plugins](#plugins).

    <a name="config"></a>
    ## `.htaccess` and `wp-config.php` tasks
    @@ -21,7 +21,7 @@ define('ABSPATH', dirname(__FILE__) . '/');
    require_once(ABSPATH . '../path/to/wp-config.php');
    ```

    #### 4. Disable file editing in `wp-config.php`
    #### 4. Disable file editing. Add the following to `wp-config.php`
    ```php
    define('DISALLOW_FILE_EDIT', true);
    ```
  19. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -56,7 +56,7 @@ RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
    RewriteRule ^(.*)$ index.php [F,L]
    ```

    #### 8. Prevent PHP execution using `.htaccess` file placed in `wp-content/uploads/`
    #### 8. Prevent PHP execution using `.htaccess`. This `.htaccess` files goes in `wp-content/uploads/`.
    ```
    # Kill PHP Execution
    <Files *.php>
  20. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ require_once(ABSPATH . '../path/to/wp-config.php');
    define('DISALLOW_FILE_EDIT', true);
    ```

    #### 5. Disable access to `wp-includes`
    #### 5. Disable access to `wp-includes/`
    ```
    # Block wp-includes folder and files
    <IfModule mod_rewrite.c>
    @@ -56,7 +56,7 @@ RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
    RewriteRule ^(.*)$ index.php [F,L]
    ```

    #### 8. Prevent PHP execution using `.htaccess` file placed in `wp-content/uploads`
    #### 8. Prevent PHP execution using `.htaccess` file placed in `wp-content/uploads/`
    ```
    # Kill PHP Execution
    <Files *.php>
  21. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@ Securing WordPress installs using a combination of [configuration changes](#conf

    #### 1. Add [keys](https://api.wordpress.org/secret-key/1.1/salt/) to `wp-config.php`

    #### 2. Hide `.htaccess`
    #### 2. Hide `.htaccess` and `wp-config.php`
    ```
    <Files .htaccess>
    order allow,deny
  22. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    # Hardening WordPress
    Securing WordPress using [configuration changes](#config) and [plugins](#plugins).
    Securing WordPress installs using a combination of [configuration changes](#config) and [plugins](#plugins).

    <a name="config"></a>
    ## `.htaccess` and `wp-config.php` tasks
  23. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 19 additions and 15 deletions.
    34 changes: 19 additions & 15 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -1,28 +1,32 @@
    # `.htaccess` and `wp-config.php` tasks
    # Hardening WordPress
    Securing WordPress using [configuration changes](#config) and [plugins](#plugins).

    ### 1. Add [keys](https://api.wordpress.org/secret-key/1.1/salt/) to `wp-config.php`
    <a name="config"></a>
    ## `.htaccess` and `wp-config.php` tasks

    ### 2. Hide `.htaccess`
    #### 1. Add [keys](https://api.wordpress.org/secret-key/1.1/salt/) to `wp-config.php`

    #### 2. Hide `.htaccess`
    ```
    <Files .htaccess>
    order allow,deny
    deny from all
    </Files>
    ```

    ### 3. Move `wp-config.php` to another location and create a new `wp-config.php` to include it
    #### 3. Move `wp-config.php` to another location and create a new `wp-config.php` to include it
    ```php
    <?php
    define('ABSPATH', dirname(__FILE__) . '/');
    require_once(ABSPATH . '../path/to/wp-config.php');
    ```

    ### 4. Disable file editing in `wp-config.php`
    #### 4. Disable file editing in `wp-config.php`
    ```php
    define('DISALLOW_FILE_EDIT', true);
    ```

    ### 5. Disable access to `wp-includes`
    #### 5. Disable access to `wp-includes`
    ```
    # Block wp-includes folder and files
    <IfModule mod_rewrite.c>
    @@ -36,13 +40,13 @@ RewriteRule ^wp-includes/theme-compat/ - [F,L]
    </IfModule>
    ```

    ### 6. Prevent username enumeration
    #### 6. Prevent username enumeration
    ```
    RewriteCond %{QUERY_STRING} author=d
    RewriteRule ^ /? [L,R=301]
    ```

    ### 7. Prevent script injection
    #### 7. Prevent script injection
    ```
    Options +FollowSymLinks
    RewriteEngine On
    @@ -52,29 +56,29 @@ RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
    RewriteRule ^(.*)$ index.php [F,L]
    ```

    ### 8. Prevent PHP execution using `.htaccess` file placed in `wp-content/uploads`
    #### 8. Prevent PHP execution using `.htaccess` file placed in `wp-content/uploads`
    ```
    # Kill PHP Execution
    <Files *.php>
    deny from all
    </Files>
    ```

    ### 9. Disable `xml-rpc.php` if not using mobile app for site management
    #### 9. Disable `xml-rpc.php` if not using mobile app for site management
    ```
    <files xmlrpc.php>
    order allow,deny
    deny from all
    </files>
    ```
    <a name="plugins"></a>
    ## Plugins and Other

    # Plugins and Other

    ### 1. Install [WordFence](https://wordpress.org/plugins/wordfence/)
    #### 1. Install [WordFence](https://wordpress.org/plugins/wordfence/)

    ### 2. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/)
    #### 2. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/)

    ### 3. Limit login attempts via functionality plugin or `functions.php` theme file
    #### 3. Limit login attempts via functionality plugin or `functions.php` theme file
    ```php
    <?php
    /**
  24. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 18 additions and 2 deletions.
    20 changes: 18 additions & 2 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    ## `.htaccess` and `wp-config.php` tasks
    # `.htaccess` and `wp-config.php` tasks

    ### 1. Add [keys](https://api.wordpress.org/secret-key/1.1/salt/) to `wp-config.php`

    @@ -52,7 +52,23 @@ RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
    RewriteRule ^(.*)$ index.php [F,L]
    ```

    ## Plugins and Other
    ### 8. Prevent PHP execution using `.htaccess` file placed in `wp-content/uploads`
    ```
    # Kill PHP Execution
    <Files *.php>
    deny from all
    </Files>
    ```

    ### 9. Disable `xml-rpc.php` if not using mobile app for site management
    ```
    <files xmlrpc.php>
    order allow,deny
    deny from all
    </files>
    ```

    # Plugins and Other

    ### 1. Install [WordFence](https://wordpress.org/plugins/wordfence/)

  25. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 9 additions and 1 deletion.
    10 changes: 9 additions & 1 deletion things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    ## `.htaccess` and `wp-config.php` tasks

    ### 1. Add [keys](https://api.wordpress.org/secret-key/1.1/salt/) to `wp-config.php`

    ### 2. Hide `.htaccess`
    @@ -50,7 +52,13 @@ RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
    RewriteRule ^(.*)$ index.php [F,L]
    ```

    ### 8. Limit login attempts if necessary
    ## Plugins and Other

    ### 1. Install [WordFence](https://wordpress.org/plugins/wordfence/)

    ### 2. Install [Exploit Scanner](https://wordpress.org/plugins/exploit-scanner/)

    ### 3. Limit login attempts via functionality plugin or `functions.php` theme file
    ```php
    <?php
    /**
  26. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 8 additions and 8 deletions.
    16 changes: 8 additions & 8 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -1,26 +1,26 @@
    ### Add [keys](https://api.wordpress.org/secret-key/1.1/salt/) to `wp-config.php`
    ### 1. Add [keys](https://api.wordpress.org/secret-key/1.1/salt/) to `wp-config.php`

    ### Hide `.htaccess`
    ### 2. Hide `.htaccess`
    ```
    <Files .htaccess>
    order allow,deny
    deny from all
    </Files>
    ```

    ### Move `wp-config.php` to another location and create a new `wp-config.php` to include it
    ### 3. Move `wp-config.php` to another location and create a new `wp-config.php` to include it
    ```php
    <?php
    define('ABSPATH', dirname(__FILE__) . '/');
    require_once(ABSPATH . '../path/to/wp-config.php');
    ```

    ### Disable file editing in `wp-config.php`
    ### 4. Disable file editing in `wp-config.php`
    ```php
    define('DISALLOW_FILE_EDIT', true);
    ```

    ### Disable access to `wp-includes`
    ### 5. Disable access to `wp-includes`
    ```
    # Block wp-includes folder and files
    <IfModule mod_rewrite.c>
    @@ -34,13 +34,13 @@ RewriteRule ^wp-includes/theme-compat/ - [F,L]
    </IfModule>
    ```

    ### Prevent username enumeration
    ### 6. Prevent username enumeration
    ```
    RewriteCond %{QUERY_STRING} author=d
    RewriteRule ^ /? [L,R=301]
    ```

    ### Prevent script injection
    ### 7. Prevent script injection
    ```
    Options +FollowSymLinks
    RewriteEngine On
    @@ -50,7 +50,7 @@ RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
    RewriteRule ^(.*)$ index.php [F,L]
    ```

    ### Limit login attempts if necessary
    ### 8. Limit login attempts if necessary
    ```php
    <?php
    /**
  27. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 8 additions and 8 deletions.
    16 changes: 8 additions & 8 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -1,26 +1,26 @@
    ### 1. Add [keys](https://api.wordpress.org/secret-key/1.1/salt/) to `wp-config.php`
    ### Add [keys](https://api.wordpress.org/secret-key/1.1/salt/) to `wp-config.php`

    ### 2. Hide `.htaccess`
    ### Hide `.htaccess`
    ```
    <Files .htaccess>
    order allow,deny
    deny from all
    </Files>
    ```

    ### 3. Move `wp-config.php` to another location and create a new `wp-config.php` to include it
    ### Move `wp-config.php` to another location and create a new `wp-config.php` to include it
    ```php
    <?php
    define('ABSPATH', dirname(__FILE__) . '/');
    require_once(ABSPATH . '../path/to/wp-config.php');
    ```

    ### 4. Disable file editing in `wp-config.php`
    ### Disable file editing in `wp-config.php`
    ```php
    define('DISALLOW_FILE_EDIT', true);
    ```

    ### 5. Disable access to `wp-includes`
    ### Disable access to `wp-includes`
    ```
    # Block wp-includes folder and files
    <IfModule mod_rewrite.c>
    @@ -34,13 +34,13 @@ RewriteRule ^wp-includes/theme-compat/ - [F,L]
    </IfModule>
    ```

    ### 6. Prevent username enumeration
    ### Prevent username enumeration
    ```
    RewriteCond %{QUERY_STRING} author=d
    RewriteRule ^ /? [L,R=301]
    ```

    ### 7. Prevent script injections
    ### Prevent script injection
    ```
    Options +FollowSymLinks
    RewriteEngine On
    @@ -50,7 +50,7 @@ RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
    RewriteRule ^(.*)$ index.php [F,L]
    ```

    ### 8. Limit login attempts if necessary
    ### Limit login attempts if necessary
    ```php
    <?php
    /**
  28. @tlongren tlongren revised this gist Aug 3, 2017. 2 changed files with 98 additions and 94 deletions.
    94 changes: 0 additions & 94 deletions class-limit-login-attempts.php
    Original file line number Diff line number Diff line change
    @@ -1,94 +0,0 @@
    <?php
    /**
    * CLASS LIMIT LOGIN ATTEMPTS
    * Prevent Mass WordPress Login Attacks by setting locking the system when login fail.
    * To be added in functions.php or as an external file.
    */
    if ( ! class_exists( 'Limit_Login_Attempts' ) ) {
    class Limit_Login_Attempts {

    var $failed_login_limit = 3; //Number of authentification accepted
    var $lockout_duration = 1800; //Stop authentification process for 30 minutes: 60*30 = 1800
    var $transient_name = 'attempted_login'; //Transient used

    public function __construct() {
    add_filter( 'authenticate', array( $this, 'check_attempted_login' ), 30, 3 );
    add_action( 'wp_login_failed', array( $this, 'login_failed' ), 10, 1 );
    }

    /**
    * Lock login attempts of failed login limit is reached
    */
    public function check_attempted_login( $user, $username, $password ) {
    if ( get_transient( $this->transient_name ) ) {
    $datas = get_transient( $this->transient_name );

    if ( $datas['tried'] >= $this->failed_login_limit ) {
    $until = get_option( '_transient_timeout_' . $this->transient_name );
    $time = $this->when( $until );

    return new WP_Error( 'too_many_tried', sprintf( __( '<strong>ERROR</strong>: You have reached authentification limit, you will be able to try again in %1$s.' ) , $time ) );
    }
    }

    return $user;
    }


    /**
    * Add transient
    */
    public function login_failed( $username ) {
    if ( get_transient( $this->transient_name ) ) {
    $datas = get_transient( $this->transient_name );
    $datas['tried']++;

    if ( $datas['tried'] <= $this->failed_login_limit )
    set_transient( $this->transient_name, $datas , $this->lockout_duration );
    } else {
    $datas = array(
    'tried' => 1
    );
    set_transient( $this->transient_name, $datas , $this->lockout_duration );
    }
    }


    /**
    * Return difference between 2 given dates
    * @param int $time Date as Unix timestamp
    * @return string Return string
    */
    private function when( $time ) {
    if ( ! $time )
    return;

    $right_now = time();

    $diff = abs( $right_now - $time );

    $second = 1;
    $minute = $second * 60;
    $hour = $minute * 60;
    $day = $hour * 24;

    if ( $diff < $minute )
    return floor( $diff / $second ) . ' secondes';

    if ( $diff < $minute * 2 )
    return "about 1 minute ago";

    if ( $diff < $hour )
    return floor( $diff / $minute ) . ' minutes';

    if ( $diff < $hour * 2 )
    return 'about 1 hour';

    return floor( $diff / $hour ) . ' hours';
    }
    }
    }

    //Enable it:
    new Limit_Login_Attempts();
    ?>
    98 changes: 98 additions & 0 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -48,4 +48,102 @@ RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR]
    RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
    RewriteRule ^(.*)$ index.php [F,L]
    ```

    ### 8. Limit login attempts if necessary
    ```php
    <?php
    /**
    * CLASS LIMIT LOGIN ATTEMPTS
    * Prevent Mass WordPress Login Attacks by setting locking the system when login fail.
    * To be added in functions.php or as an external file.
    */
    if ( ! class_exists( 'Limit_Login_Attempts' ) ) {
    class Limit_Login_Attempts {

    var $failed_login_limit = 3; //Number of authentification accepted
    var $lockout_duration = 1800; //Stop authentification process for 30 minutes: 60*30 = 1800
    var $transient_name = 'attempted_login'; //Transient used

    public function __construct() {
    add_filter( 'authenticate', array( $this, 'check_attempted_login' ), 30, 3 );
    add_action( 'wp_login_failed', array( $this, 'login_failed' ), 10, 1 );
    }

    /**
    * Lock login attempts of failed login limit is reached
    */
    public function check_attempted_login( $user, $username, $password ) {
    if ( get_transient( $this->transient_name ) ) {
    $datas = get_transient( $this->transient_name );

    if ( $datas['tried'] >= $this->failed_login_limit ) {
    $until = get_option( '_transient_timeout_' . $this->transient_name );
    $time = $this->when( $until );

    return new WP_Error( 'too_many_tried', sprintf( __( '<strong>ERROR</strong>: You have reached authentification limit, you will be able to try again in %1$s.' ) , $time ) );
    }
    }

    return $user;
    }


    /**
    * Add transient
    */
    public function login_failed( $username ) {
    if ( get_transient( $this->transient_name ) ) {
    $datas = get_transient( $this->transient_name );
    $datas['tried']++;

    if ( $datas['tried'] <= $this->failed_login_limit )
    set_transient( $this->transient_name, $datas , $this->lockout_duration );
    } else {
    $datas = array(
    'tried' => 1
    );
    set_transient( $this->transient_name, $datas , $this->lockout_duration );
    }
    }


    /**
    * Return difference between 2 given dates
    * @param int $time Date as Unix timestamp
    * @return string Return string
    */
    private function when( $time ) {
    if ( ! $time )
    return;

    $right_now = time();

    $diff = abs( $right_now - $time );

    $second = 1;
    $minute = $second * 60;
    $hour = $minute * 60;
    $day = $hour * 24;

    if ( $diff < $minute )
    return floor( $diff / $second ) . ' secondes';

    if ( $diff < $minute * 2 )
    return "about 1 minute ago";

    if ( $diff < $hour )
    return floor( $diff / $minute ) . ' minutes';

    if ( $diff < $hour * 2 )
    return 'about 1 hour';

    return floor( $diff / $hour ) . ' hours';
    }
    }
    }

    //Enable it:
    new Limit_Login_Attempts();
    ?>
    ```
  29. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 94 additions and 0 deletions.
    94 changes: 94 additions & 0 deletions class-limit-login-attempts.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,94 @@
    <?php
    /**
    * CLASS LIMIT LOGIN ATTEMPTS
    * Prevent Mass WordPress Login Attacks by setting locking the system when login fail.
    * To be added in functions.php or as an external file.
    */
    if ( ! class_exists( 'Limit_Login_Attempts' ) ) {
    class Limit_Login_Attempts {

    var $failed_login_limit = 3; //Number of authentification accepted
    var $lockout_duration = 1800; //Stop authentification process for 30 minutes: 60*30 = 1800
    var $transient_name = 'attempted_login'; //Transient used

    public function __construct() {
    add_filter( 'authenticate', array( $this, 'check_attempted_login' ), 30, 3 );
    add_action( 'wp_login_failed', array( $this, 'login_failed' ), 10, 1 );
    }

    /**
    * Lock login attempts of failed login limit is reached
    */
    public function check_attempted_login( $user, $username, $password ) {
    if ( get_transient( $this->transient_name ) ) {
    $datas = get_transient( $this->transient_name );

    if ( $datas['tried'] >= $this->failed_login_limit ) {
    $until = get_option( '_transient_timeout_' . $this->transient_name );
    $time = $this->when( $until );

    return new WP_Error( 'too_many_tried', sprintf( __( '<strong>ERROR</strong>: You have reached authentification limit, you will be able to try again in %1$s.' ) , $time ) );
    }
    }

    return $user;
    }


    /**
    * Add transient
    */
    public function login_failed( $username ) {
    if ( get_transient( $this->transient_name ) ) {
    $datas = get_transient( $this->transient_name );
    $datas['tried']++;

    if ( $datas['tried'] <= $this->failed_login_limit )
    set_transient( $this->transient_name, $datas , $this->lockout_duration );
    } else {
    $datas = array(
    'tried' => 1
    );
    set_transient( $this->transient_name, $datas , $this->lockout_duration );
    }
    }


    /**
    * Return difference between 2 given dates
    * @param int $time Date as Unix timestamp
    * @return string Return string
    */
    private function when( $time ) {
    if ( ! $time )
    return;

    $right_now = time();

    $diff = abs( $right_now - $time );

    $second = 1;
    $minute = $second * 60;
    $hour = $minute * 60;
    $day = $hour * 24;

    if ( $diff < $minute )
    return floor( $diff / $second ) . ' secondes';

    if ( $diff < $minute * 2 )
    return "about 1 minute ago";

    if ( $diff < $hour )
    return floor( $diff / $minute ) . ' minutes';

    if ( $diff < $hour * 2 )
    return 'about 1 hour';

    return floor( $diff / $hour ) . ' hours';
    }
    }
    }

    //Enable it:
    new Limit_Login_Attempts();
    ?>
  30. @tlongren tlongren revised this gist Aug 3, 2017. 1 changed file with 29 additions and 0 deletions.
    29 changes: 29 additions & 0 deletions things-to-do.md
    Original file line number Diff line number Diff line change
    @@ -20,3 +20,32 @@ require_once(ABSPATH . '../path/to/wp-config.php');
    define('DISALLOW_FILE_EDIT', true);
    ```

    ### 5. Disable access to `wp-includes`
    ```
    # Block wp-includes folder and files
    <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^wp-admin/includes/ - [F,L]
    RewriteRule !^wp-includes/ - [S=3]
    RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
    RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
    RewriteRule ^wp-includes/theme-compat/ - [F,L]
    </IfModule>
    ```

    ### 6. Prevent username enumeration
    ```
    RewriteCond %{QUERY_STRING} author=d
    RewriteRule ^ /? [L,R=301]
    ```

    ### 7. Prevent script injections
    ```
    Options +FollowSymLinks
    RewriteEngine On
    RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR]
    RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
    RewriteRule ^(.*)$ index.php [F,L]
    ```