Вопрос или проблема
В настоящее время я реализую скрипт PowerShell для вызова API Sophos (https://developer.sophos.com/intro).
Write-Output "`nВведите ключ API Sophos / клиентский секрет."
$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
Я решил использовать фиктивные клиентские секреты, чтобы проверить, регистрируются ли они в Просмотрщике событий Windows. (Наша среда использует журналирование блоков скриптов PowerShell и журналирование модулей.) Выяснилось, что они действительно регистрируются (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”
Теперь я понимаю, что вам нужны права администратора, чтобы просмотреть эти журналы (ОБНОВЛЕНИЕ: На самом деле, похоже, что ID события 800 регистрирует тот же клиентский секрет, и неадминистраторы могут его просматривать) — тем не менее, наши журналы обрабатываются сторонним SOC, поэтому мы предпочли бы, чтобы они не видели открытые клиентские секреты (а также пароли или ключи шифрования).
Существует ли способ, чтобы мы могли надежно строить запросы к API — с клиентскими секретами — в PowerShell, чтобы они не регистрировались в открытом виде?
Во-первых, вы можете надежно строить запросы к API без каких-либо клиентских секретов в вашем скрипте, храня секреты в решении управления ключами, таком как Azure Key vault или AWS Secrets Manager.
Вы можете попробовать зашифровать конфиденциальную информацию в журналах с помощью Защищенного ведения событий.
Вы также можете иметь разные уровни журналирования и не раскрывать уровни журналов, содержащие секреты, стороннему SOC.
Вы также можете попробовать интегрировать модуль SecretManagement для PowerShell. https://www.techtarget.com/searchwindowsserver/tutorial/Working-with-PowerShell-Secret-Management-and-Secret-Vault
Тогда вы сможете сделать
$ClientSecret = Get-Secret -Name ClientSecret
Ответ или решение
При реализации скриптов PowerShell для взаимодействия с API, особенно таких как API от Sophos, важным аспектом является безопасность хранения и передачи секретных данных, таких как клиентские секреты. Из описания вашего сценария видно, что клиентские секреты выводятся в явном виде в логи PowerShell, что создает потенциальные уязвимости для утечки конфиденциальной информации.
Проблема
Вы используете PowerShell для запроса API, где секреты передаются в теле HTTP-запроса. Однако, из-за включенного журналирования скриптов (Script Block Logging и Module Logging), эти секреты сохраняются в Windows Event Viewer. Это не только создает риск их утечки, но и может быть доступно внешним службам, например, SOC-поставщикам.
Решения
-
Хранение секретов в защищённых хранилищах:
Вы можете использовать решения для управления секретами, такие как Azure Key Vault или AWS Secrets Manager. Это позволяет безопасно хранить секреты и получать к ним доступ в вашем скрипте только тогда, когда это необходимо:$ClientSecret = Get-Secret -Name YourSecretName
-
Защищённое ведение журналов:
Рассмотрите возможность использования Protected Event Logging. Это поможет вам шифровать данные, которые сохраняются в журналах, и защитить их от несанкционированного доступа. -
Управление уровнями журналирования:
Настройте уровни журналирования так, чтобы敏感ной информации, такой как клиентские секреты, не записывалась в доступные для сторонних служб логи. Это поможет минимизировать риск утечки. -
Использование модуля SecretsManagement:
Модуль SecretsManagement в PowerShell позволяет безопасно управлять секретами. Запрос секретов происходит в виде:$ClientSecret = Get-Secret -Name ClientSecret
Это обеспечит вам удобный способ получения секретов без их хранения в явном виде в коде.
Заключение
Забота о конфиденциальностях данных и защита секретов в вашем коде — это не только вопрос безопасности, но и репутации. Применение предложенных методов поможет вам безопасно взаимодействовать с API, сводя к минимуму риски утечки конфиденциальной информации. Защита ваших клиентских секретов обеспечит вашему проекту надежность и поможет избежать неблагоприятных последствий, связанных с их возможной утечкой.