In his new blog, Principal Analyst Alex Caithness dives into progressive web apps and WebAPKs and comes up to ask “When is an app not an app”? And more importantly, what data can possibly be extracted from them if you know where to look?
Recently while catching up on some interesting blogs, CCL’s R&D team happened across this write-up by ESET documenting a novel phishing attack using two technologies: progressive web apps and WebAPKs. This got us thinking more widely about how these technologies operate on Android and how we could detect their use and extract the data they might store on a device. What we found highlighted a number of areas where, unless you know what to look for, opportunities to maximise the meaning of this data could be missed.
A Progressive Web App (PWA) is an application which is built using web technologies (HTML, CSS, JavaScript) but is designed to give the look and feel of a native application. It is, in essence, just another website – it still needs a browser to be viewed and used. Depending on the browser being used, it may be launched in a special window without any of the usual browser controls (e.g., address bar, navigation controls, etc.). This is done so that it may have the look and feel of being a “fully fledged” native application with its own window, launcher icon, etc.
On modern versions of Android, when PWAs are installed by Chrome they are further enhanced by Chrome generating a WebAPK. A WebAPK wraps the PWA as a “real” app, allowing it to appear on the device’s app launcher, register intents with the operating system, and so on. To the user, this “application” appears to be a “first class citizen” of the operating system, on a par with any other native application; but to a digital forensics practitioner the story is somewhat more complex. Let’s try to unpick this tangled web …
Electron (along with similar technologies like WebView2) is a framework that can “wrap” an application based on web technologies so that it can be presented to the user in a way that mirrors a native application. This sounds a lot like a PWA, and not by accident – in many cases these frameworks may just be wrapping a PWA. There are a few key, important differences though:
From a user’s perspective
The “point” of a WebAPK application for a user is that it looks and acts like a “real” application. From the perspective of the device’s UI, the app appears to have a normal icon, it appears in the app launcher alongside other apps, it appears in the settings alongside other apps for uninstalling, and so on.
One clue can be spotted by “long-pressing” the application’s icon in the launcher: an additional option for “Site settings” that sits alongside the standard “App info” and “Pause app” menu items, which leads to a settings dialog which allows the user to manage the data stored by and the permissions granted to the application.
Depending on the version of Android, another indication may be found in the “App info” screen for the application, or this screen may straight up lie to you! We tested this behaviour both on version 14 of Android (the most recent version available to most users at the time of writing), and a beta of the upcoming version 15.
In version 15, the “App info” screen will show that the application was installed by Chrome rather than another store app (typically this would be the Play Store), which helps to confirm its status as a PWA or WebAPK – this is a useful indicator for us.
In version 14 (which is much more likely to be the version encountered at the time of writing), we observed that the “App info” screen incorrectly identified the app as being installed by the Play Store (which is a lie - deeply unhelpful for us as digital investigators, and a timely reminder that we need to validate our findings always). We assume that this behaviour is a bug in Android as tapping the button to go to the (alleged) Play Store page for this app results in an error dialog.
If the app is installed as a “basic” progressive web application (the default on earlier versions of Android and Chrome) then there is a far more obvious visual cue, as the icon on the home screen will be superimposed with the browser’s icon. In this case, the PWA will also be absent from the app drawer and will not be listed as an installed application in the Settings app.
The primary indication of a WebAPK application being present on a device is its package name. The package name is used by Android as an identifier for the application. They generally take a form along the lines of “com.example.abc123”; so for example, the Chrome browser application on Android has the package name “com.android.chrome”. The package name is found throughout the file system, most notably as the application’s folder in “/data/data” and in the “packages.xml” (not actually an XML file anymore, rather an ABX file) and “packages.list” files which list installed packages on the device.
The package name for a WebAPK will take the form: “org.chromium.webapk.[an identifier]”, for example, one of the apps we tested was assigned the package name: “org.chromium.webapk.a4241cb488be5dc45_v2”. This package name could well be misleading if you weren’t on the lookout for the “webapk” portion of the name, as “org.chromium” could reasonably be assumed to be related to some official component of the Chrome/Chromium browser.
This package name is found in all of the expected locations (as a folder in “data/data”, in the two packages files, etc.), however what isn’t clear at all from that package name is which app it is.
Given its ubiquity when it comes to seeing which packages are installed on a device, the “packages.xml” file might be a good place to go searching for more details on our WebAPK application. As expected, the “package” element related to this app only shows the package name (in Android 15, the package element also lists the “installer” and “updater” as being Chrome, unlike other applications which typically show “com.android.vending”; in Android 14 it incorrectly showed the default vending value). By searching for a corresponding “package-state” element, we can find an indication of the friendly name for the application which is displayed to the user.
There are other locations we identified which can be used to correlate the package name to the friendly name:
Conventional knowledge suggests that the first place to go looking for an app’s data is its package folder in “/data/data”. For a WebAPK if we head over there, we find… not much. Some basic preferences, but little related to user activity.
During testing we were making use of NowSecure’s extremely useful fsmon to keep tabs on where data was being sent as we performed actions in the application. And, well…
The activity related to using the WebAPK based application was all hitting the data folder for the device’s installation of Chrome. On the one hand this should be of little surprise sense given that the PWA is being run by Chrome, but what was slightly jarring was how little separation there was between the PWA’s data and the rest of Chrome.
We’ve written previously about the types of technologies used by websites to persist data on users’ machines, such as IndexedDB and WebStorage, and these data stores are, of course, used by PWAs too. To process data for this application, we would be looking to artefacts in these data stores, as well as data held in the web cache, history, cookies etc., and bringing them together to give a picture of the user’s activities on the web app - exactly the approach we have been advocating when dealing with browser artefacts, and the reason that these data formats are supported directly in CCL’s data exploration tool RabbitHole and why we created our browser forensics tool Mister Skinnylegs.
This does raise a question: how do we differentiate “app” usage from general browser usage? And the answer is… for the most part it doesn’t appear that we can. The WebAPK application is just running in Chrome, even if it doesn’t look like it to the user. Data stores like Local Storage, Session Storage and IndexedDB appear no different to if the site had been used through the “real” browser and we can find no clues in cache entries either.
There are a few indications that we have identified that show that browser data might be connected to a WebAPK/PWA though, which luckily all have timestamps associated with them.
The first indicator is in the History database. Initially accessing a WebAPK is just a visit to a website and using it might also involve web navigation (although many progressive web apps are single-page sites), these all generate records in the History database.
Visits in the history database have a “transition” field, which is stored as an integer value, but is actually storing a set of binary flags. When these flag values are parsed (the flags are defined in page_transition_types.h), the visit which represents the WebAPK application being opened will contain the transition flag “PAGE_TRANSITION_FROM_API” which is distinct from normal browsing records (but could feasibly be present for other reasons). Other navigation events that take place within the PWA do not have this flag however, but it should be able to be identified as part of the app activity by way of the “from_visit” field which shows chains of navigations. Be aware that different tools parse and show this information in differing levels of detail (and some tools may not show it at all); the screenshot below is from our free research tool for Chrome artefacts and you can see the app launches where the Transition field includes “from_api”.
The next, and arguably best indicator (if it is present) comes from the “custom_tabs” artefact. This resides outside of the Chrome profile folder in “/data/data/com.android.chrome/app_tabs/custom_tabs” and contains tab and tab state files for the special “featureless” browser instances that the PWA/WebAPK runs in. These files are the same structure as those found in the main numbered folder, and the “tab” files contain navigation events (encoded as a pickle, structure documented here and supported in our Chromium Python library) which include a timestamp for when the navigation took place.
The presence of these files alone is a good indication that PWAs or WebAPKs have been used, and they do appear to persist for some time after the application has been closed (including between restarts), but we would expect to see these purged at some point, in line with Chrome’s “main” tab state files.
CCL’s R&D department have long been banging the drum with regards to the richness of evidence that can be uncovered by treating browser artefacts related to particular websites and Web apps holistically: bringing together data from all of the various data stores in the browser to get the full picture. With progressive web apps and their new elevated status as WebAPKs in Android, we have applications which otherwise appear to be native to the OS whose data can only be considered in this fashion.
Being able to identify the presence of a WebAPK application, understanding what it is and knowing where its data is likely to be stored (and where its data will not be stored) will be important skills for any DFIR practitioner working with Android devices.
Our experts are on hand to learn about your organisation and suggest the best approach to meet your needs. Contact an expert today.
Get in touch