From Saturday afternoon on my server, which hosts about 25 sites on Wordpress, wild brakes began. Since I managed to survive the previous attacks ( , ) without being noticed, I did not immediately understand what was wrong.

When I figured it out, it turned out that there was a search for passwords + a lot of requests to XMLRPC.

As a result, it was possible to cut it all off, although not immediately. By cat three simple reception how to avoid it.

These techniques are most likely known to everyone, but I stepped on a couple of rakes that I did not find in the descriptions - suddenly this will save someone time.

1. We stop the enumeration, the Limit Login Attempts plugin - we put it exactly, since other protections greatly hang the server, for example, when using Plugin Login The Security Solution server died in half an hour, the plugin heavily loads the database.

In the settings, be sure to check the "For proxy" checkbox - otherwise it will determine the ip of your server for everyone and automatically block everyone.
UPDATE, thanks, the details are below in the comments - we enable the “For proxy” checkbox only if the definition does not work when “Direct connection” is enabled

2. Disable XML-RPC - plugin Disable XML-RPC (just activate it and that's it).

3. Close wp-login.php - if you access the site via ip, the plugin does not work and the pickers continue to hammer the site. To avoid this, add to .htaccess:

Order Deny,Allow Deny from all

We copy the wp-login file, rename it to any strange name, for example poletnormalny.php and inside the file we change all wp-login.php inscriptions to poletnormalny.php by autocorrect.
Everything, now you can access the admin panel only by your file.

After these 3 simple steps, the sites began to fly again and peace came.

Well, suddenly it's interesting

One of the options is how to see that you are being attacked. This can be seen in the nginx logs (for example, here is the path for Debian /var/log/nginx access.log file).

Introduction to XML-RPC

There are many different resources on the Web that provide users with certain information. This does not mean ordinary static pages, but, for example, data retrieved from a database or archives. This can be an archive of financial data (currency rates, data on securities quotes), weather data, or more voluminous information - news, articles, messages from forums. Such information can be presented to the page visitor, for example, via a form, as a response to a request, or it can be dynamically generated each time. But the difficulty is that often such information is needed not so much by the end user - a person, but by other systems, programs that will use this data for their calculations or other needs.

A real-life example: a page on a banking site that displays currency quotes. If you access the page as ordinary user, through the browser, you see all the page design, banners, menus and other information that "frames" the true purpose of the search - currency quotes. If you need to enter these quotes into your online store, then there is nothing else left but to manually select the necessary data and transfer it to your website via the clipboard. And you have to do this every day. Is there really no way out?

If we solve the problem head-on, then the solution immediately suggests itself: the program (script on the site) that needs data receives the page from the server as a "regular user", parses (parses) the received html code and extracts the necessary information from it. It can be done or normal regular expression, or with any html parser. The complexity of the approach lies in its inefficiency. First, to get a small portion of data (data about currencies is literally a dozen or two characters), you need to get the entire page, which is at least several tens of kilobytes. Secondly, with any change in the page code, for example, the design has changed or something else, our parsing algorithm will have to be redone. Yes, and it will select resources decently.

Therefore, the developers came to the decision - it is necessary to develop some kind of universal mechanism that would allow transparent (at the protocol and transmission medium level) and easy data exchange between programs that can be located anywhere, be written in any language and run under any operating system and on any hardware platform. Such a mechanism is now called the high-profile terms "Web services" (web-service), "SOAP", "service-oriented architecture" (service-oriented architecture). For data exchange, open and time-tested standards are used - the HTTP protocol is used to transfer messages (although other protocols can be used - SMTP for example). The data itself (in our example - exchange rates) is transmitted packed in a cross-platform format - in the form of XML documents. For this, a special standard was invented - SOAP.

Yes, now web services, SOAP and XML are on everyone's lips, they are beginning to be actively implemented and large corporations like IBM and Microsoft are releasing new products designed to help the total implementation of web services.

But! For our example with exchange rates that must be transferred from the bank's website to the online store engine, such a solution will be very difficult. After all, only the description of the SOAP standard takes indecent one and a half thousand pages, and that's not all. For practical use, you will have to learn how to work with third-party libraries and extensions (only starting with PHP 5.0 it includes a library for working with SOAP), write hundreds and thousands of lines of your code. And all this to get a few letters and numbers is obviously very heavy and irrational.

Therefore, there is one more, with a stretch, we can say an alternative standard for information exchange - XML-RPC. It was developed with the participation of Microsoft by UserLand Software Inc and is designed for unified data transfer between applications over the Internet. It can replace SOAP when building simple services where all the "enterprise" features of real web services are not needed.

What does the abbreviation XML-RPC stand for? RPC stands for Remote Procedure Call - remote procedure call. This means that the application (whether a script on the server or a regular application on client computer) can transparently use a method that is physically implemented and executed on another computer. XML is used here to provide a universal format for describing the transmitted data. As a transport, the HTTP protocol is used to transfer messages, which allows you to freely exchange data through any network devices - routers, firewalls, proxy servers.

And so, to use it, you need to have: an XML-RPC server that provides one or more methods, an XML-RPC client that can form a correct request and process the server response, and also know the server parameters necessary for successful operation - address, method name and passed parameters.

All work with XML-RPC takes place in the "request-response" mode, this is one of the differences between the technology and the SOAP standard, where there are both the concepts of transactions and the ability to make deferred calls (when the server saves the request and responds to it at a certain time in future). These additional features more useful for powerful corporate services, they greatly complicate the development and support of servers, and put additional requirements on developers of client solutions.

The procedure for working with XML-RPC begins with the formation of a request. A typical request looks like this:

POST/RPC2 HTTP/1.0
User-Agent: eshop-test/1.1.1 (FreeBSD)
Host: server.localnet.com
Content-Type: text/xml
content length: 172



TestMethod
Hello XML-RPC!


The first lines form the standard HTTP POST request header. Required parameters include host, the data type (MIME type), which must be text/xml, and the length of the message. The standard also states that the User-Agent field must be filled in, but may contain an arbitrary value.

Next comes the normal header of the XML document. Root element of the request - , there can be only one, and cannot contain such nodes as children. This means that only one method on the server can be called per request.

Line TestMethod indicates that we are calling a method named TestMetod. If necessary, here you can specify the name of the program or module containing the method, as well as the path to it. Although the XML-RPC specification imposes some restrictions on the set of characters that can be used to designate a method, how to interpret them depends entirely on the implementation of the server.

Next, the passed parameters are set. For this, the section Which can contain an arbitrary number of subelements Which contain the parameter described by the tag . We will look at parameters and data types a little further. In our version, the method is passed one string parameter, enclosed in the tag .

After describing all the parameters, closing tags follow. Request and response in XML-RPC are normal XML documents, so all tags must be closed. But there are no single tags in XML-RPC, although they are present in the XML standard.

Now let's analyze the server response. The HTTP response header is normal, if the request is successfully processed, the server returns an HTTP/1.1 200 OK response. Just like in the request, you should correctly specify the MIME type, message length, and the date the response was generated.

The body of the response is the following:



true


Now instead of the root tag tag is indicated , which immediately contains the results of processing the request. Unfortunately, the method name is not passed in the response, so you should store it on the client side to avoid confusion if different methods are called at the same time.

If an error occurred while processing your request, instead of The response will have an element , in which the structure describing the error will be nested. The error description contains a numeric error code and a textual description of the error.

Now let's take a quick look at the data types in XML-RPC. There are 9 data types in total - seven simple types and 2 complex ones. Each type is described by its own tag or set of tags (for complex types).

Simple types:

Whole numbers- tag or ;

boolean type- tag , can take both values ​​0/1 and true/false;

ASCII string- described by tag and may contain an arbitrary string of characters;

Floating point numbers- tag , may also contain the sign of a number, fractional part separated by a dot;

date and time- described by tag and must conform to the iso8601 format. For further processing in scripts, this format is a little inconvenient, so it is always converted when sending / receiving a request. This can be done by a special function in the library, or if there is none, the developer must convert the date manually.

The last simple type is base64 encoded string, which is described by the tag . This type is universal, it can be used to transfer any data between the client and the server, although the amount of data transferred due to this encoding increases. But this is a consequence of the textual nature of the protocol and XML format in particular.

Complex types are represented by structures and arrays. Structure defined by root element , which can contain an arbitrary number of elements , defining each member of the structure. A structure member is described by two tags: the first, , describes the member name, second, , contains the value of the member (along with a tag that describes the data type).

Arrays have no names and are described by a tag , which contains one element , and one or more child elements , where specific data is specified. An array can contain any other types in any order, as well as other arrays, which allows you to describe multidimensional arrays. You can also describe an array of structures. But the fact that an array has no name complicates its use in some cases; in order to transfer complex data, they have to be repeatedly packed into other types (for example, to transfer several arrays, you can separately pack each array into a structure, and then create one array from these structures).

Of course, someone will say that such a list of data types is very poor and "does not allow you to expand." Yes, if you need to transfer complex objects, or large amounts of data, then it is better to use SOAP. And for small, undemanding applications, XML-RPC is quite suitable, moreover, very often even its capabilities turn out to be too much! When you consider the ease of deployment, the very large number of libraries for almost any language and platform, and the wide support in PHP, then XML-RPC often simply has no competitors. Although it is impossible to immediately advise it as a universal solution - in each case it is necessary to decide according to the circumstances.

XML-RPC technology is used in the WordPress system for various nice features like pingbacks, trackbacks, remote site management without logging into the admin area, etc. Unfortunately, attackers can use it to DDoS attacks on websites. That is, you create beautiful interesting WP projects for yourself or to order, and at the same time, without suspecting anything, you can be part of a DDoS botnet. Connecting together tens and hundreds of thousands of sites, bad people create a powerful attack on their victim. Although your site also suffers, because. the load goes to the hosting where it is hosted.

Evidence of such bad activity can be server logs (access.log in nginx) containing the following lines:

103.238.80.27 - - "POST /wp-login.php HTTP/1.0" 200 5791 "-" "-"

But back to the XML-RPC vulnerability. Visually, it manifests itself in the slow opening of sites on your server or the inability to load them at all (502 Bad Gateway error). The technical support of my FASTVPS hoster confirmed my guesses and advised:

  1. Update WordPress to latest version along with plugins. In general, if you follow, you might have read about the need to install the latest 4.2.3. due to security criticisms (just like previous versions). In short, updating is good.
  1. Install the Disable XML-RPC Pingback plugin.

Disabling XML-RPC in WordPress

Previously, it seems to me, the option to enable / disable XML-RPC was somewhere in the system settings, but now I can not find it there. Therefore, the easiest way to get rid of it is to use the appropriate plugin.

Find and download Disable XML-RPC Pingback or by installing it directly from the system admin panel. You do not need to configure anything additionally, the module starts working immediately. It removes the pingback.ping and pingback.extensions.getPingbacks methods from the XML-RPC interface. Also removes X-Pingback from HTTP headers.

In one of the blogs, I found a couple more options for removing the XML-RPC disable.

1. Disable XML-RPC in the template.

To do this, a line is added to the theme's functions.php file:

Order Deny,Allow Deny from all

I personally did not use the last two methods, because. I connected the Disable XML-RPC Pingback plugin - I think it will be enough. Just for those who do not like extra settings, I offered alternative options.