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

Implementation fails to enforce pinning (React Native) #91

Open
gabimoncha opened this issue Jun 9, 2021 · 4 comments
Open

Implementation fails to enforce pinning (React Native) #91

gabimoncha opened this issue Jun 9, 2021 · 4 comments

Comments

@gabimoncha
Copy link

gabimoncha commented Jun 9, 2021

Describe the bug
A clear and concise description of what the bug is.

I've implemented the library as is described in the documentation, without any success in enforcing the certificate pinning.

To Reproduce
Steps to reproduce the behavior.

res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="false">
        <domain includeSubdomains="true">www.example.com</domain>
        <pin-set>
            <-- Invalid certificates -->
            <pin digest="SHA-256">AAAAeJFIEmx2Y01oXXXXXXXXXXmmSFZhBXXXXXXXXXX=</pin>
            <pin digest="SHA-256">CCCCxtmctlq2Y73orFOOXXXXXXXXXXZhBXXXXXXXXXX=</pin>
        </pin-set>
    </domain-config>
    <domain-config cleartextTrafficPermitted="true">
        <-- React Native config for debugging the app in Debug mode. I have tried without it and it still fails -->
        <domain includeSubdomains="true">10.0.2.2</domain>
        <domain includeSubdomains="true">localhost</domain>
    </domain-config>
</network-security-config>

MainApplication.java

...
  @Override
  public void onCreate() {
    super.onCreate();
    // Using the default path - res/xml/network_security_config.xml
    TrustKit.initializeWithNetworkSecurityConfiguration(this);

    String serverHostname = null;
    try {
        URL url = new URL("https://www.example.com");
        serverHostname = url.getHost();

        // HttpsUrlConnection
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        connection.setSSLSocketFactory(TrustKit.getInstance().getSSLSocketFactory(serverHostname));
    } catch (MalformedURLException e) {
        System.err.println("MalformedURLException when declaring URL " + e);
    } catch (IOException e) {
        System.err.println("IOException when opening connection " + e);
    }

    // OkHttp 3
    // OkHttpClient client = OkHttpClientProvider.createClientBuilder().sslSocketFactory(TrustKit.getInstance().getSSLSocketFactory(serverHostname),TrustKit.getInstance().getTrustManager(serverHostname)).build();

    OkHttpClient client = new OkHttpClient().newBuilder().sslSocketFactory(TrustKit.getInstance().getSSLSocketFactory(serverHostname),TrustKit.getInstance().getTrustManager(serverHostname)).build();

    SoLoader.init(this, /* native exopackage */ false);
    initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  }

useValidCertificate.js which is called once the Navigation screens have mounted

export default function useValidCertificate() {
  useEffect(() => {
    (async () => {
      fetch(`https://www.example.com/account/ping`)
        .then(() => {
          console.log('Valid certificate, connected.');
        })
        .catch(() => {
          resetRoot(SECURITY_SCREENS.InvalidCertificate);
        });
    })();
  }, []);
}

Expected behavior
A clear and concise description of what you expected to happen.

The app should navigate to InvalidCertificate screen as it does when using TrustKit library for iOS.
Instead the app is behaving as if the certificate is still valid.

TrustKit configuration
Copy and paste your XML Network Security Policy.

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="false">
        <domain includeSubdomains="true">www.example.com</domain>
        <pin-set>
            <-- Invalid certificates -->
            <pin digest="SHA-256">AAAAeJFIEmx2Y01oXXXXXXXXXXmmSFZhBXXXXXXXXXX=</pin>
            <pin digest="SHA-256">CCCCxtmctlq2Y73orFOOXXXXXXXXXXZhBXXXXXXXXXX=</pin>
        </pin-set>
    </domain-config>
    <domain-config cleartextTrafficPermitted="true">
        <-- React Native config for debugging the app in Debug mode. I have tried without it and it still fails -->
        <domain includeSubdomains="true">10.0.2.2</domain>
        <domain includeSubdomains="true">localhost</domain>
    </domain-config>
</network-security-config>

App details:

  • App target SDK: 29
  • App language: React Native
  • Android version to reproduce the bug: Android 10

Additional context
Add any other context about the problem here.

@gabimoncha gabimoncha changed the title React Native implementation fails to enforce pinning Implementation fails to enforce pinning (React Native) Jun 9, 2021
@nabla-c0d3
Copy link
Member

Hello,

Unfortunately React Native is not supported. The call to fetch() does not go through TrustKit's validation code which is why the app is behaving as if the certificate is still valid.

Your app would have to instead use the HttpsURLConnection or the OkHttpClient objects to implement pinning validation.

@princealirehman1
Copy link

@gabimoncha
Are you able to achieve this on react-native ?

@Moustafa-mahmaed
Copy link

I solved this problem after I took more than 4 days with me
You can apply the following steps and they will help you solve the problem
1- put trustKit in build.gradle
implementation 'com.datatheorem.android.trustkit:trustkit:1.1.3'
2-put onCreate in mainActivity.java
@Override protected void onCreate(Bundle savedInstanceState) { TrustKit.initializeWithNetworkSecurityConfiguration(this); super.onCreate(savedInstanceState); }

3-create xml folder inside res folder
4-create network_security_config.xml

5-pass this code inside network_security_config.xml
<?xml version="1.0" encoding="utf-8" ?> <network-security-config xmlns:tools="http://schemas.android.com/tools"> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="false">localhost</domain> <domain includeSubdomains="false">10.0.2.2</domain> <domain includeSubdomains="false">10.0.3.2</domain> <trustkit-config enforcePinning="false" /> </domain-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">"replace url domain here"</domain> <trust-anchors> <certificates src="@raw/ca" /> <certificates src="system" /> </trust-anchors> <trustkit-config enforcePinning="true" /> </domain-config> </network-security-config>
6-dont forget add raw folder inside res folder
7-put certificate name as ca without extension

hope be helpful

@waohwaohwaoh
Copy link

I solved this problem after I took more than 4 days with me You can apply the following steps and they will help you solve the problem 1- put trustKit in build.gradle implementation 'com.datatheorem.android.trustkit:trustkit:1.1.3' 2-put onCreate in mainActivity.java @Override protected void onCreate(Bundle savedInstanceState) { TrustKit.initializeWithNetworkSecurityConfiguration(this); super.onCreate(savedInstanceState); }

3-create xml folder inside res folder 4-create network_security_config.xml

5-pass this code inside network_security_config.xml <?xml version="1.0" encoding="utf-8" ?> <network-security-config xmlns:tools="http://schemas.android.com/tools"> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="false">localhost</domain> <domain includeSubdomains="false">10.0.2.2</domain> <domain includeSubdomains="false">10.0.3.2</domain> <trustkit-config enforcePinning="false" /> </domain-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">"replace url domain here"</domain> <trust-anchors> <certificates src="@raw/ca" /> <certificates src="system" /> </trust-anchors> <trustkit-config enforcePinning="true" /> </domain-config> </network-security-config> 6-dont forget add raw folder inside res folder 7-put certificate name as ca without extension

hope be helpful

you are saved my day, thx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants