diff options
author | Ashutosh Agarwal <radsaggi@google.com> | 2021-06-18 18:33:24 +0000 |
---|---|---|
committer | Ashutosh Agarwal <radsaggi@google.com> | 2021-08-16 11:22:41 +0000 |
commit | ed29b433f6743f3326e888f7cb52cab911d345c0 (patch) | |
tree | d8e11c334be05e7a019543812fe40079422fac53 | |
parent | c3689c4d26d7a2ce537854202cc287cf0209b83d (diff) | |
download | cts-ed29b433f6743f3326e888f7cb52cab911d345c0.tar.gz |
STS Test for Android Security BUG 183963253.
Tapjacking Usgae Access Activity in Android Car Settings.
Bug: 183963253
Bug: 189998250
Test: 'sts-tradefed run sts-engbuild-no-spl-lock -m CtsSecurityBulletinHostTestCases -t android.security.cts.Bug_183963253' fails with vulnerable build 7440951-userdebug (http://ab/7440951)
Test: 'sts-tradefed run sts-engbuild-no-spl-lock -m CtsSecurityBulletinHostTestCases -t android.security.cts.Bug_183963253' passes with patched build 7500853-userdebug (http://ab/7500853)
Change-Id: I4552e8e62a8aba21f4c8bb735ac87b231283804d
9 files changed, 506 insertions, 0 deletions
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java new file mode 100644 index 00000000000..e31cb479c0e --- /dev/null +++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_183963253.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.cts; + +import static org.junit.Assert.assertTrue; + +import android.platform.test.annotations.AsbSecurityTest; + +import org.junit.Test; +import org.junit.Before; +import org.junit.runner.RunWith; + +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; +import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; + +@RunWith(DeviceJUnit4ClassRunner.class) +public final class Bug_183963253 extends BaseHostJUnit4Test { + private static final String TEST_PKG = "android.security.cts.BUG_183963253"; + private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest"; + private static final String TEST_APP = "BUG-183963253.apk"; + + @Before + public void setUp() throws Exception { + uninstallPackage(getDevice(), TEST_PKG); + } + + @Test + @AsbSecurityTest(cveBugId = 183963253) + public void testRunDeviceTestsPassesFull() throws Exception { + installPackage(TEST_APP); + + // Grant permission to draw overlays. + getDevice().executeShellCommand( + "pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW"); + + assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testTapjacking")); + } +} diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/Android.bp b/hostsidetests/securitybulletin/test-apps/BUG-183963253/Android.bp new file mode 100644 index 00000000000..63ac1cae84e --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/Android.bp @@ -0,0 +1,31 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +android_test_helper_app { + name: "BUG-183963253", + defaults: ["cts_support_defaults"], + srcs: ["src/**/*.java"], + test_suites: [ + "cts", + "vts10", + "sts", + ], + static_libs: [ + "androidx.appcompat_appcompat", + "androidx.test.rules", + "androidx.test.uiautomator_uiautomator", + "androidx.test.core", + ], + sdk_version: "current", +} diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/BUG-183963253/AndroidManifest.xml new file mode 100644 index 00000000000..148fc7eced5 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/AndroidManifest.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="android.security.cts.BUG_183963253" + android:targetSandboxVersion="2"> + + <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> + <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> + + <application android:theme="@style/Theme.AppCompat.Light"> + <uses-library android:name="android.test.runner" /> + <service android:name=".OverlayService" + android:enabled="true" + android:exported="false" /> + + <activity + android:name=".MainActivity" + android:label="ST (Permission)" + android:exported="true" + android:taskAffinity="android.security.cts.BUG_183963253.MainActivity"> + + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + </application> + + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.security.cts.BUG_183963253" /> + +</manifest> diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/layout/activity_main.xml new file mode 100644 index 00000000000..0ac0cf489f4 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/layout/activity_main.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="left" + tools:context=".MainActivity" > + + <LinearLayout + android:id="@+id/linearLayout1" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_below="@+id/seekShowTimes" + android:layout_centerHorizontal="true" + android:layout_marginTop="53dp" + android:orientation="horizontal" > + + <Button + android:id="@+id/btnStart" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Start" /> + + </LinearLayout> + +</RelativeLayout> diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/values/strings.xml new file mode 100644 index 00000000000..c36354599e3 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/res/values/strings.xml @@ -0,0 +1,21 @@ +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<resources> + <string name="app_name">BUG_183963253</string> + <string name="app_description">This is an overlay-activity</string> + <string name="tapjacking_text">BUG_183963253 overlay text</string> +</resources> diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/Constants.java b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/Constants.java new file mode 100644 index 00000000000..6856fc45f8c --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/Constants.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.cts.BUG_183963253; + +final class Constants { + + public static final String LOG_TAG = "BUG-183963253"; + public static final String TEST_APP_PACKAGE = Constants.class.getPackage().getName(); + + public static final String ACTION_START_TAPJACKING = "BUG_183963253.start_tapjacking"; +} diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java new file mode 100644 index 00000000000..108eaf88ccd --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/DeviceTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.cts.BUG_183963253; + +import static android.security.cts.BUG_183963253.Constants.LOG_TAG; + +import org.junit.Before; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.util.Log; + +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import androidx.test.runner.AndroidJUnit4; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; +import androidx.test.uiautomator.Until; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertNotNull; + +/** Basic sample for unbundled UiAutomator. */ +@RunWith(AndroidJUnit4.class) +public class DeviceTest { + + private static final long WAIT_FOR_UI_TIMEOUT = 10_000; + + private Context mContext; + private UiDevice mDevice; + + @Before + public void setUp() throws Exception { + Log.d(LOG_TAG, "startMainActivityFromHomeScreen()"); + + mContext = getApplicationContext(); + + // If the permission is not granted, the app will show up in the Usage Access Settings. + // This is required for the test below. + // NOTE: The permission is granted by the HostJUnit4Test implementation and should not fail. + assertEquals("Permission PACKAGE_USAGE_STATS not granted!", + mContext.checkSelfPermission("android.permission.PACKAGE_USAGE_STATS"), + PackageManager.PERMISSION_GRANTED); + + // Initialize UiDevice instance + mDevice = UiDevice.getInstance(getInstrumentation()); + if (!mDevice.isScreenOn()) { + mDevice.wakeUp(); + } + mDevice.pressHome(); + } + + @Test + public void testTapjacking() throws InterruptedException { + Log.d(LOG_TAG, "Starting tap-jacking test"); + + launchTestApp(); + + launchTapjackedActivity(); + + mContext.sendBroadcast(new Intent(Constants.ACTION_START_TAPJACKING)); + Log.d(LOG_TAG, "Sent intent to start tap-jacking!"); + + UiObject2 overlay = waitForView(By.text("BUG_183963253 overlay text")); + assertNull("Tap-jacking successful. Overlay was displayed.!", overlay); + } + + @After + public void tearDown() { + mDevice.pressHome(); + } + + private void launchTestApp() { + Intent intent = mContext.getPackageManager().getLaunchIntentForPackage( + Constants.TEST_APP_PACKAGE); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + mContext.startActivity(intent); + + // Wait for the app to appear + UiObject2 view = waitForView(By.pkg(Constants.TEST_APP_PACKAGE).depth(0)); + assertNotNull("test-app did not appear!", view); + Log.d(LOG_TAG, "test-app appeared"); + } + + private void launchTapjackedActivity() { + Intent intent = new Intent(); + intent.setAction("android.settings.USAGE_ACCESS_SETTINGS"); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + + UiObject2 view = waitForView(By.text(Constants.TEST_APP_PACKAGE)); + assertNotNull("Activity under-test was not launched or found!", view); + Log.d(LOG_TAG, "Started Activity under-test."); + } + + private UiObject2 waitForView(BySelector selector) { + return mDevice.wait(Until.findObject(selector), WAIT_FOR_UI_TIMEOUT); + } +} diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/MainActivity.java b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/MainActivity.java new file mode 100644 index 00000000000..597423dc730 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/MainActivity.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.security.cts.BUG_183963253; + +import static android.security.cts.BUG_183963253.Constants.LOG_TAG; + +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import android.view.Gravity; +import android.view.WindowManager.LayoutParams; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.SeekBar; +import android.widget.Toast; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import java.util.ArrayList; + +/** Main activity for the test-app. */ +public final class MainActivity extends AppCompatActivity { + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + startTapjacking(); + } + }; + + private Button btnStart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + registerReceiver(mReceiver, new IntentFilter(Constants.ACTION_START_TAPJACKING)); + + btnStart = (Button) findViewById(R.id.btnStart); + btnStart.setOnClickListener(v -> startTapjacking()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(mReceiver); + stopOverlayService(); + } + + public void startTapjacking() { + Log.d(LOG_TAG, "Starting tap-jacking flow."); + stopOverlayService(); + + startOverlayService(); + Log.d(LOG_TAG, "Started overlay-service."); + } + + private void startOverlayService() { + startService(new Intent(getApplicationContext(), OverlayService.class)); + } + + private void stopOverlayService() { + stopService(new Intent(getApplicationContext(), OverlayService.class)); + } +} diff --git a/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/OverlayService.java b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/OverlayService.java new file mode 100644 index 00000000000..ec21f0bf4e9 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/BUG-183963253/src/android/security/cts/BUG_183963253/OverlayService.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.cts.BUG_183963253; + +import android.app.Service; +import android.content.Intent; +import android.content.res.Resources; +import android.graphics.PixelFormat; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.provider.Settings; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.Gravity; +import android.view.WindowManager; +import android.widget.Button; + +/** Service that starts the overlay for the test. */ +public final class OverlayService extends Service { + public Button mButton; + private WindowManager mWindowManager; + private WindowManager.LayoutParams mLayoutParams; + + @Override + public void onCreate() { + Log.d(Constants.LOG_TAG, "onCreate() called"); + super.onCreate(); + + DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics(); + int scaledWidth = (int) (displayMetrics.widthPixels * 0.9); + int scaledHeight = (int) (displayMetrics.heightPixels * 0.9); + + mWindowManager = getSystemService(WindowManager.class); + mLayoutParams = new WindowManager.LayoutParams(); + mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + mLayoutParams.format = PixelFormat.OPAQUE; + mLayoutParams.gravity = Gravity.CENTER; + mLayoutParams.width = scaledWidth; + mLayoutParams.height = scaledHeight; + mLayoutParams.x = scaledWidth / 2; + mLayoutParams.y = scaledHeight / 2; + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.d(Constants.LOG_TAG, "onStartCommand() called"); + showFloatingWindow(); + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onDestroy() { + Log.d(Constants.LOG_TAG, "onDestroy() called"); + if (mWindowManager != null && mButton != null) { + mWindowManager.removeView(mButton); + } + super.onDestroy(); + } + + private void showFloatingWindow() { + if (!Settings.canDrawOverlays(this)) { + Log.w(Constants.LOG_TAG, "Cannot show overlay window. Permission denied"); + } + + mButton = new Button(getApplicationContext()); + mButton.setText(getResources().getString(R.string.tapjacking_text)); + mButton.setTag(mButton.getVisibility()); + mWindowManager.addView(mButton, mLayoutParams); + + new Handler(Looper.myLooper()).postDelayed(this::stopSelf, 60_000); + Log.d(Constants.LOG_TAG, "Floating window button created"); + } +} |