Talos Vulnerability Report

TALOS-2020-1141

Microsoft Azure Sphere networkd mdns denial-of-service vulnerability

December 18, 2020
CVE Number

Summary

A denial-of-service vulnerability exists in the networkd mDNS functionality of Microsoft Azure Sphere 20.07. A specific bind call can cause a denial of service, requiring manual recovery. An attacker can bind to port 5353 to trigger this vulnerability.

Tested Versions

Microsoft Azure Sphere 20.07

Product URLs

https://azure.microsoft.com/en-us/services/azure-sphere/

CVSSv3 Score

5.9 - CVSS:3.0/AV:L/AC:H/PR:N/UI:N/S:C/C:N/I:N/A:H

CWE

CWE-284 - Improper Access Control

Details

Microsoft’s Azure Sphere is a platform for the development of internet-of-things applications. It features a custom SoC that consists of a set of cores that run both high-level and real-time applications, enforces security and manages encryption (among other functions). The high-level applications execute on a custom Linux-based OS, with several modifications to make it smaller and more secure, specifically for IoT applications.

The main controller of all things networking related on Azure Sphere is the networkd binary. Normally spawned as uid 1001 in /mnt/config/uid_map, this binary is granted all the permissions mentioned in its app_manifest.json:

"Policy": {
    "Groups": [
        "net-adm",
        "net-restricted",
        "wifi-config",
        "sys-log",
        "tmp-admin",
        "rtc"
    ],
    "LinuxCapabilities": [
        "CAP_NET_ADMIN",
        "CAP_NET_RAW",
        "CAP_NET_BIND_SERVICE",
        "CAP_SYS_TIME"
    ]
}

In examining what exactly this binary utilizes these permissions for, we see the following:

> cat /proc/net/udp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode ref pointer drops
   74: 0100007F:0035 00000000:0000 07 00000000:00000000 00:00000000 00000000  1001        0 216 2 00000000 0
   89: 00000000:0044 00000000:0000 07 00000000:00000000 00:00000000 00000000  1001        0 261 2 00000000 0
  254: 00000000:14E9 00000000:0000 07 00000000:00000000 00:00000000 00000000  1001        0 218 2 00000000 0

Which in a more simplified version (without networkd’s 1001 uid however) looks more like:

udp        0      0 127.0.0.1:53            0.0.0.0:*                           -
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           -

The only other binary on the Azure Sphere platform that actually binds to a service like this is gatewayd, binding to TCP port 0.0.0.0:443 for a webserver that allows for configuration over the sl0 usb interface. But looking back at networkd, the usual guess would be that udp:53 is for dns and udp:5353 for multicast dns requests, but currently this cannot be gleaned as firewall restrictions prevent us from sending to udp:53. udp:5353 is much more interesting, allowing one to send traffic to it, even unprivileged, but whether or not it processes this traffic has not yet been discovered.

Since networkd binds to port udp:5353, a port that anyone can bind to without privileges (since it’s over 1024), there exists a race condition on startup of the machine: if an application can bind to udp:5353, the device becomes unresponsive until and a manual recovery over usb (via azsphere dev recover) is required.
There would be more of a description of what actually goes on here, but when triggered, the device locks up and it’s impossible to get any more info out of it. It’s not a continuous bootloop, since we can see that there’s no abort call if we look at networkd at this bind() call:

// rebase address: 0x10000
0003aae4  0df14603   add     r3, sp, #0x46
0003aae8  41f2e940   movw    r0, #5353                      // [1]
0003aaec  03f90f87   vst1.8  {d8}, [r3]
0003aaf0  13ab       add     r3, sp, #0x4c
0003aaf2  03f90f87   vst1.8  {d8}, [r3]
0003aaf6  0223       movs    r3, #2
0003aaf8  adf84430   strh    r3, [sp, #0x44] {var_3c}  {0x2}
0003aafc  d9f7d2e9   blx     #htons
0003ab00  adf84600   strh    r0, [sp, #0x46] {var_3c+0x2}   // [2]
0003ab04  1022       movs    r2, #0x10
0003ab06  606f       ldr     r0, [r4, #0x74] {big_dns_struct::mdns_sock} 
0003ab08  3946       mov     r1, r7 {var_3c}
0003ab0a  d9f72eed   blx     #bind                          // [3]
0003ab0e  0028       cmp     r0, #0
0003ab10  1eda       bge     #0x3ab50

0003ab12  d9f7a2ed   blx     #__errno_location              // [4]
0003ab16  0568       ldr     r5, [r0]
0003ab18  0021       movs    r1, #0
0003ab1a  5348       ldr     r0, [pc, #0x14c]  {data_3ac68}
0003ab1c  002d       cmp     r5, #0
0003ab1e  b8bf       it      lt
0003ab20  6d42       rsbs    r5, r5, #0
0003ab22  c5f31305   ubfx    r5, r5, #0, #0x14
0003ab26  65f31301   bfi     r1, r5, #0, #0x14
0003ab2a  68f31f51   bfi     r1, r8, #0x14, #0xc
0003ab2e  7844       add     r0, pc  {data_58b12}
0003ab30  45ea0855   orr     r5, r5, r8, lsl #20
0003ab34  ddf75efa   bl      #log_errno                     // [5]

0003ab38  2846       mov     r0, r5
0003ab3a  fdf7cffc   bl      #check_if_that_worked
0003ab3e  48b9       cbnz    r0, #0x3ab54

At [1], we see port 5353 being loaded into the htons() call and stored into a sockaddr_in structure at [2]. If the bind() at [3] fails due to another application having bound to that port already, then it falls through to the __errno_location() function at [4], logs the error at [5], and continues on its merry way. Shortly after this race, however, there is a soft-lockup that immediately stops all functionality of the device.

It should be noted that due to the race-condition occurring on execution of the networkd binary, one would need a separate vulnerability to trigger this vulnerability. Either the ability to cause networkd to crash (at which point it will restart), or the ability to maintain persistence on the device (e.g. flashing an arbitrary application) such that the exploit runs on startup before networkd can bind.

Timeline

2020-08-18 - Vendor Disclosure
2020-12-18 - Public Release

Credit

Discovered by Lilith >_>, Claudio Bozzato and Dave McDaniel of Cisco Talos.