
Magic hashes – PHP 해시 '충돌'
password 1로 등록한 다음 password 2로 로그인해 보세요. 로그인에 성공한다면 저장소가 지정된 알고리즘으로 비밀번호를 해시하고 PHP가 ==를 사용해 비교한다는 뜻입니다(MD5, SHA-1 및 plaintext의 경우).
MD5, SHA-1 및 SHA-2 계열의 경우, 오래전부터 알려진 트릭을 사용합니다(실제로는 문서화된 기능입니다. PHP 유형 비교 표 및 부동 소수점 숫자를 참조하세요). PHP에서 '0e1' == '00e2' == '0'이라는 점을 실용적인 목적으로 이용하는 것입니다. 목록에 있는 어떤 비밀번호든 다른 비밀번호와 일치합니다. 이것은 정수 문자열이 부동 소수점 숫자로 오버플로되는 트릭과는 다른 것으로, 이 두 줄의 차이를 확인해 보세요.
다음은 magic hashes가 존재하는 모든 알고리즘입니다:
md5(md5(password))@0xb0bb의 말을 인용하자면, "magic hashes는 비밀번호 비교 외에도 다른 용도(예: 캐싱 레이어나 해시 함수 출력에서 파생된 데이터)가 있으며, 이러한 알려진 취약한 알고리즘, 덜 알려진 알고리즘, 의사 해시 알고리즘은 그런 곳에서 더 쉽게 발견할 수 있습니다."
plaintext의 경우 다양한 변환 트릭을 사용합니다. 첫 번째 비밀번호는 두 번째 비밀번호와만 일치합니다. 트릭은 이를 허용하는 PHP 버전별로 그룹화되어 있습니다.
bcrypt는 비밀번호를 최대 72자로 자릅니다. 두 비밀번호의 처음 72자가 일치하면 비밀번호가 일치합니다.
descrypt(전통적인 UNIX DES crypt)는 비밀번호를 최대 8자로 자릅니다. 두 비밀번호의 처음 8자가 일치하면 비밀번호도 일치합니다. "일반 교차 확인(General cross-check)" 섹션을 참조하세요.
64바이트보다 긴 비밀번호를 PBKDF2-HMAC-SHA1로 해시하면 먼저 SHA1로 *사전 해시(pre-hash)*되므로 sha1(password1) === bin2hex(password2)인 경우 PBKDF2-HMAC-SHA1(password1) === PBKDF2-HMAC-SHA1(password2)가 성립합니다. PBKDF2-HMAC-SHA224와 PBKDF2-HMAC-SHA256의 경우에도 유사한 사전 해시가 적용됩니다.
현재로서는 Norbert Tihanyi 덕분에 각각 하나의 magic hash만 있습니다. 앞으로 더 추가되기를 바랍니다.
PHP에서 무엇이든* 비교할 때는 ==가 아니라 ===를 사용하세요. 그리고 PHP에서 비밀번호 해싱에는 password_hash()와 password_verify()를 사용하고 MD5나 SHA-1은 사용하지 마세요. *해시를 비교할 때는 hash_equals()를 사용하세요.
이 트윗에서 모든 것이 시작되었습니다. 2014년 2월에 QNKCDZO와 240610708을 생성했고, 그 이후로 인터넷 전체에 퍼졌습니다. 그냥 검색해 보세요.