Как стать автором
Обновить

Комментарии 31

К сожалению, перевод Markdown-разметки поломался при перемещении из моего редактора, пока никак не получается сделать нормальные таблицы. Пока бьюсь над этим.
Так и не получилось сделать нормальную ширину у заголовков, прошерстил помощь — не нашел ничего похожего. Очень прошу модераторов помочь пофиксить ширину табличных столбцов.
Для улучшения читаемости перевел все таблицы на вложенные списки.
Просьба всем, кто ставит минусы в карму: если уж ставите минус, то отписывайтесь сразу, что следует поправить в статье. Это образовательный материал, и нужно сделать его полезным для будущих читателей, а не просто выставлять молчаливые оценки.
Как человек, побывавший по обе стороны баррикад, могу отметить: рутованные / джейлбрейкнутые телефоны ведут себя ровно так, как и должны — можно всё и всем. Никакая дополнительная защита тут не работает — можно повеситься отладчиком в любой процесс и посмотреть нужные данные после расшифровки (неважно — зашифрованы они системой или чем-то ещё). Так что если приложение занимается действительно чем-то банковским — стоит пойти по другому пути и просто, обнаружив рут/джейл, говорить «ничего не могу гарантировать, используешь на свой страх и риск». Или вообще переставать работать.
Согласен с вами. Хотя, даже имея под рукой отладчик, если по мобильному приложению гоняются только хеши (т.е. отсутствует сама процедура расшифровки) — взломщик через отладку получит пользу только в виде изучения алгоритма, а это уже требует приличной квалификации атакующего. Запрещать работу на рутованных устройствах — хороший подход, только лично я пока не находил методов по 100%-му определению факта, что устройство взломано, по крайней мере, на iOS.
Отсутствие «расшифрованных» данных сильного усложнения исследователям не принесёт:
— Если данные используются только в виде хэшей, то эти хэши так или иначе используются. Разреверсить протокол обмена с сервером имея отладчик — несложно. Вешаем брейкпоинт на какие-нибудь сетевые функции (зависит от платформы) и гуляем по стек-трейсу до момента заполнения. Опять же, логирование на этом слое тоже обычно достаточно (даже если используется TLS — можно повеситься отладчиком/логгером до зашифровки).
— Если данные шифруются системными библиотеками — это ничем не помогает, просто опять же гуляем по стек-трейсу и ищем вызовы этих самых библиотек.
— Если данные шифруются в application-space и имена функций не определяются — всё равно можно найти в стеке необходимые функции, хоть и сложнее.

Единственный метод, дающий хоть какую-то надежду — использование статической библиотеки шифрования без каких-либо отладочных наименований (в случае с андроидом — обфускация бинарного байт-кода). Но и это не панацея.

Обфускация, действительно, Не панацея, особенно когда обфусцированный код присутствует >90% времени перед глазами. Его даже не всегда обязательно делать более читабельным :)

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

Пореверсите на досуге что-то вроде Bitwig Studio. Не андроид, но та же java. Все классы слиты в один большой jar, и имена классов и методов заменены на случайные трёхсимвольные последовательности. Кое-что понять можно, но я полтора раза мозг вывихнул, пока понял вообще порядок инициализации.
И такое доводилось встречать — стандартный продукт обфусцирования. Мозг не вывихнется, если использовать те же техники отслеживания по стектрейсу и поиска по регэкспам. Несомненно такие комья добавляют сложности, но позвольте, в чем смысл их слепого ковыряния?..
В чём смысл того ковыряния — говорить не буду, но могу сказать, что такие «комья» сильно усложняют разборку приложения. Очень сильно. Я не первый раз сталкивался с реверсингом, и имею не сильно большой, но всё же опыт в java. И всё-таки не достиг цели, что о чём-то говорит. Как минимум одного такой метод победил — может, и не зря keygen-ов для этой программы всё никак не появляется для последних версий? :)
Тут стоит добавить, что как минимум ProGuard умеет складывать несколько пакетов (package) в один.
Просто по определению, рут/джейл можно обнаружить только тогда, когда это сделано не в целях компрометации приложения. В противном же случае это тоже самое, что мы с вами не можем гарантировать, что мы сейчас не в Матрице :)
Тут можно войну вести бесконечно. Часть программ отказываются запускаться в VirtualBox/QEMU, например, хотя их довольно несложно заставить это сделать — но от новичков спасает. Точно так же, джейл например определяется по наличию библиотек вроде apt (обычным fopen или stat), но никто не мешает взять и подменить поведение этого метода для исследуемой приложеньки… Короче, чем глубже защищаемся, тем дольше придётся ломать, но абсолют недостижим.
Это понятно :) я к тому, что если мы защищаем параноидальную программу, имеет смысл добавить проверку на рут, и соответствующее поведение (показать предупреждение, молча «упасть» и т.п.). Но надеяться на достоверность проверки не стОит, и проектировать надо с предположением, что мы работаем «под микроскопом».
пароль пользователя должен уходить на сервер уже в виде хеша, и проверяться должен хеш, а не исходный пароль

Как в таком случае должен выглядеть обмен данными, если учесть то, что на сервере хранится солёный хеш пароля?

Сервер шлёт соль клиенту; клиент солит/хеширует пароль и отправляет обратно; сервер сравнивает?

Или добавить случайности: сервер генерирует случайное число, и отправляет вместе с солью клиенту; клиент солит/хеширует пароль, затем солит полученным случайным числом и отправляет обратно; сервер солит этим же числом хеш, хранящийся у него, и сравнивает. Так получится обмен, который нельзя проиграть второй раз.
Вариантов несколько. Первый и самый простой — соль генерируется случайно на клиенте, одноразово используется для засолки пароля при хешировании, и этот хеш идет на сервер. А серверу все равно, какая была соль, потому что ему не требуется эти данные расшифровывать, его задача — лишь сравнение, так что ему эта соль не нужна, ее клиент использует 1 раз и уничтожит. Либо второй вариант — да, применять пересылку соли и/или публичного ключа. Здесь уже нет смысла в дополнительной генерации чисел, если соль сама по себе создается серваком на основе генератора псевдослучайных чисел. Проблема тут в том, что если каким-то образом сетевой канал будет вскрыт, то и соль будет обнаружена. Однако только такой способ и получится применить, если требуется расшифровка данных на стороне сервера, тут никуда не денешься. С асимметричными там поинтереснее, перебрасываться можно хешами и, если надо, публичными ключами, но приватные ключи тогда нужно куда-то зашивать — тут уже начинаются проблемы рутованных устройств и хранения/защиты приватных ключей на устройстве/сервере.

Возник вопрос по первому варианту. Что и с чем сервер будет сравнивать? Если клиент посолит пароль одноразовой солью и захеширует, как сервер поймет, что за хеш ему прислали?
Можете объяснить подробнее или привести пример реализации?

Здесь все довольно просто. От сервера в данном случае требуется принять от юзера логин и хеш пароля, соответствующий этому логину, а также активировать юзера через привязку к электронной почте или телефону. После чего клиентское приложение всегда присылает в запросе на авторизацию пару логин-хеш пароля (соль для такого случая, конечно, локально хранится в защищенном хранилище на клиенте с привязкой к логину, чтобы она была одна и та же для данного логина), а сервак получает эту пару и сравнивает напрямую с той, что у него была сохранена.
Окей, а если потребуется авторизоваться под тем же аккаунтом, скажем, со второго телефона?
И ещё один момент: получается, что прослушав канал, можно проиграть обмен ещё раз, авторизовавшись на сервере. В этом случае посылать солёный хеш и посылать пароль в открытом виде — суть одно и тоже.
По авторизации — да, если вы пройдете сквозь HTTPS, то можно. Разница лишь в том, что сам пароль вы не узнаете, даже получив возможность авторизоваться с его хешем, поэтому это не одно и то же.
Как правило, приложения, требующие высокого уровня защиты, например, банковские, в принципе не должны допускать авторизацию со второго телефона. Это просто ни к чему, одному человеку вряд ли так уж понадобится именно с двух разных телефонов управлять одним и тем же аккаунтом, где у него деньги лежат. Во всяком случае везде, где я работал по банковскому направлению, второй телефон считался чем-то не самым правильным.
Почему вдруг?
Если там просто деньги и немного — зачем проблемы создавать?
Тиньков и Альфа точно не мешают например. Как и Яндекс.Деньги (их приложение по сути — банковское же).
Единственное — Тиньков любит иногда flash-sms показывать которые не перехватывается стандартными средствами и сразу на экране девайса показываются (что может быть неудобно если пользователю хочется таки редирект, на экран компьютера, есть сервисы) ну и если включена замена push и Тинькова — она включена для одного конкретного устройства (включишь на другом — выключается на прежнем). А вот допустим оплата через NFC работает именно что со всех телефонов у них.

C рутом — Сбербанк при детекте рута не вырубается напрочь а просто оставляет возможность работать только по созданным шаблонам.
Конечно если реально большие деньги на кону — то и подходы из https://habrahabr.ru/post/111232/ вполне могут быть (но вот уж там — явно никакие приложения на телефон ставить не будут, разве что только на просмотр).

С рутом вообще еще та проблема есть что CyanogenMod/Lineage OS в принципе как рут детектится часто, даже когда он там отключен (в смысле приложение НЕ может получить рут, без специального разрешения пользователя). Так же и в некоторых кастомных прошивках.
А допустим для Nexus 5 кастомная прошивка это единственный способ получить андроид с последними обновлениями в том числе и безопасности.

Вообще — в случае с банковским приложением и накрученными защитами — мы защищаем приложение от злого юзера (который и так имеет легальный доступ) или от посторонних приложений которые влезли? Если второе — так достаточно показать один раз предупреждение чтобы юзер был в курсе.

Вообще на Android есть такая штука как SafetyNet (описание со ссылками смотрим на https://koz.io/inside-safetynet/ ) — гугловский детектор одного из трех состояний: все полностью ок, на девайсе… странности… но вероятно угрозы приложению нет, все плохо. Используется куча динамически обновляемых детектов, в процессе на устройство грузится код от гугла.
Обойти при наличии рута саму проверку можно… но пока публично известные публично способы просто подменяют ответ для приложения по сигнатурам.
А вот если сделано идеологически верно, и результаты проверки отсылаются на свой сервер, который проверяет что они верны у гугла то с обходом уже все сильно сложнее.
Бинарные файлы (NSKeyedArchiver).

Штатная защищенность: Отсутствует.

Не совсем корректно. Файл можно создать с атрибутом NSFileProtectionComplete по ключу NSFileProtectionKey.


The file is stored in an encrypted format on disk and cannot be read from or written to while the device is locked or booting.

Не стоит, конечно, хранить там какие-то ключи для общения с сервером. Но вполне подходит для хранения временной чувствительной информации, которую нельзя прочесть третьему лицу, если девайс заблокирован.

Спасибо, дополню этот пункт.
" асимметричных алгоритмов вроде AES" не совсем понятно что имелось ввиду...AES симметричный алгоритм
Согласен, поправил, спасибо.
Вопрос полноты, независимости и непротиворечивости не поднимался?
Все или почти все начинается с личного опыта, так что продолжайте.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.