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