Namecheap
See the top rated post in this thread. Click here

+ Post New Thread
Results 1 to 2 of 2

Thread: Tips to secure Wordpress - Prevent malicious code execution & file modiffication

  1. #1
    Fli
    Fli is online now
    Administrator Fli's Avatar
    Join Date
    Mar 2013
    Posts
    2,464

    Tips to secure Wordpress - Prevent malicious code execution & file modiffication

    make money with your web site


    Hi, do You know any good tutorials or ways on how to secure/harden/protect wordpress against hacking?

    I found and tested following information on how to secure wordpress, these are only veriffied and the best advices filtered out of many that are low or no efficient.

    # TIP 0


    Backup your site regularly. Imagine that someone delete your website and mysql and you dont have any backup... So make sure Your wordpress website and mysql database (or entire hosting account) is backed up regularly. There are wp plugins that does this automatically (search: wordpress auto backup mysql files plugins). You may check "Script to backup website files and mysql database to the website subfolder"

    # TIP 0.5

    Install plugin like https://wordpress.org/plugins/ninjafirewall/
    But if you prefer not to install such a plugin, continue reading.

    # TIP 1


    - disallow listing of files in wordpress directories if there is no index.php or index.html file
    - disallow opening .php files directly
    - disallow opening include-only files
    - disallow opening wp-config.php file
    - disallow suspicious/hacking requests

    Add following code into .htaccess file (located in same folder as index.php, wp-config.php):

    Code:
    # Disable directory browsing
    Options All -Indexes
    
    # disallow opening/executing .php file directly
    RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /[^\ ]+\.php($|\ )
    RewriteCond %{REQUEST_URI} !wp-comments-post.php
    RewriteCond %{REQUEST_URI} !wp-login.php
    RewriteRule \.php$ / [F,L]
    
    # Block the include-only 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>
    
    # Disallow executing wp-config file
    <files wp-config.php>
    Order Allow,Deny
    Deny from All
    </files>
    
    # htaccess firewall v1.0 | https://github.com/alidbg/htaccess_firewall
    <IfModule mod_rewrite.c>
    ServerSignature Off
    Options -Indexes
    RewriteEngine On
    ErrorDocument 403 "This request is forbidden by the htaccess firewall <a href=https://github.com/alidbg/htaccess_firewall target=_blank>https://github.com/alidbg/htaccess_firewall</a>"
    RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK|DEBUG) [NC]
    RewriteRule ^(.*)$ - [F]
    RewriteCond %{REQUEST_URI} (wp-config\.php|config\.php|bb-config\.php|timthumb\.php|phpthumb\.php|thumb\.php|thumbs\.php|debug\.log) [NC,OR]
    RewriteCond %{REQUEST_URI} \.(htaccess|htpasswd|errordocs|logs|po|mo|ini|inc)$ [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} (;|<|>|'|"|\)|\(|%0A|%0D|%22|%27|%28|%3C|%3E|%00).*(libwww-perl|wget|python|nikto|curl|scan|java|winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner) [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} (havij|libwww-perl|wget|python|nikto|curl|scan|java|winhttp|clshttp|loader) [NC,OR]
    RewriteCond %{HTTP_USER_AGENT} (%0A|%0D|%27|%3C|%3E|%00|%60) [NC,OR]
    RewriteCond %{HTTP_REFERER} (%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
    RewriteCond %{THE_REQUEST} \?\ HTTP/ [NC,OR]
    RewriteCond %{THE_REQUEST} \/\*\ HTTP/ [NC,OR]
    RewriteCond %{HTTP_COOKIE} (`|'|"|%22|%0A|%0D|%27|%3C|%28|%3E|%00|%60).*(declare|char|setBAD|cast|convert|delete|drop|exec|eval|insert|meta|script|select|truncate|update|union|md5|benchmark|create|alter|order|encode|if|and|orBAD).* [NC,OR]
    RewriteCond %{QUERY_STRING} (`|'|"|%22|%0A|%0D|%27|%3C|%28|%3E|%00|%60).*(declare|char|set|cast|convert|delete|drop|exec|eval|insert|meta|script|select|truncate|update|union|md5|benchmark|create|alter|order|encode|if|and|or).* [NC,OR]
    RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http:// [NC,OR]
    RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(\.\.//?)+ [NC,OR]
    RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ [NC,OR]
    RewriteCond %{QUERY_STRING} \=PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC,OR]
    RewriteCond %{QUERY_STRING} (\.\./|%2e%2e%2f|%2e%2e/|\.\.%2f|%2e\.%2f|%2e\./|\.%2e%2f|\.%2e/) [NC,OR]
    RewriteCond %{QUERY_STRING} ftp\: [NC,OR]
    RewriteCond %{QUERY_STRING} http\: [NC,OR]
    RewriteCond %{QUERY_STRING} https\: [NC,OR]
    RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
    RewriteCond %{QUERY_STRING} ^(.*)/self/(.*)$ [NC,OR]
    RewriteCond %{QUERY_STRING} ^(.*)cPath=http://(.*)$ [NC,OR]
    RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} (\<|%3C).*embed.*(\>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} (<|%3C)([^e]*e)+mbed.*(>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} (\<|%3C).*object.*(\>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} (<|%3C)([^o]*o)+bject.*(>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} (\<|%3C).*iframe.*(\>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} (<|%3C)([^i]*i)+frame.*(>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
    RewriteCond %{QUERY_STRING} base64_(en|de)code[^(]*\([^)]*\) [NC,OR]
    RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
    RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR]
    RewriteCond %{QUERY_STRING} ^.*(\(|\)|<|>|%3c|%3e).* [NC,OR]
    RewriteCond %{QUERY_STRING} ^.*(\x00|\x04|\x08|\x0d|\x1b|\x20|\x3c|\x3e|\x7f).* [NC,OR]
    RewriteCond %{QUERY_STRING} (NULL|OUTFILE|LOAD_FILE) [OR]
    RewriteCond %{QUERY_STRING} (\.{1,}/)+(motd|etc|bin) [NC,OR]
    RewriteCond %{QUERY_STRING} (localhost|loopback|127\.0\.0\.1) [NC,OR]
    RewriteCond %{QUERY_STRING} (`|<|>|'|%0A|%0D|%27|%3C|%3E|%00|%60) [NC,OR]
    RewriteCond %{QUERY_STRING} concat[^\(]*\( [NC,OR]
    RewriteCond %{QUERY_STRING} union([^s]*s)+elect [NC,OR]
    RewriteCond %{QUERY_STRING} union([^a]*a)+ll([^s]*s)+elect [NC,OR]
    RewriteCond %{QUERY_STRING} \-[sdcr].*(allow_url_include|allow_url_fopen|safe_mode|disable_functions|auto_prepend_file) [NC,OR]
    RewriteCond %{QUERY_STRING} (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode|and|or|if) [NC,OR]
    RewriteCond %{QUERY_STRING} (sp_executesql) [NC]
    RewriteRule ^(.*)$ - [F]
    </IfModule>
    # END htaccess firewall
    To restrict admin area only to one/your IP, you can append following code to above mentioned .htaccess file:
    Code:
    # Allow only your IPs (www.myip.ms) to access login page (bots can put load on your server)
    <Files wp-login.php>
    Order deny,allow
    Deny from All
    Allow from xxx.xxx.xxx.xxx
    Allow from yyy.yyy.yyy.yyy
    </Files>
    If you see Error 500 on your site, then try to remove some parts of the code you inserted.

    # TIP 2

    Disallow executing any .php* .htm* and .js files in wp-content directory tree. So if any thief inject an bad .php script (shell,spamming script, ddos script etc), he should not be able to run it (unless he include it into an existing wordpress file). Test that website works properly after adding the rules into /wp-content/.htaccess.


    Code:
    <Files *.php*>
    Deny from All
    </Files>
    
    #<Files *.js>
    #Deny from All
    #</Files>
    
    <Files *.htm*>
    Deny from All
    </Files>
    i commented out (#) .js related block, because some plugins or themes fetch .js and php files from wp-content subdirectories, so you can uncomment it but then watch your apache error log after browsing your wordpress website if there are no errors.
    In case some plugin is denied to access its file, one can add .htaccess into its directory and allow particular file name like:
    <Files includefilename.extesion>
    Allow from All
    </Files>
    [/CODE]

    # TIP 3

    add following into /wp-includes/.htaccess and no one should execute any file from wp-includes folder in his web browser

    Code:
    RewriteRule ^(wp-includes)\/.*$ ./ [NC,R=301,L]
    do NOT add .php DENY FROM ALL into wp-includes or wordpress post editor may stop accepting any text input (more about wp editor issue)

    # TIP 4

    Disable writing permissions of the Wordpress files/folders (disallow anyone modifying files and adding new files).
    After this, wordpress updates will fail, plugin installation will fail, upload will fail. By doing this, you virtually lock wordpress files in its current state disallowing any script to change them.. I tested this and my wordpress frontend and backed worked quite OK.

    How to do it? Change permissions for files from 644 to 544 and folder permissions from 755 to 555


    • r = 4
    • w = 2
    • x = 1

    7 = r+w+x
    6 = r+w
    5 = r+x
    4= r

    Before doing any following commands, backup your files!

    option A changed all files and folders permissions to lack write bit (files - 544, folders - 555)
    I do it like this from linux command line:
    Code:
    cd /home/myusername/public_html
    find . -type f -exec chmod 544 {} \;
    find . -type d -exec chmod 555 {} \;
    use above commands very carefully, it can damage server if not done in the website directory but done for example from server / path. If its too hard for you to do above change, try placing following line in wp-config.php. It is equivalent to removing the 'edit_themes', 'edit_plugins' and 'edit_files' capabilities of all users: define('DISALLOW_FILE_EDIT', true);
    (its only from admin area change prevention, so not sufficing probably)

    Option B is to change permissions only for wp-content, wp-includes etc, but why to do it? I think its better to completelly secure site doing above commands (option A) then following ones. (i have experience my site got hacked/malicious scripts uploaded, files modiffied) using method B and C)

    Code:
    cd /home/myusername/public_html
    chmod 555 wp-content wp-includes wp-admin
    find ./wp-content -type f -print0 | xargs -0 chmod 544
    find ./wp-includes -type f -print0 | xargs -0 chmod 544
    find ./wp-content -type d -print0 | xargs -0 chmod 555
    find ./wp-includes -type d -print0 | xargs -0 chmod 555
    option C
    if one have many wordpress blogs and need to chmod 555 wp-content, wp-includes, wp-admin, one can do like: find /home/yourusername/public_html -type d -name "wp-content" -o -name "wp-includes" -o -name "wp-admin" -exec chmod 555 {} \;
    BUT that would change only these folders permission, not permission of its sub-folders (which is what i think is important). so after above command, i used following linux command for recursive subfolders change:
    Code:
    for i in $(find /home/myaccountname/public_html -iname "*wp-content*" -o -iname "*wp-includes*" -type d -exec find {} -type d \;);do chmod 555 $i;done
    it search whole /home/myaccountname/public_html path incl. subfolders for wp-content and wp-includes, find directories which has these phrasses in path and change permission so to disallow writing new changes/files into them.

    All options: if you are using any plugins which caching dynamic page elements as files, this plugin may stop working, stop be able to create files. Example my plugin "widget-cache" shown error "Fatal error: Cache file not writeable! in /home/*/public_html/wp-content/plugins/wp-widget-cache/inc/wcache.class.php on line 286", i removed this error by making this plugin cache files writable (changing their permissions): find . -path "*/wp-content/widget-cache/*" -type f -exec chmod 644 {} \;

    NOTE: After disabled writting into folders/files, you cant install any wordpress plugins without write permission to 3 folders: wp-content, wp-content/upgrade, wp-content/plugins
    Enable write permission temporarilly for these folders:
    # cd /home/yourusername/public_html
    # chmod 755 wp-content wp-content/plugins wp-content/upgrade
    then install/uninstall plugin and then disable writing again:
    # chmod 555 wp-content wp-content/plugins wp-content/upgrade

    IF REINFECTED: In case malicius files was still added into your site or files modiffied even you removed writing permission, it can mean that someone know hosting account password or there is some malicious script which changing file/folder permissions. Try to use linux tool "chattr" to enable immutable parameter for your folders/files.
    Lock files:
    # chattr +i /path/to/your/wordpress/folder -R
    Unlock files:
    # chattr -i /path/to/your/wordpress/folder -R
    It means not even root can change permissions of files/folders or change its contents, if immutalbe (i) is in place.

    # END OF TIP 4

    # TIP 5

    Find & block IP of person who abusing your hosting. If you discovered from Apache access log that IP address which accessed malicious script is always (on each re-infection) from same country like China, you may try to block this whole country IPs by adding them into .htaccess file located in your website root directory (same like index.php). I used this tool: https://www.countryipblocks.net/country_selection.php (or google: htaccess country IP deny) To veriffy that blocks really works, example google: "china web proxy" and access your website via that proxy (u need to ensure that this proxy site is really hosted in that forbidden country (put it into myip.ms)).

    ----
    Another non tested thing. Password protect the directory like wp-includes

    # TIP 6
    disallow URL ending with .php to be opened/executed: http://internetlifeforum.com/php-mys...file-directly/


    My oppinion/sumary:

    1. i think most effective is to setup automated, regular backups of the website files and database so i can recover it (# TIP 0)
    2. use file manager or linux shell to list wordpress folders/files and sort them by modification date, so you can find last modified/created files (can be malicious ones), so cleaning bad files
    3. then disable writing into all wordpress folders (# TIP 4, Option A), possibly applying immutable parameter via linux command line as mentioned above (chattr +i /path/to/your/wordpress/folder -R)

    Another Wordpress hardening tips:
    http://www.esecurityplanet.com/open-...-fix-them.html
    https://codex.wordpress.org/Hardening_WordPress

  2. #2
    Junior Member emanuelsharper's Avatar
    Join Date
    Sep 2014
    Location
    Mcclellan Afb, CA 95652
    Posts
    6


    1/1 found it usefull/helpfull Is this useful / helpfull? Yes | No
    That is very useful post for technical users. For non-tech WP users, some simple ways I often do to secure my Wordpress blogs are:

    1. never set username as "admin"
    2. use strong login passwords
    3. install anti-spam plugins: Akismet, Accurate Form Data, Disable Comments

+ Post New Thread

Similar Threads

  1. Replies: 0
    Last Post: 03-29-2015, 10:22 AM
  2. Replies: 0
    Last Post: 11-16-2014, 06:28 PM
  3. Replies: 0
    Last Post: 09-06-2014, 03:42 PM
  4. Replies: 0
    Last Post: 06-25-2014, 11:49 AM
  5. How to secure /cache folder agains malicious scripts?
    By Fli in forum HTML,CSS, Javascript Coding & Programming
    Replies: 0
    Last Post: 03-04-2014, 02:40 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
 Protected by : ZB BLOCK  &  StopForumSpam