1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.security.cts; 18 19 import android.platform.test.annotations.RestrictedBuildTest; 20 21 import com.android.compatibility.common.util.FileUtils; 22 23 import junit.framework.TestCase; 24 25 import java.io.DataInputStream; 26 import java.io.File; 27 import java.io.FileInputStream; 28 import java.io.IOException; 29 import java.io.UnsupportedEncodingException; 30 31 public class BannedFilesTest extends TestCase { 32 33 /** 34 * Detect devices vulnerable to the cmdclient privilege escalation bug. 35 * 36 * References: 37 * 38 * http://vulnfactory.org/blog/2012/02/18/xoom-fe-stupid-bugs-and-more-plagiarism/ 39 * http://forum.xda-developers.com/showthread.php?t=1213014 40 */ testNoCmdClient()41 public void testNoCmdClient() { 42 assertNotSetugid("/system/bin/cmdclient"); 43 } 44 testNoSyncAgent()45 public void testNoSyncAgent() { 46 assertNotSetugid("/system/bin/sync_agent"); 47 } 48 49 /** 50 * Detect devices allowing shell commands to be executed as root 51 * through sockets. 52 * 53 * References: 54 * 55 * https://plus.google.com/+JustinCaseAndroid/posts/e1r6c9Z9jgg 56 * https://plus.google.com/+JustinCaseAndroid/posts/5ofgPNrSu3J 57 */ testNoRootCmdSocket()58 public void testNoRootCmdSocket() { 59 assertFalse("/dev/socket/init_runit", new File("/dev/socket/init_runit").exists()); 60 assertFalse("/dev/socket/fotabinder", new File("/dev/socket/fotabinder").exists()); 61 } 62 63 /** 64 * Detect devices allowing shell commands to be executed as system 65 * through sockets. 66 * 67 * ANDROID-19679287 68 * CVE-2015-2231 69 */ testNoSystemCmdSocket()70 public void testNoSystemCmdSocket() { 71 assertFalse("/dev/socket/fota", new File("/dev/socket/fota").exists()); 72 } 73 74 @RestrictedBuildTest testNoSu()75 public void testNoSu() { 76 assertFalse("/sbin/su", new File("/sbin/su").exists()); 77 assertFalse("/system/bin/su", new File("/system/bin/su").exists()); 78 assertFalse("/system/sbin/su", new File("/system/sbin/su").exists()); 79 assertFalse("/system/xbin/su", new File("/system/xbin/su").exists()); 80 assertFalse("/vendor/bin/su", new File("/vendor/bin/su").exists()); 81 } 82 83 @RestrictedBuildTest testNoSuInPath()84 public void testNoSuInPath() { 85 String path = System.getenv("PATH"); 86 if (path == null) { 87 return; 88 } 89 String[] elems = path.split(":"); 90 for (String i : elems) { 91 File f = new File(i, "su"); 92 assertFalse(f.getAbsolutePath() + " exists", f.exists()); 93 } 94 } 95 testNoEnableRoot()96 public void testNoEnableRoot() throws UnsupportedEncodingException { 97 byte[] badPattern = "enable_root".getBytes("US-ASCII"); 98 assertFileDoesNotContain("/system/bin/adb", badPattern); 99 } 100 assertFileDoesNotContain(String filename, byte[] pattern)101 private static void assertFileDoesNotContain(String filename, byte[] pattern) { 102 try { 103 File f = new File(filename); 104 byte[] fileData = new byte[(int) f.length()]; 105 DataInputStream dis = new DataInputStream(new FileInputStream(f)); 106 dis.readFully(fileData); 107 dis.close(); 108 109 outer: 110 for (int i = 0; i < (fileData.length - pattern.length); i++) { 111 for (int j = 0; j < pattern.length; j++) { 112 if (fileData[i+j] != pattern[j]) { 113 continue outer; 114 } 115 } 116 fail("Found banned pattern in " + filename); 117 } 118 119 } catch (IOException e) { 120 // ignore - no such file, or IO error. Assume OK. 121 } 122 } 123 124 /** 125 * setuid or setgid "ip" command can be used to modify the 126 * routing tables of a device, potentially allowing a malicious 127 * program to intercept all network traffic to and from 128 * the device. 129 */ testNoSetuidIp()130 public void testNoSetuidIp() { 131 assertNotSetugid("/system/bin/ip"); 132 assertNotSetugid("/system/xbin/ip"); 133 assertNotSetugid("/vendor/bin/ip"); 134 } 135 136 /** 137 * setuid or setgid tcpdump can be used maliciously to monitor 138 * all traffic in and out of the device. 139 */ testNoSetuidTcpdump()140 public void testNoSetuidTcpdump() { 141 assertNotSetugid("/system/bin/tcpdump"); 142 assertNotSetugid("/system/bin/tcpdump-arm"); 143 assertNotSetugid("/system/xbin/tcpdump"); 144 assertNotSetugid("/system/xbin/tcpdump-arm"); 145 assertNotSetugid("/vendor/bin/tcpdump"); 146 assertNotSetugid("/vendor/bin/tcpdump-arm"); 147 } 148 assertNotSetugid(String file)149 private static void assertNotSetugid(String file) { 150 FileUtils.FileStatus fs = new FileUtils.FileStatus(); 151 if (!FileUtils.getFileStatus(file, fs, false)) { 152 return; 153 } 154 assertTrue("File \"" + file + "\" is setUID", (fs.mode & FileUtils.S_ISUID) == 0); 155 assertTrue("File \"" + file + "\" is setGID", (fs.mode & FileUtils.S_ISGID) == 0); 156 } 157 158 /** 159 * Detect "rootmydevice" vulnerability 160 * 161 * References: 162 * 163 * http://www.theregister.co.uk/2016/05/09/allwinners_allloser_custom_kernel_has_a_nasty_root_backdoor/ 164 */ testNoSunxiDebug()165 public void testNoSunxiDebug() { 166 assertFalse("/proc/sunxi_debug/sunxi_debug", new File("/proc/sunxi_debug/sunxi_debug").exists()); 167 } 168 } 169