How to detect Pushwoosh hidden Russian software in your mobile supply chain

On Monday, Reuters released an article disclosing “Russian software disguised as American finds its way into U.S. Army, CDC apps”. In it, they share:

Thousands of smartphone applications in Apple and Google’s online stores contain computer code developed by a technology company, Pushwoosh, that presents itself as based in the United States, but is actually Russian, Reuters has found.

The article is a fascinating read, almost from a spy novel, including fake business addresses and even fake LinkedIn profiles of “two Washington, D.C.-based executives” which Max Konev (Pushwoosh’s founder) acknowledged were not genuine.

Supply chain attacks are incredibly powerful precisely because a single popular SDK can surveil billons of devices and easily pass that information along to nation-state actors. According to Pushwoosh’s website, they have more than 2.3 billion devices listed in their tracking database.

In the past, researches at NowSecure (full disclosure: I’m a co-founder) have disclosed similar security and privacy flaws in other SDKs including Vungle Arbitrary Write Vulnerability (CVE-2014-9333), Adlibr and more.

The goal of this article is to help organizations detect Pushwoosh in their mobile app supply chains, specifically:

  • apps you use
  • apps you build

I’ll also provide a glimpse of a few network flows from the Pushwoosh SDK in mobile app where you can see the sensitive tracking occur.

The instructions below are more of a technical DIY so if you’d prefer to just have a quick answer about a particular app or have a large volume of apps your enterprise uses, you can just Contact Us and we can easily assist. Each of the techniques below also assume you have have a NowSecure account. You can register for a Free Trial is you’re not a customer and full instructions are documented at the end of this article. See Obtain NowSecure token and group_id below.

Pushwoosh and sensitive data

At NowSecure, we perform both static binary and dynamic analysis of mobile apps on real devices. This allows us to not only look for security issues but to also spot privacy issues as well. In particular, we are able to inspect traffic encrypted inside TLS tunnels so see if apps (or SDK!) are over tracking sensitive data.

Since Pushwoosh is a customer engagement platform, they will obviously need to collect significant amount of data about mobile users, their interactions, etc. With such power, obviously comes great responsibility and the need for trust. That’s why the industry has reacted so strongly to what appears to be intentionally hiding their Russian origins.

While we have not done extensive analysis, I did pull a few network flows from mobile apps that had the Pushwoosh SDK installed. Side note: we detected thousands of iOS and Android apps that have Pushwoosh installed so this is just a one off peek at the initial data flows (not the extensive tracking) in Pushwoosh.

Pushwoosh Android initial data flows

While there are a number of common Pushwoosh servers, what I saw across two different apps is that the primary host for sending sensitive data to change. For this Android app, the initial data was pushed to an API at https://26BC2-66AE2.api.pushwoosh.com/json/1.3/. The initial data flows registered the user and the subsequent data flows followed this pattern (some data obfuscated):

"ContentValues": "multiplicity=1 event_start=9035 sequence_nr=-1 
event_id=30 visitor_id=3707472073 session_id=1 server_id=8 
basic_segment=vv=3&va=8.231.2.1007&ap=7bca110c-b805-44d6-a45e-fea99744fc9e
&an=<APP_NAME>&ai=<APP_PACKAGEID>&vn=<APP_VER>&vb=230230383
&vi=3707472073&sn=1&rm=3593&cp=AArch64+rev+12+%28aarch64%29&os=Android+9
&mf=Google&md=Pixel+3a&rj=g&ul=en_US&sw=1080&sh=2220&sd=440&pt=0&so=p
&bl=100&fm=2077&cr=&ct=w&np=802.11x&tt=maandroid&dl=2&cl=2&vs=1&fv=pl 
event_segment=et=30&na=https%3A%2F%2F26BC2-66AE2.api.pushwoosh.com%2Fjson%2F1.3%2FgetConfig
&it=558&pa=0&s0=27&t0=9035&s1=29&t1=247&rc=200&bs=558&br=545 
session_start=1651764351256"

The items that stand out for me (but also expected for the use case) include:

  • Device name (Pixel 3a) which can include PII, e.g. (Andrew Hoog’s Pixel)
  • Specific OS and architecture info (AArch64 rev 12, aarch64, Android+9) which would be key to understanding potentially exploitable security issues in the device/OS
  • Language/locale (en_US) which is really helpful to spot people traveling in different countries/regions
  • Device config identifiers (e.g. screen resolution) which is great for fingerprinting a device and user

Again, all of this data is also useful for the express purpose that a customer engagement use case would require so this is more about trustworthiness with highly sensitive data.

Pushwoosh iOS initial data flows

Similarly with iOS, the primary API endpoint used for data uploads was https://26BC2-66AE2.api.pushwoosh.com/json/1.3/applicationOpen however I would expect this to change from platform to platform or perhaps even per region, customer, device, etc.

{
  "request": {
    "device_type": 1,
    "language": "en",
    "application": "AF674-86CC2",
    "userId": "74EA8014-4472-4BC9-8870-7F569C76816F",
    "v": "4.18.0",
    "hwid": "8C5E1337-4472-4BC9-8870-7F569C76AA61"
  }
}

as well as:

{
  "request": {
    "jailbroken": 0,
    "idfa": "AC2074C3-F609-43EC-825C-0AA60245CE29",
    "app_version": "11.1.3",
    "notificationTypes": 0,
    "application": "AF674-86CC2",
    "device_type": 1,
    "userId": "74EA8014-4472-4BC9-8870-7F569C76816F",
    "language": "en",
    "hwid": "8C5E1337-4472-4BC9-8870-7F569C76AA61",
    "package": "APP_PACKAGEID",
    "os_version": "13.3",
    "device_model": "iPad11,1",
    "v": "5.23.0"
  }
}

Again, we’re seeing similar type of user tracking, including idfa which is an intended id for advertisers but since very few folks reset the idfa, this can be a powerful tracker. Also, since a userId is created for each user, it would likely be trivial to tie changes in idfa together.

It’s also interesting to note they are tracking jailbreak status. This may also be a key proprety to understand if a particular device is easier to target and compromise.

Leverage binary analysis to detect all dependencies

After a decade of testing mobile apps, I’ve learned that nearly every mobile apps leverages 3rd party SDKs to quickly build their app. These 3rd party dependencies can be included both directly and indirectly (called transitive dependencies, or the dependencies 3rd party SDK use) in your mobile app so it’s critical you leverage a technique called binary analysis to make you to detect all dependencies in your mobile app.

If you have access to source code and only use static source analysis, you will be detect detect direct dependencies but you will miss critical transitive dependencies, especially in closed source SDKs. Also, in m any instances you will not have access to source code so binary analysis is your only good option.

If you’d like to learn more about these techniques, you can check out my blog+video “Source Code vs Binary Analysis for SBOMs”. Also, both of the techniques below will leverage NowSecure Platform to analyze the mobile app and provide a CycloneDX SBOM.

Detecting Pushwoosh in mobile apps you use

If you don’t have the source code for a mobile app, we can easily pull the latest version of the mobile app from the Apple App or Google Play stores. Log into your NowSecure account (see Obtain NowSecure token and group_id) and click on the + Add Add button. From there, you can select which store, group and then search for an app by name (in this case I searched for the amazing open source Home Assistant mobile app):

image nsp-add-app-search.png Then select “Add App & Run Assessment”:

nsp-add-app.png And choose “Run Baseline Assessment”. Finish up any final confirmations and then select the security report to monitor progress:

nsp-assessment-in-progress.png After the assessment complete, you can view the security and privacy report and select the “Software Bill of Materials - Included Libraries” finding. You’ll want to look for any components with Pushwoosh in the name .

nsp-report-sbom.png

Alternatively, you can follow the directions below to Pull CycloneDX from REST API and just use grep to search for Pushwoosh. To do this, you will need the assessment_ref which you can find in the URL (e.g. 2nd UUID in the url) or click on the “Debug -> Assessment Info section” and copy the assessmentRef from there.

nsp-debug-info.png You can then use the command line instructions below to search for Pushwoosh in the mobile app.

Detecting Pushwoosh in mobile apps you build

For this example, we’ll assume you have access to your mobile app binary (Android or iOS). Below, I’ll demonstrate how you can upload the mobile app from command line however you can add use the “+ Add App” approach above to upload from our Web UI. You can also integrate into your CI/CD system directly so a SBOM is generated each time you build the app. There are plugins for common CI/CD integrations and I have a full tutorial on how to integration with our GitHub Action in the blog+video “How to generate an Android SBOM per build with Github Actions”.

Upload app binary

With the access to the above info, you can kick off an assessment command line with the following steps (note: the group uuid is specific to an account and a group so you will need to grab that from the web UI or API as well):

$ export API_TOKEN=<your jwt token here>

$ curl -H "Authorization: Bearer ${API_TOKEN}" -X POST https://lab-api.nowsecure.com/build/?group=ad2c4c53-7fbf-4f81-8170-ee9b97a1ea5c --data-binary @path/to/android-app.apk/or/ios-app.ipa

{
  "ref": "884a9f76-2f94-11ed-8006-bf3e96875a84",
  "application": "d3e19eca-2552-11ec-802b-0706d3891337",
  "group": "2036694c-6441-11ed-8a43-6b1153bce076",
  "account": "<snip>",
  "platform": "android",
  "package": "<redacted>",
  "task": 1362936711029,
  "creator": "<snip>",
  "created": "2022-11-14T18:15:05.257Z",
  "favorite": false,
  "binary": "9e4f8023da6900e6b937323a73c77dd8ed2f3aa6b010ec054d7c1787bf557b54",
  "config": { <snip> },
  "status": {
    "static": {
      "state": "pending"
    },
    "dynamic": {
      "state": "pending"
    }
  },
  "cancelled": false,
  "task_status": "pending",
  "events": {
    "dynamic": []
  }
}

After the scan is complete, you can use the assessment reference (2036694c-6441-11ed-8a43-6b1153bce076 in this example) to pull the results.

Pull CycloneDX from REST API

NowSecure provides a REST API to transform the binary component analysis into CycloneDX format:

$ curl -H "Authorization: Bearer ${API_TOKEN}" https://api.nowsecure.com/assessment/2036694c-6441-11ed-8a43-6b1153bce076/cyclonedx/

and here’s a snippet of the results:

<?xml version="1.0"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.3" version="1">
  <metadata>
    <timestamp>2022-11-14T18:15:05.257Z</timestamp>
    <tools>
      <tool>
        <vendor>NowSecure</vendor>
        <name>Platform</name>
      </tool>
    </tools>
    <component type="application" bom-ref="redacted.app@1.34.2022101907">
      <name>Redacted App Name</name>
      <version>1.34.2022101907</version>
    </component>
  </metadata>
  <components>
    <component type="library">
      <name>com.pushwoosh</name>
      <version>unknown</version>
      <description>/base.apkclasses4.dex</description>
      <licenses>
        <license>
          <name>Pushwoosh License</name>
        </license>
      </licenses>
      <purl>pkg:maven/com/pushwoosh</purl>
    </component>
	<snip>
  </components>	
  <services>
    <service>
      <name>firebase-settings.crashlytics.com</name>
    </service>
    <service>
      <name>graph.facebook.com</name>
    </service>
    <service>
      <name>cp.pushwoosh.com</name>
    </service>
    <service>
      <name>837ac-53586.api.pushwoosh.com</name>
    </service>
    <service>
      <name>media24.pushwoosh.com</name>
    </service>
</bom>

As you can see from the above example, binary analysis is able to identify direct and transitive versions of 3rd party SDKs that source code analysis might miss. For the above snippet, the Pushwoosh component name is com.pushwoosh and you can see network flows that we track in the service portion of the CycloneDX SBOM including:

  • cp.pushwoosh.com
  • 837ac-53586.api.pushwoosh.com
  • media24.pushwoosh.com

If you wanted to use grep to quickly search for Pushwoosh components, you can use this command:

$ curl -s -H "Authorization: Bearer ${API_TOKEN}" https://api.nowsecure.com/assessment/2036694c-6441-11ed-8a43-6b1153bce076/cyclonedx/ | grep -i pushwoosh
      <name>com.pushwoosh</name>
          <name>Pushwoosh License</name>
      <purl>pkg:maven/com/pushwoosh</purl>
      <name>cp.pushwoosh.com</name>
      <name>837ac-53586.api.pushwoosh.com</name>
      <name>media24.pushwoosh.com</name>

Obtain NowSecure Platform token and group_id

If you’re a current NowSecure Platform customer, you can simply log into NowSecure Platform.

Otherwise you can sign up for 10 free SBOMs and access the results in from NowSecure Platform UI, REST API or via our Mobile SBOM GitHub Action. For NowSecure customers, this functionality is included in your subscription!

Once you have access to a NowSecure account, you’ll need to generate an API JWT token and then determine your app’s group id.

NowSecure JWT Token

First, you’ll log in to NowSecure Platform and then (step-by-step documented in “Creating an API Bearer Token in Platform”):

User Profile (upper right) -> Tokens -> Add token name -> Generate -> Copy token

Make sure you store your token security so you can reference it later.

NowSecure app group id

Similarly, let’s find out our default app group id in NowSecure Platform (see also “Where can I find the GroupID for the API?”):

Apps -> Select App -> Package Details

and they click the copy icon next to the app group (e.g. Auto Group). Go ahead and stash the copied UUID somewhere so we can use it in our command line calls.