Disclaimer. Я не «настоящий сварщик», но, в связи с поиском интересной работы в сфере информационной безопасности, в последнее время регулярно решаю разные CTF и машинки на HackTheBox. Поэтому, когда мне прислали ссылку на одно из тестовых заданий в стиле CTF, я не смог пройти мимо…

Смысл тестового задания достаточно простой. Дан дамп трафика, в котором спрятан ключ шифрования, некий мусор и зашифрованный флаг. Нужно их извлечь и расшифровать флаг. Также приведена команда 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. Через знакомых я уже сообщил разработчикам тестового о найденной проблеме, а то вдруг они очень удивляются, что это люди к ним не идут…

Смысл тестового задания достаточно простой. Дан дамп трафика, в котором спрятан ключ шифрования, некий мусор и зашифрованный флаг. Нужно их извлечь и расшифровать флаг. Также приведена команда OpenSSL, с помощью которой был зашифрован данный флаг. Трафик достаточно интересный, но уже через 10 строк кода на питоне передо мной лежал ключ шифрования, мусор и зашифрованный флаг. Казалось бы, что может пойти не так?
В задании сказано, что флаг был зашифрован приблизительно такой командой (некоторые несущественные параметры я опустил и изменил алгоритм шифрования).
echo "FLAG_xxxx…xxxxxx" | openssl enc -e -base64 -aes-256-cbc -nosalt -k $password Я вставил полученные из трафика параметры в команду, запустил и … получил мусор! Попробовал еще раз. Снова мусор. Попробовал пересобрать трафик разными способами. Нет, судя по всему, трафик собрат�� можно только однозначно. Но на выходе шифрования снова мусор!!! При этом OpenSSL честно предупреждает, что получать так ключ из пароля в 1 проход плохая идея…
echo "ENCRYPTED_FLAG" | openssl enc -d -base64 -aes-256-cbc -nosalt -k $key
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.Следующие сутки ушли в попытках взломать это безумие. Я разумно рассудил, что видимо я неправильно вычленил указанный в условиях «мусор» и написал несколько вариантов деления полученной строки на «пароль» и «зашифрованный флаг» для последующего «брутфорса». Не помогло… Начал глубоко разбираться в каждом из параметров.
Как мы знаем, для работы AES нужен ключ шифрования и IV (вектор инициализации). Параметр -k дает нам возможность использовать текстовую фразу, из которой уже сам OpenSSL получает нужный ключ и IV. Увидеть их можно с помощью параметра -p.
echo "FLAG_123" | openssl enc -e -base64 -aes-256-cbc -nosalt -p -k "password"
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
key=5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8
iv =3B02902846FFD32E92FF168B3F5D16B0
C11kA+GcqkU4ocOvZAVr3g==Это знание тоже ничего мне не дало. Тогда я всё же решил вернуться к самой безумной идее, которая возникала у меня. А именно: проблема не во мне, а что-то поменялось в OpenSSL…
Трафик датировался 2016 годом, поэтому я взял Ubuntu 14.04 и, без особой надежды на успех, просто вставил в неё первоначальные данные. И внезапно вместо мусора получил ФЛАГ! Вечер переставал быть томным… Более того, одна и та же команда с тем же паролем и параметром -p выдавала совершенно разные ключи шифрования и IV!
НОВАЯ СИСТЕМА (openssl 1.1.1h)
echo "FLAG_123" | openssl enc -e -base64 -aes-256-cbc -nosalt -p -k "password"
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
key=5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8
iv =3B02902846FFD32E92FF168B3F5D16B0
C11kA+GcqkU4ocOvZAVr3g==
СТАРАЯ СИСТЕМА (openssl 1.0.1f)
echo "FLAG_123" | openssl enc -e -base64 -aes-256-cbc -nosalt -p -k "password"
key=5F4DCC3B5AA765D61D8327DEB882CF992B95990A9151374ABD8FF8C5A7A0FE08
iv =B7B4372CDFBCB3D16A2631B59B509E94
R3N+5v3zOz9QcNt08cwqcA==Стало понятно, что опасения подтвердились. Изменился алгоритм генерации 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. Через знакомых я уже сообщил разработчикам тестового о найденной проблеме, а то вдруг они очень удивляются, что это люди к ним не идут…
