기본 인증은 편리하고 유연하지만 안전하지 않다. 사용자 이름과 비밀번호를 평문으로 보내고, 메시지를 위조하지 못하게 보호하는 어떤 시도도 하지 않는다. base-64 인코딩을 이용해 뒤섞기만 하여 쉽게 디코딩된다.
다이제스트 인증
은 기본 인증과 호환되는 더 안전한 대체재로서 개발되었다. (그렇게 많이 사용되지는 않는다.)
다이제스트 인증은 비밀번호 자체를 보호하는 것이지 그 외의 어떤 비밀 보호를 제공하는 것은 아니기 때문에(즉, 요청&응답 외의 다른 부분에 대해선 다른 사람이 엿볼 수 있다) TLS와 HTTPS보다 안전한 프로토콜이라 볼 수는 없다.
다이제스트 인증에서 가장 중요한 것은 비밀번호를 네트워크를 통해 보내지 않는 것이다. 비밀번호를 보내는 대신에 클라이언트는 비밀번호를 비가역적으로 뒤섞은 fingerprint(지문) 또는 digest(요약)을 보낸다.
서버와 클라이언트가 모두 비밀번호를 알고 있기 때문에 서버가 클라이언트가 보낸 요약과 자신이 계산한 요약이 일치하는지 확인하는 방식으로 인증이 동작한다.
요약은 단방향 함수로 동작하고, 일반적으로 입력 가능한 무한 가지의 모든 입력값들을 유한한 범위의 압축으로 변환한다.(충돌(=다른 입력값에 같은 요약)이 발생할 수는 있지만 확률이 무시해도 될 만큼 작고, 비밀번호를 맞춰본다는 목적을 생각해볼때 중요하지 않다)
MD5
나 SHA
가 인기 있는 요약 함수 중 하나이다.
요약함수는 보통 암호 체크섬이라고 불리고, 단방향 해시 함수이거나 지문 함수(fingerprint function)이다.
요약을 가로채서 서버로 재전송하는 재전송 공격을 방지하기 위해 서버가 클라이언트에게 난스
를 건네준다.
난스를 비밀번호에 섞어서 난스가 바뀔 때마다 요약도 바뀌게 만들어준다.
요약은 다음의 세 요소로부터 계산된다.
1. 단방향 해시 함수 H(d) & 요약 함수 KD(s,d) (s는 비밀, d는 데이터)
2. 비밀번호 등 보안 정보를 담고 있는 데이터 덩어리. A1
3. 요청 메시지의 비밀이 아닌 속성을 담고 있는 데이터 덩어리. A2
A1
은 사용자 이름, 비밀번호, 보호 영역, 난스와 같은 비밀 보호 정보로 이루어진 데이터 덩어리이다. (비밀 정보와만 관련)
모든 요청마다 단방향 해시를 실행하는 알고리즘
A1 = <사용자>:<영역>:<비번>
사용자 이름, 영역, 비밀번호에 대한 해시를 계산한 결과 뒤에 현재 난스와 클라이언트 난스를 붙인 것이 A1.
A1 = MD5(<사용자>:<영역>:<비밀번호>):<난스>:<c난스>
A2
는 URL, 요청 메서드, 메시지 엔터티 본문과 같은 메시지 자체의 정보를 나타낸다. 메서드, 리소스, 메시지의 위조를 방지하기 위해 사용된다.
H, KD, A1, A2를 사용해서 다이제스트를 산출한다.
WWW-Authenticate
인증 요구에 대한 클라이언트의 응답으로 그 보호 공간에 대한 인증 세션을 시작하게 한다.
인증 세션은 클라이언트가 다른 서버로부터 또다른 WWW-Authenticate 인증 요구를 받을 때까지 계속된다. 클라이언트는 인증과 관련된 정보(사용자 이름, 비번, 난스, 난스 횟수, 미래 요청에 들어갈 Authorization 헤더를 만들기 위한 인증세션과 관련된 값)를 기억하고 있어야 한다.
사전인가
: 메시지 횟수를 줄인다.난스 내용은 구현의존적이다.
예를 들어 타임스탬프(반복 불가능한 값)와 ETag(요청된 엔터티에 대한 ETag 헤더값으로, ETag를 포함하면 갱신된 리소스에 대한 재요청을 방지)를 사용하는 방식으로 구현할 수 있다.
클라이언트가 서버를 인증할 수 있도록 다이제스트 인증을 확장.
선택사항이지만 보안이 상당히 개선되므로 현대적인 클라이언트와 웹 서버라면 구현하는 게 권장된다.
qop 필드는 클라이언트와 서버가 어떤 보호 기법을 어느 정도 수준으로 사용할 것인지 협상하게 해준다.
선택적이긴 하지만, 오래된 RFC 2069 명세와의 호환성을 유지하기 위한 것이고, 모든 현대적인 요약 구현은 qop 옵션을 지원해야 한다.
qop = "auth-int"
엔터티 본문의 해시에 대해 계산
다이제스트 인증작업을 할 때 고려해야할 것들
서버는 한 리소스에 대해 여러 인증을 요구할 수 있다.
인증이 적절하지 않았을 때는 400 Bad Request를 반환하고 로그로 기록(공격자일 수도 있음)하는 것이 좋다.
프락시가 리소스 변경없이 URI를 다시 쓰기도 하는데, 이와 동시에 다이제스트 인증은 URI값의 무결성을 검사하므로, 이런 변경에 의해 다이제스트 인증이 실패할 수 있다.
어떤 공유 캐시가 Authotization 헤더를 포함한 요청과 그에 대해 응답을 받은 경우, 두 Cache-Control 지시자 중 하나가 응답에 존재하지 않는 다른 요청에 대해 그 응답을 반환해서는 안된다.
양종단 암호화나 헤더에 대한 디지털 서명으로 방지 (두개를 조합할 수 도 있다)
재전송 공격은 누군가가 트랜잭션에서 엿들은 인증 자격을 다른 트랜잭션에서 사용하는 것이다. (난스값 반복 사용으로 발생)
이를 완화하기 위해 클라이언트의 IP 주소, 타임스탬프, ETag, 개인서버키에 대한 요약을 포함하는 난스를 서버가 생성하게 할 수 있지만 클라이언트 ip를 난스생성에 사용하게 되면 프락시팜을 사용할 수 없고, ip주소를 속이는 문제가 발생할 수 있다.
완전히 재전송 공격을 피하기 위해서는 트랜잭션마다 유일한 난스값을 사용하는 것이다.
사전(dictionary) 공격은 전형적인 비밀번호 추측공격.
이를 막기 위해 크래킹이 어려운 복잡한 비밀 번호를 사용하거나 비밀번호 만료 정책을 사용할 수 있다.
프락시가 악의적이거나 보안이 허술하다면 클라이언트는 중간자 공격에 취약해질 수 있다. ( 엿듣기 공격이나 가장 약한 인증 제도로 대체)
SSL을 사용해서 공격을 방어하자
클라이언트가 서버에서 제공된 난스 대신 선택적인 c난스 지시자를 사용하여 응답을 생성할 수 있도록 한다.