August 16th, 2024

Pixel smartphones delivered with secret but inactive remote maintenance

Millions of Pixel smartphones have an inactive remote maintenance software, posing potential security risks. A patch is being developed for removal, emphasizing the need for transparency in third-party applications.

Read original articleLink Icon
Pixel smartphones delivered with secret but inactive remote maintenance

Millions of Pixel smartphones have been shipped with a remote maintenance software called Showcase.apk, which was installed at the request of Verizon since the phones' launch in 2017. Although the software is inactive by default, it poses a potential security risk as it can download unsafe code if activated by someone with physical access to the device and the user's password. The vulnerability was discovered by iVerify, which traced it back to a hidden Android software package. While the software is no longer in use, it remains present in the firmware images of Pixel devices, and users cannot uninstall it. A patch to remove the inactive software is being developed and will be made available to all affected manufacturers. Google clarified that this is not a vulnerability of the Android platform or Pixel devices, but rather a remnant of a demo function for Verizon stores. No evidence of exploitation has been found, and Verizon has stated that the demo function will be removed from all devices as a precaution. This incident highlights the need for greater transparency regarding third-party applications included in operating systems.

- Millions of Pixel smartphones contain inactive remote maintenance software that could be exploited if activated.

- The software was installed at Verizon's request for demonstration purposes and is not currently in use.

- A patch to remove the software is being developed and will be distributed to affected manufacturers.

- Google states this is not an Android or Pixel vulnerability but a remnant of a demo function.

- The incident underscores the importance of transparency regarding third-party applications in operating systems.

Link Icon 17 comments
By @daenney - 6 months
This is largely the same stuff Wired pushed.

The folks over at GrapheneOS have a much better analysis of this whole thing: https://grapheneos.social/@GrapheneOS/112967309987371034

By @progbits - 6 months
> ... but only if the perpetrator has physical access to the device, enters the user's password ...

Clickbait title. If you have physical access and password of course you can do whatever. That is the point of the password.

By @transpute - 6 months
https://www.theverge.com/2024/8/15/24221151/google-pixel-sho...

  “This was very deleterious of trust, to have third-party, unvetted insecure software on it,” Dane Stuckey, Palantir’s chief information security officer, told The Washington Post. “We have no idea how it got there, so we made the decision to effectively ban Androids internally.”

  “It’s really quite troubling. Pixels are meant to be clean,” Stuckey, of Palantir, told the Post. “There is a bunch of defense stuff built on Pixel phones.”
Pixel phones have AVF/pKVM, which can be used to isolate security-sensitive workloads in a separate VM, https://source.android.com/docs/core/virtualization/architec...
By @kelnos - 6 months
Can confirm it's on my Pixel 8:

    shiba:/ $ pm list packages -a -f
    ...
    package:/product/priv-app/Showcase/Showcase.apk=com.customermobile.preload.vzw
    ...
Gross. I have zero relationship with Verizon and yet this garbage is on my phone.
By @j1elo - 6 months
I never got to try GrapheneOS because a single unresolved doubt: does its Camera app benefit from the same image improvement features that the stock camera has?

Especially now that Pixels started shipping with hardware chipsets specifically designed to accelerate certain kinds of image processing, this is a feature that's quite important to me not to lose when changing systems.

By @Hizonner - 6 months
The real news here is that Google's internal organizational controls are so weak that some idiot from "sales", or "carrier relations", or whatever you want to call it, can get arbitrarily chosen stupid software preinstalled at the whim of some idiot from a similar function at Verizon.
By @markvdb - 6 months
Another advertisement for https://grapheneos.org ...
By @kkfx - 6 months
Ehm... Does someone think ALL smartphones are not spying devices controlled by many more than their formal human owner?
By @TaylorAlexander - 6 months
My next question is does Verizon know the users passwords (possibly via some other exploit we don’t know about) and did some state agency encourage Verizon to request that software so that access to confiscated devices was a subpoena or fisa court order away.
By @tropicalfruit - 6 months
"spyware contains spyware"

any phone when idle and seemingly "off" is doing all kinds of things and sending all kinds of info that you may not consent to if you were aware.

i dont even trust the wifi off and airplane mode anymore. they are all liars.

By @ChrisArchitect - 6 months
By @mdp2021 - 6 months
This specific to the submission is uninstalled normally (can be uninstalled by the user), I understand.

Otherwise one could try:

  pm uninstall --user 0 the.unwanted.package
I have to research about how effective the above is (uninstall only for this user - what you can do with "system" packages) to remove spyware.
By @anvilspoke - 6 months
So I decided to check if this is really as described.

I downloaded a copy of the app from here, which is the Pixel 8 firmware for June 2024: https://dumps.tadiphone.dev/dumps/google/shiba/-/raw/shiba-u...

The app has two components that are exported:

- broadcast receiver com.customermobile.preload.StartOnBoot, which receives the ACTION_BOOT_COMPLETED broadcast that is sent by the system after the device is booted and first unlocked by the user

- activity com.customermobile.preload.DebugActivity

The onReceive method in StartOnBoot is this:

        public void onReceive(Context context, Intent intent) {
            Log.d(LOG_ID, "on boot called: " + (intent != null ? intent.toString() : "null"));
            boolean demoEnabled = getDemoEnabled(context);
            boolean checkAppPermissions = checkAppPermissions(context);
            Log.d(LOG_ID, "demoEnabled: " + demoEnabled);
            Log.d(LOG_ID, "permissionsCheck: " + checkAppPermissions);
            if (demoEnabled && checkAppPermissions) {
                startDemoStub(context);
            } else {
                if (!demoEnabled || checkAppPermissions) {
                    return;
                }
                startPermissionsCheck(context);
            }
        }
It relies on the getDemoEnabled method returning true to do anything:

        public static boolean getDemoEnabled(Context context) {
            int iStoreDemoMode = 0;
            int iVzwStoreDemoMode = 0;
            String szStoreDemoMode;
            String szVzwStoreDemoMode;
            
            try {
                iStoreDemoMode = Settings.Secure.getInt(context.getContentResolver(), "store_demo_mode");
            } catch (Exception ignored) {}
            try {
                iVzwStoreDemoMode = Settings.Secure.getInt(context.getContentResolver(), "verizonwireless_store_demo_mode");
            } catch (Exception ignored) {}
            try {
                szStoreDemoMode = Settings.Secure.getString(context.getContentResolver(), "store_demo_mode");
            } catch (Exception ignored) {}
            try {
                szVzwStoreDemoMode = Settings.Secure.getString(context.getContentResolver(), "verizonwireless_store_demo_mode");
            } catch (Exception ignored) {}
            
            return
               (iStoreDemoMode > 0) || 
               (iVzwStoreDemoMode > 0) ||
               "true".equalsIgnoreCase(szStoreDemoMode) ||
               "true".equalsIgnoreCase(szVzwStoreDemoMode)
        }
Which will only happen if system settings "store_demo_mode" or "verizonwireless_store_demo_mode" are set to a positive integer or to "true".

As neither of these are set by default, none of the code behind the startDemoStub method will be executed when the device boots.

The DebugActivity layout is as follows, and consists of a single button labelled "Simulate StartOnBoot":

        <?xml version="1.0" encoding="utf-8"?>
        <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <Button
                android:id="@+id/startOnBoot"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="8dp"
                android:layout_marginTop="8dp"
                android:layout_marginRight="8dp"
                android:text="Simulate StartOnBoot"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="@+id/guideline"/>
            <androidx.constraintlayout.widget.Guideline
                android:orientation="horizontal"
                android:id="@+id/guideline"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintGuide_percent="0.1"/>
        </androidx.constraintlayout.widget.ConstraintLayout>
All this does if clicked is send an intent which will end up at the onReceive of the StartOnBoot receiver:

        public class DebugActivity extends AppCompatActivity implements View.OnClickListener {
            public void onCreate(Bundle bundle) {
                super.onCreate(bundle);
                setContentView(R.layout.activity_debug);
                findViewById(R.id.startOnBoot).setOnClickListener(this);
            }

            public void onClick(View view) {
                if (view.getId() == R.id.startOnBoot) {
                    sendStartOnBootIntent();
                }
            }

            private void sendStartOnBootIntent() {
                sendBroadcast(new Intent("com.customermobile.preload.StartOnBoot"), "com.customermobile.preload.StartOnBoot.PERMISSION");
            }
        }
We know this because the receiver filters for this action:

        <receiver
            android:name="com.customermobile.preload.StartOnBoot"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT"/>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.customermobile.preload.ManualStart"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.customermobile.preload.StartOnBoot"/>
            </intent-filter>
        </receiver>
So, nothing to worry about. The app does nothing unless one of the two system settings described above are set.
By @homero - 6 months
So what? There's people who need remote support