1

I'm currently implementing a PowerShell script to call the Sophos API (https://developer.sophos.com/intro).

Write-Output "`nEnter the Sophos API key / client secret."
$ClientSecret = Read-Host -AsSecureString
$Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($ClientSecret)
$TheClientSecret = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($Ptr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($Ptr)

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Type", "application/x-www-form-urlencoded")
    
$body = "grant_type=client_credentials&client_id=aaaaaaaa-bbbb-cccc-dddd-ffffffffffff&client_secret=$TheClientSecret&scope=token"
    
$response = Invoke-RestMethod 'https://id.sophos.com/api/v2/oauth2/token' -Method 'POST' -Headers $headers -Body $body -ErrorVariable RespErr
$response | ConvertTo-Json

I decided to use bogus client secrets to test if they were being logged in the Windows Event Viewer. (Our environment uses PowerShell Script Block Logging and Module Logging.) It turns out that they were being logged (Event ID 4103):

ParameterBinding(Invoke-RestMethod): name="Headers"; value="System.Collections.Generic.Dictionary`2[System.String,System.String]" ParameterBinding(Invoke-RestMethod): name="Body"; value="grant_type=client_credentials&client_id=aaaaaaaa-bbbb-cccc-dddd-ffffffffffff&client_secret=plaintextclientsecretuhoh&scope=token" ParameterBinding(Invoke-RestMethod): name="Uri"; value="https://id.sophos.com/api/v2/oauth2/token"

Now, I realize that you need administrator privileges to view these logs (UPDATE: Actually, it looks like Event ID 800 logs the same client secret, and non-administrators can view that)--however, our logs are being ingested by a 3rd party SOC, so we'd rather not have them viewing plaintext client secrets (and passwords or encryption keys, for that matter).

Is there any way that we can securely construct API requests--with client secrets--in PowerShell which aren't logged in plaintext?

2 Answers 2

0

First off, you can securely construct API requests without any client secrets in your script by storing the secrets in a key management solution like Azure Key vault or AWS Secrets Manager instead

you can try to encrypt the sensitive information in the logs using Protected Event Logging

you can also have different log levels and not expose the log levels containing the secrets to the 3rd party SOC.

3
  • Oh sweet, I'll go ahead and take a look at those options and see what works. Thank you! Jul 22, 2022 at 22:45
  • Actually, I'm going to need some clarification--are you saying that if I pull a client secret from a key vault, that Windows automatically knows not to log it, even if I put it in a regular string as shown above? (The script already doesn't contain the client secret; it's grabbing it from user input). I'm not sure how a key vault would circumvent the problem. (Or perhaps you mean Azure Key vault could handle the the API requests?). (/1) Jul 23, 2022 at 15:51
  • Additionally, protected event logging might not be what we are looking for because it encrypts many of the logs for later decryption, but we still want our SOC to do real-time analysis of PowerShell logs as they are being collected. (We just want to take out the client secret). And finally, I don't think we'd be able to change the level of logging since--again--we still want to do real-time analysis of all kinds of PowerShell activity. (/2) Jul 23, 2022 at 15:52
0

You could also try to integrate the SecretsManagement powershell module. https://www.techtarget.com/searchwindowsserver/tutorial/Working-with-PowerShell-Secret-Management-and-Secret-Vault

Then you should be able to do

$ClientSecret = Get-Secret -Name ClientSecret 

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .