T1108

Redundant Access

Adversaries may use more than one remote access tool with varying command and control protocols or credentialed access to remote services so they can maintain access if an access mechanism is detected or mitigated. If one type of tool is detected and blocked or removed as a response but the organization did not gain a full understanding of the adversary's tools and access, then the adversary will be able to retain access to the network. This deprecated technique has been superseded by T1136 (Create Account), T1505/003 (Web Shell), and T1133 (External Remote Services), but the underlying adversary behavior — establishing backup access channels in parallel — remains a critical detection target. Observable patterns include simultaneous deployment of web shells alongside account creation, installation of multiple remote access services within a short window, and evidence of access from multiple distinct toolsets or protocols to the same target environment.

Microsoft Sentinel / Defender
kusto
// Detect multiple distinct remote access mechanisms established within 24h on the same device
// Covers web shell drops, remote service installs, new local/domain accounts, and external remote tool execution
let LookbackWindow = 24h;
let RemoteAccessBinaries = dynamic([
  "ngrok.exe", "frpc.exe", "frps.exe", "chisel.exe", "plink.exe", "putty.exe",
  "mRemoteNG.exe", "AnyDesk.exe", "TeamViewer.exe", "ScreenConnect.exe",
  "LogMeIn.exe", "VNCviewer.exe", "vncserver.exe", "psexec.exe", "psexesvc.exe",
  "mstsc.exe", "winscp.exe", "ssh.exe", "sshd.exe"
]);
let WebShellExtensions = dynamic([".asp", ".aspx", ".php", ".jsp", ".jspx", ".shtml"]);
let WebServerPaths = dynamic(["\\inetpub\\", "\\wwwroot\\", "\\htdocs\\", "\\www\\", "\\webapps\\"]);
// Signal 1: New account creation
let NewAccounts = SecurityEvent
| where TimeGenerated > ago(LookbackWindow)
| where EventID in (4720, 4726, 4738)
| project TimeGenerated, DeviceName=Computer, AccountName=TargetUserName, Signal="AccountCreatedOrModified";
// Signal 2: Remote access tool execution
let RemoteToolExec = DeviceProcessEvents
| where Timestamp > ago(LookbackWindow)
| where FileName in~ (RemoteAccessBinaries)
   or (ProcessCommandLine has_any ("ngrok", "frpc", "chisel", "ligolo") and ProcessCommandLine has_any ("tcp", "http", "tunnel", "connect", "proxy"))
| project TimeGenerated=Timestamp, DeviceName, AccountName, Signal="RemoteAccessToolExecution", Detail=strcat(FileName, " | ", ProcessCommandLine);
// Signal 3: Remote service installation
let RemoteServiceInstall = SecurityEvent
| where TimeGenerated > ago(LookbackWindow)
| where EventID in (7045, 4697)
| where ServiceName has_any ("vnc", "rdp", "ssh", "remote", "screen", "anydesk", "teamviewer", "logmein")
   or ServiceFileName has_any ("ngrok", "frpc", "chisel", "plink", "psexec")
| project TimeGenerated, DeviceName=Computer, AccountName=SubjectUserName, Signal="RemoteServiceInstalled", Detail=ServiceName;
// Signal 4: Web shell written to web server path
let WebShellDrop = DeviceFileEvents
| where Timestamp > ago(LookbackWindow)
| where FolderPath has_any (WebServerPaths)
| where FileName has_any (WebShellExtensions)
| where InitiatingProcessFileName !in~ ("w3wp.exe", "httpd.exe", "nginx.exe", "iisexpress.exe")
| project TimeGenerated=Timestamp, DeviceName, AccountName, Signal="WebShellDropped", Detail=strcat(FolderPath, "\\", FileName);
// Signal 5: Registry run key modification for remote access persistence
let RegistryPersist = DeviceRegistryEvents
| where Timestamp > ago(LookbackWindow)
| where RegistryKey has_any ("\\Run\\", "\\RunOnce\\", "\\Services\\")
| where RegistryValueData has_any ("ngrok", "frpc", "chisel", "anydesk", "teamviewer", "vnc", "rdp")
| project TimeGenerated=Timestamp, DeviceName, AccountName, Signal="PersistenceRegistryKey", Detail=strcat(RegistryKey, " = ", RegistryValueData);
// Union all signals and find devices with 2 or more distinct signal types
let AllSignals = union NewAccounts, RemoteToolExec, RemoteServiceInstall, WebShellDrop, RegistryPersist;
AllSignals
| summarize
    SignalCount=count(),
    DistinctSignals=dcount(Signal),
    SignalTypes=make_set(Signal),
    Details=make_set(Detail),
    Earliest=min(TimeGenerated),
    Latest=max(TimeGenerated)
  by DeviceName
| where DistinctSignals >= 2
| extend TimeWindowMinutes = datetime_diff('minute', Latest, Earliest)
| project DeviceName, DistinctSignals, SignalTypes, Details, Earliest, Latest, TimeWindowMinutes
| sort by DistinctSignals desc, TimeWindowMinutes asc
high severity medium confidence

Data Sources

Process: Process Creation File: File Creation Windows Registry: Registry Key Modification User Account: User Account Creation Service: Service Creation Microsoft Defender for Endpoint Windows Security Event Log

Required Tables

DeviceProcessEvents DeviceFileEvents DeviceRegistryEvents SecurityEvent

False Positives

  • IT administrators legitimately installing multiple remote management tools (RMM agents, VNC, RDP helpers) during system provisioning or maintenance windows
  • Software deployment pipelines (SCCM, Intune, Ansible) creating local service accounts and installing remote access agents as part of automated onboarding
  • Penetration testing engagements where multiple access mechanisms are intentionally deployed — coordinate with red team to suppress expected signals
  • DevOps/CI pipelines that install SSH, tunnel tools, and create service accounts in sequence during automated deployment jobs
  • Security teams deploying honeypot infrastructure where multiple remote access mechanisms are intentionally created to attract attackers

Unlock Pro Content

Get the full detection package for T1108 including response playbook, investigation guide, and atomic red team tests.

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections