История одного «сломанного» тестового задания или осторожнее с версиями OpenSS

История одного «сломанного» тестового задания или осторожнее с версиями OpenSS
История одного «сломанного» тестового задания или осторожнее с версиями OpenSS

Смысл тестового задания достаточно простой. Дан дамп трафика, в котором спрятан ключ шифрования, некий мусор и зашифрованный флаг. Нужно их извлечь и расшифровать флаг. Также приведена команда OpenSSL, с помощью которой был зашифрован данный флаг. Трафик достаточно интересный, но уже через 10 строк кода на питоне передо мной лежал ключ шифрования, мусор и зашифрованный флаг. Казалось бы, что может пойти не так?

В задании сказано, что флаг был зашифрован приблизительно такой командой (некоторые несущественные параметры я опустил и изменил алгоритм шифрования).

Я вставил полученные из трафика параметры в команду, запустил и … получил мусор! Попробовал еще раз. Снова мусор. Попробовал пересобрать трафик разными способами. Нет, судя по всему, трафик собрать можно только однозначно. Но на выходе шифрования снова мусор!!! При этом OpenSSL честно предупреждает, что получать так ключ из пароля в 1 проход плохая идея…

Следующие сутки ушли в попытках взломать это безумие. Я разумно рассудил, что видимо я неправильно вычленил указанный в условиях «мусор» и написал несколько вариантов деления полученной строки на «пароль» и «зашифрованный флаг» для последующего «брутфорса». Не помогло… Начал глубоко разбираться в каждом из параметров.

Как мы знаем, для работы AES нужен ключ шифрования и IV (вектор инициализации). Параметр -k дает нам возможность использовать текстовую фразу, из которой уже сам OpenSSL получает нужный ключ и IV. Увидеть их можно с помощью параметра -p.

Это знание тоже ничего мне не дало. Тогда я всё же решил вернуться к самой безумной идее, которая возникала у меня. А именно: проблема не во мне, а что-то поменялось в OpenSSL…
Трафик датировался 2016 годом, поэтому я взял Ubuntu 14.04 и, без особой надежды на успех, просто вставил в неё первоначальные данные. И внезапно вместо мусора получил ФЛАГ! Вечер переставал быть томным… Более того, одна и та же команда с тем же паролем и параметром -p выдавала совершенно разные ключи шифрования и IV!

НОВАЯ СИСТЕМА (openssl 1.1.1h)

СТАРАЯ СИСТЕМА (openssl 1.0.1f)

Стало понятно, что опасения подтвердились. Изменился алгоритм генерации Key и IV из парольной фразы, что полностью сломало возможность «в лоб» решить CTF на современных версиях OpenSSL. В процессе поиска нюансов реализации я наткнулся на очень интересную работу «Password-based OpenSSL Encryption Analysis of Key Derivation Protocol» и всё стало на свои места. Вкратце, в версии 1.1.0 был добавлен новый протокол генерации ключей из пароля PBKDF2, но, что более важно в старом алгоритме PBKDF1 изменен алгоритм хеширования «по умолчанию» с MD5 на SHA-256! Таким образом, один и тот же пароль выдает разные Key и IV. Для того, чтобы расшифровать зашифрованное ранее, в новых версиях нужно использовать параметр -md md5.

“-md messagedigest: specify the message digest used for key derivation from md2, md5, sha, or sha1

После добавления этого параметра получить флаг стало возможно и на новом OpenSSL. Уж не знаю, действительно ли такой «нюанс» был учтен разработчиками тестового задания или они просто не проверяли его на современных системах, но факт остаётся фактом, пришлось глубоко погрузиться в некоторые тонкости OpenSSL.

P.S. Через знакомых я уже сообщил разработчикам тестового о найденной проблеме, а то вдруг они очень удивляются, что это люди к ним не идут…

источник