본문 바로가기
나의 개발일지/CS

HTTP와 HTTPS - 비밀번호 평문 전송은 안전할까?

by stella_gu 2024. 2. 14.

부트캠프 파이널 프로젝트 때 프론트엔드 레포에 이슈가 달렸었다.
어쩌다 지나가는 분이셨는진 모르겠지만(팀원 그 누구도 알지 못함) 덕분에 http 통신 과정에서의 데이터 암호화에 대해 생각해 볼 기회가 되었다.

 
결론은 https 통신을 하고 있으므로 평문으로 전달해도 문제가 되지 않을 것 같단 판단에 평문 전달 후 서버에서 단방향 암호화로 데이터베이스에 저장하는 방식을 취했다.
https로 클라이언트-서버 통신을 하면 SSL/TLS로 암호화되어 비밀번호는 결국 일반 텍스트가 아닌 암호화된 데이터로 전송되기 때문이다.

(이슈에 링크된 암호화 적용 기준은 오른쪽과 같다)
 
 
 

▼ HTTP (HyperText Transfer Protocol)

- 웹에서 이루어지는 모든 데이터 교환의 기초이며, 클라이언트-서버 간 통신을 위한 프로토콜
- 클라이언트가 서버에 요청(Request)을 보내고, 서버가 이에 대한 응답(Response)을 제공하는 요청-응답(Request-Response) 모델을 기반으로 한다.
 
 

[ HTTP 요청 ]

[이미지 출처] https://developer.mozilla.org/ko/docs/Web/HTTP/Overview#%EC%9A%94%EC%B2%AD

 
- Method: 클라이언트가 수행하고자 하는 동작을 정의합니다. GET, POST, PUT, DELETE 등이 있다.
- Path: 요청이 지정하는 서버의 리소스 경로이다.
- Headers: 요청에 대한 추가 정보(메타데이터)를 포함한다. 사용자 에이전트, 콘텐츠 유형 등이 있다.
- Body: 일부 HTTP 메소드(예: POST, PUT)에서 사용되며, 전송할 데이터를 포함한다.
 
 

[ HTTP 응답 ]

[이미지 출처] https://developer.mozilla.org/ko/docs/Web/HTTP/Overview#%EC%9D%91%EB%8B%B5

 
- Status Code: 요청이 성공했는지, 그리고 어떤 종류의 응답이 반환되었는지를 나타내는 코드이다. 200(성공), 404(찾을 수 없음), 500(서버 오류) 등이 있다.
- Status Message: 상태 코드의 짧은 설명이다.
- Headers: 응답에 대한 추가 정보를 제공한다. 콘텐츠 유형, 콘텐츠 길이, 서버 정보 등이 있다.
- Body: 서버가 클라이언트에 반환하는 실제 데이터이다.
 
 
 

▼ HTTPS (Hypertext Transfer Protocol Secure)

- HTTP는 데이터를 평문으로 전송하기 때문에 중간자 공격(Man-in-the-Middle Attack)에 취약하여 데이터가 도청되거나 변조될 수 있다. 이러한 보안 취약점을 개선하기 위해 나온 프로토콜이 HTTPS이다.
- SSL(Secure Sockets Layer) 또는 TLS(Transport Layer Security) 암호화 프로토콜을 사용하여 클라이언트와 서버 간의 모든 통신을 암호화한다. 간단하게 HTTP에 SSL/TLS 암호화를 얹은 거라 생각하면 된다.
 
 

[ HTTPS는 어떻게 작동되나 ]

[출처] https://blog.bytebytego.com/p/how-does-https-work-episode-6?utm_source=%2Fsearch%2FHttps&utm_medium=reader2

 
1. 클라이언트(브라우저)와 서버가 TCP 연결을 설정합니다.
2. 클라이언트가 서버에 "Client Hello"를 보냅니다. 이 메시지에는 필요한 암호화 알고리즘(암호 모음)과 지원할 수 있는 최신 TLS 버전이 포함되어 있습니다. 서버는 "Server Hello"로 응답하여 브라우저가 해당 알고리즘과 TLS 버전을 지원할 수 있는지 여부를 알 수 있도록 합니다.
그런 다음 서버는 SSL 인증서를 클라이언트로 보냅니다. 인증서에는 공개 키, 호스트 이름, 만료 날짜 등이 포함됩니다. 클라이언트는 인증서의 유효성을 검사합니다.
3.  SSL 인증서의 유효성을 검사한 후 클라이언트는 세션 키를 생성하고 공개 키를 사용하여 암호화합니다. 서버는 암호화된 세션 키를 수신하고 개인 키로 암호를 해독합니다.
4. 이제 클라이언트와 서버가 모두 동일한 세션 키(대칭 암호화)를 보유하고 있으므로 암호화된 데이터가 안전한 양방향 채널로 전송됩니다.
 
 
 

▼ HTTP 암호화 전송

- HTTP 통신에서 데이터를 암호화해서 전송하면 안전하지 않을까? 싶지만 이 경우 클라이언트에서의 키 관리 문제와 암호화 알고리즘 공개 관련 리스크가 존재하므로 추천하지 않는다.
- 키 관리 문제: 클라이언트와 서버가 동일한 키를 공유해야 하는데, 이 과정에서 키가 노출될 위험이 있다.
- 알고리즘의 취약성: 사용된 암호화 알고리즘의 취약점이 발견될 경우, 데이터의 안전성이 위협받을 수 있다. 클라이언트 측에서 사용된 알고리즘이 공개되어 있으면, 공격자가 이를 이용해 암호화를 해제할 수 있는 방법을 찾을 가능성이 높아진다.
 
 
 

HTTP와 HTTPS 외 보안성을 높이기 위한 다양한 인증 및 보안 기술

- 비밀번호 자체를 전송하지 않고 사용자를 인증하는 방법도 있다. 이러한 방법은 사용자의 편의성을 높일 수도 있겠지만 오히려 불편함을 안겨주는 일이 생길 수 있으니 서비스의 성격에 맞게 적절히 선택하여야 할 것이다.
 
1. OAuth 소셜 로그인: 사용자가 기존 소셜 미디어 계정을 사용하여 다른 웹 서비스에 로그인할 수 있게 해준다. 이 방법은 사용자가 직접 로그인 정보를 입력할 필요가 없으므로, 피싱 공격의 위험을 줄여준다.

2. 매직 링크 기반 로그인: 사용자가 이메일이나 SMS를 통해 받은 일회용 링크를 클릭하여 로그인하는 방식이다. 이 방법은 사용자가 비밀번호를 기억하거나 입력할 필요가 없어 사용 편의성을 높여준다.

3. 멀티 팩터 인증 (MFA): 로그인 과정에서 비밀번호 외에 추가적인 인증 수단을 요구하는 방식이다. 문자 메시지를 통한 인증 코드, 생체 인식 등이 있다.