APK signature verified but warns file "not protected by signature"?


Question

I'm using apksigner to verify the authenticity of a Google Podcast apk that I downloaded from an apk mirror. This apk (and older versions) verifies successfully (v1/v2/v3) and returns exit code 0 but in the output I see this warning:


WARNING: META-INF/services/com.google.protobuf.GeneratedExtensionRegistryLoader not protected by signature. Unauthorized modifications to this JAR entry will not be detected. Delete or move the entry outside of META-INF/.


I do not understand what the impact of that is. If the APK is signed, and verified, why do I see this warning? Does it mean the APK could be trojaned or modified? How could an attacker exploit that?


I am downloading some older versions of some Google apps and I want to be sure they aren't trojaned, which is why I'm trying to verify the authenticity before I install them on my phone.


Answer

Summary


The warning you have encountered only applies to the APK signature v1, but as the APK file is signed with additional signatures of the newer signature schemes you can safely ignore this message as every modification on the APK file can be detected by the newer signature schemes.


However even if the signature can be verified it does not mean that the APK file is genuine. It still could be resigned after modification, therefore you should carefully compare the certificate digests (shown when verifying it using apksigner verify --verbose --print-certs) of the APK to be verified and compare it to other APK files of the same app developer. See this answer of How can I verify the authenticity of an APK file I downloaded? for details how to compare the certificate digest of an APK.


Detailed explanation


First of all as you can see what you get is a WARNING not an ERROR. If relevant file(s) of the APK file would have been modified the verification will fail and you would get an ERROR message.


To understand the warning message you need a little understanding of Java and how Java signatures (APK signature v1) work. This old signature is stored inside the JAR in two files: META-INF/CERT.SF and META-INF/CERT.RSA. Of course a signature can not sign the files it is written into , hence those files are excluded by the signature.


Additionally the META-INF directory is location of the MANIFEST.MF - a file that is only relevant for Java on Desktop but not used by Android at all.


There can be additional files in the META-INF directory, considering the standard Java directory layout no code should be stored inside files within the META-INF directory.


Because of all this Sun as the original inventor of Java decided to exclude the META-INF directory from the Java code signature at all. Several years later Google just used the Java signature for APK files which is now known as APK signature v1.


Therefore for the APK signature v1 the files inside the META-INF directory are not covered by the signature and hence can be modified without being recognized if you only verify


Because of several attacks on the APK signature itself (such as including the same file multiple times with different content in the APK Google decided to develop a completely new APK signature that does not apply on the APK content but on the overall APK file itself. This was the beginning of APK signature v2 and it's successors.


These new APK signature schemes do sign the complete APK content at once, not excluding a single file that is stored inside the APK file.


Back to the Google Podcast APK, verifying it using apksigner outputs the following:


java -jar apksigner.jar verify --verbose "Google Podcasts Discover free trending podcasts_v1.0.0.301897054_apkpure.com.apk"
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): true
Verified using v4 scheme (APK Signature Scheme v4): false
Verified for SourceStamp: false
Number of signers: 1
WARNING: META-INF/services/com.google.protobuf.GeneratedExtensionRegistryLoader not protected by signature. Unauthorized modifications to this JAR entry will not be detected. Delete or move the entry outside of META-INF/.

As you can see the APK file is signed not only by an v1 signature but also a v2, v3 and v4 signature. This means that the WARNING only applies to the signature created by the v1 scheme. You can easily verify that by modifying a single character inside the file META-INF/services/com.google.protobuf.GeneratedExtensionRegistryLoader as it is stored uncompressed within the APK file. You can simple open the APK file in an hex editor, modify a character in the section that belongs to that file (it is the first ZIP entry within the APK) and then again verify the APK:


java -jar apksigner.jar verify --verbose "Google Podcasts Discover free trending podcasts_v1.0.0.301897054_apkpure.com - modified.apk"
DOES NOT VERIFY
ERROR: APK Signature Scheme v3 signer #1: APK integrity check failed. CHUNKED_SHA256 digest mismatch. Expected: <ac8a15569352655a22f13d3c565c2c0e5c62dc70c8f6f8c10f6fbfa63decb19b>, actual: <aa5622cd904500c38424562ef4b5be9e5716d10a85985a41f35e4ed834cee8fe>
ERROR: APK Signature Scheme v3 signer #1: APK integrity check failed. VERITY_CHUNKED_SHA256 digest mismatch. Expected: <56eeebd545733fd6408cd6a30b8bcf98a557076167902b6d9502b5aca86b78e89b42220000000000>, actual: <c37e1e1436cfd62f89592c48211ffb6ad2f1dff0f69d2203072f1e6c3872a5919b42220000000000>

As you can see now the APK signature is considered invalid. I don't know why the v3 signature fails first, may be the signatures are not verified in order v1, v2, v3...
From my understanding all signatures except v1 should fail on the modified APK file.


Topics


2D Engines   3D Engines   9-Patch   Action Bars   Activities   ADB   Advertisements   Analytics   Animations   ANR   AOP   API   APK   APT   Architecture   Audio   Autocomplete   Background Processing   Backward Compatibility   Badges   Bar Codes   Benchmarking   Bitmaps   Bluetooth   Blur Effects   Bread Crumbs   BRMS   Browser Extensions   Build Systems   Bundles   Buttons   Caching   Camera   Canvas   Cards   Carousels   Changelog   Checkboxes   Cloud Storages   Color Analysis   Color Pickers   Colors   Comet/Push   Compass Sensors   Conferences   Content Providers   Continuous Integration   Crash Reports   Credit Cards   Credits   CSV   Curl/Flip   Data Binding   Data Generators   Data Structures   Database   Database Browsers   Date &   Debugging   Decompilers   Deep Links   Dependency Injections   Design   Design Patterns   Dex   Dialogs   Distributed Computing   Distribution Platforms   Download Managers   Drawables   Emoji   Emulators   EPUB   Equalizers &   Event Buses   Exception Handling   Face Recognition   Feedback &   File System   File/Directory   Fingerprint   Floating Action   Fonts   Forms   Fragments   FRP   FSM   Functional Programming   Gamepads   Games   Geocaching   Gestures   GIF   Glow Pad   Gradle Plugins   Graphics   Grid Views   Highlighting   HTML   HTTP Mocking   Icons   IDE   IDE Plugins   Image Croppers   Image Loaders   Image Pickers   Image Processing   Image Views   Instrumentation   Intents   Job Schedulers   JSON   Keyboard   Kotlin   Layouts   Library Demos   List View   List Views   Localization   Location   Lock Patterns   Logcat   Logging   Mails   Maps   Markdown   Mathematics   Maven Plugins   MBaaS   Media   Menus   Messaging   MIME   Mobile Web   Native Image   Navigation   NDK   Networking   NFC   NoSQL   Number Pickers   OAuth   Object Mocking   OCR Engines   OpenGL   ORM   Other Pickers   Parallax List   Parcelables   Particle Systems   Password Inputs   PDF   Permissions   Physics Engines   Platforms   Plugin Frameworks   Preferences   Progress Indicators   ProGuard   Properties   Protocol Buffer   Pull To   Purchases   Push/Pull   QR Codes   Quick Return   Radio Buttons   Range Bars   Ratings   Recycler Views   Resources   REST   Ripple Effects   RSS   Screenshots   Scripting   Scroll Views   SDK   Search Inputs   Security   Sensors   Services   Showcase Views   Signatures   Sliding Panels   Snackbars   SOAP   Social Networks   Spannable   Spinners   Splash Screens   SSH   Static Analysis   Status Bars   Styling   SVG   System   Tags   Task Managers   TDD &   Template Engines   Testing   Testing Tools   Text Formatting   Text Views   Text Watchers   Text-to   Toasts   Toolkits For   Tools   Tooltips   Trainings   TV   Twitter   Updaters   USB   User Stories   Utils   Validation   Video   View Adapters   View Pagers   Views   Watch Face   Wearable Data   Wearables   Weather   Web Tools   Web Views   WebRTC   WebSockets   Wheel Widgets   Wi-Fi   Widgets   Windows   Wizards   XML   XMPP   YAML   ZIP Codes