이메일이 생겨난 이래 다른 사람의 이메일을 사칭한 공격이 정말 다양하게 발생하고 있습니다.
이를 방지할 수 있는 여러 방안이 존재하겠지만, 오늘은 그 중 SPF(Sender Policy Framework), DKIM(DomainKeys Identified Mail), DMARC(Domain Based Message Authentication, Reporting and Conformance)에 대해서 공부해보려고 합니다.
SPF (Sender Policy Framework)
SPF는 DNS에 메일 서버 관련 정보를 등록하여 수신자로 하여금 이메일 표시된 발송자 정보가 실제 메일 서버의 정보와 일치하는 지 확인할 수 있도록 만들어진 메일 검증 기술입니다.
SPF 작동 방식
SPF는 DNS Query를 통해 실제로 정상적인 도메인에서 메일이 발송되었는 지 검증을 하게 됩니다.
이를 위해서는 먼저 도메인 소유자가 메일 서버의 정보와 정책을 나타내는 SPF Record를 DNS에 등록해야합니다.
이후 수신자의 메일 서버나 솔루션에서 DNS에 등록된 SPF Record를 질의하고 수신 받은 메일에 기입된 정보와 대조하여 결과 값에 따라 수신 여부를 결정합니다.
먼저 SPF Record는 nslookup을 통해 확인할 수 있습니다. kisa.or.kr를 통해서 질의를 해보겠습니다.
$ nslookup
> set q=txt
> kisa.or.kr
서버: bns1.hananet.net
Address: 210.220.163.82
권한 없는 응답:
kisa.or.kr text =
"v=spf1 ip4:211.252.150.8 ip4:211.252.150.25 ip4:211.252.150.24 ip4:211.252.150.22
ip4:211.252.150.19 ip4:211.252.150.12 -all
위 결과를 분석해보기 전에, SPF Option들을 확인해보겠습니다.
구분 | 설명 |
all | 주로 SPF Record의 마지막 자리에 사용됨 ~all - Soft Fail로 송신자의 IP 주소가 Record와 일치하지 않는 경우에도 이메일 전송을 허용함 (단, 기록은 함) -all - Hard Fail로 송신자의 IP 주소가 Record와 일치하지 않는 경우에는 이메일을 전송하지 않음 +all - Allow All로 모든 송신자 IP 주소를 허용함 |
ip4 | IPv4의 값으로 Prefix-lenght가 정의되지 않았다면 /32를 가르킴 ex : v=spf1 ipv4:192.168.11.1/24 -all |
ip6 | IPv6의 값으로 Prefix-lenght가 정의되지 않았다면 /128를 가르킴 ex : v=spf1 ipv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334: -all |
a | 해당 도메인의 모든 A Record를 테스트하고 발송 서버의 IP가 그 중 하나라도 일치하면 Pass ex : v=spf1 a -all - 해당 도메인에 대한 테스트 ex : v=spf1 a:test.test.com -all - test.test.com의 A Record 질의 후 나온 IP가 발송 서버의 IP와 일치하면 통과 |
mx | a와 유사하게 DNS에 각각 A 대신 MX와 PTR Record를 질의하여 그 결과 값으로 판단 ex : v=spf1 mx ~all |
ptr | 고도화 DNS Query로 권장하지 않으나, 해당 도메인의 A Record 중 최소 하나 이상이 발신 서버의 IP와 일치하여야 함 ex : v=spf1 ptr:test.test.com -all - test.test.com으로 끝나는 모든 도메인을 지정함 |
include | 도메인에 대한 SPF Query를 수행함. 만약 유효한 SPF 정보를 가지고 있지 않다면, Permanent erorr를 반환함 ex : v=spf1 include:test.com -all - test.com이 SPF 정보를 가지고 있지 않다면, PermError를 발생 (Hard Fail) - 만약 SPF Record가 "v=spf1 a -all"인 경우, test.com의 A Record를 질의 ex : v=spf1 ?include:test.com -all - test.com이 SPF 정보를 가지고 있지 않더라도 이메일을 전송함 (Soft Fail) - 만약 SPF Record가 "v=spf1 a -all"인 경우, test.com의 A Record를 질의 |
위 정보를 기반으로 다시 kisa.or.kr의 SPF Record를 분석해보겠습니다.
"v=spf1 ip4:211.252.150.8 ip4:211.252.150.25 ip4:211.252.150.24 ip4:211.252.150.22 ip4:211.252.150.19 ip4:211.252.150.12 -all
kisa.or.kr은 발송지의 IP가 아래의 IP가 아닌 경우, 이메일을 전송하지 않도록 설정되어 있었습니다.
구분 |
|
211.252.150.8 | 211.252.150.19 |
211.252.150.22 | 211.252.150.24 |
211.252.150.25 | 211.252.150.12 |
DKIM (DomainKeys Identified Mail)
DKIM은 공개 키 암호화 방식을 사용하여 이메일에 디지털 서명을 함으로써 수신자에게 해당 이메일이 도메인 소유자가 전송한 것을 증명하는 방식입니다.
DKIM Protocol은 수신자에게 보내는 각 메시지에 대한 암호화 서명과 Header에 도메인 서명을 생성합니다.
이 서명을 통해 수신자는 해당 메시지가 실제로 다른 사람이 아닌 도메인 소유자가 보낸 것이 맞는 지 또는 중간에 메시지가 변조되었는 지 검증하는 데 사용됩니다.
DKIM이 설정된 도메인의 소유자는 이메일 전송 시 아래와 같은 프로세스로 작동합니다.
1. 도메인의 소유자는 DNS에 공개 키를 게시합니다. 이 공개 키는 추후 수신 서버에서 정상 메일 수신 여부를 검증할 때 사용됩니다.
2. 해당 공개 키에 대한 비공개 키 소유자인 도메인 소유자는 이메일 Header 및 본문의 일부 데이터를 포함하여 비공개키로 서명합니다. 이후 해당 서명 값은 DKIM-Signature Header에 추가됩니다.
3. 메일을 수신 받은 수신자는 DNS Query를 통하여 DKIM의 공개 키를 확인합니다.
4. 해당 공개 키를 활용하여 DKIM 서명 복호화를 시도합니다.
5. 복호화를 성공했을 경우 Pass, DKIM 서명이 없거나 복호화를 실패했을 경우 Fail을 반환합니다.
Query 방법
{Selector}._domainkey.{domain}
$ nslookup
> set q=txt
> iport._domainkey.cisco.com
서버: bns1.hananet.net
Address: 210.220.163.82
권한 없는 응답:
iport._domainkey.cisco.com text = "v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCctxGhJnvNpdcQLJM6a/0otvdpzFIJuo73OYFuw6/8bXcf8/p5JG/iME1r9fUlrNZs3kMn9ZdPYvTyRbyZ0UyMrsM3ZN2JAIop3M7sitqHgp8pbORFgQyZxq+L23I2cELq+qwtbanjWJzEPpVvrvbuz9QL8CUtS+V5N5ldq8L/lwIDAQAB;"
DMARC (Domain Based Message Authentication, Reporting and Conformance)
DMARC는 SPF와 DKIM의 결과에 따라 수행할 작업을 Record를 통해 명시하고 있는 기능입니다.
수신 서버는 이메일 발신 도메인의 DMARC Record를 조회합니다.
_DMARC.{domain}
C:\Users\USER>nslookup
기본 서버: bns1.hananet.net
Address: 210.220.163.82
> set q=txt
> _DMARC.kisa.or.kr
서버: bns1.hananet.net
Address: 210.220.163.82
권한 없는 응답:
_dmarc.kisa.or.kr text =
"v=DMARC1; p=none; rua=mailto:dkim-reports@kisa.or.kr; adkim=r; aspf=r"
위 결과를 분석해보기 전에, DMARC Option들을 확인해보겠습니다.
※ 단, 주의해야할 점은 수신 서버에서 꼭 정해진 프로토콜대로 작동할 보장은 없다는 점 입니다.
※ rua의 경우 실패 보고서 뿐만 아니고 모든 데이터에 대한 집계 정보를 제공한다는 내용도 있네요?
구분 | 설명 |
v | 버전을 나타내머 고정 값임 DMARC1 |
p | DMARC 검증 실패 시 처리할 정책을 명시함 none - 수신 서버에서 Fail한 이메일을 아무런 처리를 하지 않음 - 단, rua/ruf에 설정된 주소에 실패 보고서를 전송함 quarantine - 수신 서버에서 Fail한 이메일을 스팸으로 처리함 - 이때 스팸함으로 들어가 일반 사용자에게 메일을 보이는 경우가 있음 reject - 수신 서버에서 DMARC가 실패한 이메일을 반송 처리함 |
sp | 서브 도메인에 대한 DMARC 검증 실패 시 처리할 정책을 명시함 none - 수신 서버에서 Fail한 이메일을 아무런 처리를 하지 않음 - 단, rua/ruf에 설정된 주소에 실패 보고서를 전송함 quarantine - 수신 서버에서 Fail한 이메일을 스팸으로 처리함 - 이때 스팸함으로 들어가 일반 사용자에게 메일을 보이는 경우가 있음 reject - 수신 서버에서 DMARC가 실패한 이메일을 반송 처리함 |
pct | 정책을 적용할 이메일 비중을 나타냄 0~100(Default : 100) - 10인 경우 수신된 이메일 중 절반만이 DMARC 정책에 의해 검증됨 |
adkim | DKIM Alignment로 DKIM-Signature의 검증 강도를 설정함 d={domain}의 Domain과 비교 s - strict로 정확하게 일치한 경우에만 통과함 r (Default) - relaxed로 정확하게 일치하거나 서브도메인인 경우 통과함 |
aspf | SPF Alignment로 도메인 검증 강도를 설정함 v=spf1 Header에 명시된 Domain과 비교 s - strict로 도메인이 정확하게 일치한 경우에만 통과함 r (Default) - relaxed로 도메인이 정확하게 일치하거나 서브도메인인 경우 통과함 |
rua | 주기적으로 Fail Report를 수신할 주소 ex : rua=mailto:demarc-report@toast.com; |
ruf | Fail Report를 수신할 주소 ex : ruf=mailto:demarc-report@toast.com; |
fo | Fail Report 생성 기준 0 (Default) - SPF와 DKIM 모두 실패했을 때 Report 생성 1 - SPF와 DKIM 중 하나라도 실패했을 때 Report 생성 d - DKIM을 실패했을 때 Report 생성 s - SPF를 실패했을 때 Report 생성 |
rf | Fail Report의 형식 afrf |
ri | Fail Report를 집계할 기간 86,400(단위 초, Default) - 24시간 |
그리고 DMARC은 아래와 같이 작동합니다.
위 정보를 기반으로 다시 kisa.or.kr의 DMARC Record를 분석해보겠습니다.
"v=DMARC1; p=none; rua=mailto:dkim-reports@kisa.or.kr; adkim=r; aspf=r"
kisa.or.kr의 DMARC 설정은 아래와 같이 설정되어 있었습니다.
- DKIM과 SPF의 통과 조건은 도메인과 정확하게 일치하거나 서브 도메인과 일치해야 함
- Fail된 경우 별다른 조치를 하진 않지만, 전송된 모든 이메일을 100% 검증함
- Fail Report는 24시간마다 dkim-reports@kisa.or.kr 메일로 발송됨
Reference
https://www.cloudflare.com/ko-kr/learning/dns/dns-records/dns-dmarc-record/
https://www.cloudflare.com/ko-kr/learning/dns/dns-records/dns-dkim-record/
'Hack > Network' 카테고리의 다른 글
[CVE-2023-23997] MS Outlook EoP(Elevation of Privilege) 취약점 (0) | 2023.03.17 |
---|---|
[VUE JS] source map 파일을 통한 Frontend 소스 코드 획득 (0) | 2023.02.21 |
[CVE-2022-3786] OpenSSL punycode Decoding Vulnerability (Stack Buffer over Flow) (0) | 2022.11.03 |
[CVE-2022-3602] OpenSSL punycode Decoding Vulnerability (off-by-one) (0) | 2022.11.02 |
11월 1일 Releases 될 OpenSSL 취약점 정보 (0) | 2022.10.30 |
댓글