Skip to content

Permissions

Tao Sauvage edited this page Sep 29, 2020 · 5 revisions

User/Group 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

Application Capabilities

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.

/dev Devices

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

Networking

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.

Configuration

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.

Linux Kernel Permission Changes/Additions

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.

Azure Sphere Capability Bits

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;

Linux Capability Bits

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

Device Capabilities

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.