로그인하는 동안 일반 텍스트 암호를 보내기위한 대안

Jan 02 2021

참고 : 이미 읽었 습니다. HTTPS를 통해 일반 텍스트 암호를 보내도됩니까? 및 https 보안-암호는 서버 측 또는 클라이언트 측에서 해시해야합니까? 하지만 여기에서는 특정 교체 방법에 대한 것입니다 (아래 참조).


Cloudflare 블로그 에서 새로운 인증 방법에 대한 기사를 읽은 후 POST"개발자 도구> 네트워크"로 인증하는 동안 전송되는 요청을 살펴 보았습니다 . 많은 인기 웹 사이트 (Reddit, HN 등)는 여전히 (SSL 보안) POST요청 에서 일반 텍스트로 비밀번호를 전송합니다 (아래 스크린 샷 참조).

이 로그인 방법은 여전히 ​​업계 표준입니까?

다음 대안이 HTTPS를 통해 일반 텍스트 비밀번호를 보내는 것보다 더 안전합니까?

  • signup : 클라이언트는 random을 생성 하고 요청을 통해 salt튜플 (username, salt, hash(plain_password + salt))을 보냅니다 POST. 그러면 일반 텍스트 암호 가 서버에 도달 하지 않습니다 .

  • 후속 로그인 : 서버는 주어진으로 로그인을 시도 salt하는 모든 클라이언트에게 다시 보내야 username하므로 클라이언트는 동일한 솔트로 해시 할 수 있습니다. 따라서 이것은 서버가 주어진 사용자 이름으로 로그인 하려는salt 모든 사람 에게 공개 되고 있음을 의미합니다 .

  • 이점 : 서버는 솔트 + 해시 된 암호 (표준)를 저장 하지만 서버는 일반 텍스트 암호를 한 번도 본 적이 없습니다 (따라서 서버가 손상되면 위험이 제한됨).

노트:

  • 이후 H = hash(plain_password + salt)지금 새처럼 조금 동작 plaintext(의 두 번째 대답은 참조 ? 제로 지식 암호 증명 : 왜 클라이언트 측이 아닌 ZKP의 암호를 해싱됩니다 ), 다음 단절을 저장할 수있는 (username, salt, server_salt, hash(H + server_salt))데이터베이스에 대신 (username, salt, H).

  • 완화는 재생 공격에 대한 위험에, 서버는 또한 고유를 보낼 수 nonce와 함께 salt하나 개의 로그인 시도 후 만료 각 로그인에 대해

  • 여기서의 주요 목표는 서버가 일반 텍스트 암호 나 간단한 해시에 액세스 할 수 없다는 것입니다 (전체 사이트에 대한 단일 무지개 테이블로 종종 되돌릴 수 있음). 공격자가 사용자 당 하나의 레인보우 테이블을 계산해야하는 위험은 괜찮습니다 .

  • 완화하고 싶은 공격의 예 : 서버가 일반 텍스트 암호에 액세스 할 수 있고 손상되면 (예 : Spectre / Meltdown vuln.) 사용자의 일반 텍스트 암호 (다른 웹 사이트에서 재사용 될 수 있음)가 도용 될 수 있습니다. -해시되고 데이터베이스에 저장됩니다.


답변

14 SteffenUllrich Jan 02 2021 at 14:38

귀하의 제안이 기존 클라이언트 측 해싱 접근 방식보다 어떻게 더 나은지는 알 수 없지만 다른 것보다 구현하기가 더 복잡하다는 것을 알았습니다. 불행히도 접근하려는 특정 위험에 대해 설명하지 않았으므로 일반적으로 나타나는 일반적인 위협을 가정합니다.

중간자 공격자

이 경우 중간에있는 일부 사람이 트래픽에 액세스 할 수 있다고 가정합니다. 예를 들어 회사 방화벽에서 신뢰할 수있는 트래픽 TLS 차단을 손상했거나 superfish의 경우와 같이 신뢰할 수있는 CA를 확보했기 때문입니다 .

이 시나리오에서 공격자는 H이전에에서했던 것과 동일한 액세스 권한을 얻 습니다 plain_password. 이후 H인증을 위해 필요한 것 모든 것이 공격자는 이렇게 성공하고 당신의 접근 방식은 여기에 추가 보호 기능을 추가하지 않습니다 .

취약한 암호 및 암호 재사용 숨기기

클라이언트 측 해싱에 대한 일반적인 주장은 취약하거나 재사용 된 암호를 서버에 노출하지 않고 대신 복잡한 파생 암호로 인증하는 것입니다. 당신의 접근 방식은 해시와 함께이 작업을 수행 plain_password무작위로 생성 된 일부 사용자와 salt다음 전송 Hsalt암호 설정에 대한 서버에.

이것이 작동하는 동안 모든 인증에는 이제 추가 단계가 필요합니다 . 먼저 사용자로부터 사용자에 대해 이전에 사용 된 솔트를 검색 한 다음이를 사용 salt하여 plain_password. 이 추가 단계는 먼저 서버에서 사용자를 확인하고 나중에 암호를 확인할 수 있기 때문에 인증을 더 복잡하게 만듭니다. 추가로이를 간단히 구현 하면 추가 인증없이 사용자가 처음에 존재하는지 (소금 반환 여부) 확인할 수 있으므로 정보 유출열립니다 .

이 정보 유출은 사용자의 존재 여부에 관계없이 일부 솔트를 반환하는 서버에 의해 닫힐 수 있습니다. 물론 이것은 임의의 솔트가 될 수 없습니다. 그렇지 않으면 공격자가 동일한 사용자를 두 번 확인하고 반환 된 솔트가 다른 경우 사용자가 존재하지 않는다고 결론을 내릴 수 있기 때문입니다. 따라서 솔트는 실제로 존재하지 않는 사용자에 대해 수정되어야합니다. 즉, 사용자 이름에서 파생됩니다.

그리고 이것은 또한 접근 방식단순화 하는 경로를 보여줍니다. 사용자가 임의의 솔트를 생성하여 서버에 저장하고 나중에 다시 검색 하는 대신 클라이언트 측의 사용자 이름에서 솔트를 파생 시킬 수 있습니다 . 간단한는 salt=hash(username+domain)도메인 당 고유 염을 생성하고, 따라서 둘 수 있도록 충분한 것 saltH다른 경우에도 usernameplain_password다른 도메인에 다시 얻을. 그리고 귀하의 접근 방식과 달리 사용자를 위해 이전에 사용한 솔트를 먼저 검색 하기 위해 서버로의 추가 이동이 필요하지 않습니다 .


간단히 말해서,이 단순화 된 접근 방식은 기본적으로 hash(plain_password+username+domain)원래 암호 대신 보내는 것입니다. 도메인은 확실히 경우에도 있는지 확인하는 추가 username하고 plain_password여러 사이트에 걸쳐 재사용, 파생 된 암호가 재사용되지 않습니다.

8 mti2935 Jan 02 2021 at 21:33

이것이 바로 PAKE 및 SRP 와 같은 프로토콜 이 해결하고자하는 문제입니다. PAKE / SRP를 사용하면 클라이언트와 서버는 클라이언트에 알려진 암호 (및 서버에 알려진 암호 파생)를 기반으로 서로를 인증합니다.

클라이언트는 클라이언트가 서버에 암호 (또는 암호와 동등한 데이터)를 보내지 않고 암호를 알고 있음을 서버에 보여줍니다. 프로세스가 끝나면 클라이언트와 서버는 공유 암호를 공유합니다.

서버는 암호 (또는 암호와 동등한 데이터)를 저장하지 않으며 사전 공격에 취약하지 않습니다. 도청 자나 중간자 (man-in-the-middle)가 유선으로 전송 된 일반 텍스트를 볼 수있는 사람은 암호를 도출 할 수있는 충분한 정보를 얻을 수 없습니다. 이를 통해 가짜 인증서를 사용하는 중간자 공격을 효과적으로 방지하고 '피싱'사이트가 사용자의 암호를 도용하는 것을 방지합니다.

1password가 SRP를 구현 한 방법에 대한 좋은 글은 다음을 참조하십시오. https://blog.1password.com/developers-how-we-use-srp-and-you-can-too/

5 mentallurg Jan 02 2021 at 16:00

Steffen Ullrich 의 답변 외에도 :

로그인하는 동안 사용자가 해시 만 보내면 공격자는 암호를 알 필요가 없습니다. 암호 데이터베이스를 훔치는 것으로 충분합니다. 그런 다음 로그인 요청 중에 공격자는 데이터베이스에서 해시를 보냅니다. 서버는 클라이언트가 암호를 사용하고 해시했는지 또는 클라이언트 (공격자)가 단순히 해시를 보냈는지 구별하지 않습니다.

OPAQUE에 대한 기사는이 문제도 해결합니다. 암호 데이터베이스를 훔치는 것은 공격자에게 도움이되지 않습니다. 일반 사용자 암호를 알아야합니다.

3 MargaretBloom Jan 03 2021 at 08:43

공격자가 서버를 손상시킨 경우 서버에서 실행되는 소프트웨어뿐만 아니라 클라이언트에서 실행되는 소프트웨어도 제어 할 수 있습니다.
디자인 한 인증 체계가 무엇이든간에 공격자는 브라우저로 보내기 전에이를 변경할 수 있습니다.
이제 달걀 병아리 문제가 생겼습니다. 공격자가 암호를 수집하여 서버로 보내는 방식을 제어하는 ​​경우 암호를 보호 할 수 없습니다.

데이터 유출이 걱정되는 경우 귀하의 방법은 보호 수단으로 작동하지만 적절한 암호 해싱 서버 측도 마찬가지입니다.

MITM 공격이 걱정되는 경우 TLS가이를 해결합니다.
TLS를 통한 MITM 공격이 걱정된다면 제가 말하고 싶은대로 이에 대한 좋은 방어는 항상 Krav Maga 매뉴얼에서 시작됩니다. TLS를 끊을 수있는 충분한 자원을 지속적으로 보유한 공격자는 적절하지 않고 특수 교육을받지 않은 개인으로부터 원하는 것을 얻는 데 문제가 없습니다 (예, 고문, 협박, 납치 및 살인에 대해 이야기하고 있습니다).

서버에서받은 데이터 만 읽을 수있는 위협 행위자가 걱정된다면 Steffen이 수정 한 접근 방식이 이에 맞지 않을 것입니다. 그러나 이것은 이상하고 드문 상황이며, 종종 심하게 잘못 구성된 서버 및 잘못된 개발 관행 (예 : GET 요청을 통해 자격 증명을 전송하고 액세스 로그를 공개적으로 저장)으로 인해 발생합니다. 이러한 실수를 처리하기 위해 프로토콜을 발명하는 것보다 이러한 실수를 수정하는 것이 더 쉽습니다.

언급 한 두 가지 취약점 (실제로는 Meltdown이 기술적으로 Spectre의 변형이므로 실제로는 하나에 불과 함)은 결국 로컬 권한 상승을 초래하여 공격자가 웹 서버를 완전히 제어 할 수 있도록합니다. 공격자가 웹 서버에서받은 데이터에 대해 읽기 전용 액세스 권한을 갖는 시나리오가 얼마나 드문 지 다시 한 번 강조합니다.

따라서 많은 대형 사이트에서이를 사용하지 않는 이유는 구성이 잘못되었을 가능성이 가장 높은 특정 상황에서만 거의 아무것도 추가하지 않기 때문입니다. 또한 공격자가 서버에서 전환되는 데이터를 읽을 수 있다면 게임에서 잃어버린쪽에 도달하게된다는 점도 주목할 가치가 있습니다. 저를 염두에 두십시오. 보호를 계층화하는 것이 좋지만, 당신의 주된 목표는 처음에 일어나지 않는 것입니다. 그리고 그것에 집중하면 새로운 계획을 고안하지 않아도됩니다.

어쨌든 Steffen이 보여준 것처럼, 당신이 제안한 계획은 그런 이상한 공격 모델로 다시 작동 할 수 있습니다. 나는 여전히 사전에있는 단어 인 먼 가능성을 지배 하기 hash(hash(domain + username) + password)보다는 여전히 사용 합니다. mti2935가 보여 주듯이 SRP는 더 흥미로운 대안입니다. 인증서 기반 인증 (즉, 브라우저에서 처리하는 인증)은 또 다른 옵션입니다 (주석에서 제안한 것처럼 잠재적으로 오염 된 JS 스크립트에서 수동으로 수행하는 것보다 낫다는 것을 알았습니다).hash(domain + username + password)domain + username + password