MIT course "Computer Systems Security". Lecture 20: "Security of mobile phones", part 1
Massachusetts Institute of Technology. Lecture course # 6.858. "Security of computer systems". Nikolai Zeldovich, James Mykens. year 2014
Computer Systems Security is a course on the development and implementation of secure computer systems. Lectures cover threat models, attacks that compromise security, and security methods based on the latest scientific work. Topics include operating system (OS) security, capabilities, information flow control, language security, network protocols, hardware protection and security in web applications.
Today we will talk about the security of Android. You can think of this as an interesting example of a system that was primarily designed with security in mind. It is possible that, unlike many systems that we have considered so far, such as Unix or web browsers, where security was mostly “screwed” after creating the system and its design did not focus on these issues, Android developers were initially very worried about specific classes of attacks and constructive mechanisms of applications. ')
They came up with the best way to structure Android apps that will allow us to better enforce security policies. The great thing is that this is a fairly widely used system, unlike some research work that can only offer a new architecture, this system is actually used in practice, and devices using the Android OS are becoming more and more.
Today we will talk about how well some developers have succeeded or failed. We consider what parts of the design they considered important and what they missed, and what the result is in practice. This is quite interesting. In a sense, the developers used the existing systems that we talked about, so the “Android” is based on UNIX, in fact, it’s just the Linux kernel that runs on the whole phone.
So in many ways they use some of the familiar mechanisms that you remember from lab # 2, where you used user IDs and Unix groups and other things to separate applications from each other. But in the case of Android, they have a completely different way of setting user IDs and file permissions than a typical Linux system.
Let's start by discussing what is the level of threat here? What worries these guys on the phone? What's going on here? What are they trying to protect against? What is a threat model in a mobile device?
Student: applications that can cause harm?
Professor: Yes, they are worried that applications that can be installed on the phone can be malicious. I think that there are frankly malicious applications created to gain control over you or to steal your personal data. So you should worry about your data and things that cost money - SMS messages, phone calls, Internet connection and so on.
Thus, on the right - those things that you want to protect in your phone, and on the left - what can make them not work as they should. Since there are malicious apps, Android guys don't want users to install apps written by developers that Google has never heard of. In addition, such applications may cause harm, not because the developer wanted it so, but because he simply forgot to do something. And it would be nice to help these guys create applications that are safe, because often the application developer is not an expert in the field of vulnerabilities, which can then be used by an attacker in his application.
Since the Android OS is widespread, we can view vulnerability reports. There is a CVE database that catalogs many operating system vulnerabilities, and this is actually interesting. Of course, there are also Android error messages, many of which you encountered in lectures. In some parts of Android, buffer overflow is still possible, there is a poor choice of default cryptosystems, people forget to initialize the random number generator and create predictable keys. All this is still happening, because the software is not insured from any of the known problems.
Interestingly, these problems seem to be sporadic and occur from time to time. By and large, they can be eliminated, and the system remains fairly safe after correcting these errors. So in many ways, the Android design works quite well. Therefore, we will consider in more detail later which parts of the design work better and which parts are worse. But overall, this is a fairly well thought out software solution, or at least more thoughtful than the desktop Unix applications that you have encountered so far.
Thus, one of the ways to figure out how to protect data and various services that could cost you money from malicious applications is first of all to understand what an Android application looks like. Then we will talk about how various permissions or privileges are configured and applied in this application. Android applications are very different from what you have seen so far in desktop applications or in Internet applications.
Instead of making up the indivisible part of the code with the main function that you start to perform, Android applications are more modular. In the case of Android, you can think of one application as a set of components. The lecture article describes 4 types of components that the Android framework provides to the developer. The first component is Activity, or Activity. This is the thing that represents the user interface and allows the user to interact with the application, displays information and accepts keystrokes from it, and so on.
From a security point of view, activity has an interesting property — user input is reduced to one action at a time. The Android framework in fact guarantees that only one type of activity is possible at the same time, that is, if you start a banking application, no application will run in the background to intercept the banking application PIN-code through touch presses. So the framework provides for the use of some security properties with respect to user input. Thus, the activity is a component of the user interface.
Three other types of components help the application's own structure logic to interact with other components. So, the second component is called Service, or service. These things work in the background. For example, you may have a service that tracks your location, as in the application that these guys describe in the article. You may have services that retrieve information from the network in the background and so on. The third component is the content provider component, the Content provider. It can be thought of as a SQL database in which you can define several tables with a schema, and so on. You can call SQL queries to all data stored in this application. This component allows you to control access to the database, telling who is allowed to access it. In "Android" there is still something unusual, which is not in other systems. This is the fourth component - Broadcast receiver, or broadcast receiver. It is used to receive messages from other parts of the system. Therefore, we will talk about how applications interact with each other in terms of messages.
Thus, this is a very logical idea of ​​what Android applications are. But in fact, everything is just Java classes or Java code written by a developer.
There is only a certain standard interface that you implement for activity, for services, for a broadcast receiver, and for a content provider, and it is clear that this is just Java code. And all the components placed in the rectangle are simply the Java runtime that runs on your phone, it's just a single process on the Linux kernel that runs on your phone. And all of these components are different classes or parts of code that work in the Java runtime process. Here's how it can be reduced to traditional, more understandable to you processes.
Another thing that interacts with an application is called a manifest. The code for all components is written or compiled by the application developer, but beyond that, there is also a manifest in the system, which is outside the application components. It is a text or an XML file that describes all of these components and how other parts of the system should interact with the components of this application.
In particular, this manifesto talks about the so-called Lables tags, which we will talk about in a second, which determine the privileges of this application in terms of what it is allowed to do, and also define restrictions on who else can interact with the various components of this applications. You want to ask how it works?
Student: Is the label something that defines "this application cannot make a phone call", or "this application can send a message"?
Professor: Yes, these labels set whether this application can make a call, send an SMS or use the Internet. There are two types of tags, I'll draw them here. Each application has a list of tags describing the privileges that the application has. This is something like permissions to dial a phone number, turn on the connection to the Internet, and so on. Later I will tell you how they work.
Thus, these are the privileges that the application has. In addition, you can also attach tags to individual components, and there they acquire a different meaning — these are privileges for a particular application. If you have a component with a label, then to interact with it, any other component must also have a corresponding label. For example, you might have a label with the “View Friends” privilege, which you can use to view the location of your friends. This is a privilege that an application can have. But in order to secure this privilege, you must attach this label to a specific component, in this case to the Content Provider component, to its database, which contains information about the location of your friends. And now anyone who wants to access this database needs to have the same label in their privileges.
This is how you set permissions. You can think of it as user IDs or group IDs in Unix, with the exception of arbitrary strings, which make them a bit more flexible. That is, you will never run out of these IDs and you are not worried that someone will not have enough of them.
It turns out that the developers of "Android" were not particularly careful in determining the scope of these labels. You can have two applications that decide to provide the same label. Thus, these labels are partially defined by the application. Suppose you have two applications on your phone - Facebook and Google+, and they both declare that they would like a new line of permissions for the “View Friends” feature on the social network. You say, "no problem, it's the same string."
Of course, in reality, this line with the Labels list is much longer than I drew. There is a domain in the style of Java applications that defines the string label name. For example, the permission I have drawn for a DIALPERM call actually looks like com.google.android.dialperm. But roughly speaking, these are the lines that appear in the permissions. Therefore, if you have well-intentioned applications, they will not conflict with these permission lines.
But it turns out that, unfortunately, in the Android operating system, nothing forces the application to such behavior, and this creates potential problems. I do not know why they were not corrected. We will see what happens if we have two applications that conflict with tag names.
So, this is what an application looks like: it is a set of Java programs that form components, a manifest that describes permissions for applications, and the necessary restrictions for all components. The interaction between the application is carried out with the help of a thing that was invented by the developers of “Android” and is called the Intent - Intention. Intention is a structured message, and in a second we will see how it is used. For now, I’ll say that Intent has three key things. Of course, the intent contains other fields, but the most important is the name of the Component component to which you want to send a message. Then comes the Action action that the component needs to perform, and the Data data along with the MIME type that you want to send to the other component.
As an abstract example, you can imagine that this component is com.android.dialer / Dial - this is how the component name is indicated in Android, this is a kind of Java domain name. So, com.android.dialer is the name of the application as a whole, which needs to be sent intent, and you use a slash to write the name of the component of the target application to which you are sending the message - / Dial. Thus you name the specific component to which the message is addressed. An action represents a specific set of actions that may look like android.intend.Dial.
This is the predefined string that applications place in the Action field if they want the phone's dialer to call a specific number. For example, if you want to view a document on your phone, then in the Action field you insert an action line of the type android.intend.ViewDoc. This will tell the receiving component that you just want to look at the called contact before dialing its phone number. Finally, Data data is basically an arbitrary URL or URL of the data you want to send along with this message. It can be something like a phone number or an HTTP URL that you want to view or open, or any other applications that are indicated in the system by the URL address.
This is how you send messages that are sent through the system using the Android runtime itself, which is under all these applications. Thus, Android runtime can be perceived as a cross between applications and the kernel. This is not entirely correct, but we will try to draw some kind of picture to clarify what the architecture of this thing looks like.
Let's say we have one application that runs on Android, and another application. These rectangles App1 and App 2, and each represents what is shown in the upper picture - components, manifest, labels.
These are all processes running on top of the Linux kernel, which provides some degree of isolation between applications. There is also what the lecture article calls Reference Monitor. It will mediate all interactions at the level of intentions between different applications. Therefore, if Appendix 1 wants to send a message to Appendix 2, it first sends a message to the link monitor. So, the way you send all Intend intentions to Android, is that you create one of these messages of intent and send it via some channel to this Reference Monitor.
The Android system has its own channel implementation for sending such intentions, which is called Binder, or Bundle. Each Android application, by agreement, is going to open Binder - connect to the reference monitor so that it can receive intentions from this application, as well as send messages to this application.
In our case, if Appendix 1 writes an Intent for Appendix 2 to the link monitor, the link monitor will first find out where this intention should go, and then pass it on to Appendix 2. Then Appendix 2 can trigger some action, receive a message or execute a request SQL for Application 1.