Foundation으로 하드코딩된 HTTP URL 생성

Foundation으로 하드코딩된 HTTP URL 생성

설명

Foundation.URL(string:) 등으로 http:// 주소를 만들고 통신에 사용하면 TLS가 없는 엔드포인트에 연결할 수 있습니다. URL 객체 생성 자체는 네트워크 요청이 아니므로 실제 전송과 보호 설정을 함께 확인해야 합니다.

Apple의 URL Loading System은 App Transport Security(ATS)를 통해 평문 HTTP 연결을 기본적으로 차단합니다. 따라서 별도 예외가 없는 URLSession 요청은 일반적으로 실패합니다. 그러나 NSAllowsArbitraryLoads, NSExceptionAllowsInsecureHTTPLoads 등의 ATS 예외가 있으면 HTTP가 허용될 수 있고, Network 또는 CFNetwork 같은 하위 수준 API에는 ATS가 적용되지 않을 수 있습니다. 실제 노출 여부는 URL 사용 경로, Info.plist의 ATS 설정, 실행 환경의 네트워크 트래픽을 함께 확인해야 합니다.

잠재적 영향

해당 엔드포인트에 유효한 전송 보호 없이 연결할 수 있다면 다음 문제가 발생할 수 있습니다.

  • 네트워크 관찰자가 요청과 응답을 읽는 기밀성 침해
  • 트래픽 또는 응답 변조로 인한 무결성 침해
  • 서버 가장 또는 잘못된 엔드포인트 연결
  • 광범위한 ATS 예외로 인한 평문 통신 허용 범위 확대

HTTP에서 HTTPS로 리디렉션하더라도 최초 HTTP 요청은 TLS로 보호되지 않습니다.

해결 방법

  1. 엔드포인트를 https:로 변경하고 서버가 HTTPS에서 동일한 리소스를 직접 제공하는지 확인합니다. 최초 요청을 보호하기 위해 HTTP-to-HTTPS 리디렉션에 의존하지 않습니다.
  2. ATS를 활성화 상태로 유지하고 NSAllowsArbitraryLoads 같은 광범위한 예외를 제거합니다. 피할 수 없는 도메인 예외는 필요한 호스트와 기능으로만 제한하고 가능한 한 빨리 제거합니다.
  3. 개발·테스트용 엔드포인트는 환경별 설정으로 분리하여 프로덕션 빌드에 포함되지 않도록 합니다. 사설망이나 루프백 주소도 본질적으로 안전하다고 간주하지 않습니다.
  4. 인증서 검증을 비활성화하지 말고, Info.plist와 실제 런타임 트래픽을 함께 확인하여 HTTP 연결이 성공하는 경로가 남아 있지 않은지 검증합니다.

예시

변경 전

swift
import Foundation

func loadProfile() {
    guard let url = Foundation.URL(string: "http://api.example.com/profile") else {
        return
    }

    URLSession.shared.dataTask(with: url) { _, _, _ in }.resume()
}

변경 후

swift
import Foundation

func loadProfile() {
    guard let url = Foundation.URL(string: "https://api.example.com/profile") else {
        return
    }

    URLSession.shared.dataTask(with: url) { _, _, _ in }.resume()
}

설명:

  • 변경 전: 코드에 HTTP 엔드포인트가 고정되어 있습니다. ATS가 요청을 차단할 수 있으므로, 예외 설정과 실제 통신 여부를 추가로 확인해야 합니다.
  • 변경 후: 서버가 직접 제공하는 HTTPS 엔드포인트를 사용하여 요청의 시작부터 TLS 보호를 적용합니다.

참조