All streams
Search
Write a publication
Pull to refresh
-2
0
Send message
чтобы сервер подписывал ответ

Если потом стоит просто if(isSignatureValid) { letsPlay() }
То
код проверки и валидации, каким бы утончённым он ни был, можно просто заменить на заглушки.

Тут в соседней ветке дошли до того, что сервер после валидации покупки должен присылать зашифрованный контент и виртуальную машину для его расшифровывания. ;)

можно запрашивать факт покупки заново, и довольно часто).

Если у вас хотя бы сотня тысяч клиентов, то придётся поднимать хорошую серверную инфраструктуру для постоянной валидации покупок, а там довольно медленный RSA. Поэтому я и говорил о кэше покупок в приложении, чтобы валидацию делать как можно реже.
Понятно, что абсолютной защиты не существует и при наличии достаточно большого бюджета и/или мотивации ломается всё. Но подобные методы защиты отпугнут недостаточно мотивированных копателей. Плюс встроенный head hunting ;)

Пример подобного приложения с платным контентом пробегал здесь позавчера, lamptest.ru. В его платной версии показываются дополнительные параметры лампочек. Если не защищать весь контент, который приходит с сервера, то нехорошим людям достаточно просто сделать бесплатный клон этого приложения типа lamptest.pro, который будет круче, и зарабатывать на рекламе и/или подписках.
Да, покупки приходят потом из кэша Play Services, но если у вас валидация покупки происходит на сервере, то как приложение это сделает в оффлайне? Поэтому надо где-то хранить, что такой-то Order ID проверен. И не в открытом виде ;)
Интерес в том, чтобы максимально затруднить копирование платного контента, предоставляя каждый раз уникальный блок данных и уникальную виртуалку для его расшифровывания.
Много слоёв будут слишком медленно работать на конечном устройстве. Плюс лишние слои не добавят безопасности, если она вся основана на нескольких переменных, которые лежат почти на поверхности. Мы с вами просто не знаем, где их читать.
Отсюда и возникает изначальный вопрос, какие системные вызовы делает DroidGuard, чтобы идентифицировать устройство?
Что есть на поверхности:
  • Android ID
  • Application ID
  • Order ID — уникальный идентификатор покупки
  • марка/модель/ABI
  • случайное число, ключ для расшифровывания которого храним в KeyStore

Раньше ещё можно было потрогать MAC, IMEI, но и этого должно хватить, чтобы сделать уникальную виртуалку со своим уникальным набором команд и регистров, на которой достаточно реализовать какой-нибудь кастомный вариант ChaCha20.
Обычно в разговоре на собеседовании сразу становится понятно, надо ли давать человеку тестовое задание, которое лишь повторяет какой-то уже реализованный кусок реального проекта, но мы не рассказываем ему, откуда такая задача взялась.
А человеки с умными словами обычно отсеиваются ещё на стадии чтения этих слов в их резюме. Типа «сетевые протоколы: HTTP, JSON, XML» ;)
И ещё очень полезно посмотреть, на какие паблики они подписаны.

Всё это множество люков-автобусов и прочих пузырьковых сортировок происходят в основном из-за неспособности интервьюеров придумать что-то своё. Или хотя бы обратить внимание, как человек краснеет, двигает ногами, смотрит и говорит. То, что он не сумел решить какую-то теоретическую задачку не говорит о том, что он будет плохо работать. Тут уже было массу статей про плохие интервью. Меня самого один раз не взяли в довольно крупную контору из-за того, что зевнул пару раз, потому что было реально скучно проходить обследование у десятка человек, никак не связанных с моей будущей должностью.

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

PS. могу купить, разобрать и собрать бензопилу
PSS. могу точить цепи от бензопил ;)
Я несколько о другом. Предположим, приложение имеет платный контент. Проверка оплаты происходит на сервере. Если сервер банально отвечает да/нет, то вся система оплаты ломается парой байт.
Если же сервер передаёт после покупки зашифрованный контент и виртуальную машину, специально заточенную для расшифровывания этого контента, причём только на этом конкретном устройстве, плюс приложение хранит в железном KeyStore какие-то данные для работы этой виртуалки, то ломать эту конструкцию будет гораздо сложнее.

Или я изобретаю ещё один велосипед? ;)
Поэтому я и не буду этим заниматься ;)
Мне было интересно, копал ли топикастер эту тему дальше. С практической точки зрения меня больше интересует применение вирутальных машин внутри приложения для защиты его данных.

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

Так кто вам больше нужен: лесорубы, которые делают конечный продукт, или кузнецы, шахтёры, металлурги, геологи? Если мне надо посмотреть на реализацию Base64, то я быстро найду Base64.java в том же Android. Но не каждый Senior, а тем более Middle знает, что бывают другие, более эффективные кодировки типа Base85, или более простые типа Hex. А уж вопрос какую где лучше применять сможет поставить в тупик даже интервьюера ;)

Чтобы проверить, что человек умеет мыслить, то ему надо дать задание по конкретной теме, например, тестировщикам я предлагал придумать 10 способов разбить стакан, стоящий на соседнем столе, а все без исключения разработчики делали тестовое задание очень близкое к тому, чем они потом будут заниматься. Сразу было видно, знает ли человек нужный нам язык или фреймворк.
Каждый раз, когда мне приходит push-уведомление, я вспоминаю Google Play Services, которые постоянно в онлайне ;)

Весь мир строится на доверии, и надежды на то, что «нас-то всяко пронесёт». Иначе как ездить на машине, ходить по улице и писать на Хабр? :)
Спасибо за информацию. Со времён книжек Криса Касперски я знал, что виртуалки используются для защиты приложений, но даже не догадывался, как их может использовать Google в Android.
Если там нет криптопротоколов, то конкретная железка всегда будет отвечать то же самое, если BRAND, ABI, DEVICE не меняются. Если парни из Google знают, что Samsung A10 всегда выдаёт «bar» на вызов foo(), то на этом могут строить свою проверку. Соответственно, достаточно один раз прогнать на живом A10 виртуалку DroidGuard, записать всё, что система ей отдавала, и в дальнейшем всегда успешно проходить проверку.
Системных вызовов меньше 400 ;) И не удивлюсь, если Google под каждую железку, которая проходила у них сертификацию, уже сгенерила набор виртуалок, которыми пользуется.

Но это всё чисто теоретические измышлизмы, без конкретной цели монетизации этого взлома можно даже не начинать разбираться, слишком много работы :)
Вопрос несколько в другом: если DroidGuard работает в контексте стандартного Linux-процесса, то к железу за данными он пойдёт через системные вызовы, которые наверняка можно локализовать и идентифицировать? Я к тому, что может быть не надо разбирать, что делает внутри себя конкретная инкарнация виртуальной машины, может достаточно поместить её в окружение, которое предоставит ей все нужные для прохождения проверки данные?
Виртуальная машина DroidGuard пользуется системными функциями для получения информации из системы? Если они заранее известны и их количество ограничено, то что мешает эмулировать эти функции, если они вызываются в контексте обычного процесса?
Я не силён в PHP, но вот это оно? php.net/manual/ru/function.openssl-verify.php
Приложение передаёт на сервер originalJson и signature, которые используются в openssl_verify()

Тут есть ещё одна тонкость, что ответит сервер? Если он на проверку отвечает ok/error, то ничто не помешает в приложении подменить его ответ или убрать эту проверку. В идеале, если приложение после покупки получает доступ к какому-либо контенту, то этот контент должен загружаться с сервера с зашифрованном виде с ключом, который может быть сгенерирован только в этой инсталляции приложения. Если контент слишком большой для загрузки, то сервер может присылать что-то наподобие лицензионного ключа, позволяющего расшифровать контент в приложении.
В «покупке» идёт вместе с данными о покупке и цифровая подпись, которую надо проверить:
public class Purchase {
private final String mOriginalJson;
private final String mSignature;

Ниже я дал ссылку на пример, там есть функции проверки подписи: github.com/googlesamples/android-play-billing/blob/master/TrivialDriveKotlin/app/src/main/java/com/kotlin/trivialdrive/billingrepo/Security.kt

Надеюсь, перевести его с Kotlin на PHP не составит труда, там обычная проверка подписи с открытым RSA — ключом.
Не раскрыто две важных темы:
1. Кэш покупок, чтобы приложение могло работать в оффлайне.
2. Проверка валидности подписи покупки. Отсюда ещё возникает проблема скрытного хранения ключа проверки этой подписи внутри приложения (что не надёжно) или запуск собственного сервера по проверке этой покупки вне приложения (что рекомендуется Google).
В общих чертах это разобрано в свежем примере от Google: github.com/googlesamples/android-play-billing/tree/master/TrivialDriveKotlin

Добавьте разрешение в манифесте.

Billing-библиотека делает это сама, отдельно не надо ничего добавлять.
Про MVVM уже давно написано: antonioleiva.com/mvvm-vs-mvp
и снято, там есть видео от автора.
Что значит «почти в открытом виде»?

Они передавали MD5(password), считая это защищённым решением. Эти же данные хранили в базе без всяких солей и нонсов. Как их не взломали за несколько лет работы сайта я не знаю ;)

TLS пока не взломан

Я тоже так думал, пока мне антивирус не написал в отправляемом через gmail.com письме, что оно проверено, вирусов нет. Без пининга сертификата TLS бесполезен, хотя и работает в большинстве случаев. А пининг — это та ещё головная боль.

позволяя выполнить precomputation атаку

Насколько я помню, там с двух сторон передаются случайные нонсы, они помогут от такой атаки?

делать этого никто не хочет

Странное заявление. Если строится продукт (сайт, приложение, а то и всё сразу), то написать 200 строчек кода протокола с его модульными тестами и сколько-то строк доступа к базе данных на бэке — это не большая проблема по сравнению с медиаповодом в стиле «очередная утечка паролей у <тех, кто не хочет>». Хотя да, в большинстве своём архитекторы-аналитики в основном решают бизнес-задачи, им на реальную безопасность компании и клиентов глубоко фиолетово. И начинают шевелится только тогда, когда очередные пенетраторы им показывают список найденного ;)
Года три с лишним назад самолично внедрил SCRAM-аутентификацию сначала в мобильном приложении, а потом коллеги сделали то же самое на сайте одной большой организации. До этого там передавались пароли по HTTPS почти в открытом виде, они же хранились в базе данных. Протокол SCRAM немного модернизировали так, что клиенты вообще не заметили миграции со старой схемы на новую.

Странно, что на слайде 7 упор делается на то, что длительные/прожорливые функции выполняются на сервере. Чтобы не грузить бэки все долгие расчёты должны быть на клиенте, благо сейчас они все достаточно мощные по памяти и процессорам.

И главное, что нет PKI, которую надо обслуживать.

Information

Rating
Does not participate
Registered
Activity