Swiftのホスト名正規表現による検証の回避

Swiftのホスト名正規表現による検証の回避

説明

URLやホスト名の許可リストに使う正規表現で、アンカーがない、ドットがエスケープされていない、許可ホスト名の直後の境界を制限していないといった不備があると、攻撃者のドメインを許可対象として受け入れるおそれがあります。

想定される影響

  • SSRFやオープンリダイレクトを防ぐ検証の回避。
  • 許可されていない外部ドメインへのアクセス。
  • セキュリティポリシーの迂回。

対処方法

  1. URL文字列全体を正規表現で検証せず、URLComponents で構造を解析してください。
  2. スキームとホスト名を完全一致で比較してください。ユーザー情報がなく、ポートが未指定か明示的に許可された値であることも確認してください。
  3. ホスト名の一部に正規表現が必要な場合は、先頭と末尾のアンカーを使い、ドメインの区切り文字 . を \. としてエスケープしてください。

例

変更前

swift
let regex = try Regex(#"https?://www\.example\.com"#)

変更後

swift
import Foundation

func isAllowedURL(_ value: String) -> Bool {
    guard let components = URLComponents(string: value),
          components.scheme?.lowercased() == "https",
          components.host?.lowercased() == "www.example.com",
          components.user == nil,
          components.password == nil,
          components.port == nil || components.port == 443 else {
        return false
    }
    return true
}

解説:

  • 変更前: 部分一致や検索結果だけで許可を判断すると、許可ドメインがURLの途中に含まれているだけでも検証を通過するおそれがあります。
  • 変更後: URLの構造を解析し、HTTPS、正確なホスト名、ユーザー情報がないこと、既定のポートまたは443番ポートを個別に検証します。ドメインの後ろに別の文字列を付ける方法、ユーザー情報との混同、不正なポートによる回避を防ぎます。

参考資料