Logon and boot scripts are an administrator's convenience that an intruder can turn into a persistence mechanism running on every machine a policy touches. MITRE ATT&CK T1037 Boot or Logon Initialization Scripts covers scripts that the operating system runs automatically at boot or logon, abused to keep access and sometimes to gain higher privileges. In ATT&CK v20 it sits in the Persistence and Privilege Escalation tactics, spans Windows, Linux, macOS, ESXi and network devices, and has five sub-techniques: Windows logon scripts, macOS login hooks, network logon scripts, RC scripts and macOS startup items. This guide explains where each script lives, which logs show a change, how to lock the locations down and how to evict planted scripts without breaking legitimate ones. It is for detection engineers, incident responders and the Active Directory, Linux and virtualisation teams who own those scripts. For the wider persistence picture, see the Persistence Techniques Guide; for Run keys and startup folders, see the T1547 Boot or Logon Autostart Execution Defensive Guide.
Key takeaways
- Network logon scripts have the widest reach. A script assigned through a Group Policy Object or the user's scriptPath attribute runs for every user in scope, so write access to SYSVOL, NETLOGON and GPOs is effectively code execution across the domain.
- One registry value is enough on a single host. T1037.001 only needs the per-user
HKCU\Environment\UserInitMprLogonScriptvalue, which standard users can write, so it needs its own detection. - RC scripts are the persistence route on hypervisors. On ESXi, which keeps most of its file system in memory, scripts in
/etc/rc.local.d/are one of the few ways to survive a reboot, and they run as root. - Deprecated does not mean absent. Login hooks, startup items and
rc.localare all legacy mechanisms that still run when present, so an empty baseline makes any new entry an alert. - Write permission is the control. ATT&CK lists only two mitigations, M1022 Restrict File and Directory Permissions and M1024 Restrict Registry Permissions; most of the defensive work is making sure only a small, named group can change these locations.
How the technique works
ATT&CK describes initialization scripts as legitimate administrative tooling that "may often execute other programs or send information to an internal logging server". An intruder with write access adds a line or a new script, then waits for the next boot or logon. What changes between sub-techniques is where the script is registered, who can register it and which account runs it.
| Sub-technique (v20) | Where it is registered | Runs as | Write access needed |
|---|---|---|---|
| T1037.001 Logon Script (Windows) | HKCU\Environment\UserInitMprLogonScript (a script path per user) | The logged-on user | The user themselves |
| T1037.002 Login Hook (macOS) | LoginHook and LogoutHook keys in /var/root/Library/Preferences/com.apple.loginwindow.plist | root | Administrator |
| T1037.003 Network Logon Script | GPO script settings (User Configuration and Computer Configuration, Windows Settings, Scripts) or the Active Directory scriptPath user attribute, with files on NETLOGON or SYSVOL | The user (logon scripts) or Local System (computer startup scripts) | GPO editors, or whoever can write the user object or script share |
| T1037.004 RC Scripts | /etc/rc.local, /etc/rc.common, distribution RC scripts, ESXi /etc/rc.local.d/ | root | root |
| T1037.005 Startup Items (macOS) | /Library/StartupItems/ with a StartupParameters.plist | root | Administrator |
ATT&CK publishes a detection strategy for each sub-technique, and the parent technique has its own, with analytics for Windows, Linux shell initialisation files, macOS, ESXi and network device startup configuration.
Windows: the per-user value and the domain-wide script
The two Windows sub-techniques look similar but carry very different risk. T1037.001 is local and per user: a path in UserInitMprLogonScript runs at that user's next logon. It gives persistence in a user context and, because standard users can write their own HKCU hive, it does not require administrator rights.
T1037.003 is a domain problem. Microsoft's Group Policy documentation shows logon scripts configured under User Configuration, Windows Settings, Scripts (Logon/Logoff), and startup scripts under Computer Configuration, Windows Settings, Scripts (Startup/Shutdown). Startup scripts run as Local System with full Local System rights; logon scripts run as the user. By default the Domain Admins, Enterprise Admins and Group Policy Creator Owners groups can edit GPOs. Separately, the scriptPath attribute on each user object names a logon script; Microsoft's schema documentation says it can be updated by a domain administrator or the account owner. A single edit to a script that every user runs from NETLOGON turns into execution on every workstation at the next logon, which is why this sub-technique is often paired with T1484 Domain or Tenant Policy Modification.
Linux, ESXi and network devices
On modern Linux distributions systemd has replaced SysV init, but compatibility remains. The systemd-rc-local-generator man page explains that if /etc/rc.local exists and is executable, the generator pulls rc-local.service into the boot, ordered after network.target. So a newly created, executable rc.local on a host that never had one will run at the next boot. ATT&CK's Linux analytic for the parent technique also covers shell initialisation files such as .bashrc, .profile and /etc/profile.
ESXi is where RC scripts matter most. ATT&CK notes that ESXi keeps most system files in memory and discards changes on shutdown, so /etc/rc.local.d/local.sh is one of the few persistence points. ATT&CK records that the group UNC3886 (G1048) placed a bash installation script into /etc/rc.local.d/ to persist on ESXi, so check that directory and any recently installed vSphere Installation Bundles (VIBs) together. For network devices, the ATT&CK analytic looks for boot-time configuration that persists malicious CLI commands across reboots, which means watching startup-config changes.
macOS: two deprecated mechanisms
Apple's archived developer documentation describes login and logout hooks as "a deprecated technology", recommends launchd jobs instead, and notes that hook scripts run as root, that only one login and one logout hook can exist at a time, and that other login actions wait for the hook to finish. ATT&CK notes that login hooks were deprecated in macOS 10.11, and that startup items are deprecated in favour of Launch Daemons (T1543.004). On a modern managed Mac fleet the expected state for both is "empty", which makes detection simple.
Detection: what to collect and what to alert on
All five sub-techniques have the same two observable moments: the script or registration is written, then it executes at boot or logon with an unusual parent-child chain. Detect both, and correlate them.
| Platform | Change signal | Execution signal | Notes |
|---|---|---|---|
| Windows host | Sysmon Event ID 13 (registry value set) on HKU\*\Environment\UserInitMprLogonScript; Security 4657 if a SACL with Set Value auditing is on the key | Security 4688 or Sysmon Event ID 1 where the parent is userinit.exe and the child is a script host or an unexpected binary | Any value at all is rare in most estates: alert on creation |
| Active Directory and SYSVOL | Directory Service Changes (5136) on scriptPath and on GPO objects; file auditing (4663) or 5145 share access on NETLOGON and SYSVOL script folders | 4688 for scripts started from \\domain\NETLOGON or SYSVOL paths; Group Policy events 4016 and 5312, which ATT&CK's network logon script analytic cites with 5145 and 4688 | Hash every file in the script shares and diff daily |
| Linux | auditd watches on /etc/rc.local, /etc/rc.d/, /etc/init.d/, /etc/profile, /etc/profile.d/ and user shell initialisation files; osquery file_events | auditd EXECVE records and boot logs showing rc-local.service started | Alert if rc-local.service appears on a host where it never ran before |
| ESXi | Shell activity and file changes in /etc/rc.local.d/; VIB installs (esxcli software vib) | Boot logs (vmkernel, hostd) showing scripts executing | Forward ESXi logs off the host; see the ESXi Logs Detection Guide |
| macOS | File changes to com.apple.loginwindow.plist under /var/root, and to /Library/StartupItems/ | Unified log loginwindow entries; processes with an unexpected parent at login | Expected baseline is empty |
| Network devices | Syslog configuration change messages and startup-config diffs from configuration backup | Commands executed at boot in device logs | See the Network Device Syslog and Configuration Change Detection Guide |
Practical tuning points:
- Baseline the legitimate scripts: most domains have a handful of logon scripts (drive mappings, printer setup). Record their names, hashes and the GPOs that reference them, and alert on any new or changed file rather than on every execution.
- Watch the writer, not only the write: a change to NETLOGON from a workstation, or by an account outside the GPO admin group, is a stronger signal than a change from the usual management server.
- Correlate change then execution: ATT&CK's network logon script detection strategy correlates a Group Policy update that configures a logon script with subsequent remote file execution at user logon. Build the same chain in your SIEM, keyed on script path.
- Hunt retrospectively: on Windows, query every user hive for
UserInitMprLogonScript; on Linux and ESXi, list RC script locations and compare to the gold image. The osquery Guide and Sysmon Guide cover the collection side.
Prevention and hardening
| Control | What it stops | How to apply | Trade-off |
|---|---|---|---|
| Lock down script shares (M1022) | Edits to NETLOGON and SYSVOL scripts by anyone outside a named admin group | Review NTFS and share permissions on script folders; remove broad groups with Modify or Write; record the owners | Script owners need a change route, ideally through a pipeline |
| Restrict GPO editing | New logon or startup scripts added to GPOs | Delegate GPO edit rights per OU to small groups; review membership of Group Policy Creator Owners; see the Group Policy Security Guide | More delegation administration |
Control scriptPath | Per-user network logon scripts pointing to rogue paths | Audit which accounts can write the attribute; prefer GPO-assigned scripts over per-user attributes so there is one place to review | Legacy estates may rely on the attribute |
| Registry permissions (M1024) | Logon scripts registered through the registry | Where the per-user value is never used, detect and remove it centrally; application control limits what a planted script can launch | Users own HKCU, so detection carries most of the weight |
| Application control | Scripts and binaries launched from user-writable paths | Script enforcement and path rules through App Control for Business; see the App Control for Business (WDAC) guide | Requires audit mode and tuning |
| Root-only, immutable RC locations | New RC scripts on Linux | Ensure /etc/rc.local does not exist where unused; file integrity monitoring on RC and profile paths; configuration management reasserts state | Packages occasionally ship RC scripts |
| ESXi hardening | Unsigned VIBs and scripts that restore backdoors | Keep the VIB acceptance level at the default or stricter and verify signatures; restrict shell and SSH; see the VMware ESXi Hardening Guide | Some vendor tools need shell access during maintenance |
| macOS configuration profiles | Login hooks and startup items | Restrict local admin rights; monitor the two paths through your EDR or MDM; see the macOS Security Guide for Enterprises | Few legitimate uses remain |
Choosing where to start
- Large Windows domain: start with T1037.003. Inventory every GPO script and every non-empty
scriptPath, fix share and GPO permissions, then deploy change detection. This one control protects every endpoint at once. - Virtualisation-heavy estate: start with ESXi RC scripts. Hypervisor compromise affects every guest, and ESXi rarely has an EDR agent, so log forwarding and configuration baselines are the main defence. The ESXi Ransomware Playbook covers response.
- Small organisation without a SIEM: a weekly scheduled report is enough to begin with: list GPO scripts with hashes, list RC script files on servers, and compare against last week.
- Mac-heavy organisation: both macOS sub-techniques need administrator rights, so removing standing admin from users does more than any detection rule.
Implementation: a phased rollout
- Inventory (week 1): export every GPO with script settings, every user with a non-empty
scriptPath, and RC and profile files on a sample of Linux, ESXi and network devices. Record owner and purpose for each. - Permissions (weeks 2 to 3): remove excess write access on NETLOGON, SYSVOL script folders and GPOs. Test logon on a pilot OU before and after. Rollback is restoring the previous ACL, so export ACLs first.
- Telemetry (weeks 2 to 4): enable Directory Service Changes auditing, add SACLs and Sysmon rules for
UserInitMprLogonScript, add auditd watches on RC paths, and forward ESXi and network device logs. - Detections in alert-only mode (weeks 4 to 6): run the change and execution rules for two weeks, record every legitimate change and tune.
- Enforce and route (week 7 onwards): route script changes through change management, with a ticket reference expected for every NETLOGON edit, and page on unapproved changes.
- Exercise: in a test OU, have the red team or an atomic test add a benign logon script and measure time to detect.
Evicting planted scripts
- Preserve first: copy the script, its timestamps and the GPO or attribute that references it before changing anything. On ESXi, collect before reboot, because in-memory state is lost.
- Find every registration: one script may be referenced by several GPOs, user objects or hosts. Search all GPOs and all
scriptPathvalues for the file name, and check other T1037 and T1547 locations on affected hosts. - Identify the writer: the account that edited the GPO or share is compromised or misused. Reset it and review its other changes. Treat GPO editor and domain admin accounts as Tier 0; see the Tiered Administration and Enterprise Access Model Guide.
- Remove and force refresh: delete the script and the reference, then force a Group Policy refresh and confirm on a sample host that the script no longer runs.
- Hunt for what it launched: logon scripts often install a second-stage mechanism such as a scheduled task or service. Check T1053 Scheduled Task/Job and T1543 Create or Modify System Process locations.
Where identity fits
T1037.003 is an identity problem in disguise. The ability to change a logon script is held by a few groups and service accounts: GPO editors, Domain Admins, deployment service accounts that publish scripts to NETLOGON, and accounts delegated write access to user objects. These are high-value machine and admin identities, and they are often missed in privileged access reviews because the permission sits on a file share or GPO rather than a group membership. Include them in your privileged inventory, vault their credentials and alert on interactive use. Startup scripts also run as Local System on every computer in scope, which is why our recommendation is to treat GPO edit rights as Tier 0. See the MITRE ATT&CK T1078 Valid Accounts Guide and the Active Directory Security Checklist.
Measuring it
- Script inventory coverage: percentage of GPO scripts and
scriptPathvalues with a recorded owner and hash (target 100%). - Writers per script location: number of accounts with write access to NETLOGON, SYSVOL script folders and script-bearing GPOs, tracked over time; it should fall.
- Unapproved changes: script changes without a matching change ticket per month (target zero).
- Telemetry coverage: percentage of Linux and ESXi hosts forwarding RC path changes and boot logs.
- Mean time to detect: from a test logon script being added to an alert, measured in exercises.
Common failure patterns
- Watching Run keys but not logon scripts: T1547 coverage is common, but
UserInitMprLogonScriptand NETLOGON changes are left out of the same rule set. - Broad write on NETLOGON: helpdesk or legacy groups keep Modify rights from years ago, so many identities can push code to every workstation.
- Alerting on execution only: every logon runs the legitimate scripts, so execution alerts drown. Alert on change, then use execution to confirm reach.
- Rebooting ESXi before collecting: the in-memory file system loses evidence; collect
/etc/rc.local.d/and logs first. See VMware ESXi Forensics. - Ignoring legacy macOS and Linux paths: teams assume deprecated mechanisms are inert, but
rc.localstill runs through the systemd compatibility generator when it is executable.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| MITRE ATT&CK v20 | T1037 and T1037.001 to T1037.005; mitigations M1022, M1024 | Technique definition and mitigations |
| NIST SP 800-53 Rev. 5 | CM-5 Access Restrictions for Change; CM-3 Configuration Change Control; SI-7 Software, Firmware, and Information Integrity; SI-4 System Monitoring; AC-6 Least Privilege | Who may change scripts, change control, integrity checks and monitoring |
| NIST CSF 2.0 | PR.PS-01 configuration management; DE.CM-09 monitoring computing hardware and software | Baselines and change detection |
Practitioner checklist
- Inventory every GPO logon and startup script and every non-empty
scriptPath, with owner and hash. - Remove excess write access on NETLOGON, SYSVOL script folders and script-bearing GPOs.
- Alert on any creation of
UserInitMprLogonScriptin a user hive. - Audit Directory Service Changes on
scriptPathand GPO objects. - Watch
/etc/rc.local, RC directories and profile files with auditd or osquery, and alert on first-timerc-local.serviceruns. - Forward ESXi logs off-host and monitor
/etc/rc.local.d/and VIB installs. - Expect empty login hooks and StartupItems on macOS and alert on any entry.
- Treat GPO editors and script deployment service accounts as Tier 0 identities.
- During eviction, preserve, find every reference, remove, refresh and recheck.
Standards and references
- MITRE ATT&CK: Boot or Logon Initialization Scripts (T1037)
- MITRE ATT&CK: Network Logon Script (T1037.003)
- MITRE ATT&CK: RC Scripts (T1037.004)
- Microsoft: Using Startup, Shutdown, Logon, and Logoff Scripts in Group Policy
- Microsoft: Script-Path attribute
- systemd: systemd-rc-local-generator man page
- Apple: Customizing Login and Logout
- MITRE ATT&CK: UNC3886 (G1048)
Related NHI Mgmt Group resources: Persistence Techniques Guide · T1547 Boot or Logon Autostart Execution Defensive Guide · Group Policy Security Guide · MITRE ATT&CK T1112 Modify Registry · Linux Logging and auditd for Defenders Guide