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을 각각 검증합니다. 따라서 접미 도메인, 사용자 정보 혼동, 잘못된 포트가 허용 목록을 우회하지 못합니다.

참조