Mark L. Murphy's Blog, page 13
February 1, 2021
���Elements of Android Room��� Version 0.4 Released
Subscribers now haveaccess to Version 0.4 of Elements of Android Room,in PDF, EPUB, and MOBI/Kindle formats. Just log intoyour Warescription page to download it,or set up an account and subscribe!
This update adds three more chapters, covering:
SQLite clients for inspecting your Room databases
The basics of using SQLCipher for Android for encrypted Room databases
Options for SQLCipher for Android passphrases
In addition:
A bunch of dependencies were updated, notably Room itself
Various bugs were fixed
January 27, 2021
Checking for Poisoned Projects
Yesterday, Google wrote abouta campaign to hack the machines of security researchers.One means of doing that was via malware embedded in a Visual Studio project:
After establishing initial communications, the actors would ask the targeted researcher if they wanted to collaborate on vulnerability research together, and then provide the researcher with a Visual Studio Project. Within the Visual Studio Project would be source code for exploiting the vulnerability, as well as an additional DLL that would be executed through Visual Studio Build Events. The DLL is custom malware that would immediately begin communicating with actor-controlled C2 domains.
(here, ���C2��� means ���command and control���, not a cell in the classic game of Battleship)
I have not used Visual Studio in a couple of decades, and I am rather surprisedthat one can contain a Windows DLL. Shipping binaries around like that used tobe frowned upon, just for this sort of reason, but convenience has come to theforefront in modern software development.
Android has its equivalent problems, courtesy of conventionsaround Gradle. I have warned about these for years ���the earliest warning I have found is from 2015. But, in light of this andthe SolarWinds hack,let me ���re-up��� my warnings about importing and running random projects thatyou find��� including just about anything on GitHub.
Yes, even my projects.
RULE #1: Only Use a distributionUrl That You TrustWhenever you want to use a project from a semi-random source, go intogradle/wrapper/gradle-wrapper.properties and look at the distributionUrlvalue:
distributionUrl=https\://services.gradle.org/distributions/gra...You only want to use a distributionUrl that seems safe. Primarily, thatwill be a URL pointing to services.gradle.org. In the future, it would notshock me if Google started hosting Gradle binaries, in which case we may cometo trust some google.com domain. And, in a few organizations, you may havesome dedicated tools server, in which case your projects would point to it.
Anything else is highly suspect.
This URL points to the copy of Gradle that will be used by Android Studioand other tools to build your app. If this points to a hacked copy of Gradle ���one that works but also contains malware ��� your development machine orCI server could be compromised, much as would the security researchers who openedthe malware-laden Visual Studio project.
It would be lovely if Android Studio would maintain a distributionUrl domainwhitelist and would warn users if they are importing a project with an unrecognized domain.I suggested it in 2016. Google declined.
RULE #2: Only Use a gradlew That You REALLY Trustgradlew is a shell script. gradlew.bat is a batch file. They each in turnwill run code from the gradle/wrapper/gradle-wrapper.jar file. These toorepresent executable code, commonly shipped with projects, that will run on yourdevelopment machine.
The good news is that Android Studio and CI servers will not usually use thesefiles. They use the Gradle Tooling API. So, usually these binaries are only executedwhen you manually request them.
If you created the project from Android Studio, you may as well trust those binaries,as you are trusting Android Studio itself. However, for a project that you are gettingfrom some public Web site, those binaries could have been altered ��� itsunlikely that you are going to decompile gradle-wrapper.jar and go looking formalware in it. And such altered binaries would run on your development machine orwherever else you use gradlew.
The good news is that gradlew is rather thin. If you have a complete copy ofGradle installed, you can generate a clean Gradle Wrapper (as these files are called)using the wrapper task (gradle wrapper). Or, you should be able to just replace the files with copies fromsome known-to-be-good source. Or, simply delete them, particularly if you are notlikely to use them.
In most of my public projects, I ship gradle-wrapper.properties for easy importinto Android Studio, but I do not ship the Gradle Wrapper files. Nobody should betrusting me for their Gradle Wrapper.
It would be wonderful if Google would warn developers about the risks of untrustedGradle Wrapper files. I suggested it last April;perhaps this one will be adopted.
There are other vectors for malware in a project. For example, you would bewise to examine the roster of Gradle plugins and annotation processors used by theproject, as those too represent code that will run on your development machine at therequest of the project. In particular, pulling from unrecognized artifact repositorieswould be a major warning sign.
It is relatively unlikely that you will encounter a poisoned project. However,as the SolarWinds debacle demonstrates, the cost can be extremely high.
Having tons of projects out in places like GitHub and GitLab has been a massivebenefit to modern software development. At the same time, in some respects,building one of those projects is little better than finding some USB drive in aparking lot, taking it to the office, and plugging it into your computer. Evilpeople are catching on to this, and if we are not careful, we will pay the pricefor the convenience of modern app build processes.
January 25, 2021
���Elements of Kotlin��� Version 0.4 Released
Subscribers now haveaccess to Version 0.4 of Elements of Kotlin,in PDF, EPUB, and MOBI/Kindle formats. Just log intoyour Warescription page to download it,or set up an account and subscribe!
There are a few new ���Kotlin, WTF?��� short chapters, on:
Covarianceand contravariance in generics
and Nothing
And, as usual, there were several bug fixes.
January 7, 2021
ACTION_SEND, the Chooser, and ClipData
Roderick Gadellaa pointed out an interesting problem with the ���share sheet���.In Android 10+, the share sheet can show a preview of your content. In particular,it can show a preview of an image that you are sharing. The catch is that theshare sheet needs to know what image that is��� and whether it does depends on howyou are sharing it.
Sharing content involves ACTION_SEND, and if we use EXTRA_STREAM to supplya Uri, we need to add FLAG_GRANT_READ_URI_PERMISSION and/or FLAG_GRANT_WRITE_URI_PERMISSIONon the Intent:
val intent = Intent(Intent.ACTION_SEND).apply { putExtra(Intent.EXTRA_STREAM, uri) type = "image/webp" addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)}Frequently, when using ACTION_SEND, we wrap it in a chooser Intent, suchas via Intent.createChooser(). So, we pass our Intent to createChooser() androll from there:
val intent = Intent(Intent.ACTION_SEND).apply { putExtra(Intent.EXTRA_STREAM, uri) type = "image/webp" addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)}startActivity(Intent.createChooser(intent, null))And, if you try this, you will not get a preview in the share sheet.
This, however, works:
val intent = Intent(Intent.ACTION_SEND).apply { clipData = ClipData.newRawUri(null, uri) putExtra(Intent.EXTRA_STREAM, uri) type = "image/webp" addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)}startActivity(Intent.createChooser(intent, null))The reason is that the framework copies the ClipData out of the ACTION_SENDand puts it in the ACTION_CHOOSER Intent created by createChooser().It does not copy any EXTRA_STREAM value, though.
There is also the possibility that you are using ShareCompat.IntentBuilder:
ShareCompat.IntentBuilder.from(this) .setType("image/webp") .addStream(uri) .startChooser()This too fails��� for now. cketti filed an issue for that one,and while it is fixed, I do not believe that fix has shipped yet.
Ideally, you use setClipData() on an ACTION_SEND Intent or that repaired versionof ShareCompat.IntentBuilder, so your shared images are able to be previewedproperly.
January 3, 2021
���Elements of Android Jetpack��� Version 2.0 Released
Subscribers now have
access to an update to Elements of Android Jetpack,
known as Version 2.0, in PDF, EPUB, and MOBI/Kindle formats, in addition to the
online reader. Just log into
your Warescription page and download
away, or set up an account and subscribe!
As with all of the CommonsWare x.0 releases, this is the same as the previous
release (1.9), other than some bug fixes.
The next significant release will be Version 2.1, which will come out sometime
after Android Studio 4.2 ships in stable form. Since that is in an early beta now,
my guess is that it will be late January to early February before a stable
Android Studio 4.2 ships.
December 14, 2020
���Exploring Android��� Version 2.0 Released
Subscribers now have
access to an update to Exploring Android,
known as Version 2.0, in PDF, EPUB, and MOBI/Kindle formats, in addition to the
online reader. Just log into
your Warescription page and download
away, or set up an account and subscribe!
As with all of the CommonsWare x.0 releases, this is the same as the previous
release (1.9), other than some bug fixes.
The next significant release will be Version 2.1, which will come out sometime
after Android Studio 4.2 ships in stable form.
December 6, 2020
���Elements of Android Jetpack��� Version 1.9 Released
Subscribers now have
access to Version 1.9 of Elements of Android Jetpack,
in PDF, EPUB, and MOBI/Kindle formats. Just log into
your Warescription page to download it,
or set up an account and subscribe!
This is a maintenance update, with minor tweaks for Android Studio 4.1.1.
This includes some notes about using the inline emulator (where the emulator
appears in a tool window in the IDE itself) and the Database Inspector for
examining SQLite databases.
It also replaces all uses of Kotlin synthetic accessors with view binding,
since Kotlin synthetic accessors are now deprecated. There also were some
legacy findViewById() uses in the Java samples, so those too were updated to use
view binding.
A few minor adjustments were made for Android 11, with respect to storage and
permissions. This includes switching (for a while) to use android:requestLegacyExternalStorage="true"
in the Files chapter���s main sample.
In addition:
Many dependencies were updated throughout the app
A bunch of bugs were fixed
The next update, to 2.0, should be out in a month and will only have bug fixes.
Version 2.1 should come out after Android Studio 4.2 ships a stable release.
December 4, 2020
Seeing If Your App Has the Play Core Vulnerability
A blog post from CheckPoint
has triggered a bunch of media reports
about apps still being affected by a months-old massive bug in the Play Core
library. Apps need to use an updated version of that library to help mitigate
the bug, and apparently ~8% of apps do not.
The bug is bad: a remote code execution (RCE) flaw in a privileged process ���
basically, attackers can do nearly anything they want. Fixing
the library presumably is to help with devices where Play Services itself is out of date,
as the real problem is not going to be in the apps.
The library in question is com.google.android.play:core. According to NIST,
the problem is in versions 1.3.6 through 1.7.1. Google, in
the 1.7.2 release notes,
is more general and says that anyone using ���a lower version��� should upgrade at least to 1.7.2.
However, bear in mind that you might not be using this library directly. Other
Google libraries, such as com.google.android.play:core-ktx and
androidx.navigation:navigation-dynamic-features-runtime, pull in the Play Core
library via transitive dependencies. So too do third-party libraries,
particularly those centered around in-app updates.
A reasonably quick way to see if your app is affected, directly or indirectly, is by running
a Gradle dependency report and searching for the Play Core library. From within
Android Studio, you can do this by:
Opening the Gradle tool (typically docked on the right)
For each of your modules, go into Tasks > help in the tree, and run the dependencies task by double-clicking on it
Or, you can run the report from the command line (e.g., ./gradlew app:dependencies).
Then, search the output for com.google.android.play:core, as the report shows
all configurations and all transitive dependencies. In Android Studio, Ctrl-F (or the
macOS equivalent) will bring up a search field in the report output pane. At
the command line, you can throw a grep or fgrep at the problem:
./gradlew app:dependencies | fgrep "com.google.android.play:core"
Then:
If your search comes up empty, you are fine
If your search comes up with a hit, but the version of the library is 1.7.2 or newer, you are fine
If your search comes up with a hit for an older version, you have a problem
If you have a problem, you can work your way up the tree to determine which root
dependency ��� one that should appear in your module���s build.gradle file ���
is pulling in Play Core via transitive dependencies. Or, perhaps you are pulling it in directly.
Find whatever dependency is the culprit and try upgrading to the latest version
of that dependency, then re-run this test and see if you are no longer affected by
the Play Core bug.
You may find that even the latest version of the root dependency still pulls in
a flawed Play Core edition. For example, A3InAppUpdater
seems to use older Play Core versions even for its latest (1.2.1) version��� in part
because the library has not been updated in a year. For these cases, you have two
main options that I can think of (as I race to get this post out):
Put your own dependency in build.gradle on Play Core for a known-good version.
From a compatibility standpoint, you might go with com.google.android.play:core:1.7.2.
As I write this, the now-current version is com.google.android.play:core:1.9.0.
If you have your own dependency on Play Core, Gradle should resolve those and pick the
newer one. However, the library may be dependent on stuff that is only in the older library,
so you would need to test thoroughly.
Stop using the flawed root dependency entirely, until you are in position to switch
to some safer alternative.
November 30, 2020
Initial Responses to Uncomfortable Questions
A couple of months ago, I asked some uncomfortable questions about App Signing.
Those were sparked by Google���s declaration that all new apps have to be distributed as App Bundles, which in turn require App Signing.
App Signing introduces a big problem: Google can modify apps before they sign them.
And while Google on its own may not necessarily have a reason do make any such modifications,
other parties do and may try to force Google to alter apps.
My post appears to have gotten a fair bit of attention and, for some, it has touched a nerve.
And now, with a target timeframe of August 2021 for that App Bundle requirement��� we have some responses to the questions!
Recently, Chet Haase, Wojtek Kalicinski, Iurii Makhno, and Ben Weiss held a
Q&A session on App Bundles as part of the MAD Skills presentation series.
They took questions from Twitter and YouTube comments, in addition to a few
warmup questions. And several of the questions touched upon the concerns
that I outlined in that original blog post and that others have echoed in the
days and weeks that followed.
First, I am very grateful that Google took the time to respond! And, the entire
Q&A discussion was very well done, despite 2020���s limitations (e.g., Chet���s video
stream froze at one point��� though it���s possible that it was just a very impressive
impersonation of a frozen stream, given Chet���s comedy skills).
The biggest downside of these responses coming in the form of a YouTube video
is that videos do not always get transcribed and indexed in text form. So, I took
the time to write down the questions and answers of relevance to my original post ���
though, again, the entire discussion is worth watching.
For each one, I provide:
A link to the particular offset into the video
The question
The panelist delivering the answer, and that answer
Some comments of my own for several of them
Note that in some cases, I had difficulty understanding what was being said, or
the questions were somewhat garbled.
Where you see [stuff in brackets], that is my translation of what was said to try to make
the material readable.
Where you see {stuff in braces}, that is a placeholder where
I could not even venture a guess as to what was said. My apologies for the gaps!
15:35: Is it possible to verify that an APK on the Play Store matches its open source code repository? And, is it possible to do that with app bundles as well?
Iurii:
Currently, I am not aware of any solution to [sign only DEX files] that are available right now, so but on the other hand, I can say that bundletool manipulates the DEX files for only one specific reason.
As you probably know, Android platform below 5.0 doesn���t support multiple DEX files natively for your application. So, in case your app needs to support such devices, and doesn���t fit into one DEX file, and requires multidex support, bundletool in this case will merge DEX files to {garbled} and actually make your application compatible with legacy multidex.
Other than that, bundletool doesn���t touch your DEX files at all. You can check it via checking source code of bundletool.
Also, you can install your APKs on a device, take it from it, and check in Android Studio that your DEX files are not changed at all.
Personally, my concern is not whether bundletool is modifying anything. We could find
that out easily enough. However, bundletool output can be modified by Google on their
servers before distributing the APKs based on that output ��� that is the concern.
While developers have means of inspecting a set of APKs, they do not have the means
of inspecting all sets of APKs. Google serves billions of custom Web pages
per day. Serving custom APKs ��� some altered, some not ��� is not a very big hurdle
for Google to overcome.
This next question is one that I posted via Twitter!
17:47: Will you extend App Bundles to allow for developer-signed artifacts and no App Signing?
Wojtek:
So, I talked briefly about the requirement next year for new apps to use app bundles, and one thing that comes with that is that by extension we will require Play App Signing.
So developers will need to either generate the App Signing key on Play or upload their own key to Play��� because that���s a prerequisite for app bundles.
We���ve heard from developers that some of them just don���t want to do it. They don���t want to have keys managed by Play.
And currently that���s not possible if you want to use app bundles.
But, we���ve heard that feedback, and��� I can���t talk about anything right now, we don���t have anything to announce, but we are looking into how we could alleviate some of these concerns.
It doesn���t necessarily have to be allowing to keep your own key while uploading bundles.
We���re looking into different options. We just don���t have a solution to announce right now.
But, we still have around a year until the requirement, so I���m really hopeful that we���ll have an answer for developers for this.
The fact that Google is thinking about these concerns, and discussing them publicly, is a wonderful development!
19:41: Can you address the statements that App Bundles can be decompiled by the Play Store to add malicious code?
Iurii:
I think this question really relates to something that I��� answered previously.
I already described that DEX files are not touched, and a way how developers can ensure it right now.
Google modifies uploaded content all the time. Google serves modified content all the time.
Google has more than sufficient engineering capability to extend this to modifying APKs.
The only thing that slowed them down, historically, was the signing process, and App Signing
removes that impediment. That is why I am concerned about mandatory App Signing for new apps.
28:35: [Is there a way] we can keep our existing key (without giving [it] to you) and key still take benefit of the app bundle?
Wojtek:
I briefly talked about this before. We are looking into options��� not right now, and I don���t have anything to announce, but��� we���re hearing this feedback and we are looking into it.
But I don���t know what the end result will be.
37:28: The APKs are not created on the store, runtime protectors will now see them as being tampered with. Any plans to support this going forward?
All members of the panel passed on this question. They may not have recognized the name
���runtime protector���, but I assume that they are familiar with DexGuard and
other tools that try to help defend apps against reverse engineering, kernel
debuggers, and other forms of attack.
38:19: Is there a possibility maybe in the future��� to be able to generate the APKs by a tool, maybe something like bundletool, and upload those APKs��� {Chet froze}
Wojtek:
So, again, this is a question that I think I���ve already answered.
Probably not as it���s described in the question, as this would make the publishing process even more difficult for developers, and we actually want to make it simpler and safer.
However, again, we���ve heard this feedback, and we will be looking into options how to make this possible, however probably not in the way that was described here.
I was surprised about the specific comment regarding that it would
���make the publishing process even more difficult for developers���. ZIPping
the signed APK set that bundletool creates would seem to be a trivial addition
to bundletool. Uploading a ZIP of APKs would be as easy as uploading an AAB
file��� in part because an AAB file is also a ZIP file.
Perhaps the concern is that
the ZIP-of-APKs might be larger than the corresponding AAB, and there will
be some set of developers where that incremental upload bandwidth might be a
problem. But, I expect that most developers interested in opting out of App Signing,
for the occasional app update, can deal with a few extra MB of bandwidth.
My sincere hope, though, is that this was just a case where the question arrived
in real time. Answering on-the-fly questions is difficult. That is one of the
reasons why I would not ask this sort of question that way ��� the only
reason why I raised my own was because I could do it well in advance (via Twitter) and Google
could decide whether to include it and how to respond.
So, on the whole, I considered the set of responses to be positive. They offered
no specifics, but I would not expect them to do so in that sort of presentation
anyway.
Perhaps my biggest concern is that I do not know who Google is working with in
terms of figuring out the impacts of their mandatory App Signing decision.
They are delivering apps to billions of people; decisions along these lines
desperately need the input of civil society groups (EFF and Access Now in the
US, plus their counterparts around the world).
And while I am absolutely no substitute for such groups��� if anyone at Google
would like to bounce some ideas around, just let me know.
Otherwise, now we wait for details of what (if anything) will be done, prior
to the August 2021 App Bundle requirement.
November 22, 2020
���Elements of Android R��� FINAL Version Released
Subscribers now have
access to the FINAL version of Elements of Android R,
in PDF, EPUB, and MOBI/Kindle formats. Just log into
your Warescription page to download it or read it online,
or set up an account and subscribe!
I concluded that there wasn���t anything else that I really wanted to cover in
this book. So, with a few really minor tweaks, this is the last update to
Elements of Android R, reflecting the shipping version of Android 11.


