1. Бечеда за жизнь о криптах
Омар Ганиев
QIWI Friday Security Party
Москва, 2015
2. Дисклеймер
• Бечседа о криптах
• Я мало знаю о криптах
• Я мало находил багов в криптах в работе
• Хочу пожаловаться об этом
• И услышать success-story от вас =)
4. В игре
• В цтфах много хардкора, и есть
джентельменский набор криптоатак,
некоторые из которые встречаются с
завидной регулярностью
5. В игре
• Цезари, Виженеры, подстановки и т.д.
• Всевозможные глупые (или не очень) ксоры
да Вернамы
• Взлом RSA (атаки Винера, Франклина-
Райтера, Ферма, Копперсмита, …)
• Атака расширения длины для хеш-функций
• Атаки на эллиптические алгоритмы (типа
«быстрого» дискретного логарифма)
• Распаковка рюкзаков
6. В игре
• Разные оракулы в реализации, padding
oracle
• Линейный, дифференциальный
криптоанализ
• Логические атаки с блочными шифрами
(типа использования ECB или
неправильного порядка в EDE)
• Разбор каких-то неведомых алгоритмов и
прочие интересности
7. Жизнь – игра?
• Авторы тасков берут идеи вовсе не с
потолка, а подумав, какие могут быть
ошибки в реализации того или иного
алгоритма, либо найдя ошибки в
конкретном продукте
• Расскажите в конце, какие хардкорные
криптобаги, компрометирующие систему,
вы находили при анализе защищённости?
8. Жиза
• Пригодятся ли эти хардкорные тренировки
пентестовебоэникейщикам?
• Далее несколько примеров
околокриптографических багов, которые
мне доводилось обнаружить на пентестах
9. Умный брут
• Нет, не тот, который убил Цезаря
• Представьте себе форму авторизации в
ДБО, где часть логики зашита в JS
• Для сброса 8-циферного пароля
используется фиксированный ключ PIN2. У
него есть ограничения по формату, они
проверяются в JS
• Также в JS проверяется сложность пароля,
что отсеивает 1-2% плохих паролей
10. Умный брут
• При отправке PAN сервер зачем-то в ответ
отдаёт PIN2ENC = 3DES(PIN2,
hashwithmd5(salt, password))
• Поскольку PIN2 имеет определённый
формат, можно перебирать всевозможные
8-циферные пароли (кроме плохих),
дешифровать ими PIN2ENC и проверять
соответствие формату
• Статистика показала, что подходящих
паролей остаётся всего около 400 000
11. Умный брут
• Пусть в интернет-банке есть 100 000 юзеров.
На каждого есть 3 попытки ввода пароля
• Посчитаем вероятность того, что мы
взломаем хоть одну учётку, сделав 300 000
попыток:
>>> p=1/400000.+1/399999.+1/399998.
>>> 100-pow(1-p,100000)*100
52.76356614876912
• Итак, вероятность больше 50%, вин!
12. Оракул набивки
• А что если такой вот PIN2ENC, получаемый от
клиента, расшифровывался бы на сервере?
• Классический баг реализации блочного
шифрования с утечкой данных по побочному
каналу
• Периодически встречается на цтфах, чаще
всего в вебе
• Одна из наиболее прикладных криптоатак
(была в ASP.NET, например), но не слишком
частая
13. Оракул набивки
• Из жизни: хотите отписаться от рассылки?
Жмите на /unsubscribe?long_str_in_base64
• Хм, а флипнем последний бит
• 500? Padding Oracle!
• Если даже токен не содержит интересных
данных, а бит-флиппинг не позволяет
сделать какую-либо инъекцию, можно
расшифровывать любые другие данные,
получаемые от сервера
14. Некриптовые крипты
• Есть страшно баянистый факт из доков PHP,
который с завидной регулярностью всех
шокирует
• == не проверяет на идентичность в отличие от
===!
• true === “0” == “00e123123”
• Это всё лирика, а вот прикольно проверить это
в жизни, да ещё и блекбоксом, предположив,
что разрабы допустили ошибку
15. Некриптовые крипты
• /api/payment/?sum=1337&to=hacker&md5=
…
• Хм… Почитаем доки SDK для API платёжки
• Есть параметры, не влияющие на платёж,
но меняющие строку
• Фаззим, что туда можно подавать строки из
байтов от 32 до 128
• Регаем акк и получаем легитимный ключ
16. Некриптовые крипты
• Теперь нужен PoC. Если попытаться
комбинаторно прикинуть шансы на
эксплуатацию, получается не слишком
радужная картина
>>> 2**128 / sum([10**(30 - i) for i in xrange(30)])
306254130L
• Но почему-то на практике у меня
получается находить коллизии гораздо
быстрее, надо потестить статистику ещё
17. Некриптовые крипты
• Плевать на реальность, мы хотим PoC
• Берём ключ своего аккаунта, формируем
строку запроса к API, подлежащую подписи
• Берём степень свободы (дополнительный
ненужный параметр) и фаззим её, пока не
получится хеш вида ^0+ed+$
• Делаем это на плюсах с потоками:
https://github.com/beched/php_hash_collisio
n_finder
18. Некриптовые крипты
• Оп, получили строчку и пробуем что-то
вроде
/api/payment/?dummy=%40a`/&sum=1337&t
o=hacker&md5=0
• Вин! Значит, в коде написано ==, а не ===
• Сломали подпись для своего аккаунта,
значит, можем сломать для любого, заслав
дохреннилион запросов на сервак
20. Ода блокам
• Ode to ECB:
https://twitter.com/travisgoodspeed/status/6
17746044760268800
• Тривиальные с криптографической точки
зрения баги (уровня crypto100 на цтфах),
связанные с повторным использованием
шифроблоков, порой приводят к весёлым
последствиям
21. Ода блокам
• Снова представьте себе ДБО
• Там есть интерфейс перевода с карты, при
этом, то ли согласно правилам PCI, то ли по
ошибке платёжные данные зачем-то
сохраняются в сессии в зашифрованном
виде
• Сессия у многих фреймворков хранится у
клиента в куках (с подписью, конечно)
22. Ода блокам
• Итак, в сессии лежит
Crypto.encryptAES(userInput), при этом
валидации для userInput нет
• Представьте, что мобильный интерфейс
этого интернет-банка традиционно облегчил
аутентификацию и логинит без 2FA по токену
• Токен – это Crypto.encryptAES(login + “|” +
timestamp)
• Finita la commedia
23. Стенд-ап
• А теперь жду ваших рассказов, если вы
ещё/уже не совсем пьяны
• Или кидайте зиродеи сюда:
beched@incsecurity.ru
admin@ahack.ru