GrapheneOS / os-issue-tracker

Issue tracker for GrapheneOS Android Open Source Project hardening work. Standalone projects like Auditor, AttestationServer and hardened_malloc have their own dedicated trackers.
https://grapheneos.org/
352 stars 19 forks source link

spoof/use standard sim carrier country and network country code #502

Open mlario opened 3 years ago

mlario commented 3 years ago

Hi,

Spoofing (or using standard) sim carrier/network country code would be a great addition to the privacy enhancements in GrapheneOS.

This is in relation to the effect that 3rd party apps can detect sim card carrier country, as mentioned here:

501

For example, by using Belgian sim card Whatsapp correctly sets Belgian number prefix during initial setup - without requesting location permission. By changing to German sim card Whatsapp correctly sets German number prefix.

Sim carrier country is hardwired into the sim card, cannot be reset/changed and provides extra bits of information to 3rd party apps, although with low entropy

For example system locale, time zone and country code can be easily changed. By going to Settings -> System -> Date & Time and setting manually Time zone it is possible to change country code for example from Belgium to Germany

However inserted/active sim card provides sim card carrier country that cannot be changed

Often sim cards are used in the country of origin. This provides 3rd party apps information about country without requesting location permission.

In case of setup with VPN and manually set Time zone app should not be able to guess country from sim card.

Ideally sim carrier country code could be set same as country code set by Timezone.

In case breakages are expected - this could be made as a non-default toggle in settings.

Again, many thanks for your work

muhomorr commented 1 year ago

Besides the gsm.sim.operator.iso-country system property, there's also android.location.CountryDetector#detectCountry() API that is not protected by any permissions.

code-consensus commented 5 months ago

Hi, I think this is a great suggestion, and hope to see this implemented eventually!

I do note that the GrapheneOS website does state they would like to implement something for this: "GrapheneOS will likely add further restrictions in this area and a couple toggles for certain cases like time zones to use a standard value instead". Definitely an upvote!

@muhomorr can ANY app access the CountryDetector function without any permission or privilege? I note the documentation states: "The country will be detected in order of reliability, like Mobile network, Location, SIM's country, Phone's locale". And furthermore there is also #addCountryListener, which will notify of a future change in country.

Can an app also access without permission [getSimCarrierIdName](https://developer.android.com/reference/android/telephony/TelephonyManager#getSimCarrierIdName()) or [getNetworkOperatorName](https://developer.android.com/reference/android/telephony/TelephonyManager#getNetworkOperatorName())? In that case, the app can also get the network names (gsm.sim.operator.alpha and gsm.operator.alpha, respectively), which would be further fingerprinting.

I think the issue is relevant because many users mistakenly think that denying location or changing IP addresses totally obscures location to an app. Of course, GrapheneOS is functioning exactly as it is supposed to, and it is also clearly stated on the website that this is the expected behavior. Regardless though, there are several examples of users on the GrapheneOS discussion forum that are surprised that Android functions this way, e.g. one example among many here. Considering that your average GrapheneOS user is probably much more technically savvy than the average phone user, the knowledge that this kind of location detection is possible seems to be something less generally known.

Apart from lack of user awareness, the real issue is that these identifiers (SIM or network or locale, etc) are actually used by apps to fingerprint users. While there may be legitimate reasons to do so by the app developer (e.g. GPDR compliance), the issue is more so when dealing with a large entity that may need to report to a unfriendly authority.

Ghacks wrote about Google changing users' country without user action, noting "The association is important for customers, as some countries or regions may offer better privacy and legal protections than others" (a search on the internet finds many people reporting something like this).

Of course, with respect to Google in particular, the solution would be to not install Sandboxed Play Services or any Google apps at all, but the issue is still present for using non-Google apps that connect to any kind of service.

Imagine someone is a dissident in an authoritarian country accessing a service via an app, and the service is forced to disclose to said authoritarian government which of its users are located in that country. Even if the user were using a VPN or Tor and had changed their locale to some random country, they would still get fingerprinted from the SIM card and/or the mobile network the user is using to access the app. Even if they use up the app(s) on a secondary profile using a different Tor circuit, the SIM country and mobile network country would still be able to be detected. If that user uses a SIM from a different country than the country they are located in, than that may create an even more unique fingerprint as you'd have two different countries.

The scenario above may be considering an extreme level of caution, so this is not something probably the average user needs to be that concerned about of course!

Anyway, the option to have this would certainly be interesting! An alternative to spoofing the information is to also to just return a blank as when there is no SIM card in the phone and it is in airplane mode. Or maybe the most "standard" country and UTC for the timezone or something like this.

Thanks for the great work by the GrapheneOS team!!

ihateprogramming88 commented 3 months ago

I am going to have a go at implementing this, what are the system property and APIs that need a toggle developed?

Is it just these gsm.sim.operator.iso-country android.location.CountryDetector#detectCountry getSimCarrierIdName getNetworkOperatorName Are there any more I am missing?

ihateprogramming88 commented 3 months ago

So can someone tell me if I am on the right track? I'm not that good at programming so take with a grain of salt, just trying.... I know the all the system property or APIs are not covered I just made one up but need further assistance from here if someone can advice me:) First it is needed to modify TelephonyManager class?

`public void setSimCarrierCountryCode(String countryCode) {

}

Second I would need to Add a new method to get the SIM carrier country code

java
public String getSimCarrierCountryCode() {

    return "";
}

Third I Modify the TelephonyManager Service to use new methods? Not sure if this is correct

public class TelephonyManagerService extends ITelephonyManager.Stub {

    @Override
    public void setSimCarrierCountryCode(String countryCode) {

        mTelephonyManager.setSimCarrierCountryCode(countryCode);
    }

    @Override
    public String getSimCarrierCountryCode() {

        return mTelephonyManager.getSimCarrierCountryCode();
    }
}

Then I need to add the permission and feature to android manifest.xml <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /> <uses-feature android:name="android.hardware.telephony" /> Not sure if this step is correct

Then I need to add the toggle to control the feature In the res/xml/preferences.xml file, add a new preference for the toggle: xml

Method to handle the toggle

public class SettingsActivity extends AppCompatActivity {

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (key.equals("sim_carrier_country_code_spoofing")) {
            boolean enabled = sharedPreferences.getBoolean(key, false);

        }
    }
}

Last step I don't know if this is correct either but it would need to check SIM carrier country code spoofing logic to check the toggle state before spoofing the country code

public class TelephonyManager {

    public void setSimCarrierCountryCode(String countryCode) {
        if (isSpoofingEnabled()) {

        } else {

        }
    }

    private boolean isSpoofingEnabled() {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
        return sharedPreferences.getBoolean("sim_carrier_country_code_spoofing", false);
    }
}
code-consensus commented 2 months ago

I am going to have a go at implementing this, what are the system property and APIs that need a toggle developed?

Is it just these gsm.sim.operator.iso-country android.location.CountryDetector#detectCountry getSimCarrierIdName getNetworkOperatorName Are there any more I am missing?

@ihateprogramming88 also: gsm.operator.iso-country, gsm.sim.operator.alpha and gsm.operator.alpha

Unfortunately I cannot comment on your proposed code, as I don't know the details!

N.B. There is one thing to note with regard to wi-fi calling. When you enable this, even if the phone is on airplane mode, the system will set the gsm.operator.iso-country flag. I'm not sure how this works with an eSIM, but this is the case at least with a physical SIM inserted and enabling wi-fi mode. So any toggling of the carrier code for apps must take this into consideration as it may break wi-fi calling.

atlantis451 commented 1 month ago

Even if the phone is on Airplane mode, Tiktok/Opera/Facebook, etc App can still be Check Esims and Sim Cards Your area country😒

code-consensus commented 1 month ago

@atlantis451 for your reference, if you physically remove your SIM card, and put the phone on airplane mode, there is no SIM card info for the app to get.

You can confirm this by running the getprop command via adb (on your computer: adb shell getprop).

If you are not on airplane mode, you have the following values, which are for the network you are connected to (which may be different than what your SIM card says, i.e. if you are roaming):

If you put your phone on airplane mode, the above values become blank.

What an app can detect though, even on airplane mode, is the SIM card's properties as follows:

But you eject the SIM card, the above properties also become blank. In that instance, no app can detect any SIM-card related info if you both put the phone on airplane mode and eject the SIM card.

With regard to an eSIM card, I don't have one, so I don't know if one can "turn it off", akin to ejecting a physical SIM such that then the gsm.sim.operator properties become blank. Someone else may be able to comment on that