Хотел бы рассказать о мобильных рекламных сетях, об их системе защиты и способах её обхода. Способы обхода систем защиты применялись только в образовательных целях. Также замечу, что алгоритмы атак, представленные здесь, справедливы для любых платформ, однако в примере приводится работа Android, т.к. атаки на его код самые простые для описания.
Что такое мобильная рекламная сеть? Это клиент-серверное приложение, в котором сервер принимает от клиентских приложений доклады о запуске приложения, совершения кликов по рекламе и совершения действий, а также высылает им рекламу для отображения пользователю. Клиентские приложения же являются библиотеками, способными взаимодействовать с сервером, которые обычно встраиваются в мобильные приложения сторонних разработчиков.
Мощность рекламной сети измеряется в количестве пользователей у приложений, которые показывают рекламу, что логично — чем больше рекламы сеть сможет показать пользователям, тем больше денег она заработает и тем привлекательнее она будет для других рекламодателей.
Чтобы увеличить количество приложений, показывающих рекламу, сети стараются привлечь сторонние приложения вместо написания своих. Они предоставляют разработчикам своё рекламное SDK, способное общаться с их серверами. За это они дают таким разработчикам определённый % от заработанных денег за показы клики или действия, совершённые со стороннего приложения. В этом честном сотрудничестве довольны все: рекламная сеть получает новое приложение с готовой аудиторией, которой можно показывать рекламу, сторонний разработчик получает деньги с этой рекламы, а рекламодатель — большую аудиторию.
Любому партнёру рекламной сети выдаётся пара appId — ID приложения в базе рекламной сети и secret — секретный ключ для подписывания действий. Любому — в идеале, т.к. некоторые рекламные сети выдают его только рекламодателям.
Что происходит дальше? При старте приложения эта пара поступает в рекламное SDK и всё, работа добросовестного интегратора на этом этапе заканчивается. Если это рекламирующее приложение — оно делает запрос на сервер, посылая все свои параметры (различные идентификаторы, такие как imei, openudid, udid, serial), информацию об устройстве и платформе и свой appId. Всё это она подписывает секретом, обычно делая sha1 хеш от пересылаемых параметров и добавляя его к запросу. Сервер, после проверки подлинности, выдаёт приложению рекламу. Каждая рекламная единица сопровождается комплектом из двух ссылок. Это ссылка на пока (которая есть не у всех рекламных сетей) и ссылка на клик. Когда реклама появляется на экране и пользователь её реально видит — дёргается ссылка на показ и факт показа отправляется на сервер. Если же пользователь заинтересуется и сделает клик — факт клика также уйдёт на сервер по другой ссылке.
В результате этих действий рекламирующее приложение, с которого были совершены действия — получит деньги.
Что будет, если разработчик недобросовестный и хочет получить деньги просто так? В этом случае он также регистрируется в рекламной сети, интегрирует в него рекламную SDK и выводит приложение на рынок. Далее ему нужно послать поддельный запрос на получение реальной рекламы, отослать факт показа и клика и получить деньги. Чтобы это сделать, необходимо изучить, какие параметры необходимы для запроса и их формат. Некоторые рекламные сети сами пишут эту информацию в документации, у других открыт исходный код SDK. Третьи поставляют свои SDK, как библиотеки с закрытым исходным кодом. Злоумышленник должен получить библиотеку рекламной сети, после чего изменить механизм формирования рекламного запроса таким образом, чтобы идентификаторы устройства не собирались, а генерировались случайным образом.
В итоге злоумышленник отсылает запрос на рекламу с appId своего рекламирующего приложения и несуществующего устройства. Потом получает рекламу и дёргает ссылки на совершение действий. Всё просто.
Защититься от такого мошенничества на стороне SDK невозможно, поэтому рекламные сети отказываются от рекламы с просмотрами и кликами и переходят к следующему типу рекламы — реклама за установки.
Подделывать установки сложнее, т.к. в них принимает участие рекламирующееся приложение. При добросовестном использовании сразу после клика по рекламе заинтересовавшийся пользователь начинает установку этого приложения. Когда приложение установлено оно также использует рекламную SDK, чтобы отправить факт установки на сервер. В случае рекламы за действия — факта установки не достаточно. Пользователь после установки должен выполнить в приложении определённое действие, о котором также будет доложено рекламной сети.
Злоумышленнику необходимо знать секретный ключ рекламирующегося приложения, чтобы послать поддельный факт установки или действия.
Как это сделать? Необходимо 1 раз скачать приложение, декомпилировать и получить секретный ключ. Для платформы Android это не вызовет сложности.
Пакеты приложений под ОС Android поставляются в виде архивов с расширением apk. В архиве находятся ресурсы приложения, медиа-файлы, прочие файлы и dex-файл со скомпилированными классами приложения.
Именно он и интересует злоумышленника. С помощью приложения dex2jar злоумышленник может получить jar-ахрив со скомпилированным исходным кодом приложения и после этого приступить к декомпиляции для получения секретного кода.
В случае, если разработчик приложения не уделял внимания защите приложения и не обфусцировал код, секретные параметры приложения будут храниться в открытом виде в коде. Достаточно лишь сделать поиск по классу и функции, которая вызывает рекламное SDK.
В большинстве случаев разработчики приложений стараются усложнить взлом, перенося секрет и id приложения рекламной сети из кода, где его можно просто достать, в ресурсы и обфусцируя приложение, чтобы запутать злоумышленника.
Ресурсы приложения находятся там же в apk-пакете в файле resources.arsc. Это специальный файл, содержащий таблицу ресурсов приложения. На рисунке выше видно, что цель злоумышленника — секрет и id приложения в рекламной сети спрятаны в файлах с ресурсами, а код, вызывающий их, обфусцирован.
Секрет и id данного приложения были спрятаны в файле ресурсов. Вместе с тем, все идентификаторы ресурсов при компиляции приложения под Android заносятся в R.class, который генерирует Android SDK. Поэтому злоумышленник может подсмотреть по номеру id название ресурса, который вызывается. Во фрагменте кода id приложению соответствует код 2131165201, а секрету — код 2131165202.
Поиск по этим кодам в R классе показывает, что используется ресурс с названием tapjoy_amazon_app_id и tapjoy_amazon_secret_key. Всё, что теперь нужно злоумышленнику — получить доступ к файлу ресурсов strings.xml, закодированном в resources.arsc.
Чтобы это сделать, необходимо декодировать apk-пакет приложения с помощью утилиты apktool, после чего станут доступными все ресурсы приложения и злоумышленник может просто открыть его текстовым редактором и найти ресурсы по заранее полученным именам.
Как только злоумышленник получил секретный ключ, он может отправить факт фальшивой установки с тех поддельных идентификаторов, которые он сгенирировал на этапе запроса рекламы.
Что такое мобильная рекламная сеть? Это клиент-серверное приложение, в котором сервер принимает от клиентских приложений доклады о запуске приложения, совершения кликов по рекламе и совершения действий, а также высылает им рекламу для отображения пользователю. Клиентские приложения же являются библиотеками, способными взаимодействовать с сервером, которые обычно встраиваются в мобильные приложения сторонних разработчиков.
Мощность рекламной сети измеряется в количестве пользователей у приложений, которые показывают рекламу, что логично — чем больше рекламы сеть сможет показать пользователям, тем больше денег она заработает и тем привлекательнее она будет для других рекламодателей.
Чтобы увеличить количество приложений, показывающих рекламу, сети стараются привлечь сторонние приложения вместо написания своих. Они предоставляют разработчикам своё рекламное SDK, способное общаться с их серверами. За это они дают таким разработчикам определённый % от заработанных денег за показы клики или действия, совершённые со стороннего приложения. В этом честном сотрудничестве довольны все: рекламная сеть получает новое приложение с готовой аудиторией, которой можно показывать рекламу, сторонний разработчик получает деньги с этой рекламы, а рекламодатель — большую аудиторию.
Любому партнёру рекламной сети выдаётся пара appId — ID приложения в базе рекламной сети и secret — секретный ключ для подписывания действий. Любому — в идеале, т.к. некоторые рекламные сети выдают его только рекламодателям.
Что происходит дальше? При старте приложения эта пара поступает в рекламное SDK и всё, работа добросовестного интегратора на этом этапе заканчивается. Если это рекламирующее приложение — оно делает запрос на сервер, посылая все свои параметры (различные идентификаторы, такие как imei, openudid, udid, serial), информацию об устройстве и платформе и свой appId. Всё это она подписывает секретом, обычно делая sha1 хеш от пересылаемых параметров и добавляя его к запросу. Сервер, после проверки подлинности, выдаёт приложению рекламу. Каждая рекламная единица сопровождается комплектом из двух ссылок. Это ссылка на пока (которая есть не у всех рекламных сетей) и ссылка на клик. Когда реклама появляется на экране и пользователь её реально видит — дёргается ссылка на показ и факт показа отправляется на сервер. Если же пользователь заинтересуется и сделает клик — факт клика также уйдёт на сервер по другой ссылке.
В результате этих действий рекламирующее приложение, с которого были совершены действия — получит деньги.
Просмотры и клики
Что будет, если разработчик недобросовестный и хочет получить деньги просто так? В этом случае он также регистрируется в рекламной сети, интегрирует в него рекламную SDK и выводит приложение на рынок. Далее ему нужно послать поддельный запрос на получение реальной рекламы, отослать факт показа и клика и получить деньги. Чтобы это сделать, необходимо изучить, какие параметры необходимы для запроса и их формат. Некоторые рекламные сети сами пишут эту информацию в документации, у других открыт исходный код SDK. Третьи поставляют свои SDK, как библиотеки с закрытым исходным кодом. Злоумышленник должен получить библиотеку рекламной сети, после чего изменить механизм формирования рекламного запроса таким образом, чтобы идентификаторы устройства не собирались, а генерировались случайным образом.
Взлом закрытой библиотеки
Закрытые SDK под Android обычно распространяются в виде jar-архива со скомпилированными классами. Исходный java-код можно получить с помощью Java-декомпилятора, например, jd gui. Здесь может возникнуть проблема маскировки методов во вложенных классах. Java-компилятор в случае вложенности класса в класс и вызове метода верхнего класса из нижнего меняет вызов метода на сгенерированный идентификатор метода $access. В этом случае злоумышленнику нужно догадываться, какой метод должен быть вызван по смыслу и по передаваемым параметрам. Данное неудобство не сильно затруднит действия злоумышленника, однако может затруднить автоматизацию взлома SDK.
В итоге злоумышленник отсылает запрос на рекламу с appId своего рекламирующего приложения и несуществующего устройства. Потом получает рекламу и дёргает ссылки на совершение действий. Всё просто.
Защититься от такого мошенничества на стороне SDK невозможно, поэтому рекламные сети отказываются от рекламы с просмотрами и кликами и переходят к следующему типу рекламы — реклама за установки.
Установки и действия
Подделывать установки сложнее, т.к. в них принимает участие рекламирующееся приложение. При добросовестном использовании сразу после клика по рекламе заинтересовавшийся пользователь начинает установку этого приложения. Когда приложение установлено оно также использует рекламную SDK, чтобы отправить факт установки на сервер. В случае рекламы за действия — факта установки не достаточно. Пользователь после установки должен выполнить в приложении определённое действие, о котором также будет доложено рекламной сети.
Злоумышленнику необходимо знать секретный ключ рекламирующегося приложения, чтобы послать поддельный факт установки или действия.
Как это сделать? Необходимо 1 раз скачать приложение, декомпилировать и получить секретный ключ. Для платформы Android это не вызовет сложности.
Пакеты приложений под ОС Android поставляются в виде архивов с расширением apk. В архиве находятся ресурсы приложения, медиа-файлы, прочие файлы и dex-файл со скомпилированными классами приложения.
Именно он и интересует злоумышленника. С помощью приложения dex2jar злоумышленник может получить jar-ахрив со скомпилированным исходным кодом приложения и после этого приступить к декомпиляции для получения секретного кода.
В случае, если разработчик приложения не уделял внимания защите приложения и не обфусцировал код, секретные параметры приложения будут храниться в открытом виде в коде. Достаточно лишь сделать поиск по классу и функции, которая вызывает рекламное SDK.
Декомпилированный класс
В большинстве случаев разработчики приложений стараются усложнить взлом, перенося секрет и id приложения рекламной сети из кода, где его можно просто достать, в ресурсы и обфусцируя приложение, чтобы запутать злоумышленника.
Ресурсы приложения находятся там же в apk-пакете в файле resources.arsc. Это специальный файл, содержащий таблицу ресурсов приложения. На рисунке выше видно, что цель злоумышленника — секрет и id приложения в рекламной сети спрятаны в файлах с ресурсами, а код, вызывающий их, обфусцирован.
Обфусцированный класс
Об этом можно судить по тому, что вместо строки вида TapjoyConnect.requestTapjoyConnect(paramContext.getApplicationContext(), «appId», «secret»); находится цикл, проходящий 1 раз и получающий id приложения и секрет из ресурсов. В этом случае злоумышленнику приходится искать интересующий его фрагмент кода во всём приложении и анализировать весь запутанный обфускатором код.
Об этом можно судить по тому, что вместо строки вида TapjoyConnect.requestTapjoyConnect(paramContext.getApplicationContext(), «appId», «secret»); находится цикл, проходящий 1 раз и получающий id приложения и секрет из ресурсов. В этом случае злоумышленнику приходится искать интересующий его фрагмент кода во всём приложении и анализировать весь запутанный обфускатором код.
Секрет и id данного приложения были спрятаны в файле ресурсов. Вместе с тем, все идентификаторы ресурсов при компиляции приложения под Android заносятся в R.class, который генерирует Android SDK. Поэтому злоумышленник может подсмотреть по номеру id название ресурса, который вызывается. Во фрагменте кода id приложению соответствует код 2131165201, а секрету — код 2131165202.
Поиск по этим кодам в R классе показывает, что используется ресурс с названием tapjoy_amazon_app_id и tapjoy_amazon_secret_key. Всё, что теперь нужно злоумышленнику — получить доступ к файлу ресурсов strings.xml, закодированном в resources.arsc.
Чтобы это сделать, необходимо декодировать apk-пакет приложения с помощью утилиты apktool, после чего станут доступными все ресурсы приложения и злоумышленник может просто открыть его текстовым редактором и найти ресурсы по заранее полученным именам.
Найденные ресурсы
Как только злоумышленник получил секретный ключ, он может отправить факт фальшивой установки с тех поддельных идентификаторов, которые он сгенирировал на этапе запроса рекламы.
Рекомендации рекламным сетям
Защиты рекламной SDK в данном случае недостаточно. Даже если использовать нативную библиотеку вместо Java — удастся лишь затруднить взлом (и нажить проблемы с совместимостью), т.к. она распространяется свободно и всегда будет доступна злоумышленнику. Чтобы ловить поддельные факты — нужно использовать следующее:
В случае логической защиты нужно:
Соблюдение рекомендаций для логической защиты позволит значительно снизить темпы фальсификации фактов злоумышленником, однако если он тоже догадается посмотреть этот спойлер, то рекламной сети понадобится более сложная защита.
Необходимо проверять реальное количество установок для рекламирующих приложений. К сожалению, в данный момент магазины приложений не предоставляют этой информации третьим лицам. Однако можно посмотреть в сторону Google Analytics. Если количество устройств, на которые идёт реклама, превышает количество установленных, то партнёр является злоумышленником.
Также можно следить за всеми устройствами, которые посылают факты установок/запросов на рекламу. И если в течение месяца с данных идентификаторов не было произведено никакого действия — считать такое устройство случайно сгенерированным злоумышленником и несуществующим.
Если у рекламной сети достаточно трафика, то не стоит отправлять одну и ту же рекламу одному рекламирующему приложению. Это существенно снизит скорость взлома, т.к. злоумышленник всегда будет получать секреты рекламодателей медленные, чем будет происходить ротация рекламы.
И в заключение — требуйте, чтобы ваши рекламодатели обфусцировали код в обязательном порядке и введите смену секрета раз в некоторое время либо на определённое количество подписываний фактов.
В случае логической защиты нужно:
- не учитывать клики, если перед этим не было запроса на рекламу
- не учитывать клики, если перед этим не было факта просмотра
- не учитывать установки, если после клика прошло слишком мало времени (зависит от размера скачиваемого приложения)
- запоминать, какая реклама была отдана в запросе на рекламу и не допускать просмотров/кликов по рекламе, которую пользователь не получал
- после клика не допускать кликов по другим рекламам из той же выдачи
Соблюдение рекомендаций для логической защиты позволит значительно снизить темпы фальсификации фактов злоумышленником, однако если он тоже догадается посмотреть этот спойлер, то рекламной сети понадобится более сложная защита.
Необходимо проверять реальное количество установок для рекламирующих приложений. К сожалению, в данный момент магазины приложений не предоставляют этой информации третьим лицам. Однако можно посмотреть в сторону Google Analytics. Если количество устройств, на которые идёт реклама, превышает количество установленных, то партнёр является злоумышленником.
Также можно следить за всеми устройствами, которые посылают факты установок/запросов на рекламу. И если в течение месяца с данных идентификаторов не было произведено никакого действия — считать такое устройство случайно сгенерированным злоумышленником и несуществующим.
Если у рекламной сети достаточно трафика, то не стоит отправлять одну и ту же рекламу одному рекламирующему приложению. Это существенно снизит скорость взлома, т.к. злоумышленник всегда будет получать секреты рекламодателей медленные, чем будет происходить ротация рекламы.
И в заключение — требуйте, чтобы ваши рекламодатели обфусцировали код в обязательном порядке и введите смену секрета раз в некоторое время либо на определённое количество подписываний фактов.
Дальнейшие действия
Этот спойлер не является рекомендациями злоумышленникам. Его цель — показать сетям, что возможны не только штучные взломы и им есть чего бояться.
Если злоумышленник серьёзно подойдёт к вопросу взлома, он вполне сможет его автоматизировать. Поиск даже по обфусцированному коду не является сложной задачей, т.к. имя класса и метод вызова рекламной SDK всегда открыт. А если учесть, что достаточно большой процент разработчиков не обфусцируют код — то можно в автоматическом режиме получить достаточно большое количество секретов.
Схема, по которой могут действовать злоумышленники заключается в создании нескольких приложений, задача которых — сбор большого количества рекламирующихся приложений для взлома. Как только накопится достаточно большое количество данных — можно запускать приложение, которое использует собранные базы для отправки фальсифицированных данных.
Если злоумышленник серьёзно подойдёт к вопросу взлома, он вполне сможет его автоматизировать. Поиск даже по обфусцированному коду не является сложной задачей, т.к. имя класса и метод вызова рекламной SDK всегда открыт. А если учесть, что достаточно большой процент разработчиков не обфусцируют код — то можно в автоматическом режиме получить достаточно большое количество секретов.
Схема, по которой могут действовать злоумышленники заключается в создании нескольких приложений, задача которых — сбор большого количества рекламирующихся приложений для взлома. Как только накопится достаточно большое количество данных — можно запускать приложение, которое использует собранные базы для отправки фальсифицированных данных.