Hacker News new | ask | show | jobs
by Andromxda 111 days ago
Of course the topic as a whole is much more complex than that, but I'll try to summarize it. Android has 3 systems of access control [1][2]:

- Discretionary Access Control, i.e. the standard Unix file permissions

- Mandatory Access Control, implemented in the form of the SELinux and YAMA LSMs (GrapheneOS stopped using YAMA in the 2024031400 release and replaced it with advanced SELinux policies)

- Android permissions which have to be disclosed in the AndroidManifest.xml, and most of the time need to be granted by the user at runtime

Root simply bypasses ALL of these security mechanisms. This is a clear violation of the principle of least privilege, since most of the stuff you are doing with root probably doesn't require access to your entire filesystem, and could easily run within an SELinux context. But writing and deploying a modified SELinux policy would take extra time and effort, and devs are lazy, so they just use root to completely bypass it.

As madaidan points out, only a tiny subset of system processes on Android run as root. [3] And Android has clear guidelines about what root process are and aren't allowed to do. From the AOSP documentation:

> Where possible, root code should be isolated from untrusted data and accessed via IPC.

> Root processes must not listen on a network socket.

> Root processes must not provide a general-purpose runtime for apps (for example, a Java VM).

Desktop systems are very different from Android and iOS. Out of Android's three major security mechanisms, they typically only implement one. This is why ransomware is so insanely successful. Every program has access to all the files and folders of the logged in user, including network shares, etc. Even on systems that implement application sandboxing and a permission system, such as macOS, it's only an afterthought, and isn't enforced properly. (macOS is still miles ahead of Windows and Linux though) For example, when installing a 3rd-party terminal emulator such as iTerm2 on macOS, you have to grant it the permission to access your entire file system (otherwise you will be limited to the home directory IIRC). But this permission also applies recursively to every process started within the terminal, greatly limiting its usefulness.

> I don't understand this. Could someone explain it with more details to me, please?

Android uses Verified Boot to protect against both Evil maid attacks [4], i.e. someone modifying the operating system on the hard drive, and malware persistence. By default, the Android /system partition is mounted in read-only mode, unlike for example your C:\Windows directory, or system directories like /bin on Linux. This prevents malware from modifying the operating system. If you ever get malware on Android or iOS, in most cases you can get rid of it, by simply rebooting your device. Unless of course, the malware has some persistence mechanism. Root obviously provides a great vector for persistence, since the system partition could simply be remounted in a writable mode, and the system could be modified however the attacker wants to.

When you build your own copy of AOSP or GrapheneOS, include your modifications, and sign the image with your own Verified Boot keys, that image can't be modified or tampered with by an attacker. It's perfectly secure to do that (of course only if you can trust the extra code you're including).

[1] https://source.android.com/docs/security/app-sandbox#protect...

[2] https://arxiv.org/pdf/1904.05572

[3] https://source.android.com/docs/security/overview/implement#...

[4] https://en.wikipedia.org/wiki/Evil_maid_attack

1 comments

Thanks a lot for the thorough reply!

I'll read the links you posted a bit later, but for now I have a few questions that could help me clear some misconceptions I might have. I haven't used a rooted Android device yet, so I might be wrong about how it works. I've read about magisk and other methods a bit and am at familiar with the security concepts you wrote.

Let's say I give root permissions to a terminal app TermGood and I don't give root permissions to an app GameEvil. I trust TermGood fully - I accept that if TermGood is malicious or if it has some exploitable bugs, it's game over. I don't trust GameEvil at all, but I trust the OS to limit the damage it could do since it doesn't have root permissions.

1. Could I run TermGood with root only sometimes? Run it with root, close it, then run it with the normal restricted permissions. That's just to clarify how rooting works in general.

2. For MacOS you wrote "this permission also applies recursively to every process started within the terminal, greatly limiting its usefulness.". For Android, if I run a program like ls or vi from TermGood, will it be launched with root permissions, too? Will I have fully trust that ls or vi are not malicious or exploitable in certain ways (e.g., running vi on a file created by GameEvil that exploits vi).

3. Will GameEvil have any way to compromise the OS, to circumvent some security boundaries or to do any other damage it wouldn't have been able to do if I hadn't "rooted" the OS?

3.1. Would GameEvil be able to launch TermGood on its own without my knowledge? Or somehow piggyback on TermGood to take advantage of its root permissions?

3.2. If there's a bug in the UI layer (the "display server" - what Madaidan gave as an example) and I had TermGood open as root, GameEvil could inject some keystrokes into TermGood to read its screen (like the output of a cat command, for example).

3.3. Just because TermGood could have root access, does that somehow make GameEvil more likely to gain root access itself? On Linux, if there is sudo installed, it might increase the attack surface because sudo might have exploitable bugs. What could GameEvil exploit?

4. If I don't root my OS by any of the available means, what would my alternatives be for full control and customization?

4.1. AFAIK with adb you don't get rw access on / if the OS is not rooted.

4.2. Let's say I want to X (e.g., backup / to a server when it commands it to) without rooting. Would I have to create the app, then modify security policies in a way that would enable it to run without root, but with granular permissions for X specifically and nothing else, like permissions to read / and to listen on a network socket, maybe by changing the SELinux policies and/or the Android permissions of the app? Or would that be impossible? I don't really have a specific X in mind, but I want X to be as broad as possible. That's what makes it a real OS for me - being able to do anything on it.

5. If TermGood is compromised, it could reinfect the root filesystem after booting and effectively bypass Verified Boot. Or, if I used TermGood to change something on /, e.g. `touch /testfile`, would I be able to sign the new root filesystem? Ideally I should be able to control all the keys and sign the whole chain of trust whenever I make a change.

6. Android doesn't have FDE, so evil maid seems relatively easy (although any unrestricted physical access to the device should be treated extremely seriously, even with FDE in place). Is that correct?

Basically, if we assume that:

* I fully trust TermGood and the processes it spawns to not be malicious or have exploitable bugs;

* I could resign any changes I've made so I can keep Verified Boot working.

Then, would I be able to give TermGood root and keep my security?