SIP 인증암호를 복잡하게 해야되는 이유
※ 과거 제가 네이버 카페에 작성했던 글을 옮긴 포스트 입니다.
안녕하세요.
요즘 딱히 할 일 없어서, 이전에 SIP 인증암호는 '복잡하게', '자주 변경' 해야되는 이유에 대해 간단히 적어 봅니다.
암호를 복잡하고 주기적으로 변경하는게 좋은 것을 모르는 IT 쪽 사람은 아무도 없을 껍니다.
그러나...SIP가 다른 웹 사이트보다 더 복잡하게, 더 자주 변경해야 되는 이유는 아래와 같습니다.
1. TLS 미지원
- 모든건 여기서 시작 됩니다. TLS (SIPS) 지원하는 통신사 아직 못 봤습니다.
회사에서 고객 대상으로 TLS 올리려 시도 해보았으나 아래 같은 이유로 포기 했습니다.
우선 고객쪽에선 단말가격이 비싸집니다...
그리고 사업자 쪽에선, 대부분의 장비가 TLS를 지원하지만...완벽하지 않습니다.
어떤장비는 SIP URI Scheme 을 그냥 TLS로 암호화 해서 보내고 어떤 장비는 SIPS URI Scheme 으로 보내고 아주
환장 합니다.
무엇보다 중요한건...SIP 장비는 대부분 B2BUA 방식으로 동작(아랫단으로는 서버 역할, 윗단으로는 클라이언트 역할)
해서, 결국 SIP 관련 장비 (SBC, GW, PBX 등등) 지날때마다 복호화 하고 다시 보낼 때 암호화 하기 때문에,
암호화에서 가장 중요한 단대단 암호화 및 무결성 검증이 불가능 합니다.
결국 TLS 사용의 의미가 없죠. 그래서 대부분 TLS 적용 고객은 사내 전화망에만 사용 합니다.
그래서 평문 SIP에 SRTP만 쓰는 경우도 있는데, SRTP는 결국 코덱 네고 시 키 교환을 하기 떄문에 처음부터 끝까지
패킷을 도청 당한다면 의미없습니다...
2. 대부분 키 해시함수로 md5 알고리즘을 씁니다.
- 표준에 키 해시알고리즘으로 md5, sha-256, sha-512, token 까지 쓸 수 있다 했지만,
표준에도 sha-256을 추천하지만 md5 외에 다른 알고리즘을 쓰는 경우를 못 봤습니다.
웹 분야에서 보안 수검을 할 때, "md5 알고리즘으로 키가 암호화 되어 있습니다." 라고 하면
신명나게 까입니다...
여담으로 SIP 인증의 한 축인 Authorization 헤더가 어떻게 만들어지는지 보면...
1. 클라이언트에서 인증 없이 request 전송
2. 서버에서 401 Unauthorized 인증을 위안 nonce 및 알고리즘 응답
ex) WWW-Authenticate: DIGEST realm="BroadWorks",qop="auth",nonce="BroadWorksXl8cllu6vT2lz9coBW",algorithm=MD5
3. 인증값을 다시 추가하여 서버로 전송
ex) Authorization: Digest username="0709999999", realm="BroadWorks", nonce="BroadWorksXl8cllu6vT2lz9coBW", uri="sip:192.168.10.10", response="7d1dac0fb87740a72b7c753875b5f0c3", algorithm=MD5, cnonce="000027dc5d764a9ead0e6f3fb99e12d6", qop=auth, nc=00000001
인데, 여기서 응답 값인 response 는, 아래와 같이 만들어 집니다.
algorithm=MD5 해시함수는 md5 사용,
A1 = md5(username:realm:password)
A2 = md5(method:ur")
response = md5(A1:nonce:nc:cnonce:qop:A2)
로 만들어지는데, 여기서 모르는건 password 밖에 없으니, 숫자로 6~7 자리로 만들면 무작위 대입에 수십분 안에 찾을 수 있습니다.
관련 RFC 문서는 http의 인증 절차와 같은데,
sip 단독으로 나오는 RFC 문서는 https://datatracker.ietf.org/doc/html/draft-smith-sipping-auth-examples-01 입니다.
파이썬 코드로 짜면 기껏해야 몇 줄 안됩니다.
#!/usr/bin/env python
#Upgraded python 3.6
from hashlib import md5
# Authorization: Digest username="0709999999", realm="BroadWorks", nonce="BroadWorksXl8cllu6vT2lz9coBW", uri="sip:192.168.10.10", response="7d1dac0fb87740a72b7c753875b5f0c3", algorithm=MD5, cnonce="000027dc5d764a9ead0e6f3fb99e12d6", qop=auth, nc=00000001
login = str('0709999999')
uri = str('sip:192.168.10.10')
nonce = str('BroadWorksXl8cllu6vT2lz9coBW')
realm = str('BroadWorks')
password = str('1234')
nc = str('00000001')
cnonce = str('000027dc5d764a9ead0e6f3fb99e12d6')
qop = str('auth')
str1 = md5("{}:{}:{}".format(login,realm,password).encode('utf-8')).hexdigest()
str2 = md5("REGISTER:{}".format(uri).encode('utf-8')).hexdigest()
str3 = md5("{}:{}:{}:{}:{}:{}".format(str1,nonce,nc,cnonce,qop,str2).encode('utf-8')).hexdigest()
print(str3)
결론...암호는 복잡하게...IP허용 및 차단은 철저히...뭔가 이상하면 암호 변경...
이 답입니다.