Pangram verdict · v3.3
We believe that this document is primarily human-written, with some AI-generated and AI-assisted content detected
AI likelihood · overall
MixedArticle text · 1,975 words · 6 segments analyzed
Updates#2026-05-06. I opened a coordination case with CERT/CC’s VINCE covering the findings below. CVE assignment will go through that process.2026-05-07. Naxclow contacted me one day after this post went live, acknowledged the report, and started their internal review process.Naxclow’s reply, the day after publication.Recently I bought a smart doorbell off Temu, the Chinese marketplace that has been gaining popularity worldwide over the past couple of years. I wanted to know how secure the cheap connected hardware sold on that platform actually is. The unit ships under the name “Smart Doorbell X3” and pairs through a mobile app called “X Smart Home”. Camera, microphone, two-way audio, sub-GHz indoor receiver. The kind of gear that has quietly shown up on a lot of front doors.By the end of a few weekends with one I could:silently steal any of these doorbells off its owner’s accountimpersonate the device on a live call, with attacker-chosen video on the owner’s phonelift the home WiFi password through a debug port behind a screwdriver$12 on the front. Whole-network compromise on the back. The first of those takes a free account on the platform, and redirects every real call from the door to my phone instead of the owner’s. The second takes nothing at all, and invents new calls into the owner’s phone with whatever video I want. The real doorbell stays online either way and never knows. You are basically paying $12 to let anyone on the internet ring your doorbell.The findings sit at the platform layer of the backend, not in any one box on a Temu listing. The doorbell talks to a backend operated under the brand Naxclow, by a Guangzhou-based company called Guangzhou Qiangui IoT Technology Co., Ltd. The same hardware ships rebadged under several reseller brands, and the same provider runs a small family of consumer apps under Naxclow, each on its own subdomain. V720 is one (publicly reverse-engineered already, see intx82/a9-v720). A sibling app called “ix cam” is the other I noticed. I did not separately test either of them.
Their web frontends share the same Vue scaffolding as X Smart Home, and that public work already covers the wire-protocol overlap between V720 and the doorbell. The shared SPA codebase plus the protocol overlap suggest the same backend code is running under each branded hostname. This is a story about a platform, not a box.This blog is part of a sanitized responsible disclosure. Finding contact info for Naxclow was not easy. They have no contact page on their website. I eventually found an email address on one of their pages, and brute-forced common alias names on the same domain to widen the net. Most of those bounced. On April 29, 2026 I sent the report through the addresses that delivered, and through the X Smart Home in-app feedback form. As of writing I have not received a reply. I am publishing one week after the notification, with sensitive specifics stripped out.The list of issues is long, so grab your favorite snack or drink and settle in.Scope and Ethics#I tested everything below on devices I own, with two of my own X Smart Home accounts. The traffic touched Naxclow’s production backend, but only under my own credentials. I never touched anyone else’s account, device, or traffic.Real endpoint paths, exact parameter names, the literal hardcoded salt, the full signing implementation, and any working PoC code stay out of this post. The point is the methodology and the failure modes, not a recipe.The Device#Three pieces:the doorbell: camera, push button, mic, speaker, WiFi, sub-GHz transmittera small indoor receiver that listens on sub-GHz and rings a tone when the button is presseda mobile companion app for live view, two-way audio, and event historyThe doorbell and its sub-GHz indoor receiver, before I opened anything up.
Back of the unit.The label is more interesting than the box. The hardware OEM is Shenzhen Ruilang Technology Co., Ltd, not Naxclow and not whatever brand the seller printed on the listing. FCC ID 2A5LK-X3PRO, approved in March 2024 for 2.4 GHz WiFi plus 433.91 MHz sub-GHz. Ruilang’s grantee code 2A5LK has at least seven WiFi-camera filings under it. One of them is the A9 model that intx82 reverse-engineered as the V720 mini camera. Same factory, fleet of WiFi cameras under different model codes, all pointed at Naxclow’s backend out of the box. The EU and UK importer-of-record on the label is Whaleco, Temu’s corporate arms in those jurisdictions.Open it up and the chip count is low. One MCU does almost everything: a Beken BK7252N, a cheap WiFi-plus-audio combo. JTAG and UART headers sit on the front of the board. UART is unusually laid out for a debug header: TX and RX paired together as a small pair of pads, GND off on the edge, no VCC pad. I probed TX during boot, saw voltage moving in a way that looked like serial chatter, and the rest of the day was downhill from there.Front of the PCB: camera, IR LEDs for night vision, microphone, USB-C port, ring button.UART is 115200 8N1. The sub-GHz link is Princeton-encoded 24-bit OOK on 433.91 MHz, replayable with anything that emits OOK at that frequency. WiFi runs RT-Thread 3.1.0 plus the Beken SDK. None of this is exotic. All of it leaks information freely.Close-up of the BK7252N: unpopulated JTAG header, UART pads, audio amp.
Press the button and three things happen at once:a sub-GHz pulse goes out to the indoor receiver, which rings inside the housethe doorbell sends an HTTP request to Naxclow’s backend, which pushes a notification to the owner’s phoneif the owner taps “answer”, the device and the app set up a peer-to-peer call for two-way audio and videoThe sub-GHz leg is replayable from the sidewalk with a Flipper Zero. I captured the press once and played it back from the device, and the indoor receiver rang as if I had pushed the real button. I did not chase it any further: well-trodden ground, and not what I came for. I focused on the WiFi side: how the button press reaches the phone, and how the call starts.Phase 1: Reading the Wire#MITM in the lab, long Wireshark session, single capture from button press to call answer.The first thing on the wire is the alert. The doorbell hits the backend in plain HTTP, the backend pushes a notification to the owner’s phone, and the call leg starts only after.Send-alert request and response, in cleartext. No TLS anywhere on the control plane.The request is a multipart upload. Three fields stand out: a device ID, a random per-request string, and a token that looks like a signature (fixed-length hex, changes when the parameters change). There is also a JPG attached, which is the snapshot the owner sees in their notification.The alert request body. Device ID, nonce-style random field, signature-style token, and a JPG attached as the alert image.The response is where things get interesting. There is a conf key carrying the host and per-device credentials needed for the P2P call that follows. The credentials are static. They are keyed to the device ID and survive both factory reset and rebinding to a different account. The same value comes back every time.The alert response. The conf block hands back the device’s permanent P2P credentials in plaintext.Looking across captures, the random and token values change on every request. The device never makes any prior call to fetch either of them, so whatever produces them runs locally on the device itself. The token has the shape of a cryptographic signature: a fixed-length hex string that changes unpredictably across requests.
The random field changes alongside it, which suggests it feeds extra entropy into whatever the token is signing.I tried replaying the request and it worked: the backend generated a new event ID and pushed the notification through. Tampering with any primitive parameter (the random field, say) broke the request, confirming the token does cover them. Replace the JPG body, though, and the alert sails through, with my new image displayed on the owner’s phone. The image is not part of the signature.After the alert returns, the device opens a TCP connection to the host and port from the conf block. From here on the protocol is binary and looks like a homegrown STUN.I spent a while reverse-engineering the framing. Each message has a 20-byte fixed header followed by a JSON body. The header packs a length field, a type discriminator (data vs heartbeat), and a session ID. The body carries a command code and the parameters for that command. Once I had the framing, the rest of the exchange read itself.The full signaling session between the device and the server, from authentication through call setup to a status-0 hangup from the app. Custom binary header, JSON body, plaintext credentials throughout.The first message is authentication. The device sends its device ID, the relay password from conf, and the domain it received in the same response. The domain in the request suggests the same backend serves multiple device families behind a domain selector, not a separate instance per device.After the registration ACK, the connection sits idle. The alert has already gone out; the device is waiting for the owner to answer on their phone.The mobile app runs the same auth flow on its own connection. It registers with the relay using its account ID and the account’s persistent token, then issues a call request naming the target device. That is what wakes the device’s connection back up. The relay forwards a message to the device, in the same framing, with everything it needs to reach the calling phone: the account ID of the target client (the mobile app), the matching account-side token, the client’s public and private IP addresses, and the NAT-mapped ports the client probed. Classic STUN-style rendezvous, and the relay’s job is to bridge two authenticated registrations into a peer-to-peer call.
After a handful more configuration parameters get traded, both sides have what they need to NAT-hole-punch directly to each other over UDP, and the call streams peer-to-peer on that channel.The P2P leg after hole punching: a session setup carrying both sides’ tokens, a status-200 ack, then raw JPEG frames flowing between device and app.The first message on the P2P leg is a small JSON envelope carrying both cliToken and devToken together: the device’s token and the account’s token in the same packet. The peer acks with status 200. From that point on the channel is mostly raw bytes: JPEG frames with the JFIF magic, plus audio samples in the same stream. Nothing on this leg is encrypted either.That session setup is itself a credential broadcast. Anyone observing this packet on either end of the hole punch walks away with the long-lived tokens for both the device and the account. Since the media is also unencrypted, anyone on path also gets the live video and audio off the wire.This was passive recon: read traffic, map protocols. To do anything beyond that I needed to forge requests, and the signing function lives on the device. Which meant the firmware.Phase 2: What the UART Says Without Being Asked#The case is already open and the UART pair is already identified. For easy access I soldered fine wires to the TX and RX pads. PCBite probes would have been the cleaner option, but I did not have any on hand.Small wires soldered to the TX and RX pads on the front of the board.Wires went into a Flipper Zero in UART bridge mode, terminal emulator on the host. The doorbell sleeps deep between events: a press wakes it, runs the full application loop, and sends it back to sleep. Everything below is from one such cycle, starting the moment I pressed the bell button.The first thing on the wire is the boot banner. Firmware version, an unredacted register dump, the RT-Thread copyright block, and an early OTA initialization failure:BK7252N_1.0.14 REG:cpsr spsr r13 r14