…so there are a lot of IOT devices and IOT brands out there…
🕵️♂️ Are competing products looking suspiciously similar to you?
Most are white-labelled products, the biggest ecosystem vendor being
👨💻 Use someone else’s code
💹 Fast profit turnaround
⚠️ Use someone else’s code
🔓 Potentially security vulnerabilities
IOT ecosystems often have a centralised system to manage their fleet (devices).
A centralised management is so much simpler/easier/faster/cheaper/‘better’ than a decentralised one.
⚠️ Device functionality dependent on system availability
⚠️ Little transparency about what/where/when/why data is transmitted
A smart vacuum cleaner, with integrations to both and (depending on model)
It works pretty well, according to reviews.
But is it safe to connect to your home?
Thesis A - Disassembled the device (many, many screws)
Thesis A - Found the UART pins and got some terminal
Thesis A - Got root access (Device runs Ubuntu 14.04.3 LTS)
Thesis B - Firmware dump (dd
) for offline/static analysis
Thesis B - Inspection of system (privileged processes)
Thesis B - Recovery partition manipulation (see proof of concept)
Thesis B - Capture of device traffic (port-mirroring)
Thesis B - Inspection of system services (netstat
, ip{,6}tables
)
Thesis B - Remote access persistence (see proof of concept)
Thesis B - Investigating tcpdump
Thesis B - Investigating rrlogd
Thesis B - Investigating adbd
adbd
A novel but not-so-useful way to perform arbitrary code execution
Command injection vulnerability exists within the modified adbd
binary
uart_test
and ruby_flash
adb shell
vinda
, device IDSYS_PASSWD = /mnt/default/vinda := ABCD1234ABCD1234
# Get challenge
CHALLENGE $= adb shell [SYS_PASSWD]rockrobo dynamickey
# Generate response
ADB_PASSWD = generate(challenge, device_id)
# Perform command
adb shell [SYS_PASSWD][ADB_PASSWD] [COMMAND*]
/mnt/default/adb.conf
(RO)&
, ;
, |
, `
characters are also forbidden😢 No arbitrary command execution…
$> py -3 adbStart "whoami"
src/rr_ruby.c::adb_check_unlock_level1():not support /adb shell sys_passwd#adb_passwd whoami in level 1
… where did /bin/sh
come from..?
Avoiding the forbidden characters (&
, ;
, |
, `
) we can exploit command substitution and redirections to inject commands.
Allows us to write to the filesystem
Or read from the filesystem too!
/mnt/default/vinda
fileadb_lock != 0
$> cat /etc/OS_VERSION
ro.product.device=MI1558_TANOS_MP_S2020032500REL_M3.3.0_RELEASE_20200325-204847
$> # ^^^^^^ ^^^^^^^^
$> # \/\\// \\\\////
$> # Xiaomi v01.15.58 25th March 2020
$> #
Performed a diff
check against the Ubuntu 14.04.3 Core LTS (armhf) OS.
ntpdate
(synchronise computer time via NTP)-ro.product.device=MI1558_TANOS_MP_S2020032500REL_M3.3.0_RELEASE_20200325-204847
+ro.product.device=TANOS_V2902-2022042802REL_M3.5.8_T4.1.4-2_RELEASE_20220428-202811
-ro.build.display.id=TANOS_MP_R16_RELEASE_20200325-204847
+ro.build.display.id=TANOS_MP_R16_RELEASE_20220428-202811
ro.sys.cputype=R16.STM32.A3.G1
-ro.build.version.release=1558
+ro.build.version.release=V2902
-ro.build.date.utc=1585140527
+ro.build.date.utc=1651148891
The update process performed several incremental updates..
finally updating to (28th April 2022)
> 01.17.08 (17th April 2020)
- Supports multi-floor map saving and robot knows which floor it is
- Update to new structured SLAM algorithm to make map more reliable
- Support customised room cleaning sequence
- Support no-mop zone
> 01.19.98 (9th June 2020)
* Improvised Wi-Fi Easy Connect
* overall improvements
* bug fixes
* UX fixes
> 01.20.76 (23rd June 2020)
* Obstacle avoidance enhancements
* Bug fixes and UI optimisation
> probably more updates (got locked out)
> 02.29.02 (28th April 2022)
* Optimized the quick mapping experience
> 01.17.08 (17th April 2020)
* /opt/rockrobo/watchdog/WatchDoge iptables drop SSH
* /opt/rockrobo/rrlog/rrlogd iptables drop SSH
* Utilities change to busybox
* SSH server changed to dropbear
* /opt/rockrobo/rriot/rriot_rr added (but not enabled)
> 01.19.98 (9th June 2020)
* Serial handler changed to /sbin/rr_login
> 01.20.76 (23rd June 2020)
-
> probably more updates (got locked out)
> 02.29.02 (28th April 2022)
* /opt/rockrobo/rriot/rriot_rr enabled
rr_login
...
* /opt/rockrobo/rriot/rriot_rr added (but not enabled)
> 01.19.98 (9th June 2020)
* Serial handler changed to /sbin/rr_login
> 01.20.76 (23rd June 2020)
-
...
After the update, serial shell access was denied, uh oh!
getty
rr_login
dropbear
Both only allow login as the root
user
The vinda
file is no longer used for auth!
Login attempts now verify against
[mmcblk0p6]/shadow
[mmcblk0p6]/shadow.sign
But these files don’t exist on my device…
Affected: rr_login
(serial), dropbear
(SSH), adbd
? (USB)
(1) Enter bootloader and force entrypoint to a shell
(2) Patch /etc/inittab
to revert back to a normal login shell
verify_shadow
)strace
)apt-get
and dpkg
removedip6tables
rules to drop all packets 👏
rrlogd
now drops access on bad version match
WatchDoge
immediately drops access on start
rrlogd
and wlanmgr
wlanmgr
now has the functionality to call tcpdump
rrlogd
will upload the following
Content | Description |
---|---|
/etc/resolv.conf |
DNS resolvers |
netstat -anp |
All sockets and their PIDs |
ifconfig |
Network interface status |
PCAP | Packet capture |
rrlogd
)?What can the manufacturer see?
See: Privacy Policy
Effective: 30th April 2019
Cleaning-related information ... last 20 items will be saved by your device and server...
...stored in the server for up to 180 days, ... automatically deleted after expiration.
Network information: ...the password information is only stored on the device side...
... will not be uploaded to the server.
Timing information... Cleanable Area Information... Other information: For example, ....
“Password […] only stored on the device” -
rrlogd
| FW: v02.29.02 (28th April 2022)
Test untouched directories during a firmware update and factory reset
/mnt/reserve
/mnt/data
/mnt/reserve
Partition | Purpose |
---|---|
mmcblk0p1 |
Device registration, WiFi, map data, logs |
mmcblk0p11 |
Statistics, calibration data |
mmcblk0p11
| mcu_ready
| try
| hwinfo
| anonymousid1
| lds_calibration.txt
| counter
| CompassBumper.cfg
| blackbox.db
| rrBkBox.csv
| endpoint.bin
| RoboController.cfg
| last_partition
|
\---rriot
tuya.json
⚠️ All files kept between disassociations
Endpoint | Protocol | Description |
---|---|---|
m2.tuyaeu.com |
MQTT | Inbound requests |
a2.tuyaeu.com |
HTTPS | Outbound requests |
awsde0.fds.api.xiaomi.com |
FDS | Logs upload |
fds
, a2
, ms
, m2
m2.tuyaeu.com
instead of ms.tuyaeu.com
xx.ot[t].io.mi.com
Most (if not all) communications were encrypted
1. Break the encryption too much effort
/* Send test to 10.251.252.253:28422 */
void hook(void* data, uint data_len) {
int sock = create_udp4_connection(IPV4_ADDR(10,251,252,253), 28422);
send(sock, data, data_len, 0);
}
*: Application logs are less verbose in newer FW versions
However they communicate the same way as the older FW versions
{m2,ms}.tuyaeu.com
)Server Request
{
"id": 889,
"method": "get_prop",
"params": [ "get_status" ]
}
Device Response
{
"id": 889,
"result": [{
"msg_ver": 2,
"msg_seq": 275,
"state": 8,
"battery": 100,
"clean_time": 0,
"clean_area": 0,
"error_code": 3,
"map_present": 1,
"in_cleaning": 0,
"in_returning": 0,
"in_fresh_state": 1,
"lab_status": 0,
"water_box_status": 0,
"fan_power": 102,
"dnd_enabled": 0,
"map_status": 1,
"lock_status": 0,
"events": []
}]
}
a2.tuyaeu.com
)Device Request
HTTP POST
https://a2.tuyaeu.com/d.json?a=tuya.device.timer.count&devId=...&et=1&t=...&v=4.0&sign=...
{"devId":"...","lastFetchTime":"0","t":1657046157}
Server Response
{
"result": {
"devId": "...",
"count": 0,
"lastFetchTime": 0
},
"t": 1657046159,
"success": true
}
/mnt/data/rockrobo/rrlog/**
/dev/shm/**
/mnt/reserve/...
wlanmgr tcpdump
#ModifyingTheRecoveryPartitionForFunAndProfit
mmcblk0p1
(data)mmcblk0p10
(updbuf)mmcblk0p8
(bootA) / mmcblk0p9
(bootB)updbuf
to bootA
/ bootB
bootA
/ bootB
updbuf
to bootB
/ bootA
bootB
/ bootA
Both filesystems are overwritten (existing changes will disappear)
mmcblk0p1
(data)mmcblk0p10
(updbuf)updbuf
mmcblk0p8
(bootA) / mmcblk0p9
(bootB)updbuf
to bootA
/ bootB
bootA
/ bootB
updbuf
to bootB
/ bootA
bootB
/ bootA
Modify the extracted updated firmware, so changes propagate
/mnt/updbuf
/etc/passwd
/usr/bin/adbd
/usr/sbin/dropbear
SysUpdate
{
"method": "miIO.ota",
"params": {
"mode": "normal",
"install": "1",
"app_url": "http://192.168.8.110:8322/firmware", // this looks definitely controllable!
"file_md5": "6e24b0454b170f67676693b759fba742",
"proc": "dnld install"
},
"id": 474627483
}
During device initialisation, an OTA update payload could be sent…
Remote root / backdoor!!
However… patched a long time ago
exc: Usage of the data in the cloud
Data Visibility and Ownership
Data includes: map data, [camera], [microphone], app logs,
process list, network config, network data, statistics
Device Visibility and Ownership
❌ Communications are encrypted
❌ Logs are encrypted
❌ Restricted adbd
, ssh
, serial
The “friend-who-has-your-WiFi-password-even-though-you-didn’t-give-it-to-them”
✔️ Efforts to restrict serial access
⚠️ Supply chain
✔️ adbd
(USB access) is restricted
✔️ No fast hands-off attack vector
Need to open up the device
Takes time to gain shell access
Reset + OTA root
The “coffee shop hacker”
✔️ All data is encrypted (application level, not just TLS)!
✔️ IPv6 blocked
✔️ SSH server port blocked by default
⚠️ …other services?
⚠️ OTA rooting (patched Nov 2019)
❌ Wireless credentials can be sniffed during pairing (+ promiscuous)
⚠️ Access to user/device/app data
⚠️ Ability to issue remote commands
⚠️ Network packet logging
⚠️ Potential arbitrary execution in future releases
⚠️ Privacy policy discrepancy
⚠️ Is my device backdoored?
⚠️ Unknown nature of expected traffic (see later)
⚠️ Vuln > RCE = root control
✔️ Evidence of buffer overflow checks in the binary
✔️ Application-level encryption
✔️ Reduction in log verbosity (though not consistent)
✔️ ip{,6}tables
rules
✔️ Tightening of access through adb
, ssh
, serial
✔️ They seem to respond to security incidents
✔️ (some) effort to uphold privacy and define data usage
⚠️ They seem to respond to security incidents.
(IoT Ecosystem, Whitelabel Vendor) and Xiaomi (IoT Ecosystem) have published CVEs
Both companies have white-papers / publications about security minimums.
Note
The Tuya paper mentions encryption during the pairing process.
The Roborock S6 (which integrates the Tuya platform), .
Is there a compliance check / verification between either party?
RFC 8520 - Manufacturer Usage Description
MUD files whitelist the nature of network traffic that a device should transmit/receive. (e.g. Transmit IPv4 tcp/8890 to (DNS) example.com)
Traffic that does not match the MUD are discarded (or allowed but flagged). Mitigates unexpected ports/hosts - but ineffective against (e.g.) C2 payloads
IoT Research Team @ UNSW EE&T has done some research
But is anyone adopting it?
✔️ Data is cleared during resets
✔️ Lockdown on access methods (ADB, Serial, MiIO, SSH, IPv6)
✔️ Data is encrypted during transit
🔥 Further transparency in disclosures
🔥 Improved privacy policy
🔥 Pairing encryption
🔥 Data should be cleared on device disassociation
🔥 Better co-ordination between ecosystems and vendors
🔥 MUD files - both devices and infrastructure
🔥 Whitepapers, bug bounties
rr_loader
service
Andrew Wong
w: featherbear.cc/UNSW-CSE-Thesis
e: