Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parseAppMeta(): Extract app's source (app store and URL) #128

Open
baltpeter opened this issue Apr 12, 2024 · 7 comments
Open

parseAppMeta(): Extract app's source (app store and URL) #128

baltpeter opened this issue Apr 12, 2024 · 7 comments
Labels
feature New feature or request research

Comments

@baltpeter
Copy link
Member

Can we get this data from the app files?

See tweaselORG/cyanoacrylate#39 for why we need that.

@baltpeter
Copy link
Member Author

The iOS apps that I have on hand (all downloaded from the app store), have an iTunesMetadata.plist file that looks just like what we are looking for. Here's an example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>MacUIRequiredDeviceCapabilities</key>
	<dict>
		<key>arm64</key>
		<true/>
	</dict>
	<key>UIRequiredDeviceCapabilities</key>
	<dict>
		<key>arm64</key>
		<true/>
	</dict>
	<key>apple-id</key>
	<string>[email protected]</string>
	<key>artistId</key>
	<integer>281941100</integer>
	<key>artistName</key>
	<string>Bloomberg Finance LP</string>
	<key>bundleDisplayName</key>
	<string>Bloomberg</string>
	<key>bundleShortVersionString</key>
	<string>5.69.0</string>
	<key>bundleVersion</key>
	<string>3266194</string>
	<key>copyright</key>
	<string>© Bloomberg L.P.</string>
	<key>drmVersionNumber</key>
	<integer>0</integer>
	<key>fileExtension</key>
	<string>.app</string>
	<key>gameCenterEnabled</key>
	<false/>
	<key>gameCenterEverEnabled</key>
	<false/>
	<key>genre</key>
	<string>News</string>
	<key>genreId</key>
	<integer>6009</integer>
	<key>hasOrEverHasHadIAP</key>
	<true/>
	<key>itemId</key>
	<integer>281941097</integer>
	<key>itemName</key>
	<string>Bloomberg: Business News</string>
	<key>kind</key>
	<string>software</string>
	<key>playlistName</key>
	<string>Bloomberg Finance LP</string>
	<key>product-type</key>
	<string>ios-app</string>
	<key>rating</key>
	<dict>
		<key>content</key>
		<string>Advisory.NO.TRUE_GAMBLING , Advisory.NO.GAMBLING_CONTESTS and Advisory.NO.UNRESTRICTED_WEB_ACCESS</string>
		<key>label</key>
		<string>4+</string>
		<key>rank</key>
		<integer>100</integer>
		<key>system</key>
		<string>itunes-games</string>
	</dict>
	<key>releaseDate</key>
	<string>2019-02-01T08:00:00Z</string>
	<key>requiresRosetta</key>
	<false/>
	<key>runsOnAppleSilicon</key>
	<true/>
	<key>runsOnIntel</key>
	<false/>
	<key>s</key>
	<integer>143443</integer>
	<key>software-platform</key>
	<string>ios</string>
	<key>softwareIcon57x57URL</key>
	<string>https://is2-ssl.mzstatic.com/image/thumb/Purple116/v4/d9/ec/35/d9ec3598-9db4-ef73-e7de-5da9863518e6/AppIcon-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/114x114bb.jpg</string>
	<key>softwareIconNeedsShine</key>
	<false/>
	<key>softwareSupportedDeviceIds</key>
	<array>
		<integer>2</integer>
		<integer>9</integer>
		<integer>4</integer>
	</array>
	<key>softwareVersionBundleId</key>
	<string>com.bloomberg.Bloomberg</string>
	<key>softwareVersionExternalIdentifier</key>
	<integer>847839440</integer>
	<key>softwareVersionExternalIdentifiers</key>
	<array>
		<integer>10992</integer>
		<integer>21242</integer>
		<integer>294794</integer>
		<integer>493163</integer>
		<integer>1154963</integer>
		<integer>1323563</integer>
		<integer>1468803</integer>
		<integer>1478344</integer>
		<integer>1607362</integer>
		<integer>1698583</integer>
		<integer>1741745</integer>
		<integer>1836081</integer>
		<integer>1889054</integer>
		<integer>1910403</integer>
		<integer>1964132</integer>
		<integer>2110833</integer>
		<integer>2209612</integer>
		<integer>2564521</integer>
		<integer>2778106</integer>
		<integer>2843541</integer>
		<integer>3066209</integer>
		<integer>3124625</integer>
		<integer>3225082</integer>
		<integer>3263940</integer>
		<integer>3321795</integer>
		<integer>3459605</integer>
		<integer>3649073</integer>
		<integer>3808125</integer>
		<integer>3895935</integer>
		<integer>4005183</integer>
		<integer>4050663</integer>
		<integer>4212102</integer>
		<integer>4352583</integer>
		<integer>7115631</integer>
		<integer>7374923</integer>
		<integer>14060260</integer>
		<integer>51622652</integer>
		<integer>73762652</integer>
		<integer>244582844</integer>
		<integer>306772964</integer>
		<integer>355842641</integer>
		<integer>386272692</integer>
		<integer>518922646</integer>
		<integer>591032673</integer>
		<integer>597022697</integer>
		<integer>614703182</integer>
		<integer>646922650</integer>
		<integer>661362683</integer>
		<integer>693013996</integer>
		<integer>730452810</integer>
		<integer>749123468</integer>
		<integer>755332750</integer>
		<integer>776622680</integer>
		<integer>810914842</integer>
		<integer>811130357</integer>
		<integer>811445595</integer>
		<integer>811535406</integer>
		<integer>811689997</integer>
		<integer>811827009</integer>
		<integer>811968285</integer>
		<integer>812205164</integer>
		<integer>812512200</integer>
		<integer>812877726</integer>
		<integer>813139137</integer>
		<integer>813516953</integer>
		<integer>813680781</integer>
		<integer>813944394</integer>
		<integer>814209438</integer>
		<integer>815386087</integer>
		<integer>815956508</integer>
		<integer>816107575</integer>
		<integer>816140570</integer>
		<integer>816148663</integer>
		<integer>816275381</integer>
		<integer>816357848</integer>
		<integer>816664875</integer>
		<integer>816774705</integer>
		<integer>816949878</integer>
		<integer>817135995</integer>
		<integer>817257857</integer>
		<integer>817351469</integer>
		<integer>817467912</integer>
		<integer>817555116</integer>
		<integer>818141801</integer>
		<integer>818313438</integer>
		<integer>818845438</integer>
		<integer>819087154</integer>
		<integer>819984767</integer>
		<integer>820257255</integer>
		<integer>820398137</integer>
		<integer>820740072</integer>
		<integer>821657543</integer>
		<integer>821708116</integer>
		<integer>822040722</integer>
		<integer>822176464</integer>
		<integer>822304553</integer>
		<integer>822526063</integer>
		<integer>822572872</integer>
		<integer>822625493</integer>
		<integer>822677648</integer>
		<integer>822764899</integer>
		<integer>822874773</integer>
		<integer>823330440</integer>
		<integer>823681197</integer>
		<integer>823933243</integer>
		<integer>823969249</integer>
		<integer>824086550</integer>
		<integer>824231771</integer>
		<integer>825405200</integer>
		<integer>825516711</integer>
		<integer>825568914</integer>
		<integer>825800882</integer>
		<integer>825845855</integer>
		<integer>826155030</integer>
		<integer>826192540</integer>
		<integer>826223419</integer>
		<integer>826326951</integer>
		<integer>826364292</integer>
		<integer>826594231</integer>
		<integer>826635250</integer>
		<integer>826708681</integer>
		<integer>826751991</integer>
		<integer>826788459</integer>
		<integer>826934248</integer>
		<integer>827211308</integer>
		<integer>827253956</integer>
		<integer>827432827</integer>
		<integer>827466182</integer>
		<integer>827565809</integer>
		<integer>827681659</integer>
		<integer>827759307</integer>
		<integer>827850348</integer>
		<integer>827963934</integer>
		<integer>827993773</integer>
		<integer>828154093</integer>
		<integer>828323814</integer>
		<integer>828497578</integer>
		<integer>828585442</integer>
		<integer>828700453</integer>
		<integer>828766157</integer>
		<integer>828970543</integer>
		<integer>829077067</integer>
		<integer>829187285</integer>
		<integer>829311279</integer>
		<integer>829506734</integer>
		<integer>829593801</integer>
		<integer>829609241</integer>
		<integer>829883094</integer>
		<integer>830094665</integer>
		<integer>830379216</integer>
		<integer>830475567</integer>
		<integer>830508876</integer>
		<integer>830885618</integer>
		<integer>831272694</integer>
		<integer>831521482</integer>
		<integer>831678487</integer>
		<integer>831795102</integer>
		<integer>831995899</integer>
		<integer>832133598</integer>
		<integer>832329295</integer>
		<integer>832576398</integer>
		<integer>832634100</integer>
		<integer>832864140</integer>
		<integer>833115864</integer>
		<integer>833439251</integer>
		<integer>833912202</integer>
		<integer>833937027</integer>
		<integer>833970683</integer>
		<integer>834158169</integer>
		<integer>834309082</integer>
		<integer>834404922</integer>
		<integer>834443876</integer>
		<integer>834636844</integer>
		<integer>834640362</integer>
		<integer>834818832</integer>
		<integer>835045141</integer>
		<integer>835094139</integer>
		<integer>835202299</integer>
		<integer>835369365</integer>
		<integer>835590493</integer>
		<integer>835786537</integer>
		<integer>836023547</integer>
		<integer>836088947</integer>
		<integer>836200242</integer>
		<integer>836321200</integer>
		<integer>836373594</integer>
		<integer>836598828</integer>
		<integer>836797280</integer>
		<integer>837001632</integer>
		<integer>837276800</integer>
		<integer>837565142</integer>
		<integer>837589674</integer>
		<integer>837861559</integer>
		<integer>838085546</integer>
		<integer>838250997</integer>
		<integer>838454352</integer>
		<integer>838538531</integer>
		<integer>839116992</integer>
		<integer>839347069</integer>
		<integer>839468892</integer>
		<integer>839803201</integer>
		<integer>840167584</integer>
		<integer>840379763</integer>
		<integer>840554745</integer>
		<integer>840768317</integer>
		<integer>840980853</integer>
		<integer>841219428</integer>
		<integer>841601636</integer>
		<integer>842009827</integer>
		<integer>842221990</integer>
		<integer>842425731</integer>
		<integer>842629536</integer>
		<integer>842829918</integer>
		<integer>843023602</integer>
		<integer>843230972</integer>
		<integer>843477729</integer>
		<integer>843742581</integer>
		<integer>843952104</integer>
		<integer>844178627</integer>
		<integer>844252257</integer>
		<integer>844431671</integer>
		<integer>844716233</integer>
		<integer>845028803</integer>
		<integer>845311036</integer>
		<integer>845594234</integer>
		<integer>845829944</integer>
		<integer>846447442</integer>
		<integer>846788771</integer>
		<integer>847015166</integer>
		<integer>847246950</integer>
		<integer>847336002</integer>
		<integer>847526858</integer>
		<integer>847839440</integer>
	</array>
	<key>userName</key>
	<string>[email protected]</string>
	<key>vendorId</key>
	<integer>8949</integer>
	<key>versionRestrictions</key>
	<integer>0</integer>
</dict>
</plist>

@baltpeter
Copy link
Member Author

Information that I can see immediately:

  • Apple ID that downloaded the app (apple-id).
  • Developer ID on the App Store (artistId)
  • App's numerical ID on the App Store (called bundleId here, usually called adam_id by Apple)
    • from that, we can trivially infer the URL: https://apps.apple.com/app/id<bundleId>

Currently1, there of course aren't exactly many ways of distributing apps for iOS. However, tweaks and apps for jailbroken devices are a thing. So, while I would assume that "presence of iTunesMetadata.plist" iff "app was downloaded from the App Store", we'll have to verify that.

Footnotes

  1. I guess, we'll have to re-evaluate that once the first "DMA App Stores" pop up. :D

@baltpeter baltpeter self-assigned this Apr 12, 2024
@baltpeter
Copy link
Member Author

I've downloaded a whole bunch of IPAs from various… unofficial sources. None of them had an iTunesMetadata.plist file.

@baltpeter
Copy link
Member Author

On Android, meanwhile this is a lot harder (impossible, maybe?).

We can verify an app's signature using keytool -printcert -jarfile <app.apk> (https://security.stackexchange.com/a/226815).

For some apps, this will output a signature from Google:

❯ keytool -printcert -jarfile be.stib.mivb.mobile-203137.apk
Signer #1:

Certificate #1:
Owner: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
Issuer: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
Serial number: 583ce60a3e6050859f1b5ca6a563c1c217272cd7
Valid from: Tue Jun 12 17:12:40 CEST 2018 until: Fri Jun 12 17:12:40 CEST 2048
Certificate fingerprints:
	 SHA1: CF:9F:C9:31:79:42:D9:21:51:D3:C9:8B:E6:8B:E3:BB:97:2A:77:9C
	 SHA256: AB:D9:92:5E:3A:D9:D1:E9:C4:6C:E4:A8:43:4D:2C:72:19:08:B4:A9:7B:0B:77:E7:2C:8F:D6:69:32:09:AB:06
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3

Extensions: 

#1: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:true
  PathLen: no limit
]

And it also makes it possible to identify F-Droid apps:

❯ keytool -printcert -jarfile org.mozilla.fennec_fdroid_1092020.apk
Signer #1:

Certificate #1:
Owner: CN=FDroid, OU=FDroid, O=fdroid.org, L=ORG, ST=ORG, C=UK
Issuer: CN=FDroid, OU=FDroid, O=fdroid.org, L=ORG, ST=ORG, C=UK
Serial number: 53f12705
Valid from: Sun Feb 01 18:48:32 CET 2015 until: Thu Jun 19 19:48:32 CEST 2042
Certificate fingerprints:
	 SHA1: F5:54:5E:C2:F9:68:1D:40:BA:42:11:A0:96:7A:3B:BD:4F:4B:F5:4B
	 SHA256: 06:66:53:58:EF:D8:BA:05:BE:23:6A:47:A1:2C:B0:95:8D:7D:75:DD:93:9D:77:C2:B3:1F:53:98:53:7E:BD:C5
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

Extensions: 

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 7B 90 A2 0F E4 70 F3 8A   E4 E5 77 6B F2 B6 73 45  .....p....wk..sE
0010: BA 19 15 E3                                        ....
]
]

However, this does not work for all apps from the Play Store, some are self-signed or unsigned(?):

❯ keytool -printcert -jarfile com.digibites.accubattery-201004.apk
Signer #1:

Certificate #1:
Owner: O=Digibites Technology, L=Rotterdam, ST=Zuid-Holland, C=NL
Issuer: O=Digibites Technology, L=Rotterdam, ST=Zuid-Holland, C=NL
Serial number: 2525ae18
Valid from: Tue Mar 22 12:13:51 CET 2016 until: Wed Feb 27 12:13:51 CET 2115
Certificate fingerprints:
	 SHA1: 7C:AC:F9:2E:A3:02:DE:15:D6:5A:CA:84:9D:FF:A3:3F:F6:D2:96:12
	 SHA256: 64:A5:40:DE:F3:35:EF:35:08:80:CB:66:08:C9:26:5B:B4:CB:F7:FB:DE:40:D3:D8:C0:6A:EB:99:7C:27:63:5E
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

Extensions: 

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 32 95 C1 8A 67 16 D3 22   EC E6 56 B9 32 89 80 0F  2...g.."..V.2...
0010: 60 0B 53 F9                                        `.S.
]
]

❯ keytool -printcert -jarfile com.airbnb.android-28003318.apk
Not a signed jar file

@baltpeter
Copy link
Member Author

And for the other Android app formats we support:

  • XAPK: When downloaded from APKPure, these appear to have ZIP file comments indicating such (zipinfo -v <file.xapk>):

    image

    Raw APKs from APKPure appear to retain their original signature, which makes sense. And I feel like it is also fair to classify them as coming from the Play Store in this case, since they are literally the exact same file.

    ❯ keytool -printcert -jarfile STIB-MIVB_2.7.3_Apkpure.apk
    Signer #1:
    
    Certificate #1:
    Owner: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
    Issuer: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
    Serial number: 583ce60a3e6050859f1b5ca6a563c1c217272cd7
    Valid from: Tue Jun 12 17:12:40 CEST 2018 until: Fri Jun 12 17:12:40 CEST 2048
    Certificate fingerprints:
     SHA1: CF:9F:C9:31:79:42:D9:21:51:D3:C9:8B:E6:8B:E3:BB:97:2A:77:9C
     SHA256: AB:D9:92:5E:3A:D9:D1:E9:C4:6C:E4:A8:43:4D:2C:72:19:08:B4:A9:7B:0B:77:E7:2C:8F:D6:69:32:09:AB:06
    Signature algorithm name: SHA256withRSA
    Subject Public Key Algorithm: 4096-bit RSA key
    Version: 3
    
    Extensions: 
    
    #1: ObjectId: 2.5.29.19 Criticality=false
    BasicConstraints:[
    CA:true
    PathLen: no limit
    ]
    
  • APKM files from APKMirror contain an APKM_installer.url:

    [InternetShortcut]
    URL=https://www.apkmirror.com/installer
    

    They are also signed:

    ❯ keytool -printcert -jarfile de.exaring.waipu_2024.7.0-627905_2arch_1dpi_14lang_cd16c95160d887e6b0dec2086eb1aa31_apkmirror.com.apkm
    Signer #1:
    
    Certificate #1:
    Owner: CN=APKMirror.com, OU=APKMirror.com, O=APKMirror.com, L=San Francisco, ST=California, C=US
    Issuer: CN=APKMirror.com, OU=APKMirror.com, O=APKMirror.com, L=San Francisco, ST=California, C=US
    Serial number: 1449abd5
    Valid from: Wed Jul 24 16:20:09 CEST 2019 until: Fri Jun 30 16:20:09 CEST 2119
    Certificate fingerprints:
     SHA1: E6:FF:20:92:50:78:84:16:6D:18:74:BC:BD:6C:77:5B:33:4D:8C:2A
     SHA256: 7B:1A:6D:25:E5:E8:71:1A:6E:79:28:3D:F1:0C:64:8B:47:A4:20:C4:E5:41:3C:2C:51:35:1A:8C:A5:08:DE:25
    Signature algorithm name: SHA256withRSA
    Subject Public Key Algorithm: 2048-bit RSA key
    Version: 3
    
    Extensions: 
    
    #1: ObjectId: 2.5.29.14 Criticality=false
    SubjectKeyIdentifier [
    KeyIdentifier [
    0000: 71 B1 93 3F E0 23 7E F8   5B 6B 22 73 B3 99 47 F0  q..?.#..[k"s..G.
    0010: 5B 7A 87 EA                                        [z..
    ]
    ]
    

    Raw APKs also retain their signature:

    ❯ keytool -printcert -jarfile com.bonial.kaufda_24.8.1-1039328_minAPI23\(arm64-v8a,armeabi-v7a,x86,x86_64\)\(nodpi\)_apkmirror.com.apk
    Signer #1:
    
    Certificate #1:
    Owner: CN=kaufDA.de, OU=kaufDA, O=Juno Internet GmbH, L=Berlin, ST=Berlin
    Issuer: CN=kaufDA.de, OU=kaufDA, O=Juno Internet GmbH, L=Berlin, ST=Berlin
    Serial number: 4c359512
    Valid from: Thu Jul 08 11:06:26 CEST 2010 until: Mon Jul 02 11:06:26 CEST 2035
    Certificate fingerprints:
    	 SHA1: A9:B7:8D:CE:CE:46:98:F3:B8:32:02:01:D7:79:EE:AC:8D:39:90:B8
    	 SHA256: F2:B5:1D:2C:85:66:91:81:8C:01:F9:B9:3C:91:30:34:31:2A:F8:E7:C6:3C:0B:0E:0A:58:2E:73:9D:2E:C7:64
    Signature algorithm name: SHA1withRSA (weak)
    Subject Public Key Algorithm: 1024-bit RSA key (weak)
    Version: 3
    
    
    Warning:
    The certificate uses the SHA1withRSA signature algorithm which is considered a security risk. This algorithm will be disabled in a future update.
    The certificate uses a 1024-bit RSA key which is considered a security risk. This key size will be disabled in a future update.
    

@baltpeter
Copy link
Member Author

Oh, actually: it seems like a good idea to also include the signature in the app meta. That way we could show that we performed the analysis on an unmodified app as distributed by the developer.

@baltpeter
Copy link
Member Author

While it would definitely be useful to have all this information extracted automatically, this seems like a bigger rabbit hole than we should be going down right now. Let's put this on the back burner for now.

@baltpeter baltpeter removed their assignment Apr 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request research
Projects
None yet
Development

No branches or pull requests

1 participant