# Author: Scott Sutherland, NetSPI (@_nullbind / nullbind) # Function to parse configuration files for credentials function Get-CredentialsFromConfigFile { param ( [string]$configFilePath ) # Load the config file as XML [xml]$configXml = Get-Content $configFilePath # Initialize a DataTable to store results $dtCredentials = New-Object System.Data.DataTable $null = $dtCredentials.Columns.Add("Name", [string]) $null = $dtCredentials.Columns.Add("Section", [string]) $null = $dtCredentials.Columns.Add("URL", [string]) $null = $dtCredentials.Columns.Add("Server", [string]) $null = $dtCredentials.Columns.Add("Port", [string]) $null = $dtCredentials.Columns.Add("UserName", [string]) $null = $dtCredentials.Columns.Add("Password", [string]) # Helper function to add rows to DataTable function Add-CredentialsToDataTable { param ( [string]$name, [string]$section, [string]$url, [string]$server, [string]$port, [string]$username, [string]$password ) $null = $dtCredentials.Rows.Add($name, $section, $url, $server, $port, $username, $password) } # Dictionary to temporarily store related credentials $credentialPairs = @{} # Function to store credentials in temporary dictionary function Add-CredentialPair { param ( [string]$name, [string]$section, [string]$key, [string]$value ) if ($credentialPairs[$name]) { $credentialPairs[$name][$key] = $value } else { $credentialPairs[$name] = @{} $credentialPairs[$name][$key] = $value $credentialPairs[$name]["Section"] = $section } # If both username and password are available, add them to the DataTable if ($credentialPairs[$name]["UserName"] -and $credentialPairs[$name]["Password"]) { Add-CredentialsToDataTable -name $name -section $credentialPairs[$name]["Section"] ` -url $credentialPairs[$name]["URL"] -server $credentialPairs[$name]["Server"] ` -port $credentialPairs[$name]["Port"] -username $credentialPairs[$name]["UserName"] ` -password $credentialPairs[$name]["Password"] # Clear the stored credential after adding it to the table $credentialPairs.Remove($name) } } # Parse all instances of appSettings for OAuth, WebClient, API, and other credentials if ($configXml.SelectNodes('//appSettings')) { foreach ($appSettings in $configXml.SelectNodes('//appSettings')) { foreach ($setting in $appSettings.add) { $key = $setting.key $value = $setting.value $section = "AppSettings" # Handle specific cases for OAuth, API, and WebClient settings switch ($key) { "OAuthServiceUrl" { Add-CredentialPair -name "OAuth" -section $section -key "URL" -value $value } "ClientId" { Add-CredentialPair -name "OAuth" -section $section -key "UserName" -value $value } "ClientSecret" { Add-CredentialPair -name "OAuth" -section $section -key "Password" -value $value } "ServiceUrl" { Add-CredentialPair -name "WebClient" -section $section -key "URL" -value $value } "ServiceUserName" { Add-CredentialPair -name "WebClient" -section $section -key "UserName" -value $value } "ServicePassword" { Add-CredentialPair -name "WebClient" -section $section -key "Password" -value $value } "ApiEndpoint" { Add-CredentialPair -name "API" -section $section -key "URL" -value $value } "ApiUserName" { Add-CredentialPair -name "API" -section $section -key "UserName" -value $value } "ApiPassword" { Add-CredentialPair -name "API" -section $section -key "Password" -value $value } "ApplicationUsername" { Add-CredentialPair -name "Application" -section $section -key "UserName" -value $value } "ApplicationPassword" { Add-CredentialPair -name "Application" -section $section -key "Password" -value $value } } } } } # Parse custom serviceCredentials section if ($configXml.configuration.serviceCredentials) { foreach ($setting in $configXml.configuration.serviceCredentials.add) { $key = $setting.key $value = $setting.value $section = "ServiceCredentials" # Handle specific cases for custom service credentials switch ($key) { "ServiceUrl" { Add-CredentialPair -name "CustomService" -section $section -key "URL" -value $value } "UserName" { Add-CredentialPair -name "CustomService" -section $section -key "UserName" -value $value } "Password" { Add-CredentialPair -name "CustomService" -section $section -key "Password" -value $value } } } } # Parse connectionStrings for server, port, username, and password if ($configXml.configuration.connectionStrings) { foreach ($connection in $configXml.configuration.connectionStrings.add) { $connectionString = $connection.connectionString $providerName = $connection.providerName $name = $connection.name # Initialize variables for potential data $server = $null $port = $null $user = $null $password = $null $url = $null # Parse connection strings if ($connectionString -match "Host\s*=\s*([^;]+).*?Port\s*=\s*(\d+).*?Username\s*=\s*([^;]+).*?Password\s*=\s*([^;]+)") { $server = $matches[1] $port = $matches[2] $user = $matches[3] $password = $matches[4] $url = "Host=$server;Port=$port" } elseif ($connectionString -match "(Server|Data Source)\s*=\s*([^;,]+)(?:,(\d+))?") { $server = $matches[2] if ($matches[3]) { $port = $matches[3] } $url = "Server=$server" } if ($connectionString -match "User\s*Id\s*=\s*([^;]+)") { $user = $matches[1] } if ($connectionString -match "Password\s*=\s*([^;]+)") { $password = $matches[1] } # Add row to the DataTable if username and password exist if ($user -and $password) { Add-CredentialsToDataTable -name $name -section "ConnectionStrings ($providerName)" -url $url -server $server -port $port -username $user -password $password } } } # Parse system.net/mailSettings for SMTP credentials and URLs if ($configXml.configuration.'system.net'.mailSettings) { foreach ($smtp in $configXml.configuration.'system.net'.mailSettings.smtp) { $smtpServer = $smtp.network.host $smtpPort = $smtp.network.port $smtpUser = $smtp.network.userName $smtpPass = $smtp.network.password $url = "smtp://${smtpServer}:${smtpPort}" if ($smtpUser -and $smtpPass) { Add-CredentialsToDataTable -name "SMTP Configuration" -section "SMTP" -url $url -server $smtpServer -port $smtpPort -username $smtpUser -password $smtpPass } } } # Output the parsed credentials using the DataTable if ($dtCredentials.Rows.Count -eq 0) { Write-Host "No credentials found." -ForegroundColor Red } else { $dtCredentials | select Name, Section, URL, Server, Port, UserName, Password } } # Example of calling the function with a file path Get-CredentialsFromConfigFile -configFilePath "c:\temp\configs\app.config" <# app.config
#>