기본 인증과 다이제스트 인증

ChoiYongHyeun·2024년 1월 21일
0

HTTP

목록 보기
10/17

때마침 로그인 관련 UI 를 연습해보려던 찰나

HTTP 서적의 진도도 기본 인증과 다이제스트 인증이더라

룰루룰

가보자고


인증

웹 서버는 클라이언트가 특정 인증이 필요한 리소스를 필요로 할 때

클라이언트가 해당 리소스에 접근 권한이 있는지를 확인해야 한다.

이를 인증 요구 라고 한다.

클라이언트가 서버 측에 리소스 요청을 보냈을 때

서버측은 인증이 필요하면 클라이언트측에 401 상태 코드와 함께 인증이 필요하다는 상태 설명서를 함께 보낸다.

이후 헤더에는 WWW-Authenticate : Basic realm = '리소스 영역명' 을 함께 보낸다.

Basic 은 클라이언트가 본인의 로그인 정보를 보낼 때 인코딩 하는 방식이다.

여기서 realm보안영역 으로 인증이 필요한 리소스들의 영역을 일컫는다.

리소스마다 영역을 나눔으로서, 하나의 인증만으로 모든 보안이 필요한 리소스들에게 접근이 가능하게 하는 것이 아닌 계층 별로 다른 인증을 제공 할 수 있다.

사용자는 401 상태 코드와 함께 인증을 위한 로그인, 비밀번호를 입력하는 창으로 리다이렉트 되거나 새로운 창을 받게 되고

해당 페이지에서 로그인과 비밀번호를 작성한다.

이렇게 작성된 로그인과 비밀번호는 Authorization 헤더에 인코딩 되어 서버 측에 보내진다.

인코딩 하는 이유는 로그인과 비밀번호와 같이 보안이 필요한 내용을 평문으로 적어 통신 하던 중, 정보가 유출 될 경우 로그인과 비밀번호 또한 유출 될 수 있기 때문이다.

서버측은 받은 정보를 통해 클라이언트를 인증하고, 리소스를 제공한다.

기본 인증

위와 같은 인증 방법을 기본인증 이라고 한다.

하지만 이런 인증 방법은 치명적인 결합이 존재한다.

로그인과 비밀번호를 인코딩시켜 서버와 통신 했을 때

인코딩한 값이 유출 되었다면 , 인코딩 시킨 방법을 이용해 똑같이 디코딩 하여 로그인과 비밀번호를 알아낼 수 있다.

대부분의 사용자는 로그인과 비밀번호는 다른 웹사이트들과 크게 차이를 두지 않기 때문에 유출 시 큰 문제가 발생 할 수 있다.

또 만약 인코딩 시켜둔 Authorization 값이 유출된다면 디코딩 할 필요 없이

인코딩 시켜준 값만 이용해도, 해당 클라이언트와 동일한 인증을 할 수 있다.

이미 인코딩 시켜둔 값 자체가 인증에 필요한 문구이기 때문이다.

따라서 보안이 취약한 기본 인증은 암호화된 데이터 전송 (SSL)과 함께 연계해서 사용 할 수 있다.

SSL 전송은 SSL 인증서 를 발급 받은 비교적 안전한 웹 페이지와 헤더 정보를 암호화 시켜 주고 받기 때문에 신뢰 할 수 있는 웹 페이지라는 것 뿐 아니라 탈취되어도 서버의 개인키 없이 복호화 할 수 없기 때문에 안전해진다.


다이제스트 인증

캭 여기서 쓰이는 다이제스트는 digest 로 요약을 의미한다.

위에서 기본인증의 가장 큰 문제점 두 개를 알았다.

첫 째는 나의 로그인, 비밀번호 정보를 통째로 인코딩 하여 보내기 때문에 유출 될 경우 디코딩 하면 나의 로그인, 비밀번호 정보가 유출된다는 점

두 번째는 디코딩 할 필요 없이 통째로 인코딩 된 값들이 전송되기에 유출 될 경우 해당 인코딩 값을 이용해 웹 서버와 인증이 가능하다는 점

이다.

이를 방지하기 위해 다이제스트 인증은 요약된 정보 일부와 수시로 바뀌는 암호화 방식을 이용하여 기본 인증의 문제를 해결한다.

다이제스트 인증은 기본 인증에 비해 더 보안이 강력하다.
하지만 책에서도 나오고 지피티도 그러는데 다이제스트 인증 자체는 많이 사용되는 인증 방식은 아니라고 한다.
몇 가지 단점이 존재하기 때문이다.
이에 요즘에는 토큰 기반 인증이나 OAuth 등을 이용한다고 한다.

그럼에도 불구하고 다이제스트 인증 방식을 알아두면 좋다고 하여 공부해보았다.

다이제스트 인증의 방식을 가볍게 살펴본 이미지이다.

해당 이미지를 보면 클라이언트의 이름과 비밀번호를 주고 받을 때

digest() 라는 암호화 시키는 함수에 비밀번호를 통과 시켜 실제 비밀 번호를 암호화 한 후 주고 받는다.

서버는 암호화 해서 받은 정보를 다시 복호화 하여 확인하고 인증을 주고 받는다.

이렇게 암호화 된 비밀번호를 digest 라고 한다.

난스(nonce)

위 설명만 보면 암호화 시킨 비밀번호도 유출되면 기본 인증 방식과 동일하게 문제가 생기는게 아닌가 ? 하는 생각이 든다.

어차피 내 digest 가 유출되면 해당 digest 로 인증 가능한 것은 마찬가지이니 말이다.

하지만 다이제스트 인증 방식에선 유출된 digest 로 인증하는 Replay Attack 을 방지하기 위해 nonce 라는 증표를 이용한다.

nonce 는 매 시각 마다 혹은 매 요청 마다 변경되는 문자열로

클라이언트의 비밀번호를 digest 로 만들기 전 nonce 값과 함께 암호화 하여 digest 로 만든다.

이후 웹 서버는 digest 를 복호화 한 후 요청시 보냈던 nonce 를 이용하여 인증한다.

매 시점마다 변경되는 nonce 를 이용해 digest 는 항상 변경된다.

비밀번호는 고정적이여도 nonce 는 변경되기에 암호화 된 digest 는 항상 다르다.

그렇기 때문에 나의 digest 가 유출 되더라도 다른 시점에서의 digest 는 다르기 때문에

다른 시점에서는 nonce 값이 다르기에 웹 서버가 기대하는 digest 도 다른 것이다

Replay Attack 에서 안전하다.

nonce 값은 웹 서버가 클라이언트에게 인증을 요구 할 때 전송된다.


digest 알고리즘

이 부분은 MD5 , MD5-sess , A1 , A2 등 다양한 내용이 있는데 해당 부분은

나중에 생각해보도록 하자 .. 내용이 생각보다 깊고 어렵다 ㅠ_ㅠ


digest 인증 세션

HTTPstateless 이다.

그렇기 때문에 digest 를 이용한 인증에서 보안이 필요한 사이트의 하위 사이트 등으로 이동 할 때

하위 사이트 또한 보안 영역이기 떄문에 인증을 새롭게 해야 한다.

예를 들어 www/example.com/index.html 에서 인증이 필요했다면 www/example.com/index.html/image1.img 또한 인증이 필요하다.

하지만 보안 영역에서 다른 것들을 누르거나 요청 할 때 마다 로그인 창이 뜨는 것은 너무나도 귀찮은 일이다.

그렇기에 웹 서버단에서 stale = true 로 정의함으로서 로그인을 새롭게 할 필요 없이

보안 영역에서 행위 시, 너의 아이디와 비밀번호 + 새로 발급 된 nonce 값으로 요청을 다시 보내라 말 할 수 있다.

사전(preemptive) 인가

사전 인가 방식은 인증이 완료되어 웹 서버에서 클라이언트에게 리소스를 보낼 때

다음 요청 시 필요한 nonce 를 응답에 포함 시켜 보내는 방식이다.

이렇게 하면 불필요한 3-way-handshaking 의 과정을 간략하게 할 수 있다.

다음 난스 미리 생성하기

그래서 ! 사전 인가 때 필요한 nonce 를 미리 만들어 응답과 함께 보낸다면 물론 nonce 3-way-handshaking 보다 빠르게 할 수 있다.

하지만 이러한 방식의 단점은 요청 떄 응답에서 오는 다음 nonce 가 다음 요청에서 필요하기 때문에 이전 요청에 대한 응답이 도착해야지만 다음 요청을 보낼 수 있다.

이는 파이프라인 하는 능력 (응답이 오든 말든 내 요청을 우다다 보내버리는) 을 사용할 수 없기 때문에 성능상 불이익은 더욱 커진다.

제한된 난스 생성

그래서 , nonce 를 요청 시 마다 새로 만드는 것이 아니라 몇 번 혹은 몇 초간 재사용 할 수 있다.

그렇게 하면 요청자는 요청 할 때 하나의 nonce 를 가지고 요청을 우다다 보낼 수 있고 (파이프라이닝 가능) 만약 nonce 의 유효기간이 중단된 경우에는 새로 발급 받은 nonce 를 이용해 재인증을 하게 된다.

제한된 난스를 생성하게 되면 보안과 속도의 트레이드 오프 관계로 인해

속도는 빨라질지언정 보안과 관련된 부분은 기본 인증때처럼 유출 될 경우 보안상 문제가 생길 수 있다.

동기화 된 난스 생성

이는 클라이언트와 서버가 제 3자가 쉽게 예측 할 수 없는 비밀키에 기반해

순차적으로 생성될 난스에 대한 정보를 서로 알고 있는 것이다.

제일 안전하긴 하지만, 이는 다이제스트 인증 명세의 범위를 넘어서는 것이다.


상호 인증

상호인증은 Autherntication-Info 헤더를 통해

클라이언트와 서버가 추가적인 인증 정보를 공유하는 것을 의미한다.

헤더 필드 설명
qop Quality of Protection (qop) 값. "auth" 또는 "auth-int"와 같은 값이 사용됨.
rspauth 서버가 생성한 응답에 대한 `response` 필드의 값. 클라이언트가 응답을 검증하는 데 사용됨.
cnonce 클라이언트가 생성한 임의의 문자열. Digest Authentication에서 한 번만 사용되는 값.
nc Nonce Count. 클라이언트가 요청을 재전송하는 경우를 방지하기 위해 사용되는 값.
nextnonce 서버가 다음 요청에 사용할 새로운 `nonce` 값을 클라이언트에게 알려줌.

qop 는 말 그대로 보안의 정도를 나타내는 헤더 필드이다. 값이 auth-int 일 때는 반드시 repauth , cnonce , nc 가 존재해야 한다.

rspauth 는 클라이언트가 서버로부터 응답 받은 리소스가, 본인이 받은 리소스와 서버가 제공한 리소스가 동일한지를 확인 할 수 있도록 해주는 값이다.

cnonce 는 클라이언트가 서버로부터 전달하는 nonce 값이다. 예전에는 서버로부터 받은 nonce 값을 이용해 digist 를 생성했다면 cnonce 값을 이용해 digist 를 생성하고 서버에게 보낸다. 그럼 서버는 cnonce 를 이용해 digist 값을 해석한다.

cnonce 는 클라이언트와 서버가 인증을 수행하는 동안만 유효하며, 이 또한 nonce 때 처럼 인증 때 마다 새롭게 변경된다. cnonce 를 이용하여 클라이언트가 digist를 생성하면 , 서버가 보내는 nonce 값이 유출되었을 때 무차별적으로 인증을 뚫기 위해 다른 컴퓨터에서 보내는 요청들에게서 안전해질 수 있다.

오로지 클라이언트가 보낸 cnonce 만을 이용하니 말이다.

ncNonce Count 의 준말로 클라이언트가 서버에게 리소스를 요청 할 때마다 선형적으로 증가되는 값이다. 그러니 요청을 할 때 마다의 값을 적는다.

nc 가 필요한 이유는 만약 A 라는 클라이언트가 서버와의 10번째 요청에서 헤더가 B에게 유출 되었다고 해보자

그리고 A는 서버와 계속 요청을 하면서 요청이 30번째에 넘어가고 nc 도 30이 되었다고 해보자

이 때 B가 서버측에 A의 헤더 정보를 이용해 요청을 보낼 때 A가 서버와 몇 번 요청을 했는지 모르기 때문에 요청 횟수인 nc 를 추정 할 수 없다.

서버는 요청이 들어왔을 때 nc 값을 확인하고 nc 값이 선형적으로 증가하지 않은 경우의 요청은 replay attack 으로 간주하고 응답을 보내지 않는다.

profile
빨리 가는 유일한 방법은 제대로 가는 것이다

0개의 댓글