Russian Chinese (Simplified) English
Войти

В общем начитавшись про Secure Boot стало интересно и я решил сделать нечто свое. Простое, понятное, для всех. Тем более аналогов ASL, обладающих таким же функционалом (или хотя бы похожим) я не нашел. Данная статья является продолжением статьи про Secure Boot и первым мои опытом в данной области. Идея и реализация описаны максимально подробно, исходники имеются в открытом доступе.


Собственное что такое ASL?
Это мехнизм доверенной загрузки, суть которого заключается в контроле целостности системных файлов в разделе (/system) при каждой загрузке устройства с помощью хеш-сумм (в текущем варианте с помощью алгоритма SHA-1) на ранней стадии инициализации системы.
Обеспечивает защиту системных файлов от модификации, подмены и удаления на ранней стадии загрузки устройства (до начала инициализации самой ОС). Также препятствует внедрению в системный раздел руткитов и др. вредоносов. В случае нарушения целостности системного раздела производит операцию восстановления.


На данный момент ASL работает только в момент загрузки устройства на начальной стадии загрузки. В процессе работы устройства защиту не обеспечивает (пока что). Расчитан на защиту от вредоносов, целью которых является именно внедрение в системный раздел, что в подавляющем процессе случаев требует перезагрузки устройства (для применения изменений).

 

Из чего состоит механизм ASL?
1. Небольшой драйвер в ядре, который создает в ProcFS (/proc/asl)  интерфейсы необходимые для работы ASL:
enabled - инф. о том вкл/откл ASL
status - статус проверки
files_count - количство файлов в системном разделе (хранится в ядре)
list - список хеш-сумм всех файлов сстемного раздела (хранится в ядре)
asl_img_hash - хеш образа восстановления (хранится в ядре)
permissions - конфигурация прав и владельцев файлов и директорий системного раздела (хранится в ядре).
version - версия ASL
2. init.asl.rc скрипт запуска ASL в Ramdisk + bash скрипты (init.asl.sh и init.recovery.asl.sh), выполянющие проверку системного раздела на целостность  и восстановление файлов соответственно.
3. Сборник утилит busybox.
4. Конфиг-файл sdcard.conf, необходимый для монтирования карты памяти в случае восстановления.
5. Сборочные скрипты обеспечивающие подготовку списка контрольных сумм всех файлов на системном разделе, расчет по полученном корневой суммы, количества системных файлов и экспорт их в ядро с последующей пересборкой.
6. Образ восстановления asl.img.
7. Приложение ASL Monitor.

 

Как это работает?
Для начала вспомним как грузится ОС Android: сначала грузится загрузчик, потом ядро, рамдиск, а после стартует система с раздела /system. Вцелом схема одинакова для всех устройств на ОС Андроид.
Нам нужно не допустить чтобы вредонос выполнил свой нехороший код при загрузке ОС или же модифицированное приложение  упало с ошибкой. Логично, что нужно предотвратить это до инициализации системы. Поэтому действовать надо сразу после того как скрипт инициализации в Ramdisk примонтирует разделы. Монтирование разделов происходит по триггеру "on fs", в нем то и выполняет свой код init.asl.rc, который в свою очередь импортируется и выполняется из init.rc в самом начале:


import /init.asl.rc


Скрипт init.asl.rc запускает на выполнение скрипты init.asl.sh и init.recovery.asl.sh, которые делают то что показано на диаграммах ниже

Рис.1 - Общий процесс загрузки

 

Рис. 2 - Декомпозиция процесса проверки

 

Расшифровка диаграммы проверки

Порядковый номер блока/Выполняемая функция
1
Получение из интерфейса ASL (/proc/asl/enabled) значения.
«0» - механизм выключен
«1» - механизм включен
2
Копирование оригинального списка хеш-сумм (/proc/asl/asl_list) в рабочий каталог ASL (/dev/asl/asl_list)
3
Запуск утилиты sha1sum с ключом «-c». Проверка файлов на целостность по списку
4
Запись результатов проверки в файл протокола (/dev/asl/asl_protocol)
5
Парсинг файла протокола на наличие строк «FAILED», означающих несовпадение контрольной хеш-суммы или отсутствие файла.
6
Перенаправление результатов парсинга протокола в файл (/dev/asl/failed_detected)
7
Цикл по всем строкам файла (/dev/asl/failed_detected)
8
Если файл, указанный в строке «line» существует, данная строка с абсолютным путем к файлу записывается в файл обнаруженных модифицированных файлов (/dev/asl/mod_detected)
9
Получение оригинального количества файлов в системном разделе из интерфейса ASL (/proc/asl/files_count)
10
Подсчет количества файлов на системном разделе (с учетом символьных ссылок и скрытых файлов). Переменная CountFilesOnSystem
11
Подсчет количества ненайденных файлов в протоколе (разница между количеством обнаруженных файлов в /dev/asl/failed_detected и количеством модифицированных файлов в  /dev/asl/mod_detected)
12
Подсчет количества найденных файлов в протоколе (разница между оригинальным количеством файлов в системном разделе и количеством ненайденных файлов в протоколе). Переменная ExistFilesInProtocol
13
Создание списка всех файлов системного раздела (файл /dev/asl/file_list)
14
Создание списка (копированием протокола /dev/asl/asl_protocol) без статусов проверки файлов (/dev/asl/proto_no_stat)
15
Выполнение операции сравнения двух списков (/dev/asl/proto_no_stat и /dev/asl/file_list)
16
Запись результатов сравнения в файл обнаруженных удаленных и добавленных файлов (/dev/asl/doa_detected)
17
Проверка файла (/dev/asl/mod_detected) на наличие обнаруженных модифицированных файлов
18
Проверка файла (/dev/asl/doa_detected) на наличие обнаруженных удаленных и добавленных файлов
19
Запись статуса проверки («0» - проверка не пройдена) в случае нарушения целостности. Установка значения «1» для флага восстановления.
20
Запись статуса проверки («1» - проверка пройдена) в случае отсутствия модифицированных, удаленных или добавленных файлов. Установка значения «0» для флага восстановления.

 

Рис. 3 - Процесс восстановления

 

Расшифровка диаграммы восстановления

Порядковый номер блока/Выполняемая функция
1
Если флаг восстановления (/dev/asl/need_recovery) установлен в значение «1», то выполняется проверка наличия образа восстановления по указанному пути «по умолчанию» (/data/asl.img) с последующей проверкой данного образа на целостность посредством вычисления контрольной суммы SHA-1 и сравнения ее с оригинальной в ядре
2
Монтирование карты памяти (SD card) устройства и проверка наличия на ней образа восстановления (asl.img)
3
Отключения питания устройства
4
Проверка архива восстановления на целостность посредством вычисления контрольной суммы SHA-1 и сравнения ее с оригинальной в ядре (/proc/asl/archive_hash)
5
Распаковка архива восстановления во временный каталог (/dev/asl/system)
6
Проверка файла (/dev/asl/mod_detected) на наличие обнаруженных модифицированных файлов
7
Замена обнаруженных модифицированных файлов оригинальными из временного хранилища (/dev/asl/system)
8
Проверка файла (/dev/asl/doa_detected) на наличие обнаруженных удаленных и добавленных файлов
9
Восстановление обнаруженных удаленных файлов оригинальными из смонтированного образа восстановления. Удаление обнаруженных добавленных файлов из системного раздела

 

Чтобы лучше понимать, что это все из себя представляет и как отдельные части механизма между собой взаимодействуют, ниже показана диаграмма развертывания

Рис. 4 - Диаграмма развертывания

 

 

Руководство для разработчика


ASL создан для работы на любом устройстве с любой версией ОС Android, однако советую использовать репозиторий CyanogenMod и версию ОС 4.1 и выше. Это просто совет, работать должно на всех версиях.
Сам мануал по сборке ТУТ. Он на английском, но там все понятно.
Ссылки на исходный код внизу поста. Исходники полные, как есть. Распространяются свободно, однако при распространении ссылка на мой репозиторий или данный пост обязательна!
Из советов - busybox из стандартных исходников собирать не надо, нужно использовать либо проприетарный, либо собрать его из исходного кода что идет вместе с ASL. Я вносил в него некоторые модификации, поэтому со сторонним busybox работать будет коряво. Насчет исходников init - данные исходники для CM10, использовать их вовсе не обязательно. Важно не забыть взять правильный init.rc от своей версии ОС и пропатчить его добавив строчку импорта скрипта ASL.
Можно также собрать ядро с поддержкой ASL и образ восстановления вручную, используя инструменты из папки AMB.

 

Краткая инструкция для пользователя

После включения устройства, необходимо подождать некоторое время пока механизм контроля целостности ASL выполнит проверку системного раздела и в случае необходимости, если обнаружено нарушение целостности системного раздела, восстановит файлы и директории. При этом на внешней карте памяти либо в разделе DATA обязательно должен находиться образ восстановления, файл «asl.img». В случае его одновременного отсутствия в данных хранилищах либо если данный образ не является оригинальным, проверка будет прервана, устройство выключено. В данном случае необходимо извлечь из устройства внешнюю карту памяти и скопировать на нее через ПК образ восстановления, файл «asl.img», после чего вставить карту памяти обратно в устройство и включить его. Время выполнения проверки зависит от количества файлов в системном разделе и мощности устройства. Во время проверки, на экране отображается ход работы ASL. После загрузки устройства результаты проверки можно увидеть в программе ASL Monitor.

 

Ответы на некоторые вопросы

На сколько увеличится время загрузки устройства с включенным механизмом ASL?
Все зависит от мощности устройства и количества файлов на системном разделе. Приведу пример: у меня смарт на Exynos4, около 3900 файлов на системном разделе. Время загрузки (с учетом проверки+восстановления+автоматического исправления разрешений) возрастает примерно на 1 мин 20 сек. Не думаю что это катастрофичеки много. Плата за безопасность как никак!

 

Насколько ASL обеспечивает безопасность?
ASL расчитан в первую очередь на тот случай, если злоумышленник действует удаленно (вредонос проникает на устройство например через сеть). Для подавляющего большинства вредоносов требуется перезагрузка устройства в результате которой применяются нужные изменения(запускаются левые сервисы, устанавливаются вредоносные компоненты в системный раздел и т.д.). Вот тут то они и попадутся ;)   
Однако! Если к устройству есть физический доступ, то конечно же от компрометации загрузочных образов ядра и Ramdisk механизм ASL не спасет. Всегда есть возможно перепрошить данные образы. В данном случае ASL может дополнить использование подписанного загрузчика и подписанных образов, но это уже другая история.
Что касается того момента мол "а я возьму и подделаю системный файл чтобы совпала хеш-сумма с оригиналом!". Удачи! Вероятность возникновения коллизии при использовании SHA1 ничтожно мало. Время на подбор файла с таким же хешем стремится к перевернутой восьмерке (по крайней мере с точки зрения длины жизни человека). Т.е. без физического доступа поломать ASL не получиться (или я чего то упустил?).

 

В чем отличие от других механизмов котроля целостности?
Если сравнивать с Secure Boot который используется в ChromeOS и Андроид 4.4+, то у меня вычисление контрольных сумм производится по файлам, а в Secure Boot по блокам (дольше? надо тестить. да и вообще зачем по блокам? перебор на мой взгляд) + место хранения сумм отличается + алгоритм другой. Взять например HTC - у них используется S-ON, защищающий разделы от записи + автоматически восстанавливаются системные приложения при загрузке (вроде только приожения...).  Ну и конечно iPhone, куда же без него. Инженеры сотворившие его пошли еще дальше - в айфоне есть специальный сопроцессор выполняющий криптографические операции, который даже в случае компрометации программых компонентов (ядра или загрузчика) способен выявить неладное. Ну и конечно там все подписано сертификатами, используется поэтапная проверка подлинности (сначала пред-загрузчик, потом загрузчик, потом ядро и т.д.). Так что мой вариант - чисто программный, конечно уступает всем кроме 1-го варианта (1 надо еще поизучать), зато он простой и относительно быстрый (на мой взгляд SHA1 - это оптимальное сочетание безопасность/скорость вычисления)

 

Почему бы просто не смонтировать раздел /system на r/o и запретить его перемонтирование?
Если посмотреть ниже, один уважаемый товарищъ внес такое предложение - запретить перемонтирование раздела system на четиние/запись в ядре.
Я думаю владельцам аппаратов HTC (в особенности), Sony, Acer и др. знакома такая вещь как залочка системного раздела и невозможность даже с рут-правами что-либо с ним сделать. При попытке перемонтировать системный раздел из под рута устройство просто перезагружается... Также многие знают про модуль ядра wp_mod.ko и его аналоги. Этот модуль преспокойно снимает данную защиту и в режиме реального времени снимает защиту от перемонтирования системного раздела на чтение/запись, достаточно подгрузить модуль ядра и вуаля!
Временный рут, руткиты для несанкционированного получения прав суперпользователя (да так что пользователь ничего не заметит), модуль ядра wp_mod.ko....я думаю вы понимаю к чему я клоню?)

 

Планы на будущее:
*реализовать функционал скрипта init.asl.sh на C++ (скорость проверки должна поидее повыситься)
*подумать насчет защиты от компрометации модулей ASL
*реализовать сжатие файлов в asl.img для уменьшения размера образа восстановления. Использование для этих целей squshfs и возможно, сделать проверку целостности образа восстановления необязательной
*реализовать возможность патча системного раздела после создания образа восстановения без его пересборки (на основе доверенного списка...короче тут подумать надо). Возможность патчить на работающей системе

 

Исходный код ASL