Go to list of users who liked
令和の SSO × PAM 攻防戦
Zero Trust 時代の「認証・特権の継ぎ目」を徹底解剖
企業のDXが加速する中、SSOとPAMの連携が当たり前となった現在。しかし、その「継ぎ目」こそが最大の攻撃対象となっています。
この記事では、攻撃者の視点から見た最新の攻撃手法と、それに対する実践的な防御策を、実装コードとともに解説します。
SSO やPAM については、以下の記事で詳しく説明しています。
令和のアイデンティティ地図:IdP ↔ PAM ↔ ワークロード
現代のエンタープライズ環境では、Identity Provider(IdP)とPrivileged Access Management(PAM)が密接に連携し、ユーザーのアクセス制御を行っています。しかし、この連携部分にこそ脆弱性が潜んでいます。
この図で重要なのは、3つの境界です。
- User ↔ IdP:初期認証の境界
- IdP ↔ PAM:トークン検証の境界
- PAM ↔ Target:特権セッションの境界
攻撃者は、これらの境界の「継ぎ目」を狙って侵入を試みます。
攻撃者の常套手段 2025 — Token Theft → 横移動の実際
CryptoChameleon攻撃の分析
2024年3月に初確認されたCryptoChameleon攻撃は、FCCの職員を標的としたOktaを模倣したフィッシング攻撃として報告され、従来の手法を大幅に進化させています。
攻撃の流れ
- 巧妙なフィッシングサイト:完全にOktaのUIを模倣
- MFA バイパス:リアルタイムでプロキシ経由でMFAコードを中継
- セッションハイジャック:取得したトークンを即座に悪用
- PAM侵入:有効なトークンでPAMゲートウェイを突破
長寿命トークン悪用の実態
最も危険なのは、Refresh Tokenや長寿命アクセストークンの悪用です。
// 攻撃者が取得したトークンの例conststolenToken={access_token:"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",expires_in:3600,refresh_token:"AQABAAAA...",// 90日間有効scope:"openid profile email"};// 攻撃者は refresh_token を使って長期間アクセス可能
[ 対策ポイント ]
- Refresh Tokenの有効期限を最短に設定
- Token Binding(デバイス固有の暗号化)を実装
- 異常なトークン使用パターンの検知
SAML / OIDC フロー徹底分解
SAML Assertion Manipulation攻撃
SAMLの仕組みを悪用した攻撃は、特にAssertion Replay とSignature Wrapping が危険です。これらの攻撃は、正規のSAMLアサーションを改竄・再利用することで認証を突破しようとします。
以下は、正常なSAMLアサーションの構造例です。
<!-- 正常なSAMLアサーション --><saml:Assertionxmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"ID="_12345"IssueInstant="2025-01-15T10:00:00Z"><saml:Subject><saml:NameIDFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"> user@company.com</saml:NameID><saml:SubjectConfirmationMethod="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationDataNotOnOrAfter="2025-01-15T10:05:00Z"/></saml:SubjectConfirmation></saml:Subject></saml:Assertion>
攻撃手法
- Replay Attack:過去のアサーションを再送信
- Signature Wrapping:署名を残したまま内容を改竄
- XML Signature Exclusion:署名対象外の要素を操作
実装レベルでの対策
PAM側でJWTトークンを検証する際は、単純な署名チェックだけでなく、厳格な検証パラメータ を設定することが重要です。以下は.NET 8を使用した実装例で、Azure Entra IDとの連携を想定しています。
// .NET 8 での堅牢なJWT検証publicclassTokenValidator{privatereadonlyJwtSecurityTokenHandler_handler=new();privatereadonlyHttpClient_httpClient;publicTokenValidator(HttpClienthttpClient){_httpClient=httpClient;}publicasyncTask<bool>ValidateTokenAsync(stringtoken){try{// 1. JWKSエンドポイントから公開鍵を取得varjwks=awaitGetJwksAsync();// 2. 検証パラメータを厳格に設定varparameters=newTokenValidationParameters{IssuerSigningKeys=jwks,ValidateIssuer=true,ValidIssuer="https://login.microsoftonline.com/<tenant>/v2.0",ValidateAudience=true,ValidAudience="api://your-pam-gateway",ValidateLifetime=true,ClockSkew=TimeSpan.FromMinutes(1),// 時刻のズレを最小限にRequireSignedTokens=true,RequireExpirationTime=true};// 3. トークンの検証実行varprincipal=_handler.ValidateToken(token,parameters,outvarvalidatedToken);// 4. 追加の検証(Nonceチェックなど)returnawaitAdditionalValidationAsync(validatedToken);}catch(SecurityTokenException){returnfalse;}}privateasyncTask<bool>AdditionalValidationAsync(SecurityTokentoken){// Nonce の重複チェック// IP アドレス制限チェック// デバイス認証チェックreturntrue;}}
PAM の "継ぎ目" を突く:Vault 完全回避ルート
Legacy認証の残存問題
多くの企業でPAMを導入していても、以下のようなバイパス経路 が残存しています。攻撃者はこれらの抜け道を見つけて、PAMの制御を回避しようとします。
# 攻撃者が発見する典型的なバイパス経路# 1. 古いSSHキーが残存~/.ssh/id_rsa_old# PAM管理外# 2. ローカルadminアカウントのキャッシュnet user administrator /active:yes# 3. サービスアカウントの平文パスワード# config.xml 内に <password>PlainTextPassword123</password># 4. 共有アカウントの直接アクセス# PAM を経由せずに直接 DB サーバーに接続
重要
既存システムの棚卸しとレガシー認証の段階的廃止が必要です
RDP Clipboard攻撃の実態
PAM経由のRDPセッションでも、クリップボード共有が有効だと機密情報が漏洩します。攻撃者は正規のRDPセッション内で、クリップボードにアクセスして機密データを外部に持ち出そうとします。
以下は、攻撃者がRDPセッション内で実行する可能性があるコマンド例です。
# 攻撃者がRDPセッション内で実行Get-Clipboard|Out-File-Path"C:\temp\stolen_data.txt"# クリップボードの内容をローカルに保存
[ 対策ポイント ]
- RDPクリップボード共有を無効化
- セッション内でのファイル転送を制限
- 画面録画とキーロガー検知
防御パターン:SSO 強化 + PAM JIT 化
Azure Entra PIM でのJust-In-Time実装
Azure Entra Privileged Identity Management (PIM) を使用すると、管理者権限を「必要な時だけ」有効化できます。これにより、常時管理者権限を持つリスクを大幅に軽減できます。
以下は、PIMの設定例をYAML形式で表現したものです(実際の設定はAzureポータル経由で行います)。
# Azure Entra PIM 設定例privileged_role_assignments:-role:"GlobalAdministrator"assignment_type:"Eligible"max_duration:"PT2H"# 最大2時間approval_required:truemfa_required:truejustification_required:trueconditional_access:-name:"PAMGatewayAccess"conditions:applications:["PAM-Gateway-App"]locations:["CorporateNetwork"]device_platforms:["Windows","macOS"]access_controls:require_mfa:truerequire_compliant_device:truerequire_approved_client_app:true
KeeperPAM OIDC 連携の実装
KeeperPAMは、OpenID ConnectプロトコルでIdPと連携し、シームレスなSSO体験と強固なアクセス制御を実現できます。以下の設定例では、Azure Entra IDとの連携を行い、JIT(Just-In-Time)アクセス制御を実装しています。
特に重要なのは、TTL(Time To Live) の設定で、特権アクセスの時間を最小限に制限することです。
# KeeperPAM 設定ファイルoidc_configuration:issuer:"https://login.microsoftonline.com/<tenant>/v2.0"client_id:"pam-gateway-client"client_secret:"${KPR_OIDC_SECRET}"scopes:-"openid"-"profile"-"email"-"groups"access_policies:-name:"DatabaseAdministrators"role:"JustInTimeAdmin"ttl:300# 5分間のみ有効approval_workflow:-approver:"security-team@company.com"-emergency_access:false-name:"EmergencyAccess"role:"EmergencyAdmin"ttl:900# 15分間approval_workflow:-approver:"ciso@company.com"-emergency_access:true-audit_log:"high_priority"session_recording:enabled:truestorage:"azure_blob"retention:"90_days"real_time_monitoring:true
BeyondTrust Entitle でのクラウドJIT設定
2024年4月16日にBeyondTrustがEntitleを買収して実現されたクラウドJIT機能を活用した設定例です。この機能により、クラウドリソースへの特権アクセスも時間制限付きで管理できるようになりました。
以下のJavaScriptコードは、BeyondTrust APIを使用して一時的なアクセス権限を付与する例です。
// BeyondTrust API を使用したJITアクセス制御constgrantTemporaryAccess=async(userId,resourceId,duration)=>{constaccessRequest={user_id:userId,resource_id:resourceId,duration_minutes:duration,justification:"Production incident response",auto_revoke:true};try{constresponse=awaitfetch('/api/v1/access/grant',{method:'POST',headers:{'Authorization':`Bearer${awaitgetAccessToken()}`,'Content-Type':'application/json'},body:JSON.stringify(accessRequest)});returnawaitresponse.json();}catch(error){console.error('JIT access grant failed:',error);throwerror;}};
実装ハンズオン
JWT署名検証の実装
PAMゲートウェイでは、IdPから受け取ったJWTトークンの署名検証が最重要です。単純な文字列チェックではなく、暗号学的な署名検証を行うことで、トークンの改竄を確実に検知できます。
以下は、ASP.NET Core 8でDI(依存性注入)パターンを使用した実装例です。
// Program.cs (ASP.NET Core 8)usingMicrosoft.AspNetCore.Authentication.JwtBearer;usingMicrosoft.IdentityModel.Tokens;usingSystem.Text;varbuilder=WebApplication.CreateBuilder(args);// HttpClient と TokenValidator を DI に登録builder.Services.AddHttpClient<TokenValidator>();// JWT 認証の設定builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options=>{options.TokenValidationParameters=newTokenValidationParameters{ValidateIssuer=true,ValidateAudience=true,ValidateLifetime=true,ValidateIssuerSigningKey=true,ValidIssuer=builder.Configuration["JwtSettings:Issuer"],ValidAudience=builder.Configuration["JwtSettings:Audience"],IssuerSigningKey=newSymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JwtSettings:Key"]!))};});varapp=builder.Build();// PAM エンドポイントの保護app.MapGet("/pam/access",async(HttpContextcontext,TokenValidatorvalidator)=>{vartoken=context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();if(string.IsNullOrEmpty(token)){returnResults.Unauthorized();}// カスタム検証ロジックvarisValid=awaitvalidator.ValidateTokenAsync(token);if(!isValid){returnResults.Unauthorized();}returnResults.Ok(new{access="granted",duration=300});}).RequireAuthorization();app.Run();
KeeperPAM コンテナ設定
KeeperPAMをコンテナ環境で運用する場合の設定例です。Dockerを使用することで、環境の一貫性と運用の自動化を実現できます。特に、機密情報は環境変数で管理し、設定ファイルとセッションログは永続化ボリュームに保存することが重要です。
📚参考:Docker 公式ドキュメント
# DockerfileFROM keepersecurity/keeperpam:latestCOPY config/pam-config.yaml /etc/keeperpam/COPY certificates/ /etc/ssl/certs/EXPOSE 443 22CMD ["keeperpam", "--config=/etc/keeperpam/pam-config.yaml"]
# docker-compose.ymlversion:'3.8'services:keeperpam:image:keepersecurity/keeperpam:latestports:-"443:443"-"2222:22"environment:-KPR_OIDC_SECRET=${OIDC_SECRET}-KPR_DB_PASSWORD=${DB_PASSWORD}volumes:-./config:/etc/keeperpam-./sessions:/var/log/keeperpamdepends_on:-postgrespostgres:image:postgres:15environment:-POSTGRES_DB=keeperpam-POSTGRES_USER=pam_user-POSTGRES_PASSWORD=${DB_PASSWORD}volumes:-postgres_data:/var/lib/postgresql/datavolumes:postgres_data:
監査 & シグナル設計
セッション録画の実装
PAMシステムにおいて、セッション録画は監査とインシデント調査の要となります。ただし、録画データは改竄されないよう、各イベントにハッシュ値を付与して整合性を保証することが重要です。
以下のPythonクラスは、セッションイベントをハッシュ化して記録し、AWS S3に暗号化して保存する実装例です。
# セッション録画ハッシュ化保存importhashlibimportjsonfromdatetimeimportdatetimeclassSessionRecorder:def__init__(self,session_id,user_id):self.session_id=session_idself.user_id=user_idself.events=[]defrecord_event(self,event_type,data):event={"timestamp":datetime.utcnow().isoformat(),"event_type":event_type,"data":data,"hash":self._calculate_hash(data)}self.events.append(event)def_calculate_hash(self,data):"""イベントの整合性確保用ハッシュ"""returnhashlib.sha256(json.dumps(data,sort_keys=True).encode()).hexdigest()defsave_session(self):"""セッションをS3に保存"""session_data={"session_id":self.session_id,"user_id":self.user_id,"events":self.events,"session_hash":self._calculate_session_hash()}# S3に暗号化して保存# 実装省略def_calculate_session_hash(self):"""セッション全体の整合性確保"""session_string=json.dumps(self.events,sort_keys=True)returnhashlib.sha256(session_string.encode()).hexdigest()
SIEM連携クエリ例
SSOとPAMのログをSIEM(Security Information and Event Management) で統合分析することで、高度な脅威を検知できます。以下は、Azure SentinelとAWS Athenaでの実装例です。
[ Azure Sentinelでの異常検知クエリ ]
長寿命トークンの使用や異常なアクセス頻度を検知します。
-- Azure Sentinel (KQL) でのSSOトークン異常検知SecurityEvent|whereTimeGenerated>ago(1h)|whereEventID==4648//ログオンイベント|whereProcessNamecontains"PAM"|extendTokenLifetime=datetime_diff('minute',TokenExpiry,TimeGenerated)//TokenExpiryは独自に拡張したカラム例。//Sentinelに取り込む際はAADトークンの有効期限を計算して追加してください|whereTokenLifetime>60//1時間以上の長寿命トークン|summarizeCount=count()byAccount,IpAddress|whereCount>10//異常な頻度|orderbyCountdesc
[ AWS Athenaでの長期トレンド分析 ]
PAMアクセスログを分析して、異常なセッション時間やアクセスパターンを特定します。
-- AWS Athena でのPAMアクセス分析-- date は Glue テーブルで yyyy-MM-dd 形式の partition_key として登録している前提SELECTuser_id,source_ip,target_resource,session_duration,COUNT(*)asaccess_countFROMpam_access_logsWHEREdate>=current_date-interval'7'dayANDsession_duration>3600-- 1時間以上のセッションGROUPBYuser_id,source_ip,target_resource,session_durationHAVINGaccess_count>5ORDERBYaccess_countDESC;
令和のセキュリティチェックリスト
SSO側の対策
- トークンの有効期限を最短化(15分以内)
- Device Bindingの実装
- 異常なIPアドレスからのアクセス検知
- MFA の強制適用
PAM側の対策
- Just-In-Time アクセスの実装
- セッション録画の暗号化保存
- Legacy認証経路の完全除去
- 緊急アクセス手順の文書化
監査・運用
- SIEM連携による異常検知
- 定期的なアクセス権限レビュー
- インシデント対応手順の整備
- 従業員向けセキュリティトレーニング
さいごに
SSOとPAMの連携は、現代のエンタープライズセキュリティにおいて不可欠です。しかし、その「継ぎ目」に潜む脆弱性を理解し、適切な対策を講じることがとても重要です。
特に重要なのは!!
- 最小権限の原則:必要最小限の権限を、必要最小限の時間だけ付与
- 多層防御:単一の防御策に依存せず、複数の防御層を構築
- 継続的監視:異常を早期発見し、迅速に対応
攻撃者は常に進化し続けています。私たちも、最新の脅威に対応できる防御策を継続的に実装し、運用していく必要があります。
参考文献
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme