概要
GoアプリケーションにおけるJSON、XML、YAMLパーサの予期せぬ挙動が、認証・認可バイパスや機密情報漏洩の脆弱性を引き起こす事例が多発。 パーサ設定ミスや設計ミスによる攻撃シナリオを具体例とともに解説。 Go標準ライブラリと主要YAMLライブラリの挙動差分にも注意が必要。 安全なパーサ設定方法と、Go標準ライブラリのセキュリティギャップを補う戦略を提案。 実際の脆弱性事例や検出ルールも紹介。
Goアプリケーションにおけるパーサの危険な落とし穴と攻撃シナリオ
-
未検証データのパース による攻撃面の拡大
- JSON、XML、YAMLパーサ の挙動を突いた攻撃事例多数
- CVE-2020-16250(Hashicorp Vault認証バイパス)など、実際の脆弱性事例
-
主な攻撃シナリオ
- (Un)Marshaling unexpected data(意図しないデータの(逆)シリアライズ)
- 本来非公開にすべきフィールドの露出・操作
- Parser differentials(パーサ間の挙動差異)
- サービス間でパース結果が異なることで認証・認可バイパス
- Data format confusion(異なるデータ形式の混入)
- 予想外の形式をパースし、意図しない動作や情報漏洩
- (Un)Marshaling unexpected data(意図しないデータの(逆)シリアライズ)
-
パーサのセキュリティ状況一覧
- JSON, XML, YAMLの各項目ごとに「安全」「デフォルトで危険」「安全設定不可」など分類
- 例:重複キーはJSON/YAMLは「最後を採用」、XMLはサポート外
- フィールド名の大文字・小文字無視なども挙動が異なる
- JSON, XML, YAMLの各項目ごとに「安全」「デフォルトで危険」「安全設定不可」など分類
Goにおけるパース処理の基礎
- 標準ライブラリ: encoding/json, encoding/xml
- YAML: サードパーティ製(yaml.v3が主流)
- Marshal/Unmarshal による構造体⇔フォーマット変換
- 構造体タグ でフィールドごとのパース挙動を制御
- 例:
json:"username_json_key,omitempty"
- 例:
例:User構造体のパース
- 構造体タグでキー名・オプション指定
- Unmarshal時はタグで指定したキー名でのみ値がセットされる
- io.Reader対応のストリームAPIも提供(HTTPリクエスト処理等で利用)
攻撃シナリオ1: 意図しないデータの(逆)シリアライズ
-
一部フィールドのみタグ指定 時の落とし穴
- タグ未指定フィールドも名前でパース可能
- セキュリティ意識の低い実装で権限昇格などのリスク
-
タグの設定ミス例
json:"-,omitempty"と誤記:-キーで値がセットされてしまう- 実例:Flipt、langchaingoプロジェクトで発生(既に修正済み)
- 正しい設定 :
json:"-"のみで完全に(逆)シリアライズ対象外
-
omitemptyの誤用
json:"omitempty"と記述:フィールド名がomitemptyとなる- 例:Gitea、Kustomize等で発生(既に修正済み)
- 正しくは
json:",omitempty"
-
検出ルール
- Semgrepルールでコードベースの誤用を検出可能
- 例:
semgrep -c r/trailofbits.go.unmarshal-tag-is-dash
- 例:
- Semgrepルールでコードベースの誤用を検出可能
攻撃シナリオ2: パーサ間の挙動差異(Parser differentials)
-
マイクロサービス構成 での典型的な脆弱性
- Proxy ServiceとAuthorization Serviceで異なるパーサ利用
- 同一入力に対し、サービス間で解釈が異なり認可バイパス発生
-
実例
- CVE-2017-12635(Apache CouchDBの認可バイパス)
- macOSサンドボックスエスケープ(XMLパーサ差異)
- 0-click Zoom RCE(XMLパーサ差異)
- GitLab SAML認証バイパス(XMLパーサ差異)
-
重複キーの扱い
-
GoのJSONパーサは「最後の値」を採用
-
他言語やパーサでは挙動が異なる場合があり、攻撃者が意図的に差異を突くことが可能
-
例:
{"role": "user", "role": "admin"}Goのパーサではroleは"admin"になる
-
パーサ設定の安全化と対策
-
全フィールドに明示的なタグ付与 推奨
- 意図しないフィールドの(逆)シリアライズ防止
-
タグ設定ミスの自動検出
- Semgrep等の静的解析ツール活用
-
パーサ間の挙動差異を認識し、統一
- クリティカルな認証・認可処理は同一パーサ・設定を使用
-
Go標準ライブラリの限界を認識
- セキュリティギャップを補うための追加バリデーション実装
-
ドキュメントとテストの徹底
- 仕様・挙動を明文化し、ユニットテストでパースの境界条件を網羅
このように、Goアプリケーションでのパーサ設定・運用には細心の注意が必要です。 小さなミスや設計上の盲点が、重大なセキュリティインシデントにつながる可能性があるため、 全ての開発者・セキュリティエンジニアは、パーサの仕様と落とし穴を正しく理解し、 安全な実装・運用を徹底してください。