You probably already know that WordPress websites are vulnerable to brute force attacks, called so because they just try over and over again to guess your username and password combination. But in the never-ending arms race between hackers and site owners there is also the problem of much more sophisticated bots that will try to worm their way into weaknesses in your website’s PHP code, too. Both of these hacks are popular ways of testing your defenses and they both underline the need for constant vigilance on the part of site owners and admins. To that end, you need to consistently upgrade your WordPress so that it’s always one step ahead of potential PHP vulnerabilities and you also need to make sure that you only use the most up-to-date versions of your plugins and themes.
If you didn’t already know, your WordPress website, themes, plug-ins, and apps such as PhpMyAdmin rely on a language called PHP to work properly. Now, the developers who write all of that stuff are not lazy and they aren’t deliberately leaving doors open for hackers to slip in through. The truth is, it’s hard for developers to write code that anticipates every single way that a bad actor might choose to attack. They do their best, release the software, and then it’s often only through everyday use that any holes in the defenses become apparent. Users’ experiences with attacks help to inform the process making everything secure. It’s a case of building it as best you can and testing it ‘in the wild’, responding to each new security alert as fast as possible, and then bracing for the next. It will become clear as you read that the majority of the PHP vulnerabilities shown here come about because of unsafe user input, meaning that someone has fed malevolent code to the web app or moved it to a section of the app in such a way that a vulnerability is created. This highlights why it’s important to pay special attention to all situations where user input can either deliberately or inadvertently introduce dangerous code to the system. These are always the leakiest parts of any WordPress ship.
There are a few different classifications of PHP vulnerabilities. We’ve include a few of the most frequently encountered ones with a basic explanation for each of them, but we haven’t included any PHP code as we’re aiming this to be an overview for people like admins rather than an exhaustive report for developers.
RCE – Remote Code Execution
Remote Code Execution (RCE) is just like it sounds. It happens when someone attacks and manages to upload code to your website and then runs it. A problem with a PHP application might let a user enter code which it then treats as PHP code, which might subsequently make it possible for the hacker to do various things. It could allow them to create a new file containing code that gives them full access to your website, for instance. This opportunity to remotely run malicious code is referred to as an RCE vulnerability. As you can imagine, the ability to do whatever they want with your website makes remote code execution an extremely dangerous kind of attack.
SQL Injection or SQLi
SQL Injection is similar, it’s when the hacker can get your database to run their own instructions. Anytime a PHP developer invites data input from a website visitor they should only pass it to the database after they’ve checked it to make sure that it isn’t trying to sneak in any dangerous code. SQL Injection gives a hacker free rein with the data on your website, which means they could create new data in your database including links to spammy or equally undesirable URLs. Hackers might also want to create their own admin level user account, to give themselves full access to and control of your website. It’s easily done with SQL injection. It’s another very serious security vulnerability because again, it hands the hacker the keys to your site.
Sometimes a PHP developer might believe that they are properly validating that a site visitor has the right access level before performing an action, but they’ll actually be checking the wrong thing.
This problem can insinuate itself into WordPress apps via a mistake that WordPress developers frequently make where they use the ‘is_admin()’ function when trying to confirm that someone is indeed an admin. The problem is that this function only tells you if someone is viewing an admin page, but it doesn’t prove that a site visitor is actually an administrator. If a developer inadvertently uses this function, then they are handing admin level features to users who aren’t really admins.
There are other examples in the same vein, and they occur most often when a developer doesn’t check to make sure that the user is permitted this kind of access before they allow a function to be executed.
PHP Object Injection
A PHP object Injection attack is more sophisticated because a PHP app passes input from the user to a function called ‘unserialize()’. This takes a stored object and puts it in memory. Although this seems complex, the main thing to remember with PHP object Injection is that it happens when a developer doesn’t do the right kind of gatekeeping and allows unsafe input from the user to enter a PHP application.
Cross-Site Scripting (XSS)
This is when a hacker causes a website visitor’s browser to load and run dangerous code, which might then (for example) grab their cookies and hand administrator-level access to the intruder, meaning that Bell once again be able to do whatever they like.
Cross-Site Scripting comes in two flavors – Stored and Reflected. A Stored Cross-Site Scripting vulnerability is one where the hacker tricks the website into allowing in dangerous code which later gets sent to and run in a visitor’s web browser. This kind of thing often happens when a comment is posted on your WordPress website that contains dangerous code. It then steals user cookies and passes them on to the hacker.
Reflected Cross-Site Scripting happens when a hacker puts dangerous code in a link. If it then gets loaded into a browser, the website serves it up along with the content. This code then runs in the visitor’s browser and it can steal cookies or perform other nefarious tasks. One example of a Reflected Cross-Site Scripting attack is a WordPress search results page that includes the search query included in the URL and is not cleaned properly. The page then serves up the search results as well as the initial query, which could be dangerous code that runs within the visitor’s browser. Hackers could use Reflected Cross-Site Scripting to compromise a website by creating a link to a page of search results with dangerous code in it, and they could then send that to the site administrator to steal their cookies.
Cross-Site Request Forgery – CSRF
A Cross-Site Request Forgery (CSRF) refers to when someone creates a link and manages to get a site admin (or in fact anybody with high-level access) to follow it, and this causes the site to perform an action. So, for instance, if somebody built a link that creates a new admin with a known password when a site admin clicks on it, this would be an example of a Cross-Site Request Forgery attack. It’s not all plain sailing though. The difficult part for the hacker is finding a way to convince the site admin to follow the link, and then set up the new admin with one of the currently used passwords which the bad guys hope to steal. WordPress does already have a way of protecting itself from this kind of approach. It uses a security token (just a number) known as a “nonce” which is granted to the admin each time they log in, and this number is included every time the WordPress site admin does something of the sensitive nature. If a hacker takes the approach we’ve described, trying to use a link in a Cross-Site Request Forgery attack, they also need to know the nonce to send with it. Since this number changes every day, successfully executing a Cross-Site Request Forgery attack becomes much more difficult, if not impossible. With that in mind, it should be the case that every developer knows not to build themes and plug-ins that don’t use nonces for request verification, but not everyone is as diligent as they should be. But they can put it right after the fact, and for an easy remedy they just need to use code to access WordPress’s native nonce feature.
Remote File Inclusion (RFI) and Local File Inclusion (LFI)
Remote File Inclusion or RFI happens when a PHP app passes user input to a function that loads a file. If the file turns out to be a URL, the function would then load PHP code from the hacker’s specially built website to attack your website. Including a remote file in a URL is called Remote File Inclusion or RFI. If the file a hacker passes is a local file, the application might send its contents to the screen. This is an approach frequently used by hackers to help them break into a WordPress website’s wp-config.php file. This approach is known as Local File Inclusion or LFI. Functions vulnerable to RFI and LFI in PHP are: include, include_once, fopen, file_get_contents, require and require_once.
All of these functions load PHP code or content from a place that the developer decides on. If they don’t configure the website’s PHP installation in the safest way, a hacker can then load a dangerous file as PHP code or content and use it give them access to your site. The majority of PHP installations keep you safe from RFI attacks which load remote URLs by restricting where files can be included from. But it’s not uncommon for PHP developers to inadvertently produce code that lets a hacker access a local file like wp-config.php. This helps to explain why Remote File Inclusion vulnerabilities happen less often than Local File Inclusion vulnerabilities.
We hope this overview of frequently seen PHP vulnerabilities and their creation has helped you in your role as a WordPress administrator. You might have seen a few of them on your security updates. We hope that the insights that we’ve shared about what they do will help you to stay vigilant and deal with them more effectively. This knowledge should make you better able to ask questions of developers and better able to see how vulnerabilities work before you deal with them.