HTTP를 통해 안전하게 비밀번호를 보내는 방법은 무엇입니까?


115

로그인 화면에서 사용자가 자신의 사용자 이름과 암호로 양식을 제출하면 암호가 일반 텍스트로 전송됩니다 (POST를 사용하더라도 틀린 경우 수정).

그렇다면 문제는 통신 데이터를 도청 할 수있는 제 3 자로부터 사용자와 그의 암호를 보호하는 올바른 방법이 무엇입니까?

HTTPS가 문제에 대한 해결책이라는 것을 알고 있지만 표준 HTTP 프로토콜 (POST 요청)을 사용하여 적어도 일정 수준의 보안을 보장 할 수있는 방법이 있습니까? (아마도 어떤 식 으로든 자바 스크립트 사용)

편집 나는 몇 가지 중요한 것들을 생략했을 수 있습니다.

제가 한 것은 페이지였습니다. PHP 생성 로그인 페이지는 물론 HTTP GET 요청으로 사용자에게 HTML 파일로 전송됩니다. 서버와 클라이언트 사이에 (@Jeremy Powel) 연결이 설정되어 있지 않으므로 이러한 핸드 셰이 킹 프로토콜을 만들 수 없습니다. 그리고 나는 완전한 프로세스가 사용자에게 투명하기를 원합니다. 그는 암호를 다루지 않고 암호를 제출하기를 원합니다.

감사.


1
클라이언트가 암호화를 사용하지 않으면이 작업을 수행 할 수 없지만 사용자는 이러한 프로세스를 볼 필요가 없습니다. 그는 비밀번호를 입력하기 만하면 PHP가 생성하는 코드 (예 : 자바 스크립트)가 모든 것을 처리합니다.
Jeremy Powell

13
설명하신 문제는 HTTPS가 발명 된 이유입니다. 암호를 암호화하기 위해 클라이언트에 암호를 보내면 도청자가 돌아올 때 암호를 스니핑하고 암호를 해독 할 수 있습니다.
jnoss

1
따라서 제안에서 S는 사용자가 가진 유일한 "비밀"이기 때문에 암호 (또는 어떤 식 으로든 조합 된 사용자 이름 + 암호) 일 수 있습니다. 나 맞아? 따라서 솔루션은 다음과 같습니다.-서버는 숨겨진 양식 필드가있는 HTML 페이지를 제공합니다. R-사용자가 비밀번호를 입력하고 비밀번호를 보내기 전에 자바 스크립트가 H (R, S)를 계산하여 서버로 보냅니다. 심지어 AJAX를 사용하여 - 서버 H (R, S)를 계산하고, 수신과 비교하여위한 인증 합격 여부를 AJAX 요청에 대한 응답을 전송 - 자바 스크립트가 원하는 웹 페이지에 브라우저를 리디렉션
Kornelije PETAK

2
@jeremy powell-설명하는 것은 일반적인 관행이지만 헤더에서 쿠키를 스니핑하고 쿠키를 재사용하여 사용자를 가장 할 수있는 중개자에게 취약합니다. HTTPS를 사용하지 않는 중앙 공격에 남자가에 확보하기 어려운
jnoss

1
앞으로이 질문을받는 사람은 로그인 한 후 세션 쿠키를 보호해야합니다. (따라서 HTTPS를 사용하는 것이 훨씬 더 쉽습니다.)
Arjan

답변:


66

SSL과 함께 HTTP를 사용하면 삶이 훨씬 쉬워지고 안심할 수 있습니다. 아주 똑똑한 사람들 (적어도 저보다 똑똑합니다!)은이 비밀 통신 방법을 수년간 면밀히 조사해 왔습니다.


14
... 그리고 "하지만 SSL 인증서 비용을 지불해야합니다 !!" 요즘에는 $ 30에받을 수 있기 때문에 유효한 불만이 아닙니다. 데이터를 보호하기 위해 실제로 30 달러의 가치가 없습니까?
caf

3
구독 한 웹 호스트가 SSL 인증서 추가를 지원하지 않으면 어떻게됩니까?
Calmarius

89
@Calmarius은 - 당신은 진짜 웹 호스트로 이동
BornToCode

3
@BornToCode 이것은 기술적으로 전용 IP가 필요하고 HTTPS를 사용하려면 서버 하드웨어 (또는 적어도 VPS)를 소유해야 함을 의미합니다. 공유 웹 호스트는 전체 서버가 호스트 소유자의 인증서로 보호되지 않는 한 HTTPS를 수행 할 수 없습니다.
Calmarius

6
공유 웹 호스트는 확실히 사용하여 HTTPS를 할 수 en.wikipedia.org/wiki/Server_Name_Indication를
브라이언 민튼에게

39

보안 인증은 광범위한 주제입니다. 간단히 말해서 @ jeremy-powell이 언급했듯이 HTTP 대신 HTTPS를 통해 자격 증명을 보내는 것을 항상 선호합니다. 보안과 관련된 많은 골칫거리를 없앨 것입니다.

TSL / SSL 인증서는 요즘 꽤 저렴합니다. 실제로 돈을 전혀 쓰고 싶지 않다면 무료 letsencrypt.org ( 자동 인증 기관)가 있습니다.

한 단계 더 나아가 백그라운드에서 letsencrypt 를 호출 하는 caddyserver.com 을 사용할 수 있습니다 .

자, 일단 우리가 HTTPS를 제거하면 ...

POST 페이로드 또는 GET 매개 변수를 통해 로그인 및 비밀번호를 보내면 안됩니다. 대신 다음과 같이 구성된 Authorization 헤더 (기본 액세스 인증 체계)를 사용합니다.

  • 사용자 이름과 비밀번호는 콜론으로 구분 된 문자열로 결합됩니다. 예 : username : password
  • 결과 문자열은 Base64의 RFC2045-MIME 변형을 사용하여 인코딩됩니다. 단 76 자 / 줄로 제한되지 않습니다.
  • 인증 방법과 공백 즉 "Basic"이 인코딩 된 문자열 앞에 놓입니다.

출처 : Wikipedia : 인증 헤더

조금 복잡해 보일 수도 있지만 그렇지 않습니다. 이 기능을 즉시 사용할 수있는 좋은 라이브러리가 많이 있습니다.

Authorization 헤더를 사용해야하는 몇 가지 이유가 있습니다.

  1. 표준입니다
  2. 간단합니다 (사용 방법을 배운 후)
  3. 다음과 같이 URL 수준에서 로그인 할 수 있습니다. https://user:password@your.domain.com/login(예를 들어 Chrome은 자동으로 Authorization헤더 로 변환합니다 )

중요 :
@zaph가 아래의 주석에서 지적했듯이 민감한 정보를 GET 쿼리로 보내는 것은 서버 로그에 기록 될 가능성이 높기 때문에 좋은 생각이 아닙니다.

여기에 이미지 설명 입력


11
자격 증명 (비밀번호)을 GET 매개 변수로 보내는 문제는 사용자 / 비밀번호 쌍이 아마도 서버 로그에 남게 될 것이며 이는 좋은 생각이 아닙니다. POST에서 자격 증명을 보내는 것이 가장 좋습니다.
zaph

아 ... 전혀. 현재보고있는 스크린 샷은 브라우저에서 일어나는 일을 설명하기 위해 수정됩니다. 브라우저에 들어가는 순간 Authorization헤더를 만드는 URL이 변환됩니다 . 그냥 가세요. 로그는 깨끗한 것을 상기시킵니다. 물론 서버에서 호출하는 경우 (걱정하는 시나리오 인 경우) 물론 프로그래밍 방식으로 헤더를 생성해야합니다.
FullStackForger 2016

볼 수없는 것은 기록 할 수 없습니다. username:password@url브라우저에서 다음으로 번역됩니다. url+ Authorization요청 헤더. GET 쿼리에 관해서는 ... 내가 말했듯이 Authroziation 헤더를 사용하십시오. 더 좋습니다.
FullStackForger 2011

2
중간자 도청으로부터 민감한 데이터를 보호한다는 질문의 요점을 해결하지 않습니다. 초점은 자격 증명을 전달하는 대안 및 / 또는 더 표준화 된 방법을 찾는 것이 아니라 안전하지 않은 채널을 통해이를 보호하는 것입니다.
제왕

3
이 솔루션은 이미 TLS / SSL로 연결을 암호화하는 경우에만 작동한다는 점을 강조해야합니다. base64는 암호화가 아닙니다.
Scot

14

챌린지 응답 체계를 사용할 수 있습니다. 클라이언트와 서버가 모두 비밀 S를 알고 있다고 가정합니다. 그러면 서버는 다음과 같은 방법으로 클라이언트가 암호를 알고 있는지 확인할 수 있습니다.

  1. 서버는 난수 R을 클라이언트에 보냅니다.
  2. 클라이언트가 H (R, S)를 서버로 다시 보냅니다 (여기서 H는 SHA-256과 같은 암호화 해시 함수 임).
  3. 서버는 H (R, S)를 계산하고이를 클라이언트의 응답과 비교합니다. 일치하는 경우 서버는 클라이언트가 암호를 알고 있음을 압니다.

편집하다:

여기에는 R의 신선함과 HTTP가 상태 비 저장이라는 사실에 문제가 있습니다. 이것은 서버가 비밀을 생성하도록 하여 서버 만 알고있는 Q라고 부르는 것으로 처리 할 수 ​​있습니다 . 그런 다음 프로토콜은 다음과 같습니다.

  1. 서버는 난수 R을 생성합니다. 그런 다음 클라이언트 H (R, Q) (클라이언트가 위조 할 수 없음)로 보냅니다.
  2. 클라이언트는 R, H (R, Q)를 보내고 H (R, S)를 계산하고 모든 것을 서버로 다시 보냅니다 (여기서 H는 SHA-256과 같은 암호화 해시 함수 임).
  3. 서버는 H (R, S)를 계산하고이를 클라이언트의 응답과 비교합니다. 그런 다음 R을 가져 와서 (다시) H (R, Q)를 계산합니다. 클라이언트의 H (R, Q) 및 H (R, S) 버전이 서버의 재계 산과 일치하면 서버는 클라이언트가 인증 된 것으로 간주합니다.

참고로 H (R, Q)는 클라이언트에 의해 위조 될 수 없기 때문에 H (R, Q)는 쿠키 역할을하므로 실제로 쿠키로 구현 될 수 있습니다.

다른 편집 :

프로토콜에 대한 이전 편집은 H (R, Q)를 관찰 한 사람이 올바른 해시로 재생할 수있는 것처럼 보이기 때문에 올바르지 않습니다. 서버는 어떤 R이 더 이상 신선하지 않은지 기억해야합니다. 나는 당신이 이것을 편집하고 좋은 일을 할 수 있도록이 대답을 CW입니다.


+
1-

10
중간자 또는 가장 공격을 막지 않습니다. 예 : Wi-Fi를 통해. 이것이 보안에 대한 잘못된 감각을 줄 것 같습니다, IMO.
Tom Hawtin-tackline

2
그것은 수동적 공격으로부터 보호하지만, 중간에있는 남자는 여전히 공격 할 수 있습니다.
Douglas Leeder

7
또한 서버가 원래 암호를 알아야합니다.
Douglas Leeder

3
암호 화폐를 재발 명하지 마십시오! (생산 중)
bryanph 2015

11

웹 호스트에서 허용하거나 민감한 데이터를 처리해야하는 경우 HTTPS, 마침표를 사용하십시오. (종종 법률 afaik에서 요구합니다).

그렇지 않으면 HTTP를 통해 작업을 수행하려는 경우. 나는 이런 식으로 할 것입니다.

  1. 서버는 공개 키를 로그인 페이지에 내장합니다.
  2. 클라이언트가 로그인 양식을 채우고 제출을 클릭합니다.
  3. AJAX 요청은 서버에서 현재 타임 스탬프를 가져옵니다.
  4. 클라이언트 측 스크립트는 자격 증명, 타임 스탬프 및 솔트 (예 : 마우스 움직임, 키 누르기 이벤트와 같은 아날로그 데이터에서 해시)를 연결하고 공개 키를 사용하여 암호화합니다.
  5. 결과 해시를 제출합니다.
  6. 서버가 해시를 해독합니다.
  7. 타임 스탬프가 충분히 최근인지 확인합니다 (짧은 5-10 초 창만 허용). 타임 스탬프가 너무 오래된 경우 로그인을 거부합니다.
  8. 20 초 동안 해시를 저장합니다. 이 간격 동안 로그인에 대해 동일한 해시를 거부합니다.
  9. 사용자를 인증합니다.

따라서 이렇게하면 암호가 보호되고 동일한 인증 해시를 재생할 수 없습니다.

세션 토큰의 보안에 대해. 조금 더 어렵습니다. 그러나 훔친 세션 토큰을 재사용하는 것을 조금 더 어렵게 만들 수 있습니다.

  1. 서버는 임의의 문자열을 포함하는 추가 세션 쿠키를 설정합니다.
  2. 브라우저는 다음 요청시이 쿠키를 다시 보냅니다.
  3. 서버는 쿠키의 값을 확인합니다. 쿠키 값이 다르면 세션을 파괴합니다. 그렇지 않으면 모두 괜찮습니다.
  4. 서버는 다른 텍스트로 쿠키를 다시 설정합니다.

따라서 세션 토큰이 도난 당하고 다른 사람이 요청을 보낸 경우 원래 사용자의 다음 요청에서 세션이 파괴됩니다. 따라서 사용자가 사이트를 적극적으로 탐색하고 링크를 자주 클릭하면 도둑은 훔친 토큰을 가지고 멀리 가지 않을 것입니다. 이 체계는 계정 삭제와 같은 중요한 작업에 대해 다른 인증을 요구하여 강화할 수 있습니다.

편집 : 공격자가 다른 공개 키로 자신의 페이지를 설정하고 서버에 대한 요청을 프록시하는 경우 이것은 MITM 공격을 방지하지 않습니다. 이를 방지하려면 공개 키를 브라우저의 로컬 저장소 또는 앱 내에 고정하여 이러한 종류의 트릭을 감지해야합니다.

구현 정보 : RSA는 아마도 가장 잘 알려진 알고리즘이지만 긴 키의 경우 상당히 느립니다. PHP 또는 Javascript 구현이 얼마나 빠를 지 모르겠습니다. 그러나 아마도 더 빠른 알고리즘이있을 것입니다.


이 경우 암호가 실제로 보호됩니까? 누군가가 전송 된 내용을 알아 내고 공개 키를 사용하여 해독 한 다음 나중에 사용할 때 타임 스탬프를 업데이트 할 수 없습니까? 내가 뭔가를 놓치고 있습니까?
michaellindahl 2014 년

@michaellindahl 비대칭 암호화는 서버를 떠나지 않는 개인 키만 암호를 해독하는 데 사용할 수 있음을 의미합니다. 공개 키는 암호화에만 사용할 수 있습니다.
Dan Pantry

2
브라우저와 서버 사이의 컴퓨터는 로그인 페이지에서 공개 키를 변경할 수 있습니다.
Antti

방법을 공유해 주셔서 감사합니다. 매우 흥미로운 것을 발견했습니다. 자격 증명을 보낼 때 추가 된 타임 스탬프는 좋은 캐치입니다! 값이 임의의 문자열 인 추가 세션 쿠키를 사용하는 것에 대한 한 가지 질문 : 다음 요청에 대한 토큰과 같습니까?
Victor

4

나는 인터넷에서 좋은 구현을 보지 못하더라도 서버 측 및 클라이언트 측 Diffie-Hellman 키 교환 시스템을 AJAX 또는 여러 양식 제출 (전자 권장)과 함께 사용합니다. JS 라이브러리는 항상 MITM에 의해 손상되거나 변경 될 수 있습니다. 로컬 스토리지를 사용하여 어느 정도까지 이러한 문제를 해결할 수 있습니다.


4

SRP 를 사용하여 안전하지 않은 채널을 통해 보안 암호를 사용할 수 있습니다 . 장점은 공격자가 트래픽을 스니핑하거나 서버를 손상 시키더라도 다른 서버에서 암호를 사용할 수 없다는 것입니다. https://github.com/alax/jsrp 는 브라우저 또는 서버 측 (노드를 통해)에서 HTTP를 통해 보안 암호를 지원하는 자바 스크립트 라이브러리입니다.


1

HTTPS는 비대칭 암호화를 사용하기 때문에 매우 강력합니다. 이러한 유형의 암호화를 사용하면 암호화 된 터널을 만들 수있을뿐만 아니라 해커가 아닌 올바른 사람과 대화하고 있는지 확인할 수 있습니다.

다음은 비대칭 암호 RSA (PGP에서 사용)를 사용하여 통신하는 Java 소스 코드입니다. http://www.hushmail.com/services/downloads/


0

호스트에 SSL을 사용할 수 있습니다. letsencrypt https://letsencrypt.org/ 와 같은 SSL에 대한 무료 프로젝트가 있습니다.


2
문제의 세 번째 문장을 확인하십시오. (또한, 항상 당신이 덜 상세한 중복을 추가하지 않을 수 있도록 다른 답변을 참조하십시오.)
나단 Tuggy에게

0

https를 사용하는 것이 가장 좋은 옵션입니다 (요즘에는 인증서가 그렇게 비싸지 않습니다). 그러나 http가 요구 사항 인 경우 일부 암호화를 사용할 수 있습니다. 서버 측에서 암호화하고 사용자 브라우저에서 구분합니다 (키를 별도로 전송).

우리는 safevia.net 을 구현하는 동안 이것을 사용했습니다. 암호화 는 클라이언트 (송신자 / 수신자) 측에서 이루어 지므로 사용자 데이터는 네트워크 나 서버 계층에서 사용할 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.