[security] 소금이 사전 공격을 ‘불가능’하게 만드는 이유는 무엇입니까?

업데이트 : 나는 소금이 무엇인지, 무지개 테이블이 무엇인지, 사전 공격이 무엇인지, 소금의 목적이 무엇인지 묻지 않습니다. 나는 질문하고 있습니다 : 사용자 솔트와 해시를 알고 있다면 암호를 계산하는 것이 쉽지 않습니까?

프로세스를 이해하고 일부 프로젝트에서 직접 구현합니다.

s =  random salt
storedPassword = sha1(password + s)

데이터베이스에 다음을 저장합니다.

username | hashed_password | salt

내가 본 모든 솔팅 구현은 비밀번호의 끝 또는 시작 부분에 솔트를 추가합니다.

hashed_Password = sha1(s + password )
hashed_Password = sha1(password + s)

따라서 소금 (ha ha)의 가치가있는 해커의 사전 공격은 위에 나열된 일반적인 조합으로 저장된 소금에 대해 각 키워드를 실행합니다.

확실히 위에서 설명한 구현은 근본적인 문제를 실제로 해결하지 않고 단순히 해커에게 또 다른 단계를 추가합니까? 이 문제를 해결할 수있는 대안이 있습니까? 아니면 문제를 오해하고 있습니까?

내가 생각할 수있는 유일한 일은 솔트와 비밀번호를 임의의 패턴으로 묶거나 해싱 프로세스에 다른 사용자 필드를 추가하는 비밀 블렌딩 알고리즘을 사용하는 것입니다. 즉, 해커가 데이터베이스에 액세스하고 코드를 묶어야한다는 의미입니다. 사전 공격을 통해 유익한 것으로 입증되었습니다. (댓글에서 지적했듯이 해커가 모든 정보에 액세스 할 수 있다고 가정하는 것이 가장 좋으므로 이것이 최선이 아닐 수 있습니다).

해커가 암호 및 해시 목록을 사용하여 사용자 데이터베이스를 해킹하는 방법에 대한 예를 들어 보겠습니다.

해킹 된 데이터베이스의 데이터 :

RawPassword (not stored)  |  Hashed   |     Salt
--------------------------------------------------------
letmein                       WEFLS...       WEFOJFOFO...

공통 암호 사전 :

   Common Password
   --------------
   letmein
   12345
   ...

각 사용자 레코드에 대해 공통 암호를 반복하고 해시합니다.

for each user in hacked_DB

    salt = users_salt
    hashed_pw = users_hashed_password

    for each common_password

        testhash = sha1(common_password + salt)
        if testhash = hashed_pw then
           //Match!  Users password = common_password
           //Lets visit the webpage and login now.
        end if

    next

next

이것이 내 요점을 훨씬 더 잘 보여주기를 바랍니다.

10,000 개의 공통 암호와 10,000 개의 사용자 레코드가 주어지면 가능한 많은 사용자 암호를 찾으려면 100,000,000 개의 해시를 계산해야합니다. 몇 시간이 걸릴 수 있지만 실제로는 문제가되지 않습니다.

크래킹 이론 업데이트

우리는 SHA1 해시와 솔트의 데이터베이스에 액세스 할 수있는 손상된 웹 호스트이며이를 혼합하는 알고리즘과 함께 있다고 가정합니다. 데이터베이스에는 10,000 개의 사용자 레코드가 있습니다.

이 사이트 는 GPU를 사용하여 초당 2,300,000,000 SHA1 해시를 계산할 수 있다고 주장합니다. (실제 상황에서는 아마도 더 느리 겠지만 지금은 인용 된 수치를 사용할 것입니다).

(((95 ^ 4) / 2300000000) / 2) * 10000 = 177 초

최대 길이가 4 자이고 계산 속도 (변수)로 나눈 값으로 나눈 95 개의 인쇄 가능한 ASCII 문자의 전체 범위가 10,000에 대해 2로 나눈 값 (암호 검색에 걸리는 평균 시간이 평균 순열의 50 %를 필요로한다고 가정) 사용자는 길이가 4 미만인 모든 사용자 암호를 계산하는 데 177 초가 걸립니다.

사실감을 위해 약간 조정 해 봅시다.

(((36 ^ 7) / 1000000000) / 2) * 10000 = 2 일

대소 문자를 구분하지 않고 암호 길이가 7 미만이고 영숫자 문자로만 가정하면 10,000 개의 사용자 레코드를 해결하는 데 4 일이 걸리며 오버 헤드와 비 이상적인 상황을 반영하기 위해 알고리즘 속도를 절반으로 줄였습니다.

이것은 선형적인 무차별 대입 공격이며 모든 계산은 서로 독립적이므로 여러 시스템에서 해결해야 할 완벽한 작업이라는 것을 인식하는 것이 중요합니다. (예외 시간의 절반이되는 서로 다른 끝에서 공격을 실행하는 2 대의 컴퓨터를 쉽게 설정할 수있는 IE).

이 작업을 계산적으로 더 비싸게 만들기 위해 암호를 1,000 번 재귀 적으로 해싱하는 경우를 고려합니다.

(((36 ^ 7) / 1000000000000) / 2) * 1000 초 = 10.8839117 시간

이는 한 명의 사용자에 대해 인용 된 숫자에서 절반 미만의 속도로 실행되는 최대 7 개의 영숫자 문자를 나타냅니다 .

재귀 적으로 1,000 회 해싱하면 포괄적 인 공격을 효과적으로 차단하지만 사용자 데이터에 대한 표적 공격은 여전히 ​​취약합니다.



답변

예, sha1 (salt | password)에 3 일만 있으면됩니다. 이것이 바로 좋은 암호 저장 알고리즘이 1000 회 반복 해싱을 사용하는 이유입니다. 8 년이 필요합니다.


답변

사전 공격을 중지하지 않습니다.

그것이하는 일은 암호 파일의 복사본을 관리하는 누군가가 무지개 테이블 을 사용 하여 해시에서 암호가 무엇인지 알아내는 것을 막는 것입니다 .

하지만 결국에는 무차별 대입이 될 수 있습니다. 이 부분에 대한 대답은 사용자가 사전 단어를 암호로 사용하지 않도록하는 것입니다 (예 : 최소 하나의 숫자 또는 특수 문자 요구 사항).

업데이트 :

앞서 언급 했어야했지만 일부 (대부분?) 암호 시스템은 각 암호에 대해 다른 솔트를 사용하며 아마도 암호 자체와 함께 저장됩니다. 이것은 하나의 무지개 테이블을 쓸모 없게 만듭니다. 이것이 UNIX crypt 라이브러리가 작동하는 방식이며 최신 UNIX 유사 OS는 새로운 해시 알고리즘으로이 라이브러리를 확장했습니다.

SHA-256 및 SHA-512에 대한 지원이 최신 버전의 GNU crypt에 추가되었다는 사실을 알고 있습니다.


답변

더 정확하게 말하면, 사전 공격 , 즉 완전한 목록의 모든 단어를 시도하는 공격은 “불가능”하지는 않지만 비실용적입니다 . 각 소금은 필요한 저장 및 계산 양을 두 배로 늘립니다 .

이것은 소금이 비밀인지 여부가 중요하지 않은 레인보우 테이블과 관련된 공격과 같은 사전 계산 된 사전 공격과 다릅니다.

예 : 64 비트 솔트 (예 : 8 바이트)를 사용하면 사전 공격에서 2 64 개의 추가 암호 조합 을 확인해야합니다 . 200,000 단어가 포함 된 사전을 사용하면

200,000 * 2 64 = 3.69 * 10 24

최악의 경우 테스트-소금없이 200,000 테스트 대신.

솔트 사용의 또 다른 이점은 공격자가 사전에서 암호 해시를 미리 계산할 수 없다는 것입니다. 너무 많은 시간 및 / 또는 공간이 필요합니다.

최신 정보

업데이트는 공격자가 이미 솔트를 알고 있거나 훔쳤다고 가정합니다. 물론 이것은 다른 상황입니다. 여전히 공격자가 미리 계산 된 레인보우 테이블을 사용하는 것은 불가능합니다. 여기서 중요한 것은 해싱 함수의 속도입니다. 공격을 비실용적으로 만들려면 해싱 기능이 느려 야합니다. MD5 또는 SHA는 빠르도록 설계 되었기 때문에 여기에서 좋은 후보가 아닙니다. 해싱 알고리즘에 대한 더 나은 후보는 Blowfish 또는 일부 변형입니다.

업데이트 2

일반적으로 암호 해시 보안 문제에 대한 좋은 읽기 (원래 질문을 훨씬 넘어서지 만 여전히 흥미 롭습니다) :

Rainbow Tables로 충분 : 보안 암호 체계에 대해 알아야 할 사항

기사의 결과 : bcrypt (Blowfish 기반) 또는 Eksblowfish로 만든 솔트 해시 를 사용하여 구성 가능한 설정 시간을 사용하여 해싱 속도를 늦출 수 있습니다.


답변

사전은 값이 키로 인덱싱되는 구조입니다. 사전 계산 된 사전 공격의 경우 각 키는 해시이고 해당 값은 해시를 생성하는 암호입니다. 사전 계산 된 사전을 손에 들고 공격자는 로그인에 필요한 해시를 생성하는 암호를 “즉시”조회 할 수 있습니다.

솔트를 사용하면 사전을 저장하는 데 필요한 공간이 빠르게 증가합니다. 너무 빠르게 암호 사전을 미리 계산하려는 시도가 곧 무의미 해집니다.

최고의 솔트는 암호화 난수 생성기에서 무작위로 선택됩니다. 8 바이트는 실제 크기이며 16 바이트 이상은 용도가 없습니다.


소금은 단순히 “공격자의 일을 더 짜증나게 만드는 것”이상의 역할을합니다. 사전 계산 된 사전 사용과 같은 전체 공격 클래스를 제거합니다.

암호를 완벽하게 보호하려면 또 다른 요소가 필요합니다. 바로 “키 강화”입니다. SHA-1 한 라운드로는 충분하지 않습니다. 안전한 암호 해싱 알고리즘은 계산 속도 매우 느려 .

많은 사람들이 결과를 해시 함수에 피드백하는 키 파생 함수 인 PBKDF2를 사용합니다. 수천 번 합니다. “bcrypt”알고리즘은 유사하며 느린 반복 키 파생을 사용합니다.

해싱 작업이 매우 느리면 미리 계산 된 테이블이 공격자에게 점점 더 바람직해집니다. 그러나 적절한 소금은 그러한 접근 방식을 이깁니다.


코멘트

아래는 질문에 대한 의견입니다.


솔트가 없으면 공격자는 “업데이트 2″에 설명 된 방법을 사용하지 않습니다. 그는 단순히 미리 계산 된 테이블에서 조회를 수행하고 O (1) 또는 O (log n) 시간 (n은 후보 암호 수)에 암호를 얻습니다. Salt는이를 방지하고 “Update 2″에 표시된 O (n) 접근 방식을 사용하도록합니다.

O (n) 공격으로 축소되면 각 시도에 걸리는 시간을 고려해야합니다. 키 강화는 루프의 각 시도에 1 초가 걸릴 수 있습니다. 즉, 1 만 명의 사용자에 대해 1 만 개의 암호를 테스트하는 데 필요한 시간이 3 일에서 3 년으로 늘어납니다 .… 그리고 1 만 개의 암호만으로도 제로 크랙이 발생할 가능성이 높습니다. 그 시간에 암호.

공격자는 PHP가 아닌 가장 빠른 도구를 사용할 것임을 고려해야합니다. 따라서 100 번이 아닌 수천 번의 반복이 키 강화를위한 좋은 매개 변수가 될 것입니다. 단일 암호에 대한 해시를 계산하는 데는 1 초의 많은 시간이 걸립니다.

키 강화는 PKCS # 5의 표준 키 파생 알고리즘 PBKDF1 및 PBKDF2의 일부로, 훌륭한 암호 난독 화 알고리즘을 만듭니다 ( “파생 키”는 “해시”임).

StackOverflow의 많은 사용자 가이 기사를 참조하는 이유는 레인보우 테이블의 위험성에 대한 Jeff Atwood의 게시물에 대한 답변 이었기 때문입니다. 내가 가장 좋아하는 기사는 아니지만 이러한 개념에 대해 자세히 설명합니다.


물론 공격자가 솔트, 해시, 사용자 이름 등 모든 것을 가지고 있다고 가정합니다. 공격자가 myprettypony.com 팬 사이트의 사용자 테이블을 버린 부패한 호스팅 회사 직원이라고 가정합니다. 그는 돌아 서서 당신의 조랑말 팬들이 그들의 citibank.com 계정에서 동일한 암호를 사용했는지 확인할 것이기 때문에 이러한 암호를 복구하려고합니다.

잘 설계된 암호 체계로, 그것은 것 없는 이 사람이 어떤 암호를 복구하기.


답변

염분의 요점은 공격자의 노력이 상각되는 것을 방지하는 것입니다.

솔트없이 미리 계산 된 해시-암호 항목의 단일 테이블 (예 : 모든 영숫자 5 개 문자열의 MD5, 온라인에서 쉽게 찾을 수 있음)을 전 세계 모든 데이터베이스의 모든 사용자에게 사용할 수 있습니다.

사이트 별 솔트를 사용하여 공격자는 테이블을 직접 계산 한 다음 사이트의 모든 사용자에게 사용할 수 있습니다.

사용자 별 솔트를 사용하면 공격자는 모든 사용자를 위해 이러한 노력을 개별적으로 소비해야합니다.

물론 이것은 사전에있는 정말 약한 암호를 보호하는 데 많은 역할을하지 않지만, 이러한 상각으로부터 합리적으로 강력한 암호를 보호합니다.


답변

또한-한 가지 더 중요한 점-USER 특정 솔트를 사용하면 동일한 암호를 사용하는 두 명의 사용자가 감지되지 않습니다-해시가 일치합니다. 그래서 해시는 해시 (salt + username + password) 인 경우가 많습니다.

해시 비밀을 유지하려고하면 공격자가 해시를 확인할 수도 없습니다.

편집-위의 주석에서 요점이 작성되었음을 알았습니다.


답변

레인보우 테이블 공격을 방지하기 위해 솔트가 구현됩니다. 무지개 테이블은 미리 계산 된 해시 목록으로, 해시를 구문으로 훨씬 더 간단하게 변환 할 수 있습니다. 최신 해싱 알고리즘이 없으면 솔팅이 암호 크래킹에 대한 현대적인 예방책으로 효과적이지 않다는 것을 이해해야합니다.

따라서 우리가이 알고리즘으로 발견 된 최근 익스플로잇을 활용하여 SHA1을 사용하고 있다고 가정 해 보겠습니다. 컴퓨터가 초당 1,000,000 해시로 실행되고 있다고 가정 해 보겠습니다 . 충돌을 찾는 데 530 만 년이 걸립니다. . 그래서 예 php 1 초에 300 번 일할 수 있습니다. 우리가 염두에 두는 이유는 누군가가 모든 일반적인 사전 구문을 생성하려고했다면 (2 ^ 160 명, 2007 시대의 공격에 오신 것을 환영합니다) 때문입니다.

여기에 테스트 및 관리 목적으로 사용하는 2 명의 사용자가있는 실제 데이터베이스가 있습니다.

RegistrationTime        UserName        UserPass
1280185359.365591       briang      a50b63e927b3aebfc20cd783e0fc5321b0e5e8b5
1281546174.065087       test        5872548f2abfef8cb729cac14bc979462798d023

실제로 솔팅 방식은 sha1 (등록 시간 + 사용자 이름)입니다. 계속해서 내 비밀번호를 알려주세요. 이건 프로덕션의 실제 비밀번호입니다. 거기에 앉아서 PHP로 단어 목록을 해시 할 수도 있습니다. 야생으로 가십시오.

나는 미쳤지 않고 이것이 안전하다는 것을 알고 있습니다. 재미를 위해 테스트 비밀번호는test 입니다.
sha1(sha1(1281546174.065087 + test) + test) = 5872548f2abfef8cb729cac14bc979462798d023

다음과 같이 전체 무지개 테이블을 생성해야합니다. 27662aee8eee1cb5ab4917b09bdba31d091ab732 위해 단지 이 사용자를. 즉, 실제로 내 비밀번호가 단일 레인보우 테이블에 의해 손상되지 않도록 허용 할 수 있으며, 해커는 테스트를 위해 27662aee8eee1cb5ab4917b09bdba31d091ab732에 대해 전체 레인보우 테이블을 생성하고 briang에 대해 다시 f3f7735311217529f2e020468004a2aa5b3dee7f를 생성해야합니다. 모든 해시에 대해 530 만 년을 생각해보십시오. 2 ^ 80 개의 해시 (20 yottabytes가 훨씬 넘음 ) 만 저장하는 크기를 생각해보십시오 . 그렇게되지 않을 것입니다.

해독 할 수없는 해시를 만드는 수단으로 솔팅을 혼동하지 마십시오. 레인보우 테이블이 모든 사용자 암호 를 번역하지 못하도록 방지하는 수단입니다 . 이 수준의 기술에서는 불가능합니다.