모범 사례 : 비밀번호에 소금을 칠하고 후추 칠하는 방법


145

나는 내가하고있는 일이 실제로 암호에 소금을 뿌리는 것이 아니라 후추를 뿌리는 것이라는 것을 알게 된 토론을 보았습니다.

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

선택한 해시 알고리즘을 무시합니다 (이것은 소금과 후추에 대한 토론이며 특정 알고리즘은 아니지만 안전한 알고리즘을 사용하고 싶습니다), 이것은 안전한 옵션입니까 아니면 다른 일을해야합니까? 용어에 익숙하지 않은 사람들을 위해 :

  • 소금은 보통 불가능 암호를 해독하기 위해 해시 테이블을 사용 할 수 있도록 설계 데이터베이스의 문자열로 저장 무작위로 생성 된 값입니다. 각 암호에는 고유 한 소금이 있으므로 암호를 해독하려면 모두 개별적으로 무차별 적으로 시행해야합니다. 그러나 소금이 암호 해시와 함께 데이터베이스에 저장되므로 데이터베이스 손상은 두 가지를 모두 잃는 것을 의미합니다.

  • 고추는 비밀하기위한 것입니다 (일반적으로 응용 프로그램의 소스 코드에 하드 코딩) 데이터베이스에 별도로 저장 사이트 전체 정적 값입니다. 데이터베이스가 손상되어 전체 응용 프로그램의 암호 테이블이 무차별 화되지 않도록 사용됩니다.

내가 잃어버린 것이 있습니까? 비밀번호를 소금에 절인 후 후추 칠하는 것이 사용자의 보안을 보호하는 가장 좋은 옵션입니까? 이 방법으로 수행 할 수있는 잠재적 인 보안 결함이 있습니까?

참고 : 토론의 목적으로 응용 프로그램 및 데이터베이스가 별도의 컴퓨터에 저장되어 있고 암호 등을 공유하지 않아야하므로 데이터베이스 서버의 위반이 자동으로 응용 프로그램 서버의 위반을 의미하지는 않습니다.


3
아니 중복,하지만 매우 관련 : stackoverflow.com/questions/16594613/...은
ircmaxell

2
교차 사이트 복제 : security.stackexchange.com/q/3272/2113
Jacco

답변:


307

확인. 나는 이것에 대해 쓸 필요로 보는 이상이상 , 나 혼자 고추에 마지막 정규 대답을 할 것이다.

고추의 명백한 거꾸로

고추가 해시 함수를 더 안전하게 만들어야한다는 것은 분명합니다. 공격자가 데이터베이스 만 가져 오면 사용자 암호는 안전해야합니다. 논리적 인 것 같습니까?

그래서 많은 사람들이 고추가 좋은 생각이라고 믿습니다. 말이 되는군요".

고추의 현실

보안 및 암호화 영역에서는 "이해하기"만으로는 충분하지 않습니다. 뭔가 증명할 수 있어야 하고 이 안전한 것으로 간주되는 순서를 의미합니다. 또한 유지 관리 가능한 방식으로 구현할 수 있어야합니다. 유지 관리 할 수없는 가장 안전한 시스템은 안전하지 않은 것으로 간주됩니다 (보안의 일부가 고장 나면 전체 시스템이 분리되므로).

후추는 입증 가능한 모델이나 유지 보수 가능한 모델에 맞지 않습니다 ...

고추의 이론적 문제

이제 무대를 설정 했으므로 고추의 문제점을 살펴 보겠습니다.

  • 하나의 해시를 다른 해시에 공급하는 것은 위험 할 수 있습니다.

    귀하의 예에서는을 수행 hash_function($salt . hash_function($pepper . $password))합니다.

    우리는 과거의 경험을 통해 하나의 해시 결과를 다른 해시 함수에 "그냥 공급"하면 전반적인 보안이 저하 될 수 있음을 알고 있습니다. 그 이유는 두 해시 함수가 모두 공격의 대상이 될 수 있기 때문입니다.

    그렇기 때문에 PBKDF2 와 같은 알고리즘은 특수 연산을 사용하여 결합합니다 (이 경우 hmac).

    요점은 큰 문제는 아니지만 그냥 버리는 것이 사소한 일이 아니라는 것입니다. 암호화 시스템은 "작동해야하는"사례를 피하기 위해 설계되었으며 대신 "작동하도록 설계된"사례에 중점을 둡니다.

    이것은 순전히 이론적으로 보이지만 실제로는 그렇지 않습니다. 예를 들어 Bcrypt는 임의의 비밀번호를 허용 할 수 없습니다 . 따라서 전달 bcrypt(hash(pw), salt)하면 실제로 이진 문자열을 반환하는 bcrypt(pw, salt)경우 보다 훨씬 약한 해시가 발생할 수 있습니다 hash().

  • 디자인에 대한 작업

    bcrypt (및 기타 비밀번호 해싱 알고리즘)가 설계된 방식은 솔트를 사용하는 것입니다. 고추의 개념은 소개되지 않았습니다. 이것은 사소한 것처럼 보이지만 그렇지 않습니다. 그 이유는 소금이 비밀이 아니기 때문입니다. 공격자에게 알려진 값일뿐입니다. 반면에 후추는 암호화의 비밀입니다.

    현재 비밀번호 해싱 알고리즘 (bcrypt, pbkdf2 등)은 모두 하나의 비밀 값 (비밀번호) 만 사용하도록 설계되었습니다. 알고리즘에 다른 비밀을 추가하는 것은 전혀 연구되지 않았습니다.

    그렇다고 안전하지 않다는 의미는 아닙니다. 그것은 우리가 안전한지 모른다는 것을 의미합니다. 그리고 보안 및 암호화에 대한 일반적인 권장 사항은 우리가 모른다면 그렇지 않다는 것입니다.

    따라서 비밀 값 (고추)과 함께 사용하기 위해 암호 작성자가 알고리즘을 설계하고 검사 할 때까지 현재 알고리즘을 사용해서는 안됩니다.

  • 복잡성은 보안의 적입니다

    믿거 나 말거나, 복잡성은 보안의 적 입니다. 복잡해 보이는 알고리즘을 만드는 것은 안전하거나 그렇지 않을 수 있습니다. 그러나 안전하지 않을 가능성은 매우 높습니다.

고추의 중요한 문제

  • 유지할 수 없습니다

    페퍼를 구현하면 페퍼 키를 회전시킬 수 없습니다. 후추는 단방향 함수의 입력에 사용되므로 값의 수명 동안 후추를 변경할 수 없습니다. 즉, 키 회전을 지원하기 위해 약간의 해킹이 필요합니다.

    이다 매우 당신이 암호의 비밀을 저장할 때마다이 필요한 것으로 중요합니다. 주기적으로 그리고 위반 후 키를 회전시키는 메커니즘이없는 것은 큰 보안 취약점입니다.

    그리고 현재의 후추 접근 방식은 모든 사용자가 회전에 의해 암호를 완전히 무효화하거나 다음 로그인이 회전 할 때까지 기다려야합니다 (절대 절대는 아닙니다) ...

    기본적으로 귀하의 접근 방식은 즉각적으로 진행됩니다.

  • 자신의 암호를 굴려야합니다.

    현재 고추는 고추의 개념을 지원하지 않으므로 고추를 지원하기 위해 알고리즘을 구성하거나 새로운 알고리즘을 발명해야합니다. 그리고 왜 이것이 정말 나쁜지 즉시 볼 수 없다면 :

    가장 단서가없는 아마추어에서 최고의 암호 전문가에 이르기까지 누구나 자신이 깰 수없는 알고리즘을 만들 수 있습니다.

    자신의 암호를 굴리지 마십시오 ...

더 나은 방법

따라서 위에서 설명한 모든 문제 중에서 상황을 처리하는 두 가지 방법이 있습니다.

  • 알고리즘을 그대로 사용하십시오.

    bcrypt 또는 scrypt를 올바르게 사용하면 (고비용으로) 가장 약한 사전 암호를 제외한 모든 암호가 통계적으로 안전해야합니다. 비용이 5 인 해시 bcrypt의 현재 레코드는 초당 71k 해시입니다. 이 속도에서 6 자 임의의 암호조차도 몇 년이 걸릴 것입니다. 그리고 최소 권장 비용이 10 인 것을 고려하면 초당 해시가 32 배로 줄어 듭니다. 따라서 초당 약 2200 개의 해시 만 말하고 있습니다. 그 속도로, 일부 사전 문구 나 변형어도 안전 할 수 있습니다.

    또한, 약한 비밀번호 클래스를 확인해야하며 비밀번호를 입력하지 않아야합니다. 비밀번호 크래킹이 발전함에 따라 비밀번호 품질 요구 사항도 높아야합니다. 그것은 여전히 ​​통계 게임이지만 적절한 저장 기술과 강력한 암호를 사용하면 모든 사람들이 실제로 매우 안전해야합니다 ...

  • 저장하기 전에 출력 해시 암호화

    위에서 언급 한 모든 것을 처리하도록 설계된 알고리즘이 보안 영역에 존재합니다. 블록 암호입니다. 가역적이므로 키를 회전시킬 수 있습니다 (예 : 유지 관리 성!). 설계된대로 사용되기 때문에 좋습니다. 사용자에게 정보를 제공하지 않기 때문에 좋습니다.

    그 줄을 다시 봅시다. 공격자가 알고리즘을 알고 있다고 가정합니다 (보안에 필요하며, 그렇지 않으면 모호함을 통한 보안). 전통적인 후추 접근 방식으로 공격자는 센티넬 암호를 만들 수 있으며 소금과 출력을 알고 있기 때문에 후추를 무차별하게 만들 수 있습니다. 좋아, 그것은 긴 일이지만 가능하다. 암호로 공격자는 아무것도 얻지 못합니다. 그리고 소금이 무작위이기 때문에 센티넬 암호는 그를 도울 수조차 없습니다. 따라서 그들이 남는 최선은 암호화 된 형식을 공격하는 것입니다. 즉, 암호화 키를 복구하려면 먼저 암호화 된 해시를 공격 한 다음 해시를 공격해야합니다. 그러나 암호의 공격에 대한 많은 연구가 있으므로 우리는 그것에 의존하고 싶습니다.

TL / DR

고추를 사용하지 마십시오. 여기에는 많은 문제가 있으며 두 가지 더 좋은 방법이 있습니다. 서버 측 암호를 사용하지 않고 (예, 괜찮습니다) 저장하기 전에 블록 암호를 사용하여 출력 해시를 암호화합니다.


6
해시 값 암호화의 마지막 부분을 포함 해 주셔서 감사합니다. 이것이 전적으로 동의 할 수있는 답변입니다. 암호화가 비밀번호 api의 일부 가된다면, 그것을 사용하지 않을 이유가 없을 것입니다. 어쩌면 ... (문서를 작성하고
싶습니다

2
@ martinstoeckli : 단순화 된 해싱 API에 암호화 단계를 추가하는 것에 동의하지 않습니다. 그 이유는 비밀 (키) 저장이 사람들이 생각하는 것보다 훨씬 어렵 기 때문에 발로 자신을 쏠 수 있기 때문입니다. 99.9 %의 사용자에게있어 원시 bcrypt는 가장 단순한 암호를 제외한 모든 암호에 충분합니다.
ircmaxell

7
@ircmaxell-다른 한편으로는 아무것도 풀지 않을 것입니다. 최악의 경우 키가 알려지면 공격자는 여전히 BCrypt 해시를 해독해야합니다 (암호화가없는 것과 동일한 상황). 이것은 데이터 암호화를위한 키를 저장하는 것과 같지 않습니다. 이것은 서버 측 암호를 추가하는 것입니다. 공격자가 서버 / 코드를 제어 할 수없는 한 하드 코드 된 키조차도 약한 암호를 보호합니다. 이러한 상황은 드문 일이 아닙니다. SQL 주입 외에도 백업을 버리고 서버를 버리는 등…이 상황이 발생할 수 있습니다. 많은 PHP 사용자가 호스트 서버에서 작업합니다.
martinstoeckli 2016 년

2
@ martinstoeckli 여기서 ircmaxwell에 동의해야합니다. 암호는 암호 API에 속한다고 생각하지 않습니다. 그러나 최대 보안 암호화를 위해 해시를 사용할 수있는 추가 조항이 있습니다.
foochow 2016 년

저장하기 전에 출력의 암호화에 관한 질문이 있습니다. 내가 실수하지 않으면 암호화 키는 일반적으로 메시지를 고유하게 또는 일시적으로 암호화하는 데 사용됩니다. 그러나 200,000 개의 사용자 암호가 모두 동일한 키로 암호화되어 함께 저장되어 있으면 키를 쉽게 공격 할 수 있습니까? 이제 1 또는 2에 비해 200,000 개의 메시지가 있습니다.
AgmLauncher

24

주먹 고추정확한 장점에 대해 이야기해야합니다 .

  • Pepper는 공격자가 데이터베이스 (해시 포함)에 대한 읽기 액세스 권한을 갖지만 Pepper로 소스 코드에 액세스 할 수없는 특수한 경우 사전 공격으로부터 취약한 비밀번호를 보호 할 수 있습니다.

일반적인 시나리오는 SQL 주입, 백업 버리기, 서버 폐기 등입니다. 이러한 상황은 들리는 것처럼 드문 일이 아니며 종종 제어 (서버 호스팅) 상태가 아닙니다. 당신이 사용하는 경우 ...

  • 비밀번호 당 고유 한 소금
  • BCrypt와 같은 느린 해싱 알고리즘

... 강력한 암호는 잘 보호됩니다. 소금이 알려진 경우에도 이러한 조건에서 강력한 암호를 무차별 처리하는 것은 거의 불가능합니다. 문제는 취약한 암호로, 무차별 사전의 일부이거나 파생 된 암호입니다. 가장 일반적인 비밀번호 만 테스트하기 때문에 사전 공격은 매우 빠른 속도로이를 공개합니다.

두 번째 질문은 고추를 적용하는 방법입니다 .

후추를 적용하는 데 자주 권장되는 방법은 비밀번호와 후추를 해시 함수에 전달하기 전에 결합하는 것입니다.

$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);

그래도 더 좋은 방법이 있습니다.

$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);

이를 통해 서버 측 비밀을 추가 할 수있을뿐만 아니라 $ serverSideKey를 교환 할 수도 있습니다. 이 방법에는 약간의 작업이 필요하지만 코드가 한 번 존재하면 (라이브러리) 사용하지 않을 이유가 없습니다.


고추가 소금보다 안전을 더한다고 하시겠습니까? 구현 방법에 대한 도움을 주셔서 감사합니다.
글리치 욕망

1
@LightningDust-예. 후추가 비밀로 유지되는 한 암호가 약합니다. 잘 정의 된 위협 유형을 완화합니다.
martinstoeckli 2016 년

@martinstoeckli는 확실히 이것을 구현하는 좋은 방법입니다. 보안 경험이있는 사람이이 방법을 지원한다는 것을 알게되어 기쁩니다. MySQL AES_ENCRYPT($passwordHash, $serverSideKey)호출도 이것을 구현하는 적절한 방법일까요?
foochow

1
@Foo_Chow-MySQL 함수의 구현을 모르지만 IV- 벡터를 피하기 위해 EBC 모드를 사용한 것 같습니다. 알려진 일반 텍스트 (해시 값은 항상 같은 문자로 시작)와 함께 문제가 될 수 있습니다. 내 홈페이지 에서이 암호화를 처리하는 구현 예제를 게시했습니다.
martinstoeckli 2016 년

@martinstoeckli 흥미롭고 개념에 너무 익숙하지 않습니다. 그러나 가장 강력한 결과를 얻으려면 IV가 바람직 할 것 같습니다. 추가 혜택에 많은 오버 헤드가 추가되지 않는 것 같습니다.
foochow

2

소금과 후추의 요점은 레인보우 테이블이라는 미리 계산 된 비밀번호 조회 비용을 높이는 것입니다.

일반적으로 단일 해시에 대한 충돌을 찾으려고 시도하는 것은 어렵습니다 (해시가 안전하다고 가정). 그러나 짧은 해시의 경우 컴퓨터를 사용하여 가능한 모든 해시를 하드 디스크 조회로 생성 할 수 있습니다. 이것을 레인보우 테이블이라고합니다. 무지개 테이블을 만들면 세계로 나가서 (고염되지 않은) 해시에 대한 그럴듯한 암호를 신속하게 찾을 수 있습니다.

고추의 요점은 암호 목록을 해킹하는 데 필요한 무지개 테이블을 고유하게 만드는 것입니다. 따라서 레인보우 테이블을 구성하기 위해 공격자에게 더 많은 시간을 낭비합니다.

그러나 소금의 요점은 각 사용자의 레인보우 테이블을 사용자에게 고유하게 만들어 공격의 복잡성을 더욱 증가시키는 것입니다.

실제로 컴퓨터 보안의 요점은 수학적으로나 실제로는 비현실적으로 (수학적으로) 불가능하게 만드는 것이 아니며 (예를 들어 안전한 시스템에서 단일 사용자의 암호를 계산하려면 우주의 모든 엔트로피가 필요합니다).


그렇다면 salt + pepper는 단순한 소금보다 더 많은 안전성을 제공합니까? 아니면 후추를 떨어 뜨리고 더 많은 반복을 실행하는 것이 더 좋을까요?
글리치 욕망

2
레인보우 테이블의 주요 특징은 특정 공격에 대해 생성하지 않고 기존 테이블을 다운로드한다는 것입니다. Google에서 멀리 떨어진 인기있는 해시 알고리즘에 사용할 수있는 긴 레인보우 테이블이 있습니다!
Richard

1
@LightningDust 나는 어떤 이유도 생각할 수 없다. 그러나 다른 스레드에서 Richard는 하나를 생각해 냈습니다. 소스 코드에서 후추를 숨길 수 있습니다. 즉, 레인보우 테이블을 얻기 위해 공격자가 액세스해야하는 다른 장소를 의미합니다.
Aron

@Aron-데이터베이스 서버와 분리 된 응용 프로그램 서버가 있기 때문에 (즉, rootDB 서버에 접속해도 응용 프로그램 서버에 액세스 할 수 없음) 소스 코드에 후추를 숨기고 있다고 생각했습니다. 구성 파일)은 추가 보안을 제공합니다.
글리치 욕망

1

보안 관련성이있는 것으로 소스 코드에 하드 코드 된 값을 저장하는 것을 볼 수 없습니다. 모호함을 통한 보안입니다.

해커가 데이터베이스를 획득하면 사용자 암호를 무차별 적으로 시작할 수 있습니다. 암호를 해독하는 해커가 후추를 식별하는 데 시간이 오래 걸리지 않습니다.


1
무염 암호 테이블에 대해 미리 계산 된 레인보우 테이블을 쓸모 없게 만듭니다. 간단히 말해서 공격자가 후추를 알고 있어도 새로운 무지개 테이블을 만들어야합니다.
Aron

3
데이터베이스에서 사용할 수없는 데이터를 기반으로 해시를 강화합니다. 데이터베이스에있는 것은 취약점으로 드러날 수 있습니다. 코드의 값이 같은 방식으로 액세스 될 가능성은 적습니다.
Richard

소금은 일방 통행 기능이며, 암호를 성공적으로 무차별 적으로 적용해도 암호 만 제공 할 수 있으며 후추 값 자체를 얻는 데 도움이되지 않습니다.
글리치 욕망

1
@LightningDust 당신은 "해쉬 트랩 기능"을 의미한다고 생각합니다. 예. 안전한 해시 (실제로 보안 해시의 정의)에서 소금 및 / 또는 후추를 알아내는 것은 불가능합니다.
Aron

6
@Aron Security Through Obscurity는 방어 계층으로 사용되는 유효한 기술 일 수 있습니다. 요점은 방어 수단에 의존 해서는 안되며 대신 "공격자를 늦추는"데 사용된다는 것입니다. 그렇지 않은 경우 허니팟과 같은 것이 사용되지 않습니다. 대신, 애플리케이션의 보안에 의존하지 않는 한, 모호함을 통해 보안을 효과적으로 활용하여 공격자의 속도를 늦출 수 있습니다.
ircmaxell
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.