-
Notifications
You must be signed in to change notification settings - Fork 1
Host Device Management
The azsphere_connect.sh
script is used to setup a SLIP tunnel over the USB -> Serial connection (Service UART on the Seeed MT3620 Mini Dev Board and create the sl0
interface:
ubuntu ~> sudo azsphere_connect.sh
Azure Sphere device connected
ubuntu ~> ifconfig sl0
sl0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 296
inet 192.168.35.1 netmask 255.255.255.255 destination 192.168.35.2
slip txqueuelen 10 (Serial Line IP)
RX packets 16 bytes 2077 (2.0 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 17 bytes 1504 (1.5 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Host IP: 192.168.35.1 Device IP: 192.168.35.2
The device has only one listening TCP/IP service, an HTTPS server:
ubuntu ~> sudo nmap -A -p- 192.168.35.2
Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-08 17:22 UTC
Nmap scan report for 192.168.35.2
Host is up (0.012s latency).
Not shown: 65534 closed ports
PORT STATE SERVICE VERSION
443/tcp open https
|_http-title: Site doesn't have a title (application/octet-stream).
| ssl-cert: Subject: commonName=192.168.35.2/organizationName=Microsoft Corporation/stateOrProvinceName=Washington/countryName=US
| Subject Alternative Name: DNS:*.devices.sphere.azure.local, DNS:192.168.35.2, IP Address:192.168.35.2
| Not valid before: 2018-08-22T16:51:43
|_Not valid after: 2038-08-17T16:51:43
The HTTPS service is implemented in the gatewayd
executable. This executable can be extracted from one of the *.bin files from the recovery Firmware. It is a C++ binary with a custom HTTP stack. We did not fully reverse engineer this binary, but did extract the endpoints that can be accessed by locating a global dispatch table:
- /abi_versions
- GET
> curl -k https://192.168.35.2/abi_versions
{"SecureWorldRuntime":1,"OSRuntime":1,"ApplicationRuntime":5}
- /restart
- POST
> curl -k -d '' https://192.168.35.2/restart
{"restartingSystem":true}
- /status
- GET
> curl -k https://192.168.35.2/status
{"uptime":6812}
- /log
- GET
- binary goo… log messages
- GET
- /images
- GET
- Lists all components that are installed… including those that are built in
- GET
> curl -k https://192.168.35.2/images
{
"is_ota_update_in_progress": false,
"has_staged_updates": false,
"restart_required": false,
"components": [
{
"uid": "ec96028b-080b-4ff5-9ef1-b40264a8c652",
"image_type": 7,
"is_update_staged": false,
"does_image_type_require_restart": true,
"images": [
{
"uid": "bec97446-60fd-40f7-abd8-ef396c36e88e",
"length_in_bytes": 2491164,
"uncompressed_length_in_bytes": 2491164,
"replica_type": 0
}
],
"name": "NW Kernel"
},
...
- /telemetry
- /wifi/scan
- GET
- lists wifi networks it sees
- GET
> curl -k https://192.168.35.2/wifi/scan
{"values":[{"bssid":"xx:xx:xx:xx:xx:xx","freq":2462,"signal_level":-67,"ssid":"xxxx","securityState":"psk"},...]}
- /wifi/config/networks
- GET
- POST
- PATCH
- DELETE
- /wifi/interface
- GET
> curl -k https://192.168.35.2/wifi/interface
{"ssid":"","configState":"unknown","connectionState":"disconnected","securityState":"unknown","mode":"","key_mgmt":"UNKNOWN","wpa_state":"DISCONNECTED","address":"ec:9c:32:f2:24:7a","id":0,"configName":""}
- PATCH
- Updates config
- /wifi/diagnostics/networks
- GET
> curl -k https://192.168.35.2/wifi/diagnostics/networks
{"values":[{"timestamp":"2000-01-01t00:45:21+0000","networkId":9,"ssid":"ABCD","error":"NetworkNotFound",...}
- /update/stage
- PUT
- Used to upload images and other binary config blobs
- PUT
- /update/install
- POST
- Device will parse whatever was uploaded in /update/stage and install/apply the image.
- POST
- /app/status
- GET
- PATCH
- /app/image
- DELETE
- /app/quota
- GET
- /net/interfaces
- GET
> curl -k https://192.168.35.2/net/interfaces
{"interfaces":[{"interfaceName":"lo","interfaceUp":true,"connectedToNetwork":false,"ipAcquired":false,"connectedToInternet":false},{"interfaceName":"sl0","interfaceUp":true,"connectedToNetwork":false,"ipAcquired":false,"connectedToInternet":false},{"interfaceName":"wlan0","interfaceUp":true,"connectedToNetwork":false,"ipAcquired":false,"connectedToInternet":false}]}
- /net/status
- GET
> curl -k https://192.168.35.2/net/status
{"deviceAuthenticationIsReady":false,"networkTimeSync":"incomplete"}
- /device/manufacturing_state
- GET
> curl -k https://192.168.35.2/device/manufacturing_state
{"manufacturingState":"Blank"}
- PUT
- /device/security_state
- GET
> curl -k https://192.168.35.2/device/security_state
{"securityState":"SECURE","deviceIdentityPublicKey":"7BEE580B2EB6391D272AB42BF62FDDCC4E0AAB7475C0B1AFFB0D5CE24F2AACBA1E424224D6B571005518AEFD89A900D9A33EB2E8795598CF63826E348CBCDAA2"}
- /certstore/certs
- GET
- POST
- DELETE
- /certstore/space
- GET
> curl -k https://192.168.35.2/certstore/space
{"AvailableSpace":"24514"}
Since the REST API is over HTTPS, we must break into the encrypted tunnel in order to view the HTTP requests. We accomplished this by:
- Extracting the SSL certificate and private key from the device's firmware.
- Using ProxyChains to hook libc network functions to add proxy support.
- Using mitmproxy to record/proxy the azsphere CLI requests.
The gatewayd
image from the recovery Firmware contains the gatewayd-server-cert.pem
and gatewayd-server-key.pem
. When we extract the contents of the image's file system, the files are located in the bin directory.
We used the following configuration for ProxyChains:
strict_chain
tcp_read_time_out 15000
tcp_connect_time_out 8000
[ProxyList]
http 127.0.0.1 8080
For mitmproxy, we first merged the device's SSL certificate key and PEM files together:
> cat gatewayd-server-cert.pem gatewayd-server-key.pem > device_rest_api.pem
Then we started mitmproxy with the --ssl-insecure
and the --ignore-hosts prod.releases.sphere.azure.net
arguments. The --ignore-hosts
option allows the CLI tool to access Microsoft's cloud services to download recovery images and obtain entitlements in order to enable features such as development mode.
> mitmproxy --ssl-insecure --certs /mnt/hgfs/MediaTek/Certs/device_rest_api.pem --ignore-hosts prod.releases.sphere.azure.net
Now when using proxychains we can proxy the requests and review the actions taken by the CLI tool:
> proxychains azsphere dev wifi add -s ABCD -p BBBBBBBBBB -cn ZZZZ
ProxyChains-3.1 (http://proxychains.sf.net)
|S-chain|-<>-127.0.0.1:8080-<><>-192.168.35.2:443-<><>-OK
|S-chain|-<>-127.0.0.1:8080-<><>-192.168.35.2:443-<><>-OK
|S-chain|-<>-127.0.0.1:8080-<><>-192.168.35.2:443-<><>-OK
Add network succeeded:
ID : 10
SSID : ABCD
Configuration state : enabled
Connection state : unknown
Security state : psk
Targeted scan : False