Pull to refresh

Подключение зашифрованных контейнеров TrueCrypt с помощью USB накопителя

Information Security *
image
Приветствую всех Хаброжителей! В этой статье я хочу поделиться с вами своими наработками, относительно автоматического подключения зашифрованных контейнеров, с помощью любого USB накопителя используемого в качестве ключевого файла.

По специфике своей работы мне приходится пользоваться зашифрованным контейнером, для этих целей мною был выбран всем давно уже известный инструмент по названием – TrueCrypt.

В моем случае зашифрованный контейнер подключается после выбора буквы диска, ключевого файла и ввода правильного пароля, все это проделывается через GUI интерфейс самого же TrueCrypt. Минус этого способа я ощутил буквально сразу, теряется масса времени на подключение, каждый раз, когда покидаешь рабочее место, приходится отключать контейнер, затем по возвращению, заново проделывать те же самые рутинные манипуляции. И так несколько раз на дню. Мирился я с этим около месяца, так и появилась идея – подключать автоматически зашифрованный контейнер с помощью привязанного USB накопителя.

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

Что в итоге должно было происходить:

1. Конечно же разработка программного обеспечения для всего этого.
2. Программа должна постоянно находиться в оперативной памяти и проверять USB устройства на наличие валидного USB накопителя.
3. Валидный USB накопитель заранее привязывается к зашифрованному контейнеру.
4. В случае если привязанный USB накопитель считается валидным, то без лишних вопросов и т.п. подключается зашифрованный контейнер.
5. В случае извлечения привязанного USB накопителя, зашифрованный контейнер отключается.

Для решения данной задачи был выбран язык программирования AutoIT.

Что из этого всего получилось:

Получилось то, что и предполагалось. Давайте по пунктам:

1. Настраиваем конфигуратор под наши требования:

$flash = "E:" ; буква USB накопителя, который собираемся привязать
$passwd = "Pa$$w0rd" ; пароль от зашифрованного контейнера
$path = "c:\windows\storage.tc" ; путь до зашифрованного контейнера
$mount = "R:" ; буква диска на которую будем подключать зашифрованный контейнер
$key = "0x1234Af3d21" ; ключ для шифрования значений в реестре, может быть все что угодно. Главное его запомнить, пригодится для основной программы.


Исходный код конфигуратора.

#include <md5.au3> ; библиотека для работы с md5
#include <string.au3> ;

AutoItSetOption ("TrayIconHide", 1 ) ; скрываем значок в трее
AutoItSetOption ("TrayIconDebug", 1 ) ;

$flash = "E:" ; буква флеш накопителя из которого будем делать токен
$passwd = "Pa$$w0rd" ; пароль на зашифрованный контейнер TrueCrypt
$path = "c:\windows\storage.tc" ; путь до зашифрованного контейнера
$mount = "R:" ; буква диска на которую будем подключать зашифрованный контейнер
$key = "0x1234Af3d21" ; ключ для шифрования значений в реестре

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Шифруем полученные данные в реестре алгоритмом RC4
; и серийный номер флеш накопителя в MD5+RC4

$a = _StringEncrypt(1, md5(DriveGetSerial( $flash )),$key,2)
$b = _StringEncrypt(1, $passwd,$key,2)
$c = _StringEncrypt(1, $mount,$key,2)
$d = _StringEncrypt(1, $flash,$key,2)
$e = _StringEncrypt(1, $path,$key,2)

RegWrite("HKCU\Software\USBToken", "Serial", "REG_SZ", $a)
RegWrite("HKCU\Software\USBToken", "Master", "REG_SZ", $b)
RegWrite("HKCU\Software\USBToken", "Mount", "REG_SZ", $c)
RegWrite("HKCU\Software\USBToken", "Flash", "REG_SZ", $d)
RegWrite("HKCU\Software\USBToken", "Path", "REG_SZ", $e)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Cоздаем ключевой файл для крипто-контейнера
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$file = FileOpen("master.key", 2)
FileWrite ($file, _StringEncrypt(1,$a & $b & $c & $d & $e & @ComputerName & @UserName, $key,2))
FileClose($file)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


2. Запускаем это дело, конфигуратор пишет необходимые значения в зашифрованном виде в ветку реестра HKCU\Software\USBToken (от любопытных глаз), на основе введенных данных, создается ключевой файл в папке с конфигуратором. С этим ключевым файлом (master.key) мы создаем новый (либо конфигурируем старый) контейнер + пароль, в нашем случае это параметр $passwd, который имеет значение (Pa$$w0rd).

image

image

3. В итоге мы должны получить контейнер который бы подключался при вводе пароля Pa$$w0rd + указав ключевой файл, который создал наш конфигуратор. После всех проделанных манипуляций, удаляем ключевой файл. Дальше передаем эстафету основной программе.
4. Основная программа постоянно находится в оперативной памяти, каждые 5 секунд проверяет подключенные USB устройства, в случае, если подключен валидный USB накопитель, программа генерирует ключевой файл во временную папку пользователя, подключает зашифрованный контейнер, удаляет ключевой файл.
5. По факту извлечения валидного USB накопителя, происходит отключение зашифрованного контейнера.

Конфигурируем основную программу :

$key = "0x1234Af3d21" ; Ключ шифрования, должен быть такой-же как и в предыдущем конфигураторе
$truecrypt = "C:\Program Files\TrueCrypt\TrueCrypt.exe" ; Полный путь до TrueCryp
t

Исходный код основной программы.

#include <md5.au3> ; библиотека для работы с md5
#include <constants.au3>
#include <string.au3>

If WinExists(@ScriptName) Then Exit ; Запрещаем повторный запуск скрипта
AutoItWinSetTitle(@ScriptName)

AutoItSetOption ("TrayIconHide", 1 ) ; Спрятать иконку в трее
AutoItSetOption ("TrayIconDebug", 1 )

$key = "0x1234Af3d21" ; Ключ шифрования, должен быть такой-же как и в конфигураторе
$truecrypt = "C:\Program Files\TrueCrypt\TrueCrypt.exe" ; Путь до TrueCrypt

$drive = BinaryToString(_StringEncrypt(0,RegRead("HKCU\Software\USBToken","Flash"),$key,2))
$serial = _StringEncrypt(0,RegRead("HKCU\Software\USBToken","Serial"),$key,2)
$passwd = BinaryToString(_StringEncrypt(0,RegRead("HKCU\Software\USBToken","Master"),$key,2))
$path = BinaryToString(_StringEncrypt(0,RegRead("HKCU\Software\USBToken","Path"),$key,2))
$mount = _StringEncrypt(0,RegRead("HKCU\Software\USBToken","Mount"),$key,2)

While 1

if DriveStatus($drive) <> "READY" OR md5(DriveGetSerial($drive)) <> $serial AND DriveStatus($mount) = "READY" then
Run($truecrypt & ' /f /q /d ' & $mount)
endif

if DriveStatus($drive) = "READY" AND md5(DriveGetSerial($drive)) = $serial AND DriveStatus($mount) <> "READY" then

$file = FileOpen(@TempDir & "\master.key", 2)
FileWrite ($file, _StringEncrypt(1,RegRead("HKCU\Software\USBToken","Serial") & RegRead("HKCU\Software\USBToken","Master") & RegRead("HKCU\Software\USBToken","Mount") & RegRead("HKCU\Software\USBToken","Flash") & RegRead("HKCU\Software\USBToken","Path") & @ComputerName & @UserName, $key,2))
FileClose($file)
Run($truecrypt & ' /a /q /s /b /v ' & $path & " /l " & $mount & " /k " & @TempDir & "\master.key" & " /p " & $passwd)
Sleep(2000)
FileDelete(@TempDir & "\master.key")

else
endif
Sleep(5000)
WEnd


Выводы:

1. Валидность USB накопителя проверяется по хэшу серийного номера USB накопителя.
2. Все данные в реестре шифруются по вашему ключу с помощью алгоритма RC4.
3. Ключевой файл хранится только в самой программе и генерируется лишь после того как подключен привязанный USB накопитель, после чего сразу удаляется.
4. При извлечении валидного USB накопителя, зашифрованный контейнер отключается с параметром /force.
5. Никаких лишних окон и вопросов, все прозрачно.

Способ конечно не инновационный, но имеет право на жизнь. Я НЕ стремился за универсальностью и инсталлятором, решения данного вопроса такими радикальными методами само собой не подойдут для людей, которые вздрагивают от стука в дверь, но вполне приемлемы для обычного повседневного пользователя. Кому это пригодится, сами легко смогут сконфигурировать программу под себя, добавив при желании — автозагрузку и все что понравится. Работоспособность проверялась на XP и Win7. Все чего я хотел добиться, я добился.

Где плюсы, там есть и минусы. А это – хранения данных в реестре (хоть и в зашифрованном виде), ключевой файл генерируется программой на жесткий диск после чего удаляется. Факты на лицо.

Так-же по этому поводу хочу процитировать комментарий roman_pro
Ошибка №1: Потоковый алгоритм RC4 используется многократно с одним и тем же ключом. Если кто не в курсе — краткий ликбез — RC4 генерирует псевдослучайную гамму на основе ключа, которая потом накладывается на шифруемые данные с помощью XOR. Расшифровка происходит аналогично. Если один и тот же ключ используется дважды для разных данных, то сделав над зашифрованными данными операцию XOR, получим поток в котором данные поXOR'ены между собой без всякого влияния ключа. Если же нам в силу каких-либо причин известны открытые данные и их зашифрованная версия, то легко вычислить гамму и потом с её помощью расшифровывать остальные данные. Предсказуемые данные в нашем случае Mount, Flash и Path. Причём если Path получился длиннее чем Master (т.е. пароль короче чем путь к контейнеру), то по извлечённой из Path гамме можно будет расшифровать Master. Вывод: не используйте RC4 с одним и тем же ключом более 1 раза.

Ошибка №2: Привязка к серийному номеру флешки на самом деле является привязкой к серийному номеру тома. Об этом явно сказано в документации к AutoIt и это распространённое заблуждение. Серийный номер устройства зашит в него, при форматировании не изменяется. Серийный номер тома меняется при форматировании и легко может быть подделан. Вывод: надо получать серийный номер железа, а не тома. Ваш метод чреват потерей доступа к контейнеру если отформатировать флешку из-за изменения серийного номера тома. Впрочем всё не так страшно, см. следующий пункт.

Ошибка №3: Привязки к серийному номеру тома вообщем-то и нет, есть банальное сравненение md5 от серийника с сохранённым ранее в реестре, но неверный серийник никак не помешает сгенерировать верный ключ — все данные для генерации ключа берутся из реестра. Достаточно пропатчить сравнение и программа будет штамповать верный ключ даже без ключевой флешки. Вывод: считанный с флешки серийник должен непосредственно участвовать в генерации верного ключа, а не ранее сохранённая копия из реестра.

Ошибка №4: Ключ сбрасывается на диск во временную папку, потом удаляется. Достаточно отобрать право на удаление для папки %TEMP% у текущего пользователя и ключ наш. Про восстановление удалённых файлов — молчу. Мне непонятно желание скидывать ключ на жёсткий диск, когда есть «ключевая флешка». Куда как логичнее сохранить ключ на ней, а на диске компьютера следов ключа не будет. Впрочем, хозяин-барин как говорится.

Итого, резюмируя — сей топик — красивое повествование о том как похоронить безопасность на корню своими руками, заменив её классической obscurity. Зачем в таком случае TrueCrypt вообще не понятно. Практически все данные для открытия контейнера лежат в реестре и запущенной программе, флешка — не более чем красивая игрушка для классической проверки if (password==«mycoolpassword»).

Программа была написана на языке Autoit, использовалась сторонняя библиотека md5.au3, которую необходимо поместить в папку Program Files\Autoit3\Include (Скачать ее можно здесь). Спасибо всем за внимание! Всего хорошего!
Tags: truecrypttokenusbsecuritydiskautoit
Hubs: Information Security
Total votes 55: ↑41 and ↓14 +27
Comments 35
Comments Comments 35

Popular right now

Top of the last 24 hours