25.10 // Аудит сборки TrueCrypt 7.1a не выявил расхождения с исходными текстами
Опубликованы результаты результаты сравнения официальной бинарной сборки TrueCrypt 7.1a для Windows и сборки, сформированной собственными силами из исходных текстов. Анализ различий показал, что в официальная бинарная сборка не содержит скрытых функций и тождественна поставляемым исходным текстам. Разница наблюдается только в элементах, связанных со сборочным окружением и используемыми на этапе компиляции опциями.
Исследование показало, что правильный подбор используемых при сборке инструментов, воссоздающий оригинальные условия сборки, позволяет сформировать тождественный исполняемый файл и подтвердить, что в распространяемые производителем бинарные сборки не были внесены скрытые изменения. Таким образом удалось подтвердить отсутствие скрытых модификаций без необходимости выполнения трудоёмких операций по обратному инженерингу исполняемых файлов. В настоящее время, усилия по аудиту проекта TrueCrypt могут сосредоточится на изучении исходных текстов и методов шифрования, .
Кроме того, представителям проекта IsTrueCryptAuditedYet удалось связаться с авторами TrueCrypt, которые приветствовали идею проведения независимого аудита безопасности их продукта. Напомним, что в рамках проекта IsTrueCryptAuditedYet создана инициатива для подтверждения отсутствия в TrueCrypt проблем безопасности и скрытых бэкдоров. Одним из подозрений было отсутствие гарантии, что бинарные сборки, которые составляют основную массу загрузок, не содержат закладок и собраны на основании публично доступного исходного кода без внесения скрытых изменений.
Источник: http://www.opennet.ru/opennews/art.shtml?num=38259
комментариев: 11558 документов: 1036 редакций: 4118
Разумеется, иначе бы имело место объективное вменение (безвинная ответственность).
комментариев: 9796 документов: 488 редакций: 5664
Хороший термин.
[offtop]
При попытке поиска гугл предложил ссылки на стихи Ахматовой:
[/offtop]
комментариев: 1079 документов: 58 редакций: 59
Результаты аудита TrueCrypt 7.1a
Не помню, выкладывался или нет, сегодня перечитал – решил на всякий разместить.
комментариев: 371 документов: 19 редакций: 20
Пустая придирка. Проверка правильности расшифрования заголовка не несет никаких защитных функций, это только для удобства пользователя. Использование HMAC здесь оверкилл, достаточно сравнения с константой чтобы исключить случайное монтирование с ошибочным паролем.
Опять пустопорожняя придирка. PBKDF2 вполне стойкая функция, нареканий не вызывает, а то что сейчас придуманы другие – не повод тащить их в проект. Про стойкость scrypt еще бабушка надвое сказала (лично мне она не нравится). К тому-же scrypt в качестве KDF не применим для загрузчика, т.к. загрузчик испытывает катастрофическую нехватку памяти, то что есть – влезло только чудом, ни о каких scrypt, или других KDF использующих много памяти, не может быть и речи. Количество итераций можно увеличить, но это не принципиально. Стойкие пароли по прежнему остаются стойкими.
Еще одна глупейшая придирка. От декомпрессора в данном случае требуется ровно одно – чтобы он работал. Он работает. Если атакующий способен модифицировать сектора диска на низком уровне, абсолютно не важно какой там декомпрессор, не важно даже есть он или нет, можно модифицировать любой код. Просто написать что-то было нужно, а придраться больше не к чему.
А теперь настоящие дефекты с которыми я согласен:
Это действительно уязвимость, потенциально эксплуатируемая. Нужно будет и мне внимательно проверить DC на такие моменты, хотя я внимательно отношусь к таким вещам.
Всё как сказали. memset не гарантирует зануления, компилятор может его выбросить при оптимизации. Следует использовать RtlSecureZeroMemory, либо интринсики stosb / stosd, либо самописную функцию зануления на volatile pointer'ах. Обязателен контроль созданного компилятором кода через дизассемблер.
Малозначимые ошибки, требуют устранения, но опасности не несут.
комментариев: 1079 документов: 58 редакций: 59
комментариев: 371 документов: 19 редакций: 20
И вдумчиво прочитайте это:
Это просто шедевр! Они предлагают похерить отрицаемость для закрытия совершенно надуманной "уязвимости". У меня есть большие сомнения насчет качества этого аудита. Наговаривают почем зря.
Разве что утилиту для монтирования. Полноценное портирование слишком трудозатратно, поддержка еще более трудозатратна. У меня слишком мало свободного времени, чтобы этим заниматься.
комментариев: 1079 документов: 58 редакций: 59
Почти идентичные тексты. :-) Кстати, эта уязвимость вроде как была именно данного типа.
Не знаю, насколько страшно оно тут, но целочисленное переполнение в Linux-софте — одна из самых распространённых ошибок в багрепортах, приводящих к фатальным последствиям типа исполнения произвольного кода.
Уже есть ограниченная поддержка TC в cryptsetup и через tc-play. Возможно, поддержку DC проще было бы добавить в эти программы, чем делать полностью оригинальный софт.
Есть много ошибок из категории «так делать плохо, так делать не принято, это опасно, но в конкретно данном случае прямой уязвимости вроде не возникает, да». Это как претензии к тому, что код плохо откомментирован: само по себе это не уязвимость, но может привести к уязвимости через некоторое время. Как я понимаю, ряд претензий был именно такого рода. В то же время, могут быть разные школы, и не быть консенсуса на тему того, как делать правильно, а как не стоит. Для одних это может быть делом вкуса и предпочтений, а другие за тем же самым могут видеть потенциальную уязвимость с примером «как делать не надо».
Допустим, в простейшем случае есть некоторый предопределённый текст (сигнатура), и если он появляется в заголовке, то считается, что пароль верный. Однако, можно было бы поступить хитрее: дать пользователю самому указывать, что является такой сигнатурой. Это было бы как вторая часть пароля. Т.е. пароль сам бы в себе содержал как функции расшифрования, так и проверку корректности расшифрования. А поскольку какая должна быть сигнатура, противник не знает, он не мог бы отличить правильный исходной пароль от неправильного.
Этим свойством можно было бы пользоваться для последовательного бессигнатурного шифрования данных (не хочу говорить каскадрного, потому что смысл здесь другой: например, бессигнатурное шифрование всего диска и потом, если дать второй правильный пароль, получаем таблицу разделов; тогда не зная первый пароль, противник не знает, правильный ли он, пока не получит оба). Может быть, пример натянутый, но смысл примерно в этом: противник после осуществления cold boot атаки не должен получить всю информацию о структуре всех разделов/томов диска, если они были в отмонтированном состоянии (но считается неизбежным, что он получит информацию о тех разделах, которые были в тот момент подмонтированы).
комментариев: 11558 документов: 1036 редакций: 4118
Так и есть. В блок шифруемых метаданных ставится волшебное слово; если при расшифровании оно находится в ожидаемом месте, значит, пароль верный. Вероятность ложного срабатывания существует, но она чрезвычайно мала.
комментариев: 9796 документов: 488 редакций: 5664
А можно и рэндомное слово:
X1 = Random IV
X2 = Hash-MACX1 (KeyFromPass)
Y = EncryptKeyFromPass (X1 ║ X2)
Z = DecryptKeyFromPass (Y) = X1 ║ X2
Z' = Hash-MACX1 (KeyFromPass)
if Z' = X2 then Decrypt(KeyFromPass) is true
комментариев: 371 документов: 19 редакций: 20
Две маленькие уязвимости в TrueCrypt, чудом не ставшие большими
На днях мною были найдены еще две уязвимости в TrueCrypt 7.1a, которые остались незамеченными аудитом.
Уязвимость №1. Тип: утечка данных. Опасность: средняя. Возможность эксплуатации: низкая.
При предзагрузочной аутентификации загрузчик сохраняет пароль в первом мегабайте памяти для передачи драйверу, а драйвер его оттуда удаляет. Этот процесс нарушается при использовании гибернации. При выходе из гибернации загрузчик оставляет пароль в памяти, а драйвер ничего об этом не знает. Пароль остается по физическому адресу 0x90026 и мог бы быть доступен любым приложениям через память ntvdm, если бы не случайное везение, благодаря которому эта область памяти не попадает в отображаемые ntvdm регионы.
Уязвимость потенциально может приводить к утечке пароля от загрузочного диска.
Решение: в обработчике IRP_MN_SET_POWER отслеживать событие PowerSystemWorking и повторять поиск данных загрузчика в памяти. Отключить гибернацию до устранения уязвимости.
Уязвимость №2, Тип: утечка данных. Опасность: низкая. Возможность эксплуатации: на данный момент невозможна.
Обработчик DumpFilterWrite (файл DumpFilter.c), исполняющийся на уровне IRQL = HIGH_LEVEL подменяет содержимое writeMdl, используя функцию MmBuildMdlForNonPagedPool, которую допустимо вызывать на IRQL <= DISPATCH_LEVEL, что является грубой ошибкой. Если MmBuildMdlForNonPagedPool будет работать неправильно, возможна утечка данных, описываемых оригинальной writeMdl на диск в открытом виде, что потенциально приводит к полной компрометации всех ключей шифрования. Благодаря счастливому стечению обстоятельств этого не происходит, но поведение функции MmBuildMdlForNonPagedPool может быть изменено в следующих версиях Windows.
Решение: создавать MDL вручную. Отключить гибернацию до устранения уязвимости.
Само по себе это, пожалуй, не очень интересно. Если на то пошло, можно шифровать через cryptsetup plain mode и всегда получать на выходе набор случайных данных. Вопрос будет в том, как доказать, что эти данные и есть правильный результат расшифрования, и вы не обманываете, давая рандомный пароль.
Осмысленная схема всё равно сводится к двухпарольной в следующем смысле: дали правильный пароль — открылся скрытый контейнер, дали неправильный пароль — открылась обманка, всё как в идеологии TrueCrypt. В этом случае можно было бы сделать пароль, являющийся конкатенацией собственно KeyFromPass и IV. Тогда при правильном IV расшифровывается в правильный X2, а при неправильном IV — в X2, соответствующий обманке. Тут, конечно, интуитивно хочется, чтобы одни и те же шифрованные данные могли быть дешифрованы двояким образом, но на практике такое недостижимо, если я правильно понимаю (одноразовый блокнот — исключение). Соответственно, чтобы создать имитацию такой осуществимости, делают разделение данных внутри шифрованного объёма: одни соответствуют только обманке, а другие — только реальным данным, а противнику реальные данные выдаются за свободное место в контейнере/ФС/LVM и т.п. Итак, раз всё равно данные разделять, смысла делать вами приведённое расшифрование с проверкой случайной строки нет: можно точно так же сделать расшифрование через plain mode в обманку, где внутри будет ФС и всё такое, а для подключения реальных данных с этого же раздела/диска нужно будет задать иной пароль, правильный, и оффсеты (адресацию свободных блоков).
Кстати, сейчас пришла в голову гениальная мысль: вместо того, чтобы адресовать свободное пространство на ФС, можно в обманке (подключенной через plain mode) просто создать LVM volume group, внутри какие-то логические, разметить их и положить туда обманные данные. Как мне кажется, LVM, в отличие от ФС, не пишет информацию о суперблоках и остальном куда попало на дисковом пространстве, поэтому можно будет легко заранее сказать, какие сектора не будут использоваться LVM'ом для записи. Если что, можно сказать, что это место пока не используется, и из него пополянется пул при нехватке места на уже выделенных логических томах (примерно как unknown делает*). А реально неиспользуемое место элементарно адресуется через dmsetup и цепляется через всё ту же plain mode как скрытый раздел.
Чисто интуитивно кажется, что неиспользуемое место на ФС более правдоподобно отрицаемо, чем неиспользуемый объём внутри volume group, но это уже вопрос психологии. Вообще, если честно, когда переделывал схему данных для себя по уму, даже без ориентировки на отрицаемость сразу сделал именно так: большой VG, свободное место которого используется для пополнения внутренних LV по мере надобности. Вроде это вполне естественный use case. По факту сложно бывает предсказать, как быстро и насколько разрастётся тот или иной LV, поэтому добавление места «на лету по мере надобности» самое оптимальное. А когда LVM'а нет, возникает стандартная проблема: один раздел уже заполнен, ему нужно место, но взять его неоткуда; зато есть другой раздел, где место есть и пока не нужно, но оттуда его не перекинуть. А если писать данные на иной раздел, его надо будет монтировать как и первый, поэтому возникает смешивание: приходится без надобности держать ключи в памяти на те разделы, которые в данный момент, казалось бы, не должны быть нужны.
*См. пост:
комментариев: 9796 документов: 488 редакций: 5664
Хорошо бы уточнить, потому как он предназначен для лёгкого перемещения и прочих аналогичных операций. Кроме того, UID'ы томов при vgscan, lvscan и пр. могут где-то кэшироваться в системе на корневом разделе.