android
demo
MASTG-TEST-0258
MASTG-DEMO-0064: Uses of Caching UI Elements with semgrep
Download MASTG-DEMO-0064 APK
Open MASTG-DEMO-0064 Folder
Build MASTG-DEMO-0064 APK
Sample
The code sample defines a method that creates a popup dialog for user input where 3 text input fields (EditText) are instantiated. For each EditText, the inputType property is set to define the type of input expected:
password : should not be cached due to TYPE_TEXT_VARIATION_PASSWORD
passphrase : should be cached due to TYPE_CLASS_TEXT
PIN : should be cached due to TYPE_CLASS_NUMBER, despite initially being set to TYPE_NUMBER_VARIATION_PASSWORD
A dialog is also created using AlertDialog.Builder, and it includes "Sign Up" and "Cancel" buttons.
MastgTest.kt MastgTest_reversed.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 package org.owasp.mastestapp
import android.app.AlertDialog
import android.content.Context
import android.text.InputType
import android.widget.EditText
import android.widget.LinearLayout
class MastgTest ( private val context : Context ){
fun mastgTest (): String {
showPopup ( context )
return "The popup contains some caching input fields"
}
fun showPopup ( context : Context ) {
val layout = LinearLayout ( context ). apply {
orientation = LinearLayout . VERTICAL
setPadding ( 50 , 20 , 50 , 20 )
}
val input1 = EditText ( context ). apply {
hint = "Enter password (not cached)"
inputType = InputType . TYPE_CLASS_TEXT or InputType . TYPE_TEXT_VARIATION_PASSWORD
}
val input2 = EditText ( context ). apply {
hint = "Enter password (cached)"
inputType = InputType . TYPE_CLASS_TEXT
}
val input3 = EditText ( context ). apply {
hint = "Enter PIN (cached)"
inputType = InputType . TYPE_CLASS_NUMBER or InputType . TYPE_NUMBER_VARIATION_PASSWORD
}
input3 . inputType = InputType . TYPE_CLASS_NUMBER
layout . addView ( input1 )
layout . addView ( input2 )
layout . addView ( input3 )
AlertDialog . Builder ( context )
. setTitle ( "Sign Up Form" )
. setView ( layout )
. setPositiveButton ( "Sign Up" ) { _ , _ -> }
. setNegativeButton ( "Cancel" , null )
. show ()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 package org.owasp.mastestapp ;
import android.app.AlertDialog ;
import android.content.Context ;
import android.content.DialogInterface ;
import android.widget.EditText ;
import android.widget.LinearLayout ;
import kotlin.Metadata ;
import kotlin.jvm.internal.Intrinsics ;
/* compiled from: MastgTest.kt */
@Metadata ( d1 = { "\u0000\u001e\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\u0002\n\u0000\b\u0007\u0018\u00002\u00020\u0001B\r\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0002\u0010\u0004J\u0006\u0010\u0005\u001a\u00020\u0006J\u000e\u0010\u0007\u001a\u00020\b2\u0006\u0010\u0002\u001a\u00020\u0003R\u000e\u0010\u0002\u001a\u00020\u0003X\u0082\u0004¢\u0006\u0002\n\u0000¨\u0006\t" }, d2 = { "Lorg/owasp/mastestapp/MastgTest;" , "" , "context" , "Landroid/content/Context;" , "(Landroid/content/Context;)V" , "mastgTest" , "" , "showPopup" , "" , "app_debug" }, k = 1 , mv = { 1 , 9 , 0 }, xi = 48 )
/* loaded from: classes4.dex */
public final class MastgTest {
public static final int $stable = 8 ;
private final Context context ;
public MastgTest ( Context context ) {
Intrinsics . checkNotNullParameter ( context , "context" );
this . context = context ;
}
public final String mastgTest () {
showPopup ( this . context );
return "The popup contains some caching input fields" ;
}
public final void showPopup ( Context context ) {
Intrinsics . checkNotNullParameter ( context , "context" );
LinearLayout layout = new LinearLayout ( context );
layout . setOrientation ( 1 );
layout . setPadding ( 50 , 20 , 50 , 20 );
EditText $this$showPopup_u24lambda_u241 = new EditText ( context );
$this$showPopup_u24lambda_u241 . setHint ( "Enter password (not cached)" );
$this$showPopup_u24lambda_u241 . setInputType ( 129 );
EditText $this$showPopup_u24lambda_u242 = new EditText ( context );
$this$showPopup_u24lambda_u242 . setHint ( "Enter password (cached)" );
$this$showPopup_u24lambda_u242 . setInputType ( 1 );
EditText input3 = new EditText ( context );
input3 . setHint ( "Enter PIN (cached)" );
input3 . setInputType ( 18 );
input3 . setInputType ( 2 );
layout . addView ( $this$showPopup_u24lambda_u241 );
layout . addView ( $this$showPopup_u24lambda_u242 );
layout . addView ( input3 );
new AlertDialog . Builder ( context ). setTitle ( "Sign Up Form" ). setView ( layout ). setPositiveButton ( "Sign Up" , new DialogInterface . OnClickListener () { // from class: org.owasp.mastestapp.MastgTest$$ExternalSyntheticLambda0
@Override // android.content.DialogInterface.OnClickListener
public final void onClick ( DialogInterface dialogInterface , int i ) {
MastgTest . showPopup$lambda$4 ( dialogInterface , i );
}
}). setNegativeButton ( "Cancel" , ( DialogInterface . OnClickListener ) null ). show ();
}
/* JADX INFO: Access modifiers changed from: private */
public static final void showPopup$lambda$4 ( DialogInterface dialogInterface , int i ) {
}
}
Steps
Let's run semgrep rule against the sample code. The rule uses a pattern that captures every call to setInputType along with its argument.
../../../../rules/mastg-android-keyboard-cache-input-types.yml rules :
- id : mastg - android - non - caching - input - types
severity : WARNING
languages :
- java
metadata :
summary : This rule scans all usages of setInputType () .
message : "[MASVS-STORAGE] Set input type detected ($OBJ) with $ARG"
patterns :
- pattern : $ OBJ . setInputType ( $ ARG )
run.sh NO_COLOR = true semgrep - c ../../../../ rules / mastg - android - keyboard - cache - input - types . yml ./ MastgTest_reversed . java > output . txt
Observation
The rule has detected several instances. For each one, the output shows:
The line number.
The object name in the reversed code (e.g. $this$showPopup_u24lambda_u241 or input3).
The setInputType method itself.
The argument including the input type value (e.g., 129).
output.txt 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 ┌─────────────────┐
│ 4 Code Findings │
└─────────────────┘
MastgTest_reversed . java
❯❱ rules . mastg - android - keyboard - cache - input - types
[ MASVS - STORAGE ] Set input type detected ( $ this $ showPopup_u24lambda_u241 ) with 129
35 ┆ $ this $ showPopup_u24lambda_u241 . setInputType ( 129 );
⋮┆ ----------------------------------------
❯❱ rules . mastg - android - keyboard - cache - input - types
[ MASVS - STORAGE ] Set input type detected ( $ this $ showPopup_u24lambda_u242 ) with 1
38 ┆ $ this $ showPopup_u24lambda_u242 . setInputType ( 1 );
⋮┆ ----------------------------------------
❯❱ rules . mastg - android - keyboard - cache - input - types
[ MASVS - STORAGE ] Set input type detected ( input3 ) with 18
41 ┆ input3 . setInputType ( 18 );
⋮┆ ----------------------------------------
❯❱ rules . mastg - android - keyboard - cache - input - types
[ MASVS - STORAGE ] Set input type detected ( input3 ) with 2
42 ┆ input3 . setInputType ( 2 );
Evaluation
The test fails because the app doesn't use non-caching input types for some sensitive fields. Only the first input field (password) is configured correctly. The other two fields (passphrase and PIN) are set to caching input types.
See the Android InputType documentation for details about what each numeric value represents.
(PASS) Object showPopup_u24lambda_u241 is set as 129:
129 & 0x0000000F # 1 (TYPE_CLASS_TEXT)
129 & 0x00000FF0 # 128 (TYPE_TEXT_VARIATION_PASSWORD)
This is correct because it prevents the password from being cached.
(FAIL) Object showPopup_u24lambda_u242 is set as 1 (TYPE_CLASS_TEXT).
1 & 0x0000000F # 1 (TYPE_CLASS_TEXT)
This is incorrect because it allows the passphrase to be cached. The correct value should be 129 (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD).
(FAIL) Object input3 is first set to 18:
18 & 0x0000000F # 2 (TYPE_CLASS_NUMBER)
18 & 0x00000FF0 # 16 (TYPE_NUMBER_VARIATION_PASSWORD)
This would be correct, however, in the reversed code, there's a second setInputType call that sets the input type to 2 (TYPE_CLASS_NUMBER), which is a caching input type:
2 & 0x0000000F # 2 (TYPE_CLASS_NUMBER)
This is incorrect because it allows the PIN to be cached. The correct value should be 18 (TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_PASSWORD).