PowerShellMafia / PowerSploit

PowerSploit - A PowerShell Post-Exploitation Framework
Other
11.78k stars 4.59k forks source link

Add additional search entry for 'Get-UnattendedInstallFile' #266

Open sagishahar-zz opened 6 years ago

sagishahar-zz commented 6 years ago

Based on the following Microsoft Article, under the Implicit Answer File Search Order section, an additional location for an answer file may exist at HKLM\SYSTEM\Setup\UnattendFile. As pointed in the article, the full path to the file is stored under the aforementioned registry key. The file does not need to be named as Unattend.xml or the like, and can be located anywhere on the drive.

sagishahar-zz commented 6 years ago

Based on the original author's blog posts [1] [2] of the functions Get-WebConfig and Get-ApplicationHost, it occurred to me that their purpose was actually geared towards lateral movement ("breakout of the DMZ") as opposed to privilege escalation. In spite of their intentions, I still tried to see if I can squeeze out a legitimate reason for the functions to be used for privilege escalation. Here are my findings:

Get-WebConfig The function begins by looking for the existence of appcmd.exe as it uses this utility to map physical paths of the virtual directories within IIS that would most likely contain web.config files. Executing appcmd.exe as low privileged user yields the following output: capture1

Investigating this utility further pointed me to a Technet article that suggests that it is geared towards users within the Administrators group. In other words, it is indeed not suited for privilege escalation.

Putting aside the sources and the intention of appcmd.exe, the Get-WebConfig function continues by using aspnet_regiis.exe to decrypt the connectionStrings section within web.config. Under the hood, the aspnet_regiis.exe utility is using an encryption key (also known as a key container) that can either be user-level or machine-level. The default key container is machine-level that is not accessible to low privileged users. It is important to note that the exact inner workings of aspnet_regiis.exe are not fully known to me however I am aware that the encryption/decryption functionality utilizes DPAPI, meaning that only the user who encrypted the connectionStrings section can decrypt it. In addition to that this means that the decryption process must be done on the same host that the encryption process took place initially.

So the burning question is: Should this function be completely removed from PowerUp? The answer is no and here is why.

I have found out that there exist 2 independent misconfiguration conditions, which may still allow a low-privileged user to decrypt the connectionStrings section:

  1. A low privileged user can decrypt the connectionStrings section if they created a custom user-level key for encryption.
  2. A low privileged user can decrypt the connectionStrings section if they were granted access to the default key container (or any other key container) by a high privileged user.

Hopefully you are as convinced as I am why this function should remain in PowerUp. However, there is still the question of how Get-WebConfig surprisingly worked in its current implementation if a low privileged user has no permissions to run appcmd.exe?!

As can be seen in the screenshot above, the output that appcmd.exe generated is captured by PowerShell as a String array with the following items within: ["ERROR ( message:Configuration error", "", "Filename: redirection.config", "Line Number: 0", "", "Description: Cannot read configuration file due to insufficient permissions", "", ". )", ""]

From the array above, it is evident that after every line of text from appcmd.exe there is an empty string. The code at line 3079 (master branch) is searching for web.config in each virtual directory provided from appcmd.exe: $CurrentVdir | Get-ChildItem -Recurse -Filter web.config | ForEach-Object {

Given the array items above, each item in turn will be assigned to $CurrentVdir. The magic happens when the empty string ("") is assigned. The ForEach-Object loop will interpret the empty string as the current working directory. Therefore, if it just happened that the user ran Get-WebConfig from a directory that contains the file web.config within its subdirectories then they were lucky enough to get the decrypted credentials as expected. See demonstration of this below: capture2

The solution was to create a -Directory parameter that the user should provide in order to recursively search the directory tree for web.config and not rely on appcmd.exe

Get-ApplicationHost This function, similarly to Get-WebConfig also makes use of appcmd.exe however, it heavily relies on it (100% of the implementation), unlike Get-WebConfig . Unfortunately, I could not find a justifiable reason to use it for privilege escalation purposes. As previously mentioned, appcmd.exe is intended for users within the Administrators group thus a low privileged user cannot do much with this function. Probably it should be moved to a different PowerSploit module altogether.