Protection of PHP scripts from analysis and modification. Remember to change your cookie secret keys

All software products for protecting PHP scripts are divided into two categories: those that require installation of additional modules on the server and that work with the usual configuration of web servers. The former are more reliable in terms of security, as they translate PHP scripts from a textual form into a special binary code, but require access to the server with administrator rights. The latter can work on almost all hosting with PHP support, including free ones, but they are not very difficult to hack. Source code that does not use encryption or compression can be distinguished into a separate subgroup.

Server-level protections:

Zend Encoder / Zend SafeGuard Suite is the most popular commercial protection, modules for Zend support are usually installed on all paid hosting. Zend provides domain and ip scripting, trial script timing, and powerful obfuscation. All operating systems are supported. In the public domain there are several options for Zend removal utilities, all of them are modified PHP versions 4 and 5. Older versions of Zend are removed without problems, in the latter there are difficulties due to obfuscation of the source code.

New, actively developing commercial protection. It provides interaction with protected scripts at the level of its own APIs; Windows and Linux operating systems are supported. Due to its low prevalence, it is not installed on ordinary virtual hosting, but it may well be installed by users on dedicated servers. There are no public decoders.

Commercial protection is practically not found, it is not installed on virtual hosting. Allows you to set a trial period for scripts to check the date on external time servers, bind protected scripts to servers, ip-address, MAC-address of the network card, and this data is used for decryption. All operating systems are supported. There are no public decoders.

phpSHIELD. SourceGuardian for PHP prototype. After the merger of the two developers, it stopped developing as an independent product. The main functionality is the same, there are no public decoders.

ionCube PHP Encoder. The second most popular commercial product for protecting scripts. After the appearance of public decoders for Zend, it has become increasingly used and installed on shared hosting. Allows you to encrypt not only scripts, but also templates, xml-documents, images, binary files. It binds protected files to servers, there is a powerful obfuscator, all operating systems are supported. There are no public decoders, but in some cases it can be removed by deZender.

PHTML Encoder. A rare commercial security system that provides the usual functionality for products of this type, works under all operating systems. For a separate fee, you can purchase the original security codes and modify them to fit your needs. There are no public decoders.

DWebEncoder. Exotic protection for Windows designed to create scripted presentations and catalogs on CDs. In the installed form, it is something like an independent web server on which encoded php scripts are executed. There are no public decoders.

PHP Compact. The defense is theoretical rather than practical. It was developed on one of the domestic forums, but it looks like it did not progress beyond the author's releases. There are no decoders, as well as protected scripts.

An open source add-on to the vintage php accelerators Turck MMCache and eAccelerator. Converts scripts to bytecode in order to increase the speed of their execution. There are versions of modules for Windows and Linux. There are no public decoders, but perhaps the open source code of the project will somehow help in the study.

Source-level protections:

PHP LockIt! ... Popular commercial protection, it is very common, mainly in scripts from foreign developers. Allows you to set a trial period for the operation of scripts, binding to domains and ip-addresses, compresses scripts using standard php tools (gzinflate). The only tricky part is a good obfuscator. The different protection versions differ only in the modification of the unpacking module. Easily removable in both manual and automatic modes. Without an obfuscator, it is removed exactly to the source code, with an obfuscator, it requires additional processing.

CNCrypto. There is not even a demo version in the public domain, the analysis was carried out using protected scripts. The hinged module is not difficult to unpack, the protection is based only on good obfuscation of the source code.

PHPCipher. Protection is an online service. An archive with your scripts is uploaded to the site and the already protected one is downloaded back. A paid license allows you to sign protected scripts with your data and use it for commercial purposes. The free license allows for personal use only. The protection itself is a php-module protected by Zend, which connects to protected scripts. After deZend, the protection module and obtaining all the necessary constants from it is removed completely to the source code. There is no obfuscator function.

ByteRun Protector for PHP. A commercial product, depending on the type of license, allows you to protect scripts both at the server level and at the source code level. Server protection with standard features, nothing special. Script-level protection can be removed very easily automatically and manually. There is no public decoder for the server version.

Protection very popular among domestic developers. It is a protection module heavily littered with empty code, which is connected via include to protected scripts. The decoding algorithm is very simple, it does not cause any difficulties in manual and automatic removal. In all cases, it is removed completely to the source code, there is no obfuscator function. There are small features for special cases of decoding, but they will not be described here.

CodeLock. Another popular defense, a great example of illiterate programming. It is a php application that allows you to encode both the scripts themselves and the result of their work in the browser using javascript. Scripts can be protected with a password, but because of the mediocre implementation, the password is easy to find out even without removing the hinged protection. The protection module is a php script littered with empty code that connects to protected scripts. The protection algorithm is very simple, it is removed completely to the source code. There is no obfuscation function.

TrueBug PHP Encoder, more recently TrueBug PHP Obfuscator & Encoder. A very interesting tread to explore. Before version 1.0.2, the standard php tools for gzip-compression were used, since version 1.0.3 the authors have developed their own compression algorithm. The new product TrueBug PHP Obfuscator & Encoder adds the function of obfuscation and optimization of the source code. The only weak point of the protection is the invariable script decoding algorithm, but the algorithm itself changes for each version of the protection. After parsing, the protection is easily removed exactly to the source code, of course, provided that the obfuscator was not used.

Zorex PHP CryptZ. Protection, like CodeLock, is a php application, it requires a MySQL database to work. The protection module is a plug-in php script encrypted in several layers. After analysis, the algorithm is removed very easily exactly to the source code. There is no obfuscator function.

Free PHP Encoder. Free online service for coding php scripts. The protection module is a plug-in php-script covered by Zend, which must be downloaded from the site. After Zend is removed and the algorithm is parsed, the protection can be easily removed completely to the source code. The protection algorithm is unchanged, there is no obfuscator function.

Php script, primitive encoding, standard base64. It does not deserve more attention and is of no practical interest.

We create our own registration page for multisite instead of the standard wp-signup.php.

In a typical WordPress installation, the registration (login, password reset) page displays the wp-login.php file.

  • /wp-login.php - authorization
  • /wp-login.php?action=register - registration
  • /wp-login.php?action=lostpassword - reset password

There are separate conditions for multisite in wp-login.php. So, when you click on the link /wp-login.php?action=register on a multisite, WordPress will redirect to the /wp-signup.php page. In many themes, the page doesn't look very attractive, so we'll make our own.

Main site of the network

By default, WordPress opens a registration page (wp-signup.php) on the main domain (site) of the network. However, you can make a separate registration page for each site on the network, even if they have different themes. We will consider the case when all sites on the network have their own registration page, but the same theme is used and the sites differ only in language. If you are using different themes, you will need to write more code.

functions.php?

No. The name of this file seems to be mentioned in every WordPress article. In our case, given that the registration functionality is designed for several sites, it makes sense to move it into MU plugins that are loaded when you open any site.

Lyrical digression

It is worth noting that MU plugins are loaded earlier than regular plugins and before the WordPress core is fully loaded, so calling some functions can lead to fatal errors in PHP. This "early" loading has its advantages as well. For example, inside any theme, you cannot cling to some actions that are triggered even before the functions.php file is loaded from the theme. An example of this is the actions from the Jetpack plugin of the form jetpack_module_loaded_related-posts (related-posts - the name of the module) with which it is possible to track the activity of modules in Jetpack. It is impossible to "cling" to this action from the theme file, because the action has already been triggered before the theme is loaded - plugins are loaded before themes. You can take a look at a general picture of the WordPress load order on the Action Reference page in the codex.

File order

MU plugins can contain any number of files and any structure that seems logical to you. I stick to something like this hierarchy:

| -mu-plugins | - | -load.php | - | - | -selena-network | - | - | - | -signup | - | - | - | - | -plugin.php | - | - | - | - | -... | - | - | - | -jetpack | - | - | - | - | -plugin.php

All the necessary "plugins" for our network are connected in the load.php file:

// Load Traslates for all addons load_muplugin_textdomain ("selena_network", "/ selena-network / languages ​​/"); // Network Signup require WPMU_PLUGIN_DIR. "/selena-network/signup/plugin.php"; // Another plugins // require WPMU_PLUGIN_DIR ...

Plugin folders are stored inside the selena-network folder, each has its own plugin.php, which we include in load.php. This gives you flexibility and the ability to quickly turn things off and on.

Registration page address

To specify the address of the registration page, the wp_signup_location filter is used. It can be found inside the wp-login.php file and is responsible for redirecting to wp-signup.php.

Case "register": if (is_multisite ()) (wp_redirect (apply_filters ("wp_signup_location", network_site_url ("wp-signup.php"))); exit;

Let's add our function to mu-plugins / selena-network / signup / plugin.php, which will return the address of the registration page on the current site:

Function selena_network_signup_page ($ url) (return home_url (). "/ Signup /";) add_filter ("wp_signup_location", "selena_network_signup_page", 99);

selena_network is the prefix that I use in the names of all functions inside MU plugins on my site to avoid collisions, it should be replaced with my own unique prefix. The filter has a priority of 99 because some plugins like bbPress and BuddyPress may overwrite this URL with their own (MU plugins load earlier than regular plugins, see above). Note that home_url () is used instead of network_site_url () to keep the visitor on the same domain. Any URL can be used as the address.

Create a page

Now let's create a page with the address site.com/signup/ through the regular interface, and in the child theme folder, the template for our new page is page-signup.php. A unique ID can be used instead of the word "signup".

Inside the new template, you need to call the selena_network_signup_main () function, which will display the registration form.

It should be noted that the whole process with templates is not required and instead you can create your own shortcode, which will also call the selena_network_signup_main () function.

wp-signup.php and wp-activate.php

Now let's start creating a function that will display the registration form. To do this, copy the wp-signup.php and wp-activate.php files from the WordPress root to mu-plugings / selena-network / signup / (and don't forget to connect them inside mu-plugins / selena-network / signup / plugin.php) ... Further manipulations with files are extremely difficult and time-consuming to describe, so you will have to do them yourself. I'll just describe what exactly needs to be done and publish the source files of my project:

  1. At the beginning of the file, remove all require, function calls and other code outside of functions.
  2. Rename all functions by adding unique prefixes to the names.
  3. Wrap the bottom part of the wp-signup.php code in the selena_network_signup_main function and write global $ active_signup at the very beginning; ...
  4. Replace the layout with your own in the right places.

Inside wp-activate.php, you need to do approximately the same:

  1. Remove all code outside the functions, wrap the layout in a separate function.
  2. Change the layout where necessary.

The wp-activate.php file is responsible for the account activation page. As with the registration page, you need to create a separate template for it, inside which you call the function from the wp-activate.php file.

We send activation letters

The registration page sends the visitor an email with a link to activate their account. By default, this is done by the wpmu_signup_user_notification () function from the ms-functions.php file. Its functionality can be borrowed for your function. The reason to stop using this feature is because it sends the account activation link from wp-activate.php. You can "disable" this function using the wpmu_signup_user_notification filter, giving false on it (if you do not do this, the activation letter will be sent twice, okay, in fact, two different letters).

Function armyofselenagomez_wpmu_signup_user_notification ($ user, $ user_email, $ key, $ meta = array ()) (// ... // Code from function wpmu_signup_user_notification () wp_mail ($ user_email, wp_specialchars_decode ($ message_headers), $ message), $ ; return false;) add_filter ("wpmu_signup_user_notification", "armyofselenagomez_wpmu_signup_user_notification", 10, 4);

As a result, the registration page in the Selena theme looks much cleaner and more accurate.

Conclusion

There are many other not very correct ways of doing the same on the Internet - Apache redirects, AJAX forms that will not work without Java Script, etc. own website.

Note that you should edit the files carefully and try not to deviate much from the original, so that in the future, if WordPress changes the wp-signup.php and wp-activate.php files, it would be easier to compare them to find changes.

Do not forget to look into the source code of all the functions described above to fully understand what and how is happening inside the code.

Bonus. Spammer protection

Even the smallest WordPress sites are subject to frequent spam registrations. You can write endless conditions for filtering bots, often more like trying to create artificial intelligence 🙂 In the case of a multisite, the usual redirect in Apache helped me a lot, with which, when opening /wp-signup.php and /wp-acitvate.php, I asked for 404 (I am not an expert on Apache configuration, so my rules may not be very correct).

RewriteEngine On RewriteBase / RewriteRule ^ wp-signup \ .php - RewriteRule ^ wp-activate \ .php - # BEGIN WordPress # Don't touch WordPress rules by default :) # ... # END WordPress

P. S. I try to describe in as much detail as possible some third-party things, because when I started, sometimes there was no one to prompt and explain many things. I also believe that such small tips on other materials will push someone to learn something new and expand their field of knowledge. Regular expressions are used in RewriteRule entries, they are not at all complex, for example, the ^ character means the beginning of a line.

“They break bank sites for money, the Pentagon for espionage, and nobody needs my project,” unfortunately, this is what most owners of personal blogs, Internet business cards, virtual offices of small companies think. Only a few people think about how to protect the site, but in vain. In modern realities, absolutely any platform, regardless of type or popularity, is of interest in the eyes of hackers. Who may need your resource and why? Let's figure it out:
1. Pranks of scriptkiddis. Jargon refers to aspiring hackers who are taking their first steps on the "dark side". Having acquired several tools, or having written a couple of their own programs, they are eager to test their performance on the first victim they come across, and, as a rule, choose the easiest (weakly protected and not updated CMS) targets.
2. Black SEO. The services of dishonest optimizers are still in use - placing hidden links in the code of projects with more than 10 TCIs is still practiced. And, first of all, resources on open source engines (Joomla, Drupal, OpenCart and so on) come under attack.
3. Building a botnet. Protecting WordPress with htaccess and plugins is also relevant because absolutely any resource can be used to create a zombie network used in DDoS attacks, spamming, etc.
4. Collateral damage. Finally, you may not be attacked - the main goal will be hosting, and the site will serve only as one big vulnerability of the provider's IT infrastructure. Of course, hackers won't care about his fate.

The consequences of hacking can be the most unpleasant: loss of content, or the resource as a whole, pessimization in search engine results, loss of audience due to the inscription “The site can threaten the security of a computer or mobile device,” and even the risk of becoming involved in a criminal case if illegal actions have been committed on the basis of your web resource.

So, we can confidently say that security issues affect absolutely every webmaster. And if you neglect them, all efforts to promote search engine (and this is money and precious time) can go to waste overnight. The problem is very urgent, so I decided to start a series of articles devoted to network threats and methods of dealing with them. The popular CMS system - Wordpress will be considered in three issues.

Methods for securing a WordPress site

One of the most primitive hacking methods is brute force. Literally the term is translated as “brute force”, and means getting a pair of login / password by brute-force enumeration of possible options. Often, brute-forcers try to make their life easier by taking advantage of errors in the engine and server settings - this helps them, for example, find out the account name, which significantly reduces the number of combinations. It is about the elimination of these vulnerabilities, as well as the methods of combating unauthorized access attempts that will be discussed.

1. Use a unique administrator login

By default, the system offers to create a user named admin. However, in order to protect your WordPress site, it is best to use a login consisting of a set of random letters and numbers. On a live resource, the administrator's name can be changed without any problems using one of two methods:

Through the admin panel. Go to the "Users" section, click the "Add New" button and create an account. In the “Role” field, select “Administrator” and confirm the operation. Then re-login on behalf of the newly created account, return to the "Users" section, select "admin" and click "Delete". In the window that opens, put the radio button in the “Link all content” position and select a new administrator from the drop-down list, and then click on “Confirm deletion”.
... Using phpMyAdmin. It is much easier to carry out the same procedure through the database control panel. Select the required database, find the wp_users table, find the line “admin” (ID = 1), click on “Change” and enter the desired name.

2. Create a dedicated publishing account

If the administrator is "left out", this will provide additional protection. Create a separate account for posting articles and link all previously published materials to it in the manner described in paragraph 1. Next, add information and communicate with readers only from a new account.

3. Enter a strong password

Follow the generally accepted recommendations: the password must be at least 10 characters long, it must be unique and consist of a random sequence of uppercase and lowercase letters, numbers and special characters.
In no case should you:
... compose a password from meaningful phrases
... use any factual data (date of birth, maiden name, bank account number, current year ...)
This will eliminate the risk of searching for a passphrase using a dictionary, and will also significantly increase the time required for brute force. So, cracking a sequence of 10 characters, consisting only of lowercase letters and numbers (hki458p1fa), will take 10 days of computer time for one PC, but if you add uppercase letters and additional characters (Nv6 $ 3PZ ~ w1), this period will increase up to 526 years, guaranteeing almost absolute WordPress protection. Coming up with and remembering these passwords is quite difficult, especially if you are in charge of several projects. Therefore, to generate and store them, it is better to use special managers, for example, KeePassX, distributed free of charge, or a regular test document (it is better if it is packed into an archive with a password).

4. Change the password for the database

The above rules are also true for the security of the MySQL access code. After all, it is there that contains all the content, as well as the hash of the administrator's secret phrase. If you are already using a weak password, it is worth taking the trouble to change it. This is done as follows:

1. Go to your phpMyAdmin control panel
2. Open the "Users" tab and select the owner of the database
3. Click on “Edit Privileges”
4. Find the "Change password" column and enter the new secret sequence in the appropriate fields
5. Save the changes by clicking on "Ok"

Now all that remains is to edit wp-config.php, otherwise WordPress will not be able to connect to the database. Find the line define (‘DB_PASSWORD’, ‘password’); and enter the new password instead of the word password. Note that since the (‘) character is used to delimit SQL commands, it should not be used as part of a passphrase.

5. Update passwords regularly

They should be changed at least every six months. An extraordinary change of code phrases should ALWAYS be carried out after:

Transfer of data for authentication to third parties (programmers, system administrators, optimizers, and other specialists, even if they work on the staff of the hosting company)
... logging into a web resource from someone else's computer (at a party, in an Internet cafe)
... authorization from equipment that could have been compromised (a machine infected with a virus)

6. Do not forget to change the secret keys for cookies

They are located in the wp-config.php file. There are 8 of them:

define ("AUTH_KEY", "unique key"); define ("SECURE_AUTH_KEY", "unique key"); define ("LOGGED_IN_KEY", "unique key"); define ("NONCE_KEY", "unique key"); define ("AUTH_SALT", "unique key"); define ("SECURE_AUTH_SALT", "unique key"); define ("LOGGED_IN_SALT", "unique key"); define ("NONCE_SALT", "unique key");

define ("AUTH_KEY", "unique key"); define ("SECURE_AUTH_KEY", "unique key"); define ("LOGGED_IN_KEY", "unique key"); define ("NONCE_KEY", "unique key"); define ("AUTH_SALT", "unique key"); define ("SECURE_AUTH_SALT", "unique key"); define ("LOGGED_IN_SALT", "unique key"); define ("NONCE_SALT", "unique key");

As you might guess from the names of the variables, the keys are responsible for encrypting the cookies (the well-known slang: cookie - cookies, salt - salt, we feed the hackers with salty cookies), which are used to make the site "remember" your computer after authorization. The bottom line is that even if the attacker gets at his disposal the hash of the admin password, he will not be able to generate the cookies necessary to access the site without the listed secret phrases.

To improve security, the default character sequences should be replaced with unique ones immediately after the CMS is deployed. For convenience, the developers have created a web generator located at www.api.wordpress.org/secret-key/1.1/salt/ - when you enter, you will see the keys, and if you refresh the page, the combinations are updated.

7. Double authorization for the admin area

Htaccess allows you to further secure your WordPress site by adding server-level authentication. The code will look like this:

< Files wp- login. php> # We set the basic authentication type - this means that when you try# accessing the specified directory or file will be prompted for a password: AuthType basic # Enter the text that will be displayed in the header of the form: AuthName "Identify yourself" # Specify the path to the file containing the passphrase: AuthUserFile "/home/site/.htpasswd" # We indicate that when accessing the wp-login.php file, you must enter the password: Require valid- user # Deny access to the .htpasswd file to third parties:< Files . htpasswd>order allow, deny deny from all

# Select the authorization script file: # Set the basic authentication type - this means that when you try # to access the specified directory or file, you will be prompted for a password: AuthType basic # Enter the text that will be displayed in the form header: AuthName "Identify yourself" # Specify the path to the file containing the passphrase : AuthUserFile "/home/site/.htpasswd" # We indicate that when accessing the wp-login.php file, you must enter a password: Require valid-user# Deny access to the .htpasswd file to third parties: order allow, deny deny from all

At the same time, it would be nice to take care of the security of the htaccess itself. Strictly speaking, such a directive should be spelled out in the main hosting settings, but given the carelessness of some providers, you should play it safe:

Substitute the desired name instead of "login". It remains to generate the password itself, as well as encrypt it, because storing such data in clear text is an impermissible luxury. There are many services for this, but it is better to write the necessary script yourself. This is done as follows:

1) Create a .php file in notepad, for example crypt.php
2) Enter the code there, substituting your password instead of the word "Password":

3) Save the file and upload to the root directory
4) Follow the link site_name.ru / crypt.php - the password hash will appear on the screen
5) Save this value in .htpasswd file and upload it to root directory and crypt.php delete

The final touch is the prohibition of viewing the contents of the web resource directory. It is enough to add a single line to htaccess:

Options All - Indexes

Options All -Indexes

This is done so that hackers cannot find out which files are in the project directories. On many hosting sites, this directive is already included in the server settings, but if this point is overlooked, you should register it yourself.

8. Install the captcha

Using captcha will allow you to cut off, if not all, then at least most of the brute-force bots, and at the same time. The WordPress site protection plugin directory offers many options. In addition to connecting a proprietary solution from Google, Captcha by BestWebSoft of a mixed (graphics and text) type, which is based on mathematical operations, is of great interest. Service independence, clarity and acceptable level of complexity make the module one of the best.

Customization is not a big problem. The "Basic" tab allows you to choose where to display the captcha, as well as specify a title and a symbol to mark the fields that are required.

The "Advanced" section provides the ability to create your own error messages, as well as activate additional image packs to make life even more difficult for bots.

Another useful feature is the built-in whitelist of IP addresses for which captcha will not be displayed.

The result of installing and activating the plugin will be the appearance of a form on the authorization page:

9. Change the admin address

Talking about how to protect a WordPress site, it is worth mentioning a more radical, but also more complicated way - changing the login page URL at the script level. The procedure is carried out in several stages:

1. Rename the wp-login.php file. Use a random sequence of lowercase Latin letters, numbers and dashes. For example: abc-123.php
2. Find all references to wp-login.php in the resulting file and replace them with the new name.
3. For the site to work correctly, the replacement must also be done in: wp-activate.php, general-template.php, post-template.php, functions.php, class-wp-customize-manager.php, general-template.php, link-template.php, admin-bar.php, post.php, pluggable.php, ms-functions.php, canonical.php, functions.wp-scripts.php, wp-signup.php, my-sites.php, schema.php, ru_RU.po

After these manipulations, the admin panel will be located at the site / abc-123.php. Access to the new file should be limited and password protected as described above. It is also possible to mislead potential hackers by creating a fake wp-login.php file and setting a password for it as well.

An even simpler option is to use the "Rename wp-login.php" add-on. After installing the plugin to protect the site, a new field will appear in the "Settings" -> "Permalinks" menu:

10. Specify the IP of the admin

Additional security can be provided if you have a static IP address. Denying access to wp-login.php from any computer other than your own will make life much harder for hackers:

< Files wp- login. php>order deny, allow deny from all allow from 127.0.0.1, 127.0.02 # Separate your IP addresses with commas

order deny, allow deny from all allow from 127.0.0.1, 127.0.02 # Separate your IP addresses with commas

11. Disable authorization errors

When brute-forcing passwords, an attacker will find it very useful to know that the entered data was incorrect. Such messages are displayed on each unsuccessful login attempt, and WordPress also reports what was entered incorrectly, username or password. To get rid of them, you just need to add just one line to functions.php:

add_filter ("login_errors", create_function ("$ a", "return null;"));

add_filter ("login_errors", create_function ("$ a", "return null;"));

To do this, select "Appearance" -> "Editor" -> "Theme Functions" in the admin panel. It is necessary to write the code after the opening tag

12. Use a secure connection.

To encrypt traffic between the user's computer and the web server, there is the https protocol, the use of which excludes the possibility of intercepting important data, in our case, identification data. To activate it, you first need to purchase an SSL certificate that performs two functions at once: authentication of a web resource and encryption of transmitted information. You can get it in specialized centers, or from a number of domain name registrars. For non-commercial purposes it is quite enough to acquire a free entry-level certificate (such is offered by the company www.startssl.com). As for the installation process, as a rule, it is described in detail in the hoster's help section.

Having received an SSL certificate, you need to configure redirection of the administrative part of the web resource to a secure connection. In the case of WordPress, this is done using the following construction:

< IfModule mod_rewrite. c>Options + FollowSymlinks RewriteEngine On RewriteCond% (HTTPS) = off RewriteCond% (REQUEST_URI) = / wp- login. php RewriteRule (. *) https:

Options + FollowSymlinks RewriteEngine On RewriteCond% (HTTPS) = off RewriteCond% (REQUEST_URI) = / wp-login.php RewriteRule (. *) Https: //% (HTTP_HOST)% (REQUEST_URI)

You can also force the use of SSL certificates at the engine level. To do this, open the wp-config.php file and add after

define ("FORCE_SSL_ADMIN", true);

define ("FORCE_SSL_ADMIN", true);

In addition, you can set up a global redirect from http to https. For new sites, this approach is optimal, given that Google encourages secure projects, giving them some priority in search results:

< IfModule mod_rewrite. c>Options + FollowSymlinks RewriteEngine on RewriteCond% (HTTPS) = off RewriteRule ^ (. *) $ Https: //% (HTTP_HOST)% (REQUEST_URI)

Options + FollowSymlinks RewriteEngine on RewriteCond% (HTTPS) = off RewriteRule ^ (. *) $ Https: //% (HTTP_HOST)% (REQUEST_URI)

13. Block intruders

If suspicious activity from certain IPs is detected, it is worth blocking their access to the site. This is done by analogy with the previous method. The difference is that the directives are written for the project as a whole, and we list the addresses of those whom we want to ban:

Order Allow, Deny Allow from all Deny from 127.0.0.1, 127.0.02 # Specify unwanted IP

The method is reliable but ineffective. Firstly, it is somehow necessary to record the requests of brute-forcing services and separate them from respectable visitors. Secondly, with a massive attack, you simply will not be able to track and drive in the IP of hackers and bots manually. This method is only good if the administrator has a reliable blacklist of addresses.

Otherwise, you can use a WordPress site security plugin called WP Cerber. This solution is absolutely free, while offering a very impressive set of tools designed to prevent CMS hacking. You can install it directly from the admin panel.

By default, fairly sensible parameters are offered. However, the number of attempts should be increased to 5 in order to avoid misunderstandings.

The checkbox opposite “Block IP for any wp-login.php request” should be checked if you change the admin address in the manner described earlier.

For these purposes, you can also use WP Cerber's own tool:

The plugin mode for protecting the Citadel site also does not need additional configuration. It is designed to “mothball” the project during a massive brute-force attack. It is better to uncheck the box next to “Record attempts to log into a file” - this will help eliminate additional load on the server.

The “Access Lists” tab is used to create a “black” and “white” IP list (if you have a static address, be sure to add it to the list of trusted ones), and the “Tools” section allows you to import and export the previously made settings. However, these possibilities do not require separate consideration.

14. Move the config file

As we found out above, wp-config.php stores such critical data as the login and password for accessing MySQL, as well as API keys. The next step seems to be obvious - protecting WordPress through htaccess by restricting access to the file:

< Files wp- config. php>Order allow, deny Deny from all

Order allow, deny Deny from all

However, there is also a more reliable method. WordPress has a very interesting feature that few people know about. The engine allows placing the configuration file one level above the root directory .. php can be moved to the site directory. In this case, the file will become completely inaccessible via the Internet, while the information contained in it will still be read by the CMS.

15. Add REFERER check

A well-proven method for protecting WordPress from spam will also help when confronting brute-force attacks. After all, brute-forcing of passwords is by no means manual work: specialized programs are used for these purposes. This means that by enabling header checking in incoming requests, you can cut off bots that have come from nowhere with an empty HTTP REFERER:

< IfModule mod_rewrite. c>RewriteEngine On RewriteCond% (REQUEST_METHOD) POST RewriteCond% (REQUEST_URI). (wp- comments- post | wp- login) \. php * RewriteCond% (HTTP_REFERER)!. * tekseo. su. * [OR] RewriteCond% (HTTP_USER_AGENT) ^ $ RewriteRule (. *) http: //% (REMOTE_ADDR) / $ 1

RewriteEngine On RewriteCond% (REQUEST_METHOD) POST RewriteCond% (REQUEST_URI). (Wp-comments-post | wp-login) \. Php * RewriteCond% (HTTP_REFERER)!. * Site. * RewriteCond% (HTTP_USER_AGENT) ($ RewriteCond% (HTTP_USER_AGENT) ($ RewriteCond) ^ $ RewriteCond *) http: //% (REMOTE_ADDR) / $ 1

16. Protect XML-RPC

Since version 3.5, the ability to disable the XML-RPC remote procedure call protocol has disappeared from WordPress. Basically, it is needed to interact with mobile applications, but not everyone needs such functionality. At the same time, xmlrpc.php is actively used to carry out DDoS attacks, being the Achilles heel of the entire project.

In addition, hackers have thought of using XML-RPC for brute-force. Using the wp.getUsersBlogs method allows you to iterate over credentials much faster than using the admin form. Since many XML-RPC calls require authorization, a request like this:

< methodCall> < methodName>wp. getUsersBlogs < params>< param>< value>< string>admin < param>< value>< string> 12345

wp.getUsersBlogs admin 12345

will cause the engine to tell you if the passed combination is correct. To get rid of this scourge, you must completely disable the protocol. This can be done in several ways:

1) By blocking access to the xmlrpc.php file via htaccess

require_once (ABSPATH. "wp-settings.php");

need to register

function remove_x_pingback ($ headers) (unset ($ headers ["X-Pingback"]); return $ headers;) add_filter ("wp_headers", "remove_x_pingback");

4) Using the Control XML-RPC publishing plugin returning the appropriate option in Settings -> Writing:

Please note: the add-on disables the protocol immediately after activation, and in the settings you can enable it by checking the corresponding checkbox.

17. Monitor brute force attacks

Finally, it is worth mentioning an interesting plugin for logging hacking attempts - Authentication and xmlrpc log writer. Although the same WP Cerber has built-in monitoring tools, this module will still be useful, especially for those who need the capabilities of the protocol described above. AX LogWriter is able to track brute force through xmlrpc.php, so you can assess the degree of threat and the advisability of completely refusing to use its capabilities. Finally, for those who have not been involved in the security of their project at all, the plugin for protecting the site will open their eyes to the importance of the listed activities.

Using the AX LogWriter is straightforward. After installation, the corresponding section will appear in the admin menu, where you can make all the necessary changes:

In the “Error Type” field, select the saving method. Supports writing to the system log, Apache server log, as well as the ability to create a custom file. In the latter case, it can also be configured with a Custom Error Log Name and a Custom Error Log Path. This opens up wide possibilities for the system administrator - for example, the solution can be used together with fail2ban. Also, don't forget to select the appropriate time zone in the Timezone column.

Custom log can be viewed directly from the admin panel on the Custom Log Viewer page:

Let's summarize:

The listed methods will help to significantly increase the security of your resource and protect it from bots-brute-forcing, network hooligans and practicing scriptkiddis. However, everything described above is just the tip of the iceberg. The attackers have much more sophisticated methods in their arsenal. And in the next article we will talk about how to protect yourself from real hackers using various vulnerabilities of the engine and server software. As in this material, in addition to the general "rules of hygiene" will be considered the key CMS settings, ways to modify the code, as well as the most relevant plugins.


When it comes to application security, it is important to take care not only of the hardware and operating system, but also of writing secure scripts. In this article, you will learn how to keep your application secure and less vulnerable. Below is a list of measures to help you protect your application from all kinds of attacks:

  1. Incoming data validation
  2. Protection against XSS attacks
  3. Protection against CSRF attacks
  4. Preventing SQL Injection
  5. File system protection
  6. Session data protection
  7. Error processing
  8. Protecting Included Files

Incoming data validation

When designing your application, you need to strive to protect it from “bad” incoming data. The rule to follow is something like: "Never believe what the user has entered." Although most users are not a threat, there is always the possibility that someone wants to hack your site using “bad” data entered through forms or the address bar. If you always validate and filter incoming data, then you have a good chance of writing a secure application.

Always check your data in PHP scripts. If you use JavaScript to validate data, an attacker can disable it in his browser at any time. In this case, your application is at risk. Nobody is against JavaScript validation, but for good protection, you need to double-check the data in PHP scripts.

Protection against XSS attacks

A cross-site scripting or XSS attack is an attack based on injecting code into potentially vulnerable pages. The danger is that malicious code can be entered through forms and then displayed in the browser.

Suppose your site has a form for entering comments, which are immediately displayed after adding. An attacker could enter a comment containing JavaScript code. After submitting the form, the data is sent to the server and entered into the database. After that, the data is retrieved from the database and the new comment is displayed on the HTML page, including the embedded JavaScript code. It can redirect the user to some malicious page or phishing site.

To protect your applications, run the incoming data through the strip_tags () function, which will remove any tags present. When displaying data in a browser, use the htmlentities () function.

Protection against CSRF attacks

The next type of attack we will look at is a CSRF attack or cross-site request forgery. The attacker uses various tricks to obtain confidential information or make a deal without the victim's knowledge. This mainly happens on poorly protected sites, where business logic is based on the work of GET requests.

Generally speaking, GET requests are idempotent. Idempotency, in this context, means that one and the same page can be accessed any number of times without any outside interference. That is why GET requests should be used only to gain access to information, but in no case to carry out various kinds of transactions.

The following simple example shows how an unsecured site can be subject to a CSRF attack:

Suppose Bob wants to perform a CSRF attack on Alice. He formed a special url address and sent it to Alice by e-mail:

Visit my website!

If Alice is authorized on the website example.com and follows this link, then $ 1000 will be transferred from her account to Bob's account. Alternatively, Bob can send an image as well and fill in the "bad" URL in the src attribute.

The browser will not be able to display this image, since it does not exist, but the request will be made without Alice's knowledge and participation.

To prevent this kind of attacks, use only POST requests to processes designed to change information in the database. Don't use $ _REQUEST. Use $ _GET to handle GET parameters, and $ _POST to retrieve POST parameters.

As an additional measure, you can generate a unique token and attach it to each POST request. When a user logs into the system, you can generate a random token and write it to the session. Since all forms are displayed to the user, this token must be written to a hidden field. The business logic of the application must provide functionality that will check the token from the forms and the token stored in the session.

Preventing SQL Injection

You should use PDO to run queries against the database. With parameterized queries and prepared statements, you can mitigate the threat of SQL injection.

Let's take a look at the following example:

In the above code, we are sending a request to the prepare () method, including the named parameters:: name and: age. Thus, the query is pre-compiled for further data substitution. When the execute () method is called, the request is fully formed and executed. If you use this technique, then all attempts by an attacker to perform SQL injection will be nullified.

File system protection

As a responsible developer, you should always write code that does not compromise your filesystem. Let's look at the code that sends a file for download depending on the data submitted by the user.

This script is very dangerous, because it makes it possible to access any directory that is accessible from the file with the script: the directory with sessions, system folders and much more.

Session data protection

By default, all session information is written to the temp directory. If you are using shared hosting, someone besides you can write a script and read session data. Therefore, beware of storing passwords or credit card numbers in sessions.

If you still need to store such data in a session, then encryption is the best measure. This does not completely solve the problem, since the encrypted data is not 100% secure, but the stored information will be unreadable. Also, you should consider that the session data can be stored elsewhere, such as a database. PHP has a special session_set_save_handler () method that allows you to store session data in your own way.

Since PHP 5.4, you can pass an object of type SessionHandlerInterface to session_set_save_handler ().

Error processing

During the development of an application, it is worth paying attention to all kinds of errors that may arise, however, they need to be hidden from end users. If errors are displayed to users, then this makes your site vulnerable. Thus, the best solution would be different configuration for the target server and the development server.

On the public server, you need to disable options such as display_errors and display_start_up_errors, but options such as error_reporting and log_errors should be active so that all errors encountered by users are logged.

You can also use set_error_handler to define your own error handler. However, there may be limitations, because the native handler is inferior to the native PHP mechanism. Errors E_CORE_ERROR, E_STRICT, or E_COMPILER_ERROR cannot be caught in the same file as a specific handler. Moreover, errors that may occur in the handler itself also cannot be caught.

For a more elegant way of catching exceptions, potentially dangerous code should be placed in a try / catch block. All native exceptions must be objects of classes or subclasses of Exception. If exceptions were thrown, then they can be handled in the try / catch block.

Protecting Included Files

Often, other files are loaded in PHP scripts, such as connecting to the database and many others. Some developers give these files the .inc extension. PHP does not parse such files by default. If you address them directly, the user will be able to see the text of this file. If the hacker manages to get access to the file storing the data connection to the database, then later he can get access to all the data of your application. So always use the .php extension for uploaded files and store them where there is no direct user access.

Outcome

If you follow the listed 8 rules, then this will greatly improve the resistance of your application to various kinds of attacks. Do not trust the data entered by users, protect your files and database.

Let's think about who a hacker is? A hacker is not a cracker! People often confuse these concepts. A hacker is, first of all, a person with out-of-the-box thinking, and this is his strength, so to speak.

To successfully resist a hacker, you also need to learn to think outside the box. As they say, a wedge is knocked out by a wedge.

Today I will offer you a very unusual way to protect yourself from attacks like php include. Of course, he is not suitable for everyone. And if honestly he protects not from the attack itself, but from its detection. Intrigued?

How to find includ ...

Let's first understand exactly how an attacker tries to find a vulnerability.

It looks like this. The attacker modifies all incoming parameters one by one, assuming that the data of these parameters gets into the include function. Well, or if, in a simple way, it tries to "attach" files. And in order to determine whether there is a vulnerability or not, he needs to attach some file on the target system (if he knows - there is a vulnerability, no - there is no vulnerability).

Naturally, if an attacker acts from the outside, then he does not know the structure of the location of directories and files, and cannot attach any file, since he will not know the path to it. But there are files that always exist in the system, and to which there is always read permissions. For Linux, this is / etc / passwd, and for Windows, let it be C: \ boot.ini. But by the way, Windows is of little interest to us, so further we will talk about passwd

/ etc / passwd

Probably you have come across more records of the form in your logs:

Action = .. / etc / passwd% 00
? action = .. / .. / etc / passwd% 00
? action = .. / .. / .. / etc / passwd% 00
? action = .. / .. / .. / .. / etc / passwd% 00
? action = .. / .. / .. / .. / .. / etc / passwd% 00
? do = .. / etc / passwd% 00
? do = .. / .. / etc / passwd% 00
? do = .. / .. / .. / etc / passwd% 00
? do = .. / .. / .. / .. / etc / passwd% 00
? do = .. / .. / .. / .. / .. / etc / passwd% 00
? id = .. / etc / passwd% 00
? id = .. / .. / etc / passwd% 00
? id = .. / .. / .. / etc / passwd% 00
? id = .. / .. / .. / .. / etc / passwd% 00
? id = .. / .. / .. / .. / .. / etc / passwd% 00

If yes, then you should know that you tried to find php include (well, or the ability to read arbitrary files, but we are not interested in this now). So, if one of your parameters is not processed properly and ends up in a function include (), then the / etc / passwd file would be added, its contents would be interpreted as a php script, and since it does not contain php code tags, it would be displayed in the browser unchanged. This would serve as a “marker” for the attacker to have a vulnerability.

Why am I writing this, to the fact that when looking for include, the attacker will definitely (I guarantee that in 90% of cases) will try to add the file / etc / passwd.

Protect yourself, sir!

Perhaps you are now thinking: "Does he want to offer a regular WAF and filter packets by the presence of / etc / passwd in them?" No. This is the standard way. This is an example of how an ordinary person thinks.

Let's get a little creative. Why don't we just add some php code to the contents of the passwd file? And if suddenly the attacker succeeds in connecting him, then our php code will be executed. (Do you consider it nonsense? - look at the conclusion)

Since we know that the only one who will guess to include this file is a cracker, our php code must ban it, and in order to prevent our system from being hacked further, block the vulnerable file, and it is desirable to notify the administrator about the incident.

But how do you add php code to / etc / passwd because its syntax is strictly regulated? Each user has a “comment” field - a description of the user, you can enter anything you want there (except for the colon, of course). Therefore, we take and add a user to the system with the comment we need. After that, / etc / passwd will contain the following line

root: x: 0: 0: Superuser: /:
daemon: *: 1: 5 :: /: / sbin / sh
bin: *: 2: 2 :: / usr / bin: / sbin / sh
sys: *: 3: 3 :: /:
adm: *: 4: 4 :: / var / adm: / sbin / sh
securityuser: *: 1001: 1001::/:

Well, in the plug-in script, we are already performing the actions you need - ban the user, block the request, notify the administrator.

As a result, we have a kind of trap that can protect your site from hacking.

Conclusion

Yes, I am fully aware that everything written above looks like nonsense. And I perfectly understand that no one will use this in practice. But that's not what I wrote for. I wrote in order to show an example of a non-standard approach in the field of protection.

Thank you for your attention =)