설명
인증서 고정이 필요한 도메인에서 kTSKEnforcePinning: false를 사용하면 고정 값 불일치를 차단하지 않아 의도한 추가 보호가 적용되지 않습니다. 고정을 도입하는 동안 보고 전용 모드를 사용할 수 있지만, 검증을 마친 뒤에는 요구사항에 맞게 강제해야 합니다. 인증서 고정은 기본 TLS 신뢰 검증과 별개이며, 고정 강제 여부와 관계없이 서버 인증서를 검증해야 합니다.
macOS의 kTSKIgnorePinningForUserDefinedTrustAnchors가 true이면 사용자 정의 신뢰 앵커로 끝나는 인증서 체인에는 고정 검증을 적용하지 않습니다. 이 예외가 조직의 인증서 정책에 맞는지 확인하세요.
잠재적 영향
- 인증서 고정 우회
- 고정으로 차단하려던 인증서를 이용한 서버 가장
- 공격자가 통신 경로와 필요한 인증서를 확보했을 때 민감 네트워크 트래픽 노출
해결 방법
- 고정이 필요한 대상 도메인의 설정과 배포를 검증한 뒤
kTSKEnforcePinning: true를 설정하세요. - 네트워크 delegate swizzling을 끄는 경우 인증 챌린지 처리에서 TrustKit의
TSKPinningValidator를 직접 호출하세요. - macOS에서 사용자 정의 신뢰 앵커에도 고정을 강제해야 한다면
kTSKIgnorePinningForUserDefinedTrustAnchors: false를 설정하세요. 조직의 프록시 등 의도한 신뢰 정책과의 호환성도 확인하세요.
예시
고정 강제 여부를 비교하는 부분 예시입니다. 실제 구성에는 고정 값 목록, TrustKit 초기화, 네트워크 인증 챌린지 처리를 연결하는 코드가 필요합니다.
변경 전
swift
let config = [
kTSKPinnedDomains: [
"api.example.com": [kTSKEnforcePinning: false]
]
]
변경 후
swift
import TrustKit
private enum BuildEmbeddedPins {
// 실제 배포에서는 빌드 시 생성한 서버 SPKI SHA-256 pin으로 교체합니다.
static let primary = "HXXQgxueCIU5TTLHob/bPbwcKOKw6DkfsTWYHbxbqTY="
static let backup = "0SDf3cRToyZJaMsoS17oF72VMavLxj/N7WBNasNuiR8="
}
func makeTrustKitConfiguration() -> [String: Any] {
return [
kTSKPinnedDomains: [
"api.example.com": [
kTSKEnforcePinning: true,
kTSKPublicKeyHashes: [
BuildEmbeddedPins.primary,
BuildEmbeddedPins.backup
]
] as [String: Any]
]
]
}
설명:
- 변경 전: pinning 위반을 강제 차단하지 않습니다.
- 변경 후: 대상 도메인에서 pinning을 강제하고, 현재 키와 별도로 배포된 백업 SPKI pin을 함께 설정해 안전한 인증서 교체가 가능하게 합니다. 예시 값은 실제 서버의 pin으로 교체하고, 두 pin은 원격 또는 사용자 입력이 아니라 서명된 앱 빌드에 포함해야 합니다.