Comparison

1. Comparison with FlowDroid and IccTA.

FlowDroid/IccTA only outputs suspicious data-leakage flows without specifying the specific data type, thus yields a large number of non-sensitive data-related issues such as debugging output (i.e., Log Data Leakage and SD Card Data Lekage), and redundant sources (i.e., the following example of SMS Data Leakage), which requires substantial manual effort to verify it.

Specifically, for the 4 types of data leakage of GCash, 13 types of sensitive data are detected by Ausera (i.e., 3 Logging Data Leakage, 7 SD Card Data Leakage, 1 SMS Data Leakage, and 0 SharedPreference Data Leakage), however, FlowDroid/IccTA outputs 73 leakages, thus yields 62 false positives through manual cross-validation by co-authors.

SMS Data Leakage/SharedPreference Data Leakage:

Found a flow to sink virtualinvoke $r10.<android.telephony.SmsManager: void sendTextMessage(java.lang.String,java.lang.String,java.lang.String,android.app.PendingIntent,android.app.PendingIntent)>($r1, null, $r2, $r6, $r7), from the following sources:

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

***Note that we cannot know the data type of variable $r4 only relying on the data-leakage flow.

***Actually, the five sources are the redundant sources if there is no concrete data type.

***The comparison results of Ausera can be referred at https://sites.google.com/view/ausera/homepage/demo


  • Found a flow to sink interfaceinvoke $r16.<android.content.SharedPreferences$Editor: android.content.SharedPreferences$Editor putLong(java.lang.String,long)>($r8, $l0), from the following sources:

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.facebook.BrowseFacebookFriendsListActivity: void onActivityResult(int,int,android.content.Intent)>)


Logging Data Leakage/SD Card Data Leakage:

Note that all of the data are exposed by Log function, however, most of them are non-sensitive data according to our manual analysis.

  • Found a flow to sink staticinvoke <android.util.Log: int v(java.lang.String,java.lang.String)>($r2, $r1), from the following sources:

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

  • Found a flow to sink staticinvoke <android.util.Log: int d(java.lang.String,java.lang.String)>("RECEIVED", $r6), from the following sources:

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.paybills.PayBillsTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

  • Found a flow to sink staticinvoke <android.util.Log: int i(java.lang.String,java.lang.String)>("REGEX", $r2), from the following sources:

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.sendmoney.SendGcashMobileFieldsActivity: void onClickAction1(android.view.View)>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.buyload.BuyLoadTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

  • Found a flow to sink staticinvoke <android.util.Log: int i(java.lang.String,java.lang.String)>("GCashActivity", $r4), from the following sources:

- $r1 = virtualinvoke $r0.<com.globe.gcash.android.activity.dashboard.DashboardFragmentActivity: android.view.View findViewById(int)>(2131165456) (in <com.globe.gcash.android.activity.dashboard.DashboardFragmentActivity: void setActionBarIcon()>)

  • Found a flow to sink staticinvoke <android.util.Log: int d(java.lang.String,java.lang.String)>("RESULT", $r5), from the following sources:

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.paybills.BillersActivity: void onActivityResult(int,int,android.content.Intent)>)

  • Found a flow to sink staticinvoke <android.util.Log: int i(java.lang.String,java.lang.String)>("GCashUtils", $r3), from the following sources:

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.buyload.BuyLoadTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

  • Found a flow to sink staticinvoke <android.util.Log: int i(java.lang.String,java.lang.String)>("GCashActivity", $r7), from the following sources:

- $r2 = specialinvoke $r0.<roboguice.activity.RoboFragmentActivity: android.view.View findViewById(int)>($i0) (in <com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity: android.view.View findViewById(int)>)

  • Found a flow to sink staticinvoke <android.util.Log: int i(java.lang.String,java.lang.String)>("GCashActivity", $r6), from the following sources:

- $r1 = virtualinvoke $r0.<com.globe.gcash.android.activity.GcashActivity: android.view.View findViewById(int)>(2131165456) (in <com.globe.gcash.android.activity.GcashActivity: void setActionBarIcon()>)

  • Found a flow to sink staticinvoke <android.util.Log: int i(java.lang.String,java.lang.String)>("Form Validator", $r3), from the following sources:

- $r2 = virtualinvoke $r1.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.form.validator.FormValidator: boolean validateEditTextsDigitsIfExceedsRange(int,int,android.widget.EditText[])>)

- $r2 = virtualinvoke $r1.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.form.validator.FormValidator: boolean validateEditTextsDigitsIfExceedsRange(int,int,android.widget.EditText[])>)

  • Found a flow to sink staticinvoke <android.util.Log: int i(java.lang.String,java.lang.String)>("REGEX", $r2), from the following sources:

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.sendmoney.SendGcashMobileFieldsActivity: void onClickAction1(android.view.View)>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.buyload.BuyLoadTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

  • Found a flow to sink staticinvoke <android.util.Log: int v(java.lang.String,java.lang.String)>("SMS: REGISTER##", $r4), from the following sources:

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.RegistrationTransactionActivity: void doNext()>)

  • Found a flow to sink staticinvoke <android.util.Log: int w(java.lang.String,java.lang.String)>($r10, $r9), from the following sources:

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.facebook.BrowseFacebookFriendsListActivity: void onActivityResult(int,int,android.content.Intent)>)

  • Found a flow to sink staticinvoke <android.util.Log: int d(java.lang.String,java.lang.String)>("RECEIVED", $r6), from the following sources:

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.donate.DonateTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

  • Found a flow to sink staticinvoke <android.util.Log: int d(java.lang.String,java.lang.String)>($r0, $r1), from the following sources:

- $i1 := @parameter1: int (in <com.globe.gcash.android.activity.buyload.BuyLoadTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $i1 := @parameter1: int (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $i0 := @parameter0: int (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)


  • Found a flow to sink virtualinvoke $r2.<java.io.Writer: void write(int)>($c3), from the following sources:

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.paybills.PayBillsTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $r2 = virtualinvoke $r1.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBillsTransactionActivity: java.lang.String getAccountReference()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r10 = virtualinvoke $r9.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.donate.DonateTransactionActivity: void doNext()>)

- $r9 = virtualinvoke $r8.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.buyload.BuyLoadTransactionActivity: void doNext()>)

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r11 = virtualinvoke $r10.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBillsTransactionActivity: void doNext()>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.donate.DonateTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $r9 = virtualinvoke $r8.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.buyload.BuyLoadTransactionActivity: void doNext()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

  • Found a flow to sink virtualinvoke $r2.<java.io.Writer: void write(java.lang.String)>($r4), from the following sources:

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.paybills.PayBillsTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $r2 = virtualinvoke $r1.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBillsTransactionActivity: java.lang.String getAccountReference()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r10 = virtualinvoke $r9.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.donate.DonateTransactionActivity: void doNext()>)

- $r9 = virtualinvoke $r8.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.buyload.BuyLoadTransactionActivity: void doNext()>)

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $r15 = virtualinvoke $r14.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBirTransactionActivity: void doNext()>)

- $r11 = virtualinvoke $r10.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.paybills.PayBillsTransactionActivity: void doNext()>)

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.activity.donate.DonateTransactionActivity: void onActivityResult(int,int,android.content.Intent)>)

- $r9 = virtualinvoke $r8.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.buyload.BuyLoadTransactionActivity: void doNext()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

- $r7 = virtualinvoke $r6.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.transaction.SendMoneyTransactionActivity: void doNext()>)

Found a flow to sink virtualinvoke $r0.<com.globe.gcash.android.activity.sendmoney.SendGcashMobileFieldsActivity: void setResult(int,android.content.Intent)>(-1, $r3), from the following sources:

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.sendmoney.SendGcashMobileFieldsActivity: void onClickAction1(android.view.View)>)

- $r5 = virtualinvoke $r4.<android.widget.EditText: android.text.Editable getText()>() (in <com.globe.gcash.android.activity.sendmoney.SendGcashMobileFieldsActivity: void onClickAction1(android.view.View)>)

  • Found a flow to sink virtualinvoke $r3.<java.io.BufferedOutputStream: void write(byte[])>($r5), from the following sources:

- $r1 := @parameter2: android.content.Intent (in <com.globe.gcash.android.facebook.BrowseFacebookFriendsListActivity: void onActivityResult(int,int,android.content.Intent)>)

2. Comparison with CongiCrypt.

We find that most of the encryption-related weaknesses we defined in Ausera overlap with those in CongiCrypt, however, they both have some unique rules. For example, Ausera considers hard-coded key embedded in the apk while CongiCrypt does not; CongiCrypt suggests using TLSv1, TLSv1.1, or TLSv1.2 instead of TLS or SSL while Ausera does not.

Specifically, for the encryption issue types of GCash, 5 types of encryption issues are detected by Ausera (i.e., Encryption key hard-coded, Using DES/Blowfish, Improper RSA, Insecure SecureRandom, Insecure hash function (md5/sha1)). CongiCrypt also identified 5 types (i.e., ImpreciseValueExtractionError violating CrySL rule for MessageDigest, ConstraintError violating CrySL rule for MessageDigest, ConstraintError violating CrySL rule for javax.net.ssl.SSLContext [insure hash function, TLSv1/TLSv1.1/TLSv1.2], IncompleteOperationError violating CrySL rule for javax.net.ssl.SSLContext, RequiredPredicateError violating CrySL rule for javax.net.ssl.SSLContext [Insecure SecureRandom]). In summary, 3 types of security encryption issues are overlap. 2 types are unique for each of them.

(1) Unique results of Ausera

  • [Encryption key hardcoded]:[High] [Package key hardcoded]

com.globe.gcash.soap.server.container.SessionEncryptor2$1.<init> ==> enc.key

  • [The current app uses DES/Blowfish]

public void <init>() {

org.bouncycastle.jce.provider.symmetric.Blowfish$Mappings $r0;

$r0 := @this: org.bouncycastle.jce.provider.symmetric.Blowfish$Mappings;

specialinvoke $r0.<java.util.HashMap: void <init>()>();

virtualinvoke $r0.<org.bouncycastle.jce.provider.symmetric.Blowfish$Mappings: java.lang.Object put(java.lang.Object,java.lang.Object)>("Cipher.BLOWFISH", "org.bouncycastle.jce.provider.symmetric.Blowfish$ECB");

virtualinvoke $r0.<org.bouncycastle.jce.provider.symmetric.Blowfish$Mappings: java.lang.Object put(java.lang.Object,java.lang.Object)>("Cipher.1.3.6.1.4.1.3029.1.2", "org.bouncycastle.jce.provider.symmetric.Blowfish$CBC");

virtualinvoke $r0.<org.bouncycastle.jce.provider.symmetric.Blowfish$Mappings: java.lang.Object put(java.lang.Object,java.lang.Object)>("KeyGenerator.BLOWFISH", "org.bouncycastle.jce.provider.symmetric.Blowfish$KeyGen");

virtualinvoke $r0.<org.bouncycastle.jce.provider.symmetric.Blowfish$Mappings: java.lang.Object put(java.lang.Object,java.lang.Object)>("Alg.Alias.KeyGenerator.1.3.6.1.4.1.3029.1.2", "BLOWFISH");

virtualinvoke $r0.<org.bouncycastle.jce.provider.symmetric.Blowfish$Mappings: java.lang.Object put(java.lang.Object,java.lang.Object)>("AlgorithmParameters.BLOWFISH", "org.bouncycastle.jce.provider.symmetric.Blowfish$AlgParams");

virtualinvoke $r0.<org.bouncycastle.jce.provider.symmetric.Blowfish$Mappings: java.lang.Object put(java.lang.Object,java.lang.Object)>("Alg.Alias.AlgorithmParameters.1.3.6.1.4.1.3029.1.2", "BLOWFISH");

return;

}

](2) Unique results of CongiCrypt

  • Findings in Java Class: com.globe.gcash.android.activity.login.UrlConnectionUtil in Method: void <init>()

ConstraintError violating CrySL rule for javax.net.ssl.SSLContext

First parameter (with value "SSL") should be any of {TLSv1, TLSv1.1, TLSv1.2}

at statement: $r4 = staticinvoke <javax.net.ssl.SSLContext: javax.net.ssl.SSLContext getInstance(java.lang.String)>("SSL")

ConstraintError violating CrySL rule for javax.net.ssl.SSLContext

First parameter (with value "TLS") should be any of {TLSv1, TLSv1.1, TLSv1.2}

at statement: $r4 = staticinvoke <javax.net.ssl.SSLContext: javax.net.ssl.SSLContext getInstance(java.lang.String)>("TLS")

  • IncompleteOperationError violating CrySL rule for javax.net.ssl.SSLContext

Operation on object of type javax.net.ssl.SSLContext object not completed. Expected call to init

at statement: $r9 = virtualinvoke $r5.<javax.net.ssl.SSLContext: javax.net.ssl.SSLSocketFactory getSocketFactory()>()