기존 사용자를 위해 새 비밀번호를 강요하지 않고 비밀번호 해싱 업데이트


32

기존 사용자 기반으로 기존 응용 프로그램을 유지 관리합니다. 시간이 지남에 따라 현재 암호 해싱 기술이 오래되어 업그레이드해야한다고 결정됩니다. 또한 UX 이유로 인해 기존 사용자가 자신의 비밀번호를 강제로 업데이트하는 것을 원하지 않습니다. 전체 비밀번호 해싱 업데이트는 화면 뒤에서 수행해야합니다.

다음을 포함하는 사용자를위한 '단순한'데이터베이스 모델을 가정하십시오.

  1. 신분증
  2. 이메일
  3. 암호

그러한 요구 사항을 해결하는 방법은 무엇입니까?


나의 현재 생각은 :

  • 적절한 클래스에서 새로운 해싱 메소드를 생성
  • 추가 비밀번호 필드를 보유하도록 데이터베이스의 사용자 테이블을 업데이트하십시오.
  • 사용자가 오래된 비밀번호 해시를 사용하여 로그인하면 업데이트 된 해시로 두 번째 비밀번호 필드를 채 웁니다.

이로 인해 암호 해시를 업데이트하지 않은 사용자와 암호 해시를 업데이트하지 않은 사용자를 합리적으로 구별 할 수 없다는 문제가 생겨서 둘 다 확인해야합니다. 이것은 끔찍한 결함이있는 것 같습니다.

또한 이것은 기본적으로 모든 단일 사용자가 비밀번호를 업데이트 할 때까지 이전 해싱 기술을 무기한으로 유지할 수 있음을 의미합니다. 그 순간에만 이전 해싱 확인을 제거하고 불필요한 데이터베이스 필드를 제거 할 수 있습니다.

현재 '솔루션'이 더럽고 불완전하고 그렇지 않은 것이기 때문에 주로 몇 가지 디자인 팁을 찾고 있습니다.하지만 가능한 솔루션을 설명하기 위해 실제 코드가 필요한 경우 모든 언어를 자유롭게 사용하십시오.


4
왜 세트와 설정되지 않은 보조 해시를 구별 할 수 없습니까? 데이터베이스 컬럼을 널 입력 가능하게하고 널을 점검하십시오.
Kilian Foth

6
새 해시 필드 대신 해시 유형을 새 열로 사용하십시오. 해시를 업데이트 할 때 유형 필드를 변경하십시오. 이렇게하면 나중에 다시 이런 일이 발생하면 이미 처리 할 수있는 위치에있게되며 이전 (아마 덜 안전한) 해시를 유지할 가능성이 없습니다.
Michael Kohne

1
나는 당신이 올바른 길을 가고 있다고 생각합니다. 6 개월 또는 1 년 후, 나머지 사용자가 비밀번호를 변경하도록 할 수 있습니다. 1 년 후 또는 무엇이든간에, 당신은 이전 필드를 제거 할 수 있습니다.
GlenPeterson

3
왜 이전 해시를 해시하지 않습니까?
Siyuan Ren

당신이 원하기 때문에 암호가 없는 다음 'dehashed'이 될 필요가 있음을 다른 값 - (사용자에 의해 주어진 해시 하나에 비교 예)를 unhashing 당신을 제공합니다 그래서 (하지 이전 해시) 해시 할 ... 암호를 이전 방법에서. 가능하지만 깨끗하지는 않습니다.
Michael Durrant

답변:


25

새 필드 인 "hash_method"를 추가하여 기존 방법을 나타내는 1과 새 방법을 나타내는 2를 추가하는 것이 좋습니다.

합리적으로 말하면, 이런 종류의 일에 관심이 있고 응용 프로그램이 비교적 오래 지속되는 경우 (아마도 이미 존재하는 경우), 암호화 및 정보 보안이 진화하는 예측 불가능한 분야이므로 다시 발생할 수 있습니다. 해싱이 전혀 사용되지 않았다면 MD5를 통한 간단한 실행이 표준이었던 때가있었습니다! 그런 다음 SHA1을 사용해야한다고 생각할 수 있으며 이제 소금, 전역 소금 + 개별 무작위 소금, SHA3, 암호 해독 가능한 난수 생성 방법이 있습니다 ... 이것은 단지 '중지'하지 않을 것입니다. 확장 가능하고 반복 가능한 방식으로 수정하십시오.

자, 이제 당신은 (단순성을 위해 의사 자바 스크립트에서) 희망하는 것을 가지고 있다고 가정 해 봅시다.

var user = getUserByID(id);
var tryPassword = hashPassword(getInputPassword());


if (user.getPasswordHash() == tryPassword)
{
    // Authenticated!
}

function hashPassword(clearPassword)
{
    // TODO: Learn what "hash" means
    return clearPassword + "H@$I-I";
}

이제 더 좋은 방법이 있다는 것을 깨닫고 약간의 리팩토링을 제공하면됩니다.

var user = getUserByID(id);
var tryPassword = hashPassword(getInputPassword(), user.getHashingMethod());

if (user.getPasswordHash() == tryPassword)
{
    // Authenticated!
}

function hashPassword(clearPassword, hashMethod)
{
    // Note: Hash doesn't mean what we thought it did. Oops...

    var hash;
    if (hashMethod == 1)
    {
        hash = clearPassword + "H@$I-I";
    }
    else if (hashMethod == 2)
    {
        // Totally gonna get it right this time.
        hash = SuperMethodTheNSASaidWasAwesome(clearPassword);
    }
    return hash;
}

이 답변을 제작할 때 비밀 요원이나 프로그래머는 피해를 입지 않았습니다.


+1 이것은 상당히 합리적인 추상화처럼 보입니다. 감사합니다. 이것을 구현할 때 해시 및 해시 방법 필드를 별도의 테이블로 옮길 수 있습니다.
Willem

1
이 기술의 문제점은 계정이 로그인하지 않으면 해시를 업데이트 할 수 없다는 것입니다. 내 경험상 대부분의 사용자는 비활성 사용자를 삭제하지 않는 한 몇 년 동안 로그인하지 않습니다. 소금을 설명하지 않기 때문에 추상화도 실제로 작동하지 않습니다. 표준 추상화에는 검증과 작성을위한 두 가지 기능이 있습니다.
코드 InChaos

암호 해싱은 지난 15 년 동안 간신히 발전했습니다. Bcrypt는 1999 년에 출판되었으며 여전히 권장되는 해시 중 하나입니다. 그 이후로 한 가지 중요한 개선 사항이 발생했습니다. 순차적으로 메모리 하드 해시, scrypt가 개척했습니다.
코드 InChaos

예를 들어 누군가가 DB를 훔치는 경우 오래된 해시를 취약하게 만듭니다. 보다 안전한 새로운 방법으로 각 이전 해시를 해시하면 어느 정도이를 완화 할 수 있습니다 ( newHash(oldHash, salt)또는 여전히 구별하려면 해시 유형이 필요합니다)newHash(password, salt)
dbkk

42

가능한 빨리 모든 사용자에게 새 해싱 체계를 롤아웃하는 데 충분히 신경을 쓴다면 (예를 들어, 이전의 것이 실제로 안전하지 않기 때문에) 실제로 모든 암호 를 즉시 "이주"할 수있는 방법이 있습니다.

아이디어는 기본적으로 해시해시하는 것 입니다. p다음에 로그인 할 때 사용자가 기존 비밀번호 ( )를 제공하기를 기다리지 않고 기존 알고리즘 ( H2)에서 이미 생성 한 기존 해시 에서 새 해싱 알고리즘 ( )을 즉시 사용합니다 H1.

hash = H2(hash)  # where hash was previously equal to H1(p) 

해당 변환을 수행 한 후에도 여전히 암호 확인을 완벽하게 수행 할 수 있습니다. 사용자가 password로 로그인하려고 할 때마다 H2(H1(p'))이전 대신에 계산하면 됩니다 .H1(p')p'

이론적으로,이 기술은 다수의 마이그레이션 (적용 할 수있는 H3, H4등). 실제로 성능 및 가독성을 위해 이전 해시 함수를 제거하려고합니다. 다행스럽게도 다음과 같이 성공적인 로그인시 사용자 비밀번호의 새 해시를 계산하고 기존 해시 해시를 해당 비밀번호로 바꾸면됩니다.

hash = H2(p)

또한 저장중인 해시 (암호 중 하나 또는 이전 해시 중 하나)를 기억하려면 추가 열이 필요합니다. 불행히도 데이터베이스 유출의 경우이 열이 크래커의 작업을 더 쉽게 만들어서는 안됩니다. 값에 관계없이 공격자는 여전히 H2이전 보안 알고리즘 대신 보안 알고리즘 을 되돌려 야합니다 H1.


3
거대 +1 : H2 (H1 (p))는 H1이 끔찍한 경우에도 일반적으로 H2 (p)를 사용하는 것만 큼 안전합니다. MD5와 같은 "손상된"해시는 암호 해싱에 영향을 미치지 않습니다. 관련 : crypto.stackexchange.com/questions/2945/…
orip

흥미롭게도, 이전 해시를 해싱하면 일종의 보안 '문제'가 발생한다고 생각했습니다. 내가 착각 한 것 같습니다.
Willem

4
H1이 정말로 끔찍 하다면 이것은 안전하지 않습니다. 이 맥락에서 끔찍한 것은 대부분 입력에서 많은 엔트로피를 잃는 것에 관한 것입니다. MD4와 MD5조차도 이와 관련하여 거의 완벽 하므로이 접근법은 일부 홈 브루 해시 또는 실제로 짧은 출력 (80 비트 미만)을 가진 해시에만 안전하지 않습니다.
코드 InChaos

1
이 경우, 아마도 유일한 옵션 IS 당신이 망쳐 인정 하드 그냥 모든 사용자에게 가서 다시 암호를 입력합니다. 그 시점에서의 마이그레이션과 손상 관리에 관한 것이 아닙니다.
Xion

8

귀하의 솔루션 (데이터베이스의 추가 열)은 완벽하게 허용됩니다. 그것의 유일한 문제는 이미 언급 한 것입니다. 이전 해싱은 변경 이후 인증되지 않은 사용자에게 여전히 사용됩니다.

이러한 상황을 피하기 위해 가장 활동적인 사용자가 새로운 해싱 알고리즘으로 전환 할 때까지 기다릴 수 있습니다.

  1. 너무 오랫동안 인증하지 않은 사용자의 계정을 제거하십시오. 3 년 동안 웹 사이트를 방문한 적이없는 사용자의 계정을 제거해도 아무런 문제가 없습니다.

  2. 인증되지 않은 사용자 중 남은 사용자에게 전자 메일을 보내 새로운 무언가에 관심이 있다고 말하십시오. 이전 해싱을 사용하는 계정 수를 추가로 줄이는 데 도움이됩니다.

    주의 : 사용자가 웹 사이트에서 확인할 수있는 스팸 방지 옵션이 있으면이를 확인한 사용자에게 전자 메일을 보내지 마십시오.

  3. 마지막으로, 2 단계 후 몇 주 후에도 여전히 이전 기술을 사용중인 사용자의 비밀번호를 삭제하십시오. 인증을 시도 할 때 비밀번호가 유효하지 않은 것을 보게됩니다. 여전히 서비스에 관심이 있다면 재설정 할 수 있습니다.


1

아마도 해시 유형이 두 개 이상인 것은 아닐 것이므로 데이터베이스를 확장하지 않고도이 문제를 해결할 수 있습니다.

메소드의 해시 길이가 다르고 각 메소드의 해시 길이가 일정한 경우 (예 : md5에서 hmac-sha1로 전환) 해시 길이에서 메소드를 알 수 있습니다. 길이가 같은 경우 먼저 새 방법을 사용하여 해시를 계산 한 다음 첫 번째 테스트가 실패하면 이전 방법을 계산할 수 있습니다. 사용자가 마지막으로 업데이트 / 생성 된시기를 알려주는 필드 (표시되지 않음)가있는 경우이를 사용할 방법에 대한 지표로 사용할 수 있습니다.


1

나는 이와 같은 일을했고 그것이 새로운 해시인지 더 안전하게 만드는 방법이 있습니다. 해시를 업데이트하는 데 시간이 걸리면 더 안전하다고 생각합니다. ;-)

DB 테이블에 "salt"라는 새 열을 추가하고 사용자별로 무작위로 생성 된 소금으로 사용하십시오. (무지개 테이블 공격을 거의 방지합니다)

그렇게하면 내 암호가 "pass123"이고 임의의 소금이 3333이면 새 암호는 "pass1233333"의 해시가됩니다.

사용자가 소금을 가지고 있다면 새로운 해시임을 알 수 있습니다. 사용자의 소금이 null이면 이전 해시임을 알 수 있습니다.


0

마이그레이션 전략이 아무리 우수하더라도 데이터베이스를 이미 도난 당했거나 (이러한 적이 없다는 것을 부정적으로 입증 할 수없는 경우) 안전하지 않은 해시 기능으로 저장된 비밀번호가 이미 손상되었을 수 있습니다. 이를위한 유일한 완화 방법은 사용자가 비밀번호를 변경하도록 요구하는 것입니다.

코드를 작성하여 해결할 수있는 문제는 아닙니다. 해결책은 사용자와 고객에게 노출 된 위험에 대해 알리는 것입니다. 일단 공개하려는 경우, 가장 쉽고 안전한 솔루션이므로 모든 사용자의 비밀번호를 재설정하기 만하면 마이그레이션을 수행 할 수 있습니다. 모든 대안은 실제로 당신이 망친 사실을 숨기는 것에 관한 것입니다.


1
내가 과거에 한 가지 타협은 사람들이 로그인 할 때 오래된 비밀번호를 일정 시간 동안 유지하고 사람들이 다시 로그인 할 때 다시 해시하는 것이지만 그 시간이 지나면 로그인하지 않은 사람에게 비밀번호 재설정 강제 실행 그때. 따라서 보안이 취약한 기간이 있지만 시간이 제한되어 있으며 정기적으로 로그인하는 사용자의 혼란을 최소화합니다.
Sean Burton
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.