설명
URL 또는 호스트명 허용 목록 정규식에서 앵커가 빠지거나 도트가 이스케이프되지 않거나 허용 호스트 뒤의 경계를 제한하지 않으면 공격자 도메인이 허용 도메인처럼 매칭될 수 있습니다.
잠재적 영향
- SSRF 또는 오픈 리다이렉트 검증 우회
- 허용되지 않은 외부 도메인 접근
- 보안 정책 우회
해결 방법
- URL 문자열 전체를 정규식으로 검증하지 말고
URLComponents로 구조를 파싱합니다. - 스킴과 호스트를 정확히 비교하고 사용자 정보가 없으며 포트가 없거나 명시적으로 허용된 값인지 확인합니다.
- 호스트명 조각에 정규식이 꼭 필요하다면 시작·끝 앵커를 사용하고 도메인 구분자
.를\.로 이스케이프합니다.
예시
변경 전
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을 각각 검증합니다. 따라서 접미 도메인, 사용자 정보 혼동, 잘못된 포트가 허용 목록을 우회하지 못합니다.