Contents

PrivEsc: Abusing the Service Control Manager for Stealthy & Persistent LPE

Living off the Land

Earlier this week, Grzegorz Tworek posted a really cool way of establishing a persistent LPE that I haven’t previously seen in the wild. From a (compromised) privileged account we can abuse the Service Control Manager to allow any arbitrary non-administrative user to have full SYSTEM permissions on a machine persistently by feeding an overly permissive ACL to the service control manager with sdset.

Some background knowledge

Understanding what this attack is doing will require some light reading into both sdset as well as Microsoft’s Security Descriptor Definition Language (SDDL). But… to summarize both articles for you, we just need to know the format of a Security Descriptor string contains tokens to indicate each of the four main components of a security descriptor: owner (O:), primary group (G:), DACL (D:), SACL (S:), as well as tokens for the access-control entity. Security Descriptors can contain any combination of these tokens, and not all are necessarily required as we will demonstrate below.

Per the tweet, we just need to run sc.exe sdset scmanager D:(A;;KA;;;WD) from an elevated Windows shell (i.e. something with local admin privilege). Before I demonstrate the entire attack, let’s break this down a little more.

D:(A;;KA;;;WD) … wat.

If you’re like me, and have a very limited knowledge of how these Microsoft SDDL tokens work or what each portion represents, we should take some time to understand a little more. (You know, learn something new and all that jazz)

So what is this string actually representing? Let’s break each component down. To start, we should know the general access control entry syntax:

ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid;(resource_attribute)

  • D: Discretionary ACL (DACL)
    • A DACL identifies users and groups who are allowed or denied access to an object.
  • A; Access Allowed (ace_type)
    • This first segment represents the beginning of the access-control entry (ACE). An ACL contains a list of ACEs. An ACE defines access to an object for a specific user or group or defines the types of access that generate system-administration messages or alarms for a specific user or group. The user or group is identified by a security identifier (SID).
  • ace_flags is empty
  • KA; KEY_ALL_ACCESS (rights)
    • This token can also refer to Domain key credential administrators if used in the context of a SID, which isn’t at all confusing. All we need to know is this gives access to all registry keys related to SDDL.
  • object_guid is empty
  • inherit_object_guid is empty
  • WD - Security Principal of Everyone (account_sid)
    • Below you’ll find a table of some common security principals we can reference in an SDDL string.

ACE Security Principals

Abbreviation Security Principal
AU Authenticated Users
BA Built-in administrators
SY Local System
BU Built-in users
WD Everyone

TL;DR

The TL;DR here is, this command grants everyone, all, permissions on the service control manager. Meaning, I can (as a non-privileged user) create a service that will allow me to execute any arbitrary command as if I were SYSTEM due to the scmanager running as SYSTEM context. There’s a million articles you can read like this one if you want more technical references.

Example Attack Flow

Examining our normal user’s permissions.

So to start, we will use a non-privileged account and output the user information. Here I’m just basically demonstrating that the account we will privesc from has no administrative privileges.

/images/privesc/scmanager/normaluser.png

Modify the permissions of SCMANAGER via SDSET

Next, we execute the command to modify the scmanager ACL from our elevated command prompt. This must be done with an administrative account (the one that’s been compromised):

/images/privesc/scmanager/sdsetcmd.png

DETECTION OPPORTUNITY
Modifications to the ACL of the service-control manager should be scrutinized heavily. Below is a sample sigma rule to detect this blog’s POC behavior:
title: DACL Modification of Service Control Manager via sdset
id: 8998782b-66de-44e7-8335-305e2dd431b3
status: experimental
description: This rule detects usage of sdset to modify the DACL of the service-control manager service, scmanager.
references:
    - https://twitter.com/0gtweet/status/1628720819537936386?cxt=HHwWhIC87Ze9sJotAAAA
tags:
    - attack.persistence
    - attack.privilege_escalation
author: Gabriel De Jesus (0xv1n)
date: 2023/02/28
logsource:
    product: windows
    category: process_creation
detection:
    selection:
        Image|endswith:
            - '\sc.exe'
        CommandLine|contains|all:
            - ' sdset '
            - ' scmanager '
            - ' D:(A;;KA;;;WD) '
    condition: selection
fields:
    - Image
    - CommandLine
falsepositives:
    - Unknown
level: high

Confirm changes took place

We know the command was successful due to the feedback returned by the OS, but if we want to check the Security Descriptor for a service, we can do so with sdshow <service_name>. In this case, we confirm that scmanager indeed has the new security descriptor.

/images/privesc/scmanager/sdsetshow.png

Additionally (and thanks to Grzegorz!), we can run sc.exe sdshow scmanager showrights to enumerate the rights of the service. This essentially maps the tokens to their security descriptors and allows us to more easily understand the rights a particular service has:

/images/privesc/scmanager/showrights.png

Create a malicious Service for persistent LPE

We can now create a service from our non-privileged account to add our account to the local admin group of this machine:

sc create LPE displayName= "LPE" binPath= "C:\Windows\System32\net.exe localgroup Administrators nonpriv-user /add" start= auto

/images/privesc/scmanager/sccreate.png

Restart Machine

At this point, all we need to do is restart the machine and allow the service control manager to execute our new service with SYSTEM privileges. Once it comes back online, we should see that our account now is added to local admins.

/images/privesc/scmanager/admin.png

The best part of this mechanism, is that even if a smart admin removes the local admin privilege on the account, we still have the service. If the admin removes the service, we still have the ability to create a new one. The remediation for this type of persistence would be reverting the DACL of scmanager to a hardened state.

Persistent Local Privilege Escalation

And now, any time we want, we can spawn an arbitrary process with administrator privileges:

/images/privesc/scmanager/LPE.png


Hope this helps!