-
Notifications
You must be signed in to change notification settings - Fork 1
Permissions
Every application that gets installed is assigned its own user and group. These are then used as file permissions to restrict applications from accessing each other, and used to grant access to various devices.
The application-manager
stores the mapping in the /mnt/config/uid_map
file. The /etc/passwd
file is not updated to reflect the installed apps, which is not surprising since the root file system is read only. Ordinarily the /mnt/config/uid_map
is not readable by an application, but we can exploit the device node vulnerability described in Issues in order to gain access to the raw MTD device containing the /mnt/config
partition and read it.
The file is a sample mapping of UID/GID to component IDs:
1006
1001,7ba05ff7-7835-4b26-9eda-29af0c635280
1002,641f94d9-7600-4c5b-9955-5163cb7f1d75
1003,48a22e96-d078-4e34-9d7a-91b3404031da
1004,a65f3686-e50a-4fff-b25d-415c206537af
1005,89ecd022-0bdd-4767-a527-d756dd784a19
1006,8548b129-b16f-4f84-8dbe-d2c847862e78
The app_manifest.json
file includes a capabilities section. If an app wants network permissions, or access to an SPI bus, or some other resource it has to specify it by including the request in the capabilities section. A list of available capabilities is documented here. How the capabilities are enforced depends on the resource being asked for.
Access control for peripherals that are resented by /dev devices, such as UART, I2C, PWM, ADC, and so on, are consoled via group file permissions. For example, if we include the following in our capabilities:
{
"Capabilities":{
"Uart": [ "$MT3620_ISU1_UART"]
},
}
And we look at /dev/ttyS5
using our busy box shell, we can see the group has r/w access and the GID is the one mapped to our app:
> ls -l /dev/ttyS5
crw-rw---- 1 sys 1011 4, 69 Jan 1 1970 /dev/ttyS5
There are a number of networking capabilities, to restrict which hosts can be connected to, if we can listen for connections, and others. These restrictions are configured using the netfilter firewall. We did not fully explore this area, but presumably the information in the app_manifest.json
file is used to create rules that filter on the UID/GID of the socket. There is no iptables
command, so application-manager
must be doing this configuration via the netlink interface.
A number of capabilities deal with configuration (NetworkConfig
, WifiConfig
, TimeSyncConfig
, and others). These permissions are enforced in the various built-in applications.
The APIs that interact with these services use the /tmp/appcontrol_socket
to make the requests. The receiver then verifies if our app has the proper capabilities.
Microsoft has added some additional security fields and checks. These permissions are stored in the azure_sphere_task_cred
structure:
// exposed through /proc/<pid>/attr/exec
struct azure_sphere_task_cred {
union {
u8 raw_bytes[16];
struct azure_sphere_guid guid;
} component_id;
char daa_tenant_id[64];
bool is_app_man : 1;
bool job_control_allowed : 1;
unsigned int : 0;
u32 capabilities;
};
Our testing tool can display the settings for an application:
> creds
Creds:
GUID: 61ae5c57-98cd-4a0a-8b609509505c7617
daa_tenant_id: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
is_app_man: 0
job_control_allowed: 0
capabilities: 0x00000000
As expected our unprivileged application has no extended permissions.... 😞
The is_app_man
or job_control_allowed
is required to move a process into a process group. The daa_tenant_id
is your MS Azure tenant ID. The capabilities are the extended capabilities bits added by Microsoft.
In addition to file permissions and UID/GID restrictions, there are Linux capability bits. Microsoft has extended the standard set and added additional capability bits.
The security monitor has the following additional capability bits:
File: include/uapi/linux/azure-sphere/security_monitor.h
63: typedef enum {
64: AZURE_SPHERE_CAP_NONE = 0,
65: AZURE_SPHERE_CAP_UPDATE_IMAGE = 1 << 0,
66: AZURE_SPHERE_CAP_QUERY_IMAGE_INFO = 1 << 1,
67: AZURE_SPHERE_CAP_UPDATE_SECURITY_STATE = 1 << 2,
68: // 1 << 3 is reserved
69: AZURE_SPHERE_CAP_SFS = 1 << 4,
70: AZURE_SPHERE_CAP_ATTESTATION_RUNTIME = 1 << 5,
71: AZURE_SPHERE_CAP_POSTCODE = 1 << 6,
72: AZURE_SPHERE_CAP_PERIPHERAL_PIN_MAPPING = 1 << 7,
73: AZURE_SPHERE_CAP_RECORD_TELEMETRY = 1 << 8,
74: AZURE_SPHERE_CAP_MANAGE_LOG_AND_TELEMETRY = 1 << 9,
75: AZURE_SPHERE_CAP_ALL = ~AZURE_SPHERE_CAP_NONE
76: } azure_sphere_capability_t;
In addition to user/group permissions Linux has capability bits to provide more selective control. Our testing tool can lookup the capability bits:
> caps
effective = 00000000:00000000 permitted = 00000000:00000000 inheritable = 00000000:00000000
Our unprivileged app has no capability bits set. Somewhat interestingly, we can lookup the capability bits for other processes, which can be considered a slight information disclosure of PIDs and their capabilities:
> caps
effective = 00000000:00000000 permitted = 00000000:00000000 inheritable = 00000000:00000000
> caps 1
effective = ffffffff:0000003f permitted = ffffffff:0000003f inheritable = 00000000:00000000
> caps 2
effective = ffffffff:0000003f permitted = ffffffff:0000003f inheritable = 00000000:00000000
> caps 3
effective = ffffffff:0000003f permitted = ffffffff:0000003f inheritable = 00000000:00000000
> caps 4
capget: No such process
> caps 5
effective = ffffffff:0000003f permitted = ffffffff:0000003f inheritable = 00000000:00000000
> caps 30
effective = ffffffff:0000003f permitted = ffffffff:0000003f inheritable = 00000000:00000000
In addition to app capabilities, there are device capabilities as well. These enable features such as debugging. The active capabilities can be viewed using the azsphere
command:
> azsphere device capability show-attached
Device capabilities:
Enable App development
Enable RF test mode
New capabilities can be uploaded and applied to the device, but need to be signed by Microsoft. Working through decompiled azsphere
code showed that the CLI hits the https://prod.core.sphere.azure.net/v2/tenants/<tenent_id>/deviceCapabilityImage
endpoint to get a signed capabilities image, which is then flashed to the device.
We built a script and brute forced which capabilities Microsoft will sign on our behalf, an example of which can be obtained here. The only capabilities we were able to obtain was EnableAppDevelopment
and UnlockGatewayD
.