CVE-2023-2249: Wordpress Wpforo Plugin Root Cause Analysis

On June 1st, 2023, a vulnerability was published within the WPForo Plugin - a user-friendly forum solution for WordPress websites. According to the official WordPress site, the plugin boasts over 20,000 active installations.

This vulnerability registered a CVSS score of 8.8 and exposes the plugin to multiple attack vectors. which includes Local File Inclusion (LFI), Server-Side Request Forgery (SSRF), and PHP Archive (PHAR) deserialization. There is the potential of leading to Remote Code Execution. Notably, this issue affects versions up to 2.1.7, but has been addressed in subsequent updates.

Since there is no public Proof-of-Concept (POC) available, we aim to conduct a root cause analysis of the vulnerability and present a proof of concept.

Enter Patch Diffing

Since WordPress plugins are open-source, diffing should be relatively easy. Fortunately, to make our life easy, NIST references of the CVE ID gives points to the file ‘classes/Actions.php’ file of the plugin. We diffed the version 2.17 and 2.18 of the same as shown below:

Fig 1: Versions being compared

We can see only 2 functions have been modified between the vulnerable and the patched versions of the file namely the ‘profiles_default_cover_upload’ and ‘profile_cover_upload’ which seem to be functionalities related to profile picture upload.

Fig 2: Functions being changed

Also, from NIST description, we know that there was usage of ‘file_get_contents’ without any sanitization which was the cause of the vulnerability. We can see the same was patched in the diff, so we are on the right track.

Fig 3: NIST description of the vulnerability

Fig 4: image_blob data being processed

From rough static code analysis, it seems like the user input for profile image data which is passed as ‘image_blob’ parameter if it doesn’t conform to a certain format, it gets passed to ‘file_get_contents’ as part of the else block. Before proceeding further analysis, let’s setup a vulnerable environment to understand the dynamic behavior.

Cooking up the Exploit

Setting up WordPress should be relatively easy, there are countless online tutorials. We will use a docker instance to speed things up.

Fig 5: Uploading Plugins to Wordpress

Once the plugin is activated, the home webpage should have a new ‘Forums’ button as below.

Fig 6: Forums option

We can figure out what type of permission is needed for the exploit later, for now let’s login as admin in the forums area and explore.


A screenshot of a computer Description automatically generated with medium confidence

Fig 7: Logging In

Since we know from before, the vulnerability is in the profile picture upload functionality, we explore the profile section and try uploading a picture (that’s my cat below)

Fig 8: Profile picture upload

To inspect what is really going on, we fire up BurpSuite proxy and inspect the traffic.

Fig 9: Request Response from BurpSuite


We can confirm we are in-fact hitting the endpoint since we have the action name ‘wpforo_profile_cover_upload’ (the function name from before with wpforo prepended which seems to be the naming convention) and also have the parameter ‘image_blob’ as we saw during our code analysis. If we decode the value of the blob, we can see it consists of file format (image/jpeg), encoding (base64) and the actual data separated by a comma.

Fig 10: image_blob data decoded

If we look at the code again, it tries to split the data by comma and if there is no second index it will pass the entire thing to ‘get_file_contents’, so we can pass whatever we want as part of the ‘image_blob’ parameter except a comma and it should reach the vulnerable section of the code and fetch the file as shown below -

Fig 11: Exploitation

We can try the same request by replacing the action name to be ‘wpforo_profiles_default_cover_upload’ the other vulnerable and we also get a success there. We don’t get the file contents back since it’s stored as an image. Retrieving the data for the ‘profiles_default_cover_upload’ action since it saves it with a static name profiles_custom_default_cover.jpg

Fig 12: Hardcoded image path

So, we can easily retrieve the contents by sending a curl request as below -

Fig 13: contents of /etc/passwd retrieved

We can have implemented the exploit with a proof-of-concept code at https://github.com/ixiacom/CVE-2023-2249. Since ‘file_get_contents’ can also take remote paths, the exploit can be used to reach internal endpoints as following where we deploy a file which is fetched with our proof-of-concept.

Fig 14: Mimicking internal files hosted

Fig 15: SSRF able to fetch internal files

In the proof-of-concept screenshot above we provided the credentials of a user ‘victimtest’ who is just a subscriber which also works, so very little privileges is required.

Fig 16: victimtest, low privileged user

Mitigations

The plugin vendor has released patches for the vulnerability in version 2.18, so it’s advised to update your version of the plugin.

You can also use the Keysight test platforms with ATI subscription to safeguard your network against such attacks. Keysight Threat Simulator or BreakingPoint products can help you assess your network security controls and determine whether you can be protected before the patch. This kind of assessment is valuable as it can let you know if you have protection during the time before a change management window will open. More on this below.

Leverage subscription service to stay ahead of attacks

Keysight's Application and Threat Intelligence (ATI) Subscription provides daily malware and bi-weekly updates of the latest application protocols and vulnerabilities for use with Keysight test platforms. The ATI Research Centre continuously checks threats as they appear in the wild to help keep your network secure and has added coverage for this vulnerability in release ATI-2023-13. More information is present here.

Fig 8: CVE-2023-2249 in BreakingPoint

limit
3