NetSPI Blog

Decrypting IIS Passwords to Break Out of the DMZ: Part 1

Scott Sutherland
February 10th, 2014

From the perspective of a penetration tester, it would be nice if every vulnerability provided a direct path to high-value systems on the internal network.  However, the reality is that we aren’t always that lucky, and sometimes we land on an application server in the DMZ network first. In this blog I’ll cover how to use native IIS  tools to recover encrypted database passwords from web.config files and leverage them to break into the internal network from the DMZ.  This should be interesting to penetration testers, developers, and system administrators trying to gain a better understanding of the value and limitations of passwords encrypted in IIS configuration files. Below is an overview of what will be covered.

Web.config Overview

Web.config is an XML configuration file that is used to control ASP.NET servers, applications, and pages. As an attacker, web.config files are incredibly valuable because they often contain connection strings that can be used to access databases on the internal network. Usually holes are poked through the DMZ firewall that allows the application server to access backend database servers. So connecting through the firewall boundary usually isn’t a problem. Once the attacker has successfully connected to a database server on the internal network it is possible escalate to the operating system level and in a few short steps obtain Domain Admin privileges. Below I’ll cover how to find and decrypt connection strings in web.config files.

Finding web.config Files

Before the connection strings can be extracted, the web.config files will need to be located. They can be found in multiple locations, but are typically located in the web root of each application directory. For example: “c:inetpubwwwrootMyAppweb.config”. As it turns out, IIS application directories are not always in the inetpub directory, and may not be located on the C drive at all. Thankfully there is a native command that can help. The appcmd.exe command is installed along with IIS 7 and can search, view, and modify IIS configurations (assuming you’re an admin). So we can run the command below to find the application directories we are looking for.

%windir%\system32\inetsrv\appcmd list vdir

From there it’s possible to quickly recursively search the directories for web.config files with the command below:

dir /s /b c:\MyTestSite | find /I "web.config"

Finding Connection Strings in the web.config

Now that we know where the web.config files are, we can start searching for connection strings. Luckily they are pretty easy to find because they are contained within the “connectionstrings” XML tag. Below is a basic example of what an unencrypted connection string might look like in a web.config file.

<connectionStrings>
<add
name="MyConnectionString"
connectionString="Data Source=PRDSQLSRV1;
Initial Catalog=Northwind;
Persist Security Info=True;
User ID=sa;
Password=Password1" providerName="System.Data.SqlClient"
>
</add>
</connectionstrings>

Appcmd can be used to streamline the recovery of connection strings if they are not encrypted. Below is a little script example:

for /f %i in ('%systemroot%\system32\inetsrv\appcmd list site /text:name') DO %systemroot%\system32\inetsrv\appcmd list config "%i" -section:connectionstrings

Decrypting Connection Strings in the web.config

From an attacker’s perspective it’s nice if connection strings are not encrypted. The reality is that it’s becoming more and more common for the strings to be encrypted (which is good for admins). Encrypting web.config files is useful for protecting connection strings when they have been backed up. However, once an attacker has administrative access to an IIS server it is possible to use the same methods the developers use to decrypt the connection strings.  Aspnet_regiis.exe is another native tool which is installed by default with .Net for IIS. In this example we are going to use it to decrypt our web.config. Below are the basic steps.

  1. Copy the web.config out of the application directory.
    copy "c:\inetpub\wwwroot\MyApp\web.config"  c:\temp
  2. View the file to verify the connection strings are encrypted. The connection strings should be encrypted in the “cipherdata” and “ciphervalue” tags within the “connectionStrings” tab.
    type c:\temp\web.config
  3. Decrypt the connection string in the web.config with aspnet_regiis.exe.  Make sure to use the most recent version found in the Framework folder.  The newest version is typically backwards compatible and should be able to decrypt connection strings that were encrypted with an older version.
    C:\Windows\Microsoft.NET\Frameworkv2.0.50727\aspnet_regiis.exe -pdf "connectionStrings" C:\temp
  4. Recover the unencrypted connection strings from the web.config file. The cleartext connection strings should look like the example shown in the last section.
    type c:tempweb.config

To automated the entire process I’ve write a small Powershell script called “get-webconfig.ps1” with Antti Rantasaari.  It can be downloaded from github HERE.  It’s also been added to the Posh-SecMod Powershell project owned by Carlos Perez.  The toolkit has a ton of handy scripts for all sorts of things – go check it out at https://github.com/darkoperator/Posh-SecMod.  Ok, back on track…

Don’t forget to run as an administrator or system.  Below is an example of the output.  It will show the username, password, database server, IIS virtual directory, full path to the web.config, and indicate if it was found encrypted.

PS C:>get-webconfig.ps1 | Format-Table -Autosize         user    pass       dbserv                vdir               path                          encr ----    ----       ------                ----               ----                          ---- s1admin s1password 192.168.1.101server1 C:App1            C:App1web.config            No   s1user  s1password 192.168.1.101server1 C:inetpubwwwroot C:inetpubwwwrootweb.config No   s2user  s2password 192.168.1.102server2 C:App2            C:App2testweb.config       No   s2user  s2password 192.168.1.102server2 C:App2            C:App2web.config            Yes  s3user  s3password 192.168.1.103server3 D:App3            D:App3web.config            No

Connecting to the Backend Database

Now that we have decrypted the database connection strings let’s use them. In most cases, web applications hosted on an IIS server connect to a Microsoft SQL Server on the backend. In some cases the command line SQL client tools are already installed on the IIS server. Those can be leveraged to access the database without too much effort. Below are some basic examples.

isql.exe –S PRDSRV1 –U sa –P Password1 –Q “SELECT name FROM master..sysdatabases”
osql.exe –S PRDSRV1 –U sa –P Password1 –Q “SELECT name FROM master..sysdatabases”
sqlcmd.exe –S PRDSRV1 –U sa –P Password1 –Q “SELECT name FROM master..sysdatabases”

If command line SQL clients are not on the server, then PowerShell can be used to accomplish the same goal. Antti Rantasaari made a great web shell that will do all of this for you. He also wrote a nice little blog to go with it that you can find here. Below is a basic example showing how to list all of the databases on the remote server if you want to experiment on your own.  However, during a real attack you would most likely use the xp_cmdshell and xp_dirtree stored procedures to pivot into the internal network.  Antti and I put together a presentation a while back the covers those topics in more detail. You can download it from slideshare here.

$conn = New-Object System.Data.SqlClient.SqlConnection $conn.ConnectionString = "Server=PRDSRV1;Database=master;User ID=sa;Password=Password1;" $conn.Open() $sql = "SELECT name from master..sysdatabases" $cmd = New-Object System.Data.SqlClient.SqlCommand($sql,$conn) $rdr = $cmd.ExecuteReader() $test = @() while($rdr.Read()) { $test += ($rdr["name"].ToString()) } Write-Output $test

Wrap Up

Encrypting passwords in the web.config does help reduce risk related to read-only attacks and access to backup files. However, if an attacker is able to gain administrative access to a system they will be able to use administrative tools or Windows APIs such as crypt32.dll to decrypt protected passwords. As a result, attackers may be able to break out of the DMZ zone and into the internal network. That is why it is very important to also make sure that all accounts are configured with least privilege, proper network zone isolation is enforced, and sensitive accounts are being audited. Hopefully this was helpful.  Have fun and hack responsibly!

Resources

Leave a Reply

avatar

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
Notify of