суббота, 31 октября 2015 г.

Weak IV in CBC mode

Что может произойти, если использовать предсказуемый IV.

Предположим, имеется алгоритм блочного шифрования E зависящий от ключа k с размером блока b. Также, имеется сообщение m, которое является тайной и используется, предположим, для аутентификации.
Общая схема работы протокола выглядит следующим образом:
  1. Сервер генерирует случайное IV и ключ k; ожидает данные от клиента.
  2. Клиент генерирует произвольную последовательность r и отправляет
    серверу для генерации токена.
  3. Сервер, получив данные от клиента, конкатенирует их с секретом, дополняет
    до длины кратной размеру блока (или добавляет новый блок, если длина
    получившейся последовательности уже кратна размеру блока) и шифрует
    при помощи E, k, IV в режиме CBC
  4. Сервер выбирает новый IV равным последнему блоку зашифрованного текста
  5. Сервер возвращает клиенту последовательность [IV, N-блоков шифротекста]
  6. Сервер ожидает получения новых данных и переходит к пункту 3
Задача клиента - узнать секретное сообщение. Для большей конкретики, предположим, что в роли алгоритма шифрования выступает AES128. Также, для простоты конструкции, предположим, что длина секрета нам известна (задача вычисления длины секрета в данном протоколе тривиальна). Рассмотрим на практике возможное решение этой задачи.

Код серверной части протокола.

Код, который решает задачу нахождения секрета

Вся суть приведенного выше сводится к:
E(IV ^ P_i) = E(IV ^ C_0 ^ IV ^ (r || i)) = E(C_0 ^ P_1)

воскресенье, 25 октября 2015 г.

Hash Length Extension

Пример hash length extension атаки на mac-sha256.

Для проведения атаки необходимо :
  • Знание длины ключа.
  • Имеющийся mac-sha256 от известного значения.
Используя перечисленные выше знания можно сформировать валидный mac-sha256 без знания ключа.
Пример проверяющей-функции

Предположим, что уже имеем валидный mac
data - "data"
mac  - aa93be97ad171b84b38e931c980ceb70e0e0bb76c212ea9205356c9c3781e84e
Далее необходимо инициализировать внутреннее состояние функции sha256 используя имеющийся mac (подробнее об этом тут) и рассчитать mac для выбранного дополнения (в данном случае роль дополнения играет строка "flag")

Теперь необходимо подготовить входные данные для проверяющей системы, тут понадобится знание длины ключа.
Размер блока - 512 бит
Блок формируется так : данные + padding + длина данных
sizeof(Длина данных) = 8

Для sha функций endianness поля "Длина данных" = big-endian
Длина данных = длина секрета + длина полезной нагрузки
Длина секрета - 11 (это требуется знать заранее либо подобрать)
Длина полезной нагрузки - 4
Суммарная длина - 15 байт - 120 бит (именно количество бит идет в блок)

Получаем следующую последовательность данных - 
"data\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00xflag"

"data" - значение для которого был получен оригинальный MAC

"\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00x" - padding и size, здесь size выглядит как "\x00\x00\x00\x00\x00\x00\x00x",
где восьмой элемент - 'x' = 0x78 - количество бит

len(padding + size) = 64 - (len(secret) + len(data))

flag - значение, для которого хотим получить валидный MAC
Используя приведенный выше код, получаем значение MAC
186ac0f8370146bf6b999a5dfa369e3675ce58f70e3726759f9c535442c888ab
Отдаем проверяющей системе на вход полученную последовательность с дополнением и рассчитанный MAC
[+] Ok, correct digest

среда, 3 июня 2015 г.

FILE Stream Buffering

Существует три типа буферизации потоков вывода:
  • Без буферизации (_IONBF)
  • Построчная буферизация (_IOLBF)
  • Блочная буферизация (_IOFBF)
Манипулировать этими режимами можно при помощи функций 
setbuf, setbuffer, setlinebuf, setvbuf
Сколько строк напечатает данная программа?

Если скомпилировать и запустить, на экране появятся две строки:
$ gcc -Wall -pedantic example.c -o test
$ ./test
FIRST
SECOND
Однако, если перенаправить стандартный вывод в файл, то результат окажется несколько иным
$ ./test > file.txt
$ cat file.txt
FIRST
SECOND
SECOND
Все дело в буферизации. Когда текст выводится на терминал, буферизация по умолчанию работает в построчном режиме, однако, когда мы перенаправляем стандартный вывод в файл, буферизация уже находится в блочном режиме, и, следовательно, буфер не сбрасывается сразу после вызова библиотечной функции printf. А, так как этот буфер находится в user-space, его содержимое дублируется в дочернем процессе. Когда вызывается функция exit, буферы сбрасываются. Дублирование же данных переданных write не проиcходит из-за того, что write - системный вызов. Наглядно это можно увидеть, если в приведенном коде поменять местами две строки

Результат выполнения
$ gcc -Wall -pedantic example.c -o test
$ ./test
SECOND
FIRST
$ ./test > file.txt
$ cat file.txt
FIRST
SECOND
SECOND