mcpField
P
powershell-security

powershell-security

github.com/josiahsiegelセキュリティ59189 回インストール19 週間前に更新
リポジトリ

powershell-security について

資格情報の管理、スクリプトの強化、管理制御を扱う PowerShell セキュリティスキルです。スクリプト作成者や管理者向けに、SecretManagement、JEA、WDAC、署名、ログ記録を解説します。

主な機能

  1. 01SecretManagement とボールトプロバイダーの指針
  2. 02資格情報の管理と Azure 認証
  3. 03JEA のロール制限と監査ログ
  4. 04WDAC と制限付き言語モード
  5. 05スクリプト署名と実行ポリシー
  6. 06入力検証とセキュリティチェックリスト

活用シーン

  1. 01スクリプトから平文の資格情報を除去
  2. 02委任する PowerShell 管理権限の制限
  3. 03特権自動化セッションの監査
  4. 04本番用スクリプトのセキュリティ強化

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill powershell-security

インストール後、Claude Code で/powershell-securityを入力して読み込まれたか確認します。

詳細

PowerShell のセキュリティに関するベストプラクティス(2025)

PowerShell スクリプトと自動化における最新のセキュリティ対策。資格情報の管理、SecretManagement モジュール、強化の手法を含みます。

SecretManagement モジュール(2025 年推奨標準)

概要

Microsoft.PowerShell.SecretManagement は、PowerShell で資格情報を安全に保存するための公式ソリューションです。

SecretManagement を使用する理由:

  • スクリプトに平文の資格情報を保存しません
  • クロスプラットフォームのシークレットストレージ
  • 複数のボールトプロバイダーをサポート
  • Azure Key Vault、1Password、KeePass などとの統合
インストール
# Install SecretManagement module
Install-Module -Name Microsoft.PowerShell.SecretManagement -Scope CurrentUser

# Install vault provider (choose one or more)
Install-Module -Name Microsoft.PowerShell.SecretStore  # Local encrypted vault
Install-Module -Name Az.KeyVault                        # Azure Key Vault
Install-Module -Name SecretManagement.KeePass          # KeePass integration
基本的な使い方
# Register a vault
Register-SecretVault -Name LocalVault -ModuleName Microsoft.PowerShell.SecretStore

# Store a secret
$password = Read-Host -AsSecureString -Prompt "Enter password"
Set-Secret -Name "DatabasePassword" -Secret $password -Vault LocalVault

# Retrieve a secret
$dbPassword = Get-Secret -Name "DatabasePassword" -Vault LocalVault -AsPlainText
# Or as SecureString
$dbPasswordSecure = Get-Secret -Name "DatabasePassword" -Vault LocalVault

# List secrets
Get-SecretInfo

# Remove a secret
Remove-Secret -Name "DatabasePassword" -Vault LocalVault
Azure Key Vault との統合
# Install and import Az.KeyVault
Install-Module -Name Az.KeyVault -Scope CurrentUser
Import-Module Az.KeyVault

# Authenticate to Azure
Connect-AzAccount

# Register Azure Key Vault as secret vault
Register-SecretVault -Name AzureKV `
    -ModuleName Az.KeyVault `
    -VaultParameters @{
        AZKVaultName = 'MyKeyVault'
        SubscriptionId = 'your-subscription-id'
    }

# Store secret in Azure Key Vault
Set-Secret -Name "ApiKey" -Secret "your-api-key" -Vault AzureKV

# Retrieve from Azure Key Vault
$apiKey = Get-Secret -Name "ApiKey" -Vault AzureKV -AsPlainText
SecretManagement を使用した自動化スクリプト
<#
.SYNOPSIS
    Secure automation script using SecretManagement

.DESCRIPTION
    Demonstrates secure credential handling without hardcoded secrets
#>

#Requires -Modules Microsoft.PowerShell.SecretManagement

[CmdletBinding()]
param()

# Retrieve credentials from vault
$dbConnectionString = Get-Secret -Name "SQLConnectionString" -AsPlainText
$apiToken = Get-Secret -Name "APIToken" -AsPlainText

# Use credentials securely
try {
    # Database operation
    $connection = New-Object System.Data.SqlClient.SqlConnection($dbConnectionString)
    $connection.Open()

    # API call with token
    $headers = @{ Authorization = "Bearer $apiToken" }
    $response = Invoke-RestMethod -Uri "https://api.example.com/data" -Headers $headers

    # Process results
    Write-Host "Operation completed successfully"
}
catch {
    Write-Error "Operation failed: $_"
}
finally {
    if ($connection) { $connection.Close() }
}

資格情報管理のベストプラクティス

資格情報をハードコードしない
# ❌ WRONG - Hardcoded credentials
$password = "MyPassword123"
$username = "admin"

# ❌ WRONG - Plaintext in script
$cred = New-Object System.Management.Automation.PSCredential("admin", "password")

# ✅ CORRECT - SecretManagement
$password = Get-Secret -Name "AdminPassword" -AsPlainText
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential("admin", $securePassword)

# ✅ CORRECT - Interactive prompt (for manual runs)
$cred = Get-Credential -Message "Enter admin credentials"

# ✅ CORRECT - Managed Identity (Azure automation)
Connect-AzAccount -Identity
サービスプリンシパル認証(Azure)
# Store service principal credentials in vault
Set-Secret -Name "AzureAppId" -Secret "app-id-guid"
Set-Secret -Name "AzureAppSecret" -Secret "app-secret-value"
Set-Secret -Name "AzureTenantId" -Secret "tenant-id-guid"

# Retrieve and authenticate
$appId = Get-Secret -Name "AzureAppId" -AsPlainText
$appSecret = Get-Secret -Name "AzureAppSecret" -AsPlainText
$tenantId = Get-Secret -Name "AzureTenantId" -AsPlainText

$secureSecret = ConvertTo-SecureString $appSecret -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($appId, $secureSecret)

Connect-AzAccount -ServicePrincipal -Credential $credential -Tenant $tenantId

Just Enough Administration(JEA)

JEA とは?

Just Enough Administration は、PowerShell リモート処理セッションで使用できるコマンドレットとパラメーターを制限します。

ユースケース
  • 管理者権限をすべて付与せずに、管理タスクを委任する
  • コンプライアンス要件(SOC 2、HIPAA、PCI-DSS)
  • 本番環境の強化
  • 特権操作の監査証跡
JEA エンドポイントの作成
# 1. Create role capability file
New-PSRoleCapabilityFile -Path "C:\JEA\RestartServices.psrc" `
    -VisibleCmdlets @{
        Name = 'Restart-Service'
        Parameters = @{
            Name = 'Name'
            ValidateSet = 'Spooler', 'W32Time', 'WinRM'
        }
    }, 'Get-Service'

# 2. Create session configuration file
New-PSSessionConfigurationFile -Path "C:\JEA\RestartServices.pssc" `
    -SessionType RestrictedRemoteServer `
    -RoleDefinitions @{
        'DOMAIN\ServiceAdmins' = @{ RoleCapabilities = 'RestartServices' }
    } `
    -LanguageMode NoLanguage

# 3. Register JEA endpoint
Register-PSSessionConfiguration -Name RestartServices `
    -Path "C:\JEA\RestartServices.pssc" `
    -Force

# 4. Connect to JEA endpoint (as delegated user)
Enter-PSSession -ComputerName Server01 -ConfigurationName RestartServices

# User can ONLY run allowed commands
Restart-Service -Name Spooler  # ✅ Allowed
Restart-Service -Name DNS      # ❌ Denied (not in ValidateSet)
Get-Process                    # ❌ Denied (not visible)
JEA 監査ログ
# Enable transcription and logging
New-PSSessionConfigurationFile -Path "C:\JEA\AuditedSession.pssc" `
    -SessionType RestrictedRemoteServer `
    -TranscriptDirectory "C:\JEA\Transcripts" `
    -RunAsVirtualAccount

# All JEA sessions are transcribed to C:\JEA\Transcripts
# Review audit logs
Get-ChildItem "C:\JEA\Transcripts" | Get-Content

Windows Defender Application Control(WDAC)

PowerShell スクリプトの制御

WDAC は、実行可能な PowerShell スクリプトを制御するために AppLocker を置き換えます。

# Create WDAC policy for signed scripts only
New-CIPolicy -FilePath "C:\WDAC\PowerShellPolicy.xml" `
    -ScanPath "C:\Scripts" `
    -Level FilePublisher `
    -Fallback Hash `
    -UserPEs

# Allow only signed scripts
Set-RuleOption -FilePath "C:\WDAC\PowerShellPolicy.xml" `
    -Option 3 # Required WHQL

# Convert to binary policy
ConvertFrom-CIPolicy -XmlFilePath "C:\WDAC\PowerShellPolicy.xml" `
    -BinaryFilePath "C:\Windows\System32\CodeIntegrity\SIPolicy.p7b"

# Reboot to apply policy
Restart-Computer

コード署名

スクリプトに署名する理由
  • スクリプトの整合性を検証する
  • 組織のセキュリティポリシーを満たす
  • WDAC の適用を可能にする
  • 改ざんを防止する
スクリプトへの署名
# Get code signing certificate
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert

# Sign script
Set-AuthenticodeSignature -FilePath "C:\Scripts\MyScript.ps1" -Certificate $cert

# Verify signature
$signature = Get-AuthenticodeSignature -FilePath "C:\Scripts\MyScript.ps1"
$signature.Status  # Should be "Valid"
実行ポリシー
# Check current execution policy
Get-ExecutionPolicy

# Set execution policy (requires admin)
Set-ExecutionPolicy RemoteSigned -Scope LocalMachine

# Bypass for single script (testing only)
PowerShell.exe -ExecutionPolicy Bypass -File "script.ps1"

制約付き言語モード

制約付き言語モードとは?

悪意のあるコードの実行を防ぐため、PowerShell の言語機能を制限します。

# Check current language mode
$ExecutionContext.SessionState.LanguageMode
# Output: FullLanguage (admin) or ConstrainedLanguage (standard user)

# Set system-wide constrained language mode
# Via Environment Variable or Group Policy
# Set: __PSLockdownPolicy = 4

# Test constrained mode behavior
# FullLanguage allows:
[System.Net.WebClient]::new()  # ✅ Allowed

# ConstrainedLanguage blocks:
[System.Net.WebClient]::new()  # ❌ Blocked
Add-Type -TypeDefinition "..."  # ❌ Blocked

スクリプトブロックのログ記録

ログ記録を有効にする
# Enable via Group Policy or Registry
# HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging
New-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" `
    -Name "EnableScriptBlockLogging" -Value 1 -PropertyType DWord

# Log location: Windows Event Log
# Event Viewer > Applications and Services Logs > Microsoft > Windows > PowerShell > Operational
ログを確認する
# Query script block logs
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" |
    Where-Object { $_.Id -eq 4104 } |  # Script Block Logging event
    Select-Object TimeCreated, Message |
    Out-GridView

入力の検証

インジェクション攻撃を防ぐ
# ❌ WRONG - No validation
function Get-UserData {
    param($Username)
    Invoke-Sqlcmd -Query "SELECT * FROM Users WHERE Username = '$Username'"
}
# Vulnerable to SQL injection

# ✅ CORRECT - Parameterized queries
function Get-UserData {
    param(
        [ValidatePattern('^[a-zA-Z0-9_-]+$')]
        [string]$Username
    )
    Invoke-Sqlcmd -Query "SELECT * FROM Users WHERE Username = @Username" `
        -Variable @{Username=$Username}
}

# ✅ CORRECT - ValidateSet for known values
function Restart-AppService {
    param(
        [ValidateSet('Web', 'API', 'Worker')]
        [string]$ServiceName
    )
    Restart-Service -Name "App${ServiceName}Service"
}

セキュリティチェックリスト

スクリプト開発
  • 資格情報をハードコードしない(SecretManagement を使用する)
  • SQL 操作にはパラメーター化クエリを使用する
  • [ValidatePattern]、[ValidateSet] などを使って、すべてのユーザー入力を検証する
  • Set-StrictMode -Version Latest を有効にする
  • エラー処理には try/catch を使用する
  • ユーザー入力を伴う Invoke-Expression の使用を避ける
  • 本番環境のスクリプトに署名する
  • スクリプトブロックのログ記録を有効にする
自動化
  • マネージド ID またはサービスプリンシパルを使用する(パスワードは使用しない)
  • シークレットを SecretManagement または Azure Key Vault に保存する
  • 管理タスクの委任に JEA を導入する
  • すべての特権操作で監査ログを有効にする
  • 最小権限の原則を適用する
  • 資格情報を定期的にローテーションする
  • 認証失敗の試行を監視する
本番環境
  • スクリプト制御のために WDAC ポリシーを導入する
  • 管理者以外のユーザーには制約付き言語モードを使用する
  • PowerShell のログ記録(スクリプトブロックとトランスクリプション)を有効にする
  • 署名済みスクリプトを必須にする(実行ポリシーを使用)
  • セキュリティ監査を定期的に実施する
  • PowerShell を最新の状態に保つ(7.5 以降)
  • リモート管理に JEA を使用する

リソース

コメント