talsec / Free-RASP-Cordova

Cordova plugin for improving app security and threat monitoring on Android and iOS mobile devices.
https://github.com/talsec/Free-RASP-Community
MIT License
16 stars 4 forks source link

Get unofficialStore threat while installing app from Visual Studio App Center #3

Closed privaterepo2021 closed 1 year ago

privaterepo2021 commented 1 year ago

Is there a way to add Visual Studio App Center to the supportedAlternativeStores array list?

msikyna commented 1 year ago

Hello @privaterepo2021 ,

the supportedAlternativeStores accepts a package name of the application, which installs your app. If you are downloading the APK from App Center, it might be installed by Android package installer. Try to include the com.google.android.packageinstaller or com.android.packageinstaller. However, this will allow installing your APK directly even not from App Center, therefore do not use it later in production. Let us know, if it helped.

Kind regards, Matúš, Talsec developer

privaterepo2021 commented 1 year ago

Hi @msikyna, thank you for the quick response. I had tried out the solution and it works.

privaterepo2021 commented 1 year ago

Hi @msikyna, I just checked that actually the plugin did not show unofficial store threat because the plugin has fail to init.

This is my configuration:

"tlacConfig": { "androidConfig" : { "packageName" : "com.eb.sps", "certificateHash" : "2ZYTL+Z2gGVzO1QZ2VcMZ1GT1pebaNKFFoE+LVJd0AI=", "supportedAlternativeStores": [ "com.google.android.packageinstaller", "com.android.packageinstaller" ] }, "iosConfig" : { "appBundleIds": "com.eb.sps", "appTeamId": "BLT26AAEG2" }, "watcherMail" : null }

This is from the debugger:

D/PluginManager: getPlugin - put: TalsecPlugin W/CordovaPlugin: Attempted to send a second callback for ID: TalsecPlugin451479080 Result was: "Invalid action"

tompsota commented 1 year ago

Hello @privaterepo2021,

this is happening because your config is nested under tlacConfig key and therefore freeRASP is not able to parse it correctly. A valid config would look like this:

    var config = {
        androidConfig : {
            packageName : "com.eb.sps",
            certificateHash : "2ZYTL+Z2gGVzO1QZ2VcMZ1GT1pebaNKFFoE+LVJd0AI=",
            supportedAlternativeStores : [
                "com.google.android.packageinstaller",
                "com.android.packageinstaller"
            ]
        },
        iosConfig : {
            appBundleIds : "com.eb.sps",
            appTeamId : "BLT26AAEG2"
        },
        watcherMail : null 
    };

Try to pass object with this structure into talsec.start and let us know if that helped.

(Also don't forget to update the watcherMail ;) )

Best, Tomas, Talsec developer

privaterepo2021 commented 1 year ago

Hi @tompsota, I had check the plugin code, looks like supportedAlternativeStores is not supported for the current master branch of this plugin? I notice that the config value is null for supportedAlternativeStores.

private fun parseTalsecConfigThrowing(configJson: String): TalsecConfig {
        val json = JSONObject(configJson)
        val androidConfig = json.getJSONObject("androidConfig")
        val packageName = androidConfig.getString("packageName")
        val certificateHash = androidConfig.getString("certificateHash")
        val watcherMail = json.getString("watcherMail")
        val alternativeStores = mutableListOf<String>()
        if (androidConfig.has("supportedAlternativeStores")) {
            val stores = androidConfig.getJSONArray("supportedAlternativeStores")
            for (i in 0 .. stores.length()) {
                alternativeStores.add(stores.getString(i))
            }
        }
        return TalsecConfig(packageName, certificateHash, watcherMail, null)
}

this is my function

initTLAC(){
        var config = {
            "androidConfig" : {
                "packageName" : "com.eb.sps", 
                "certificateHash" : "2ZYTL+Z2gGVzO1QZ2VcMZ1GT1pebaNKFFoE+LVJd0AI=",
                "supportedAlternativeStores": [
                    "com.google.android.packageinstaller",
                    "com.android.packageinstaller"
                ]
            },
            "iosConfig" : {
                "appBundleIds": "com.eb.sps",
                "appTeamId": "BLT26AAEG2"
            },
            "watcherMail" : "tmlee@gmail.com"
        }; //serverConfig["tlacConfig"];
        var threatListener = (threatType)=>{
            this.logService.log("threat", threatType);
            switch(threatType) {
                case "privilegedAccess": // Android & iOS
                    let isEnableEmulator = serverConfig["isEnableEmulator"];
                    if(window.device.isVirtual) {
                        if(!isEnableEmulator) {
                            this.showRootEmulatorErrorMessage();
                        }
                    }
                    break;
                case "debug": // Android & iOS
                case "simulator": // Android & iOS
                case "appIntegrity": // Android & iOS
                case "unofficialStore": // Android & iOS
                case "hooks": // Android & iOS
                case "device binding": // Android & iOS
                case "deviceID": // iOS only
                case "missingSecureEnclave": // iOS only
                case "passcodeChange": // iOS only
                case "passcode": // iOS only
                    this.showRootEmulatorErrorMessage();
                    break;
                default:
                    console.log('Unknown threat type detected: ' + threatType);
                    this.showRootEmulatorErrorMessage();
            }
        };

        window.talsec.start(config, threatListener).then(() => {
            this.logService.log('Talsec initialized.');
        }).catch((error) => {
            this.logService.log('Error during Talsec initialization: ', error);
            // this.showRootEmulatorErrorMessage();
        });
}

I had try with your suggestion but still hit the same error. If I removed the supportedAlternativeStores array list then it can work.

msikyna commented 1 year ago

Hi @privaterepo2021 ,

you are right, there was a slight bug in the master branch regarding the supportedAlternativeStores.. it will be fixed in a moment, as today, we are releasing a v2.0.0.

There will be one more API change, certificateHash is now certificateHashes : ["your_signing_certificate_hash_base64"]; see the array, it now supports more certificate hashes.

privaterepo2021 commented 1 year ago

Hi @msikyna, I will test it out with the new version of the plugin. Thanks, have a great day 👍

privaterepo2021 commented 1 year ago

Hi @msikyna @tompsota , I still got the error after upgrading to the latest 2.0.0 version. Is there anything I miss out?

W/CordovaPlugin: Attempted to send a second callback for ID: TalsecPlugin1771000586
    Result was: "Invalid action"
D/PluginManager: exec() call to unknown plugin: DeleteLaunchScreenCache
I/chromium: [INFO:CONSOLE(1)] "Error during Talsec initialization: ", source: file:///android_asset/www/static/js/main.840d2e30.js (1)

This is my function

initTLAC(){
        var config = {
            "androidConfig" : {
                "packageName" : "com.eb.sps", 
                "certificateHash" : ["2ZYTi+Z2PGVzO1QZcVcMZ1GTmpebaNKFFoE+LVJd0AI="],
                "supportedAlternativeStores": [
                    "com.google.android.packageinstaller",
                    "com.android.packageinstaller"
                ]
            },
            "iosConfig" : {
                "appBundleIds": "com.eb.sps",
                "appTeamId": "BLT26AAEG2"
            },
            "watcherMail" : "tmlee@gmail.com"
        }; //serverConfig["tlacConfig"];
        var threatListener = (threatType)=>{
            this.logService.log("threat", threatType);
            switch(threatType) {
                case "privilegedAccess": // Android & iOS
                    let isEnableEmulator = serverConfig["isEnableEmulator"];
                    if(window.device.isVirtual) {
                        if(!isEnableEmulator) {
                            this.showRootEmulatorErrorMessage();
                        }
                    }
                    break;
                case "debug": // Android & iOS
                case "simulator": // Android & iOS
                case "appIntegrity": // Android & iOS
                case "unofficialStore": // Android & iOS
                case "hooks": // Android & iOS
                case "device binding": // Android & iOS
                case "deviceID": // iOS only
                case "missingSecureEnclave": // iOS only
                case "passcodeChange": // iOS only
                case "passcode": // iOS only
                    this.showRootEmulatorErrorMessage();
                    break;
                default:
                    console.log('Unknown threat type detected: ' + threatType);
                    this.showRootEmulatorErrorMessage();
            }
        };

        window.talsec.start(config, threatListener).then(() => {
            this.logService.log('Talsec initialized.');
        }).catch((error) => {
            this.logService.log('Error during Talsec initialization: ', error);
            // this.showRootEmulatorErrorMessage();
        });
}
privaterepo2021 commented 1 year ago

I using

"@angular/core": "11.0.2" "cordova-android": "11.0.0" "cordova-ios": "6.2.0"

config.xml

<platform name="android">
        <allow-intent href="market:*" />
        <preference name="android-targetSdkVersion" value="31" />
        <preference name="android-minSdkVersion" value="22" />
        <preference name="AndroidXEnabled" value="true" />
        <preference name="AndroidInsecureFileModeEnabled" value="true" />
        <preference name="AndroidWindowSplashScreenAnimatedIcon" value="res/icon/android/logo.xml" />
        <preference name="AndroidWindowSplashScreenBackground" value="#FFFFFF" />
        <icon density="ldpi" src="res/icon/android/icon-36-ldpi.png" />
        <icon density="mdpi" src="res/icon/android/icon-48-mdpi.png" />
        <icon density="hdpi" src="res/icon/android/icon-72-hdpi.png" />
        <icon density="xhdpi" src="res/icon/android/icon-96-xhdpi.png" />
        <icon density="xxhdpi" src="res/icon/android/icon-144-xxhdpi.png" />
        <icon density="xxxhdpi" src="res/icon/android/icon-192-xxxhdpi.png" />
        <resource-file src="res/icon/android/push_notification_icon.png" target="app/src/main/res/drawable-ldpi/push_notification_icon.png" />
        <resource-file src="res/icon/android/push_notification_icon.png" target="app/src/main/res/drawable-mdpi/push_notification_icon.png" />
        <resource-file src="res/icon/android/push_notification_icon.png" target="app/src/main/res/drawable-hdpi/push_notification_icon.png" />
        <resource-file src="res/icon/android/push_notification_icon.png" target="app/src/main/res/drawable-xhdpi/push_notification_icon.png" />
        <resource-file src="res/icon/android/push_notification_icon.png" target="app/src/main/res/drawable-xxhdpi/push_notification_icon.png" />
        <resource-file src="res/icon/android/push_notification_icon.png" target="app/src/main/res/drawable-xxxhdpi/push_notification_icon.png" />
        <feature name="SocialSharing">
            <param name="android-package" value="nl.xservices.plugins.SocialSharing" />
        </feature>
        <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application/activity[@android:name='MainActivity']">
            <activity android:windowSoftInputMode="adjustResize" />
        </edit-config>
        <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application/service[@android:name='com.adobe.phonegap.push.FCMService']">
            <service android:exported="true" />
        </edit-config>
        <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application/service[@android:name='com.adobe.phonegap.push.PushInstanceIDListenerService']">
            <service android:exported="true" />
        </edit-config>
        <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
            <application android:allowBackup="false" />
        </edit-config>
        <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application" xmlns:android="http://schemas.android.com/apk/res/android">
            <application android:preserveLegacyExternalStorage="true" />
            <application android:requestLegacyExternalStorage="true" />
        </edit-config>
        <preference name="CodePushDeploymentKey" value="3gv8CBCU9EIGRLWe6zsa-Fi86wrmmleURMuvlx" />
        <preference name="AndroidPersistentFileLocation" value="Compatibility" />
        <preference name="signatureHash" value="D996138BE6763C65733B541971570C6751939A979B68D28516813E2D525DD002" />
        <preference name="googleSignatureHash" value="F555229C2CECF68E8F29A76795E0B794F8B86E040B0FC738716B260A85CE9644" />
        <preference name="releaseSignatureHash" value="D996138BE6763C65733B541971570C6751939A979B68D28516813E2D525DD002" />
        <resource-file src="google-services.json" target="app/google-services.json" />
        <hook src="hooks/after_platform_add.js" type="after_platform_add" />
        <preference name="GradlePluginKotlinEnabled" value="true" />
        <preference name="GradlePluginKotlinCodeStyle" value="official" />
        <preference name="GradlePluginKotlinVersion" value="1.7.10" />
    </platform>
tompsota commented 1 year ago

@privaterepo2021 There was a breaking change in the API in v2.0.0, please change certificateHash to certificateHashes in your config.

privaterepo2021 commented 1 year ago

Hi @tompsota thanks for pointing out the mistake, it works now 👍

privaterepo2021 commented 1 year ago

Hi @tompsota , are we able to add supportedAlternativeStores for ios config? Seems like IOS is also hitting unofficial store threat if I build Ipa from xcode

msikyna commented 1 year ago

Hello @privaterepo2021 , the iOS only supports an official way (AppStore or TestFlight) of installing the application. Building an IPA from Xcode correctly hits the unofficial store threat.

Kind regards, Matúš, Talsec developer