
Волшебные хэши – PHP-хэш «коллизии»
Зарегистрируйтесь с паролем 1, а затем войдите с паролем 2. Если вы вошли, значит, хранилище использует указанный алгоритм для хеширования пароля, а PHP сравнивает их с помощью == (для MD5, SHA-1 и обычного текста).
Для MD5, SHA-1 и используется давно известный трюк (на самом деле это документированная особенность, см. и ): для PHP , просто применяется это в целях. Любой пароль с любым другим паролем из списка. Это иной трюк, нежели , просто посмотрите на разницу между .
'0e1' == '00e2' == '0'Это все алгоритмы с magic-хешами:
md5(md5(password))Если процитировать @0xb0bb, «у magic-хешей есть и другие применения, помимо сравнения паролей (например, слои кэширования или данные, производные от вывода хеш-функции), где эти известные небезопасные, малоизвестные и псевдохеш-алгоритмы можно встретить чаще».
Для обычного текста используются различные трюки с преобразованием. Первый пароль будет совпадать только со вторым. Трюки сгруппированы по версиям PHP, в которых они работают.
bcrypt усекает пароли до максимальной длины 72 символов. Пароли совпадают, если первые 72 символа обоих паролей совпадают.
descrypt (традиционный UNIX DES crypt) усекает пароли до максимальной длины 8 символов. Пароли также совпадают, если первые 8 символов обоих паролей совпадают, см. раздел «Общая перекрёстная проверка».
Если вы используете пароль длиннее 64 байт и хешируете его с помощью PBKDF2-HMAC-SHA1, он сначала предварительно хешируется с помощью SHA1, поэтому PBKDF2-HMAC-SHA1(password1) === PBKDF2-HMAC-SHA1(password2), потому что sha1(password1) === bin2hex(password2). Аналогичное предварительное хеширование применяется для PBKDF2-HMAC-SHA224 и PBKDF2-HMAC-SHA256.
Сейчас в каждом из них есть лишь один magic-хеш благодаря Norbert Tihanyi, в будущем, надеюсь, их добавится больше.
Используйте === при сравнении чего-либо* в PHP, а не ==. И используйте password_hash() и password_verify() для хеширования паролей в PHP, не используйте MD5 или SHA-1. *Используйте hash_equals() при сравнении хешей.
Всё началось с этого твита. Я сгенерировал QNKCDZO и 240610708 в феврале 2014 года, и с тех пор это распространилось по всему интернету. Просто загуглите.
В 2014 году я использовал свой ноутбук, несколько циклов for (или foreach?), много циклов CPU и внешний вентилятор, но сегодня вы можете/должны использовать GPU и модифицированный hashcat. См. эту статью от Carl Löndahl и 0xb0bb.
Chick3nman и коллеги также работают над своей версией hashcat, следите за обновлениями.
Если вам нужна реальная буквенно-цифровая коллизия, вот 72-байтовая буквенно-цифровая MD5-коллизия с различием в 1 байт, даже в 1 бит, от Marc Stevens:
md5("TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak")
=
md5("TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak")
Обратите внимание: если вы регистрируетесь с первым паролем, а входите со вторым, это всё ещё может означать, что сайт использует bcrypt(md5($password)), а не просто md5($password). Такое обёртывание хеша иногда используется при обновлении хеширования паролей, но должно применяться только временно.
См. проект Marc HashClash, если вас интересуют эти реальные коллизии или если вы хотите создать свою собственную.
Реальные LM-коллизии от @solardiz (#35, спасибо!):
db82323cb0693862: 2275490 или 0/*LUZ@44b3b60db75c15c1: 2716388 или 1}DC<XT585e239d32df1998: 8351762 или $;)5D|XСм. этот твит о том, как сгенерировать ещё несколько.