{"id":388,"date":"2025-09-30T11:49:41","date_gmt":"2025-09-30T11:49:41","guid":{"rendered":"https:\/\/hackingwithj.com\/?p=388"},"modified":"2025-09-30T11:49:41","modified_gmt":"2025-09-30T11:49:41","slug":"securing-my-smart-home","status":"publish","type":"post","link":"https:\/\/hackingwithj.com\/?p=388","title":{"rendered":"Securing my smart home"},"content":{"rendered":"\n<p>It\u2019s been a while \u2014 I was out sick and focused on getting better \u2014 but I\u2019m back and ready to post again. To get me warmed up I want to write about something practical and relevant: Home Assistant (HA) and how easy it is for poorly configured smart devices to leak sensitive data on a local network.<\/p>\n\n\n\n<p>A few days ago my brother-in-law installed HA with me and he was shocked at how much the automatic discovery showed on his network \u2014 and that some devices were sending data in the clear. That inspired this short lab: a small network compromise simulation and a defensive checklist you can use to harden a home setup.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Scenario (what I simulated)<\/h2>\n\n\n\n<p>Imagine an attacker has a foothold on your LAN. That could happen via a phishing link, a compromised laptop, or a malicious guest device. From that position the attacker does basic network discovery to enumerate devices:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"634\" height=\"135\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/arp-scan.png\" alt=\"\" class=\"wp-image-389\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/arp-scan.png 634w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/arp-scan-300x64.png 300w\" sizes=\"auto, (max-width: 634px) 100vw, 634px\" \/><\/figure>\n\n\n\n<p>In my test the scan revealed a small web panel on <code>X.X.50.10<\/code> and another host with a Home Assistant web UI. The HA UI looked normal, but further enumeration showed MQTT on a non-standard port (I saw it on 1833 in my case). That\u2019s when I wanted to see whether traffic was encrypted.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"887\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/esprencesne-webpage.png\" alt=\"\" class=\"wp-image-390\" style=\"width:374px;height:auto\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/esprencesne-webpage.png 640w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/esprencesne-webpage-216x300.png 216w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><figcaption class=\"wp-element-caption\"><em>ip changed while documenting<\/em><\/figcaption><\/figure>\n\n\n\n<p>We fingerprinted the web panel and discovered another host that my <code>arp-scan<\/code> didn\u2019t show initially. Pointing a browser at that host brought up a Home Assistant login page. A quick port scan showed an MQTT-ish service on <strong>port 1833<\/strong> (non-standard, but suspicious). That\u2019s when I decided to try a layer-2 MiTM to see if traffic (MQTT\/HTTP) was being sent in the clear.<\/p>\n\n\n\n<p>In the lab I used <strong>bettercap<\/strong> to perform ARP spoofing and live network sniffing.<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-057f0852d8e9dcb726ff809e807e381b\"><code>sudo bettercap -face wlan0\narp.spoof on\nnet.sniff on<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"980\" height=\"180\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/bettercap_arp_poisoning.png\" alt=\"\" class=\"wp-image-391\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/bettercap_arp_poisoning.png 980w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/bettercap_arp_poisoning-300x55.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/bettercap_arp_poisoning-768x141.png 768w\" sizes=\"auto, (max-width: 980px) 100vw, 980px\" \/><\/figure>\n\n\n\n<p>While the MiTM runs, open Wireshark and load the capture (or capture live). Useful filters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Capture filter (if you want only MQTT-ish traffic): <code>tcp port 1833<\/code><\/li>\n\n\n\n<li>Display filter for inspection in Wireshark: <code>mqtt<\/code> (or <code>http<\/code> for web traffic)<\/li>\n<\/ul>\n\n\n\n<p>What to look for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Plaintext MQTT payloads (topics, message bodies) \u2014 these often leak device state, tokens or credentials.<\/li>\n\n\n\n<li>Plain HTTP POST\/GET requests that contain tokens or session cookies.<\/li>\n\n\n\n<li>Any repeated auth attempts or cleartext credentials.<\/li>\n<\/ul>\n\n\n\n<p>If the traffic is TLS-protected you\u2019ll only see encrypted blobs \u2014 but many cheap IoT devices or misconfigured integrations don\u2019t use TLS at all. In my lab the beacon and some messages were clearly readable, which is a fast win for post-compromise reconnaissance.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"279\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/wire_shark_1-1024x279.png\" alt=\"\" class=\"wp-image-392\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/wire_shark_1-1024x279.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/wire_shark_1-300x82.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/wire_shark_1-768x209.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/wire_shark_1-1536x418.png 1536w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/wire_shark_1.png 1634w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>This shows messages and payloads. On my network I could see beacon updates, and \u2014 in cases where the device didn\u2019t use TLS \u2014 even login-like payloads. That\u2019s a clear privacy risk: usernames, tokens and device state information can leak. <code>http<\/code> will show HTTP requests if you\u2019re testing that:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"925\" height=\"543\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/wire_shark_2.png\" alt=\"\" class=\"wp-image-393\" style=\"width:743px;height:auto\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/wire_shark_2.png 925w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/wire_shark_2-300x176.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/09\/wire_shark_2-768x451.png 768w\" sizes=\"auto, (max-width: 925px) 100vw, 925px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Why this matters \u2014 typical weak behaviours<\/h2>\n\n\n\n<p>A lot of smart devices \u2014 cheap Wi-Fi modules, ESP32\/ESP8266 devices, older integrations \u2014 do one or more of the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <strong>unencrypted MQTT<\/strong> (plain TCP) with no TLS<\/li>\n\n\n\n<li>Use <strong>anonymous MQTT<\/strong> (no username\/password)<\/li>\n\n\n\n<li>Broadcast services (mDNS, SSDP, UPnP), leaking device names and info<\/li>\n\n\n\n<li>Expose an admin web UI with default or weak credentials<\/li>\n\n\n\n<li>Allow auto-discovery (Home Assistant\u2019s discovery can be convenient but noisy)<\/li>\n\n\n\n<li>Use insecure OTA or HTTP endpoints (no certs)<\/li>\n<\/ul>\n\n\n\n<p>If an attacker can sniff or intercept that traffic, they can learn device state, credentials, tokens, or even control some devices directly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to harden your smart home \u2014 practical checklist<\/h2>\n\n\n\n<p>Below are practical mitigations you can apply today. I split them between network-level &amp; service-level.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Network-level<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Segmentation \/ VLANs<\/strong><br>Put IoT devices on a separate VLAN from your laptops\/phones. Block inter-VLAN traffic except to the HA server (and only to required ports).<\/li>\n\n\n\n<li><strong>Client isolation \/ private LANs<\/strong><br>On Wi-Fi APs, enable AP\/client isolation for guest networks and (where supported) for IoT SSIDs.<\/li>\n\n\n\n<li><strong>Use a firewall \/ block local discovery across networks<\/strong><br>Block mDNS\/SSDP between VLANs (unless explicitly needed). Only allow control ports to your HA server.<\/li>\n\n\n\n<li><strong>Disable unused broadcast services<\/strong><br>Turn off UPnP\/SSDP in routers\/APs unless you need them for a specific device.<\/li>\n\n\n\n<li><strong>Strong Wi-Fi security<\/strong><br>Use WPA2-Enterprise or WPA3 with strong passphrases. Avoid open networks for IoT unless absolutely necessary and isolated.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Service-level<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>MQTT over TLS<\/strong>\n<ul class=\"wp-block-list\">\n<li>Configure your broker (e.g. Mosquitto) to listen on TLS (8883) and require client certs or at least username\/password + TLS.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Disable anonymous MQTT<\/strong>\n<ul class=\"wp-block-list\">\n<li>Always require credentials. Store per-device \/ per-integration credentials and avoid global shared accounts.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Use TLS for HTTP endpoints (reverse proxy)<\/strong>\n<ul class=\"wp-block-list\">\n<li>Put Home Assistant and other web UI\u2019s behind a reverse proxy (Nginx\/Caddy) and use valid certificates from Let\u2019s Encrypt.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Disable or restrict HA Discovery<\/strong>\n<ul class=\"wp-block-list\">\n<li>Home Assistant discovery is convenient but noisy. Consider disabling discovery for integrations you don\u2019t use or restrict it to specific devices.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Harden devices<\/strong>\n<ul class=\"wp-block-list\">\n<li>Change default passwords on devices (don\u2019t rely on default credentials)<\/li>\n\n\n\n<li>Keep firmware updated<\/li>\n\n\n\n<li>Use device-specific accounts (avoid reusing passwords)<\/li>\n\n\n\n<li>Use long-lived tokens wisely (rotate if possible)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Use VPN for remote access<\/strong>\n<ul class=\"wp-block-list\">\n<li>Instead of exposing HA to the public internet, use a VPN to connect to your home network, or use Home Assistant Cloud (if you prefer a managed approach).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Monitoring &amp; detection<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Enable logging and alerting in HA<\/strong><br>Watch for unexpected connections or auth failures.<\/li>\n\n\n\n<li><strong>Network monitoring<\/strong><br>Use an IDS (e.g., Suricata) or at least log unusual ARP\/traffic patterns.<\/li>\n\n\n\n<li><strong>Regular backups<\/strong><br>Backup HA configs and device settings<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Reflection \u2014 what I learned<\/h2>\n\n\n\n<p>This was a simple purple-hat exercise for myself: knowing how attacks work is useful \u2014 not to exploit people, but to better defend them.<\/p>\n\n\n\n<p>Key takeaways:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Many cheap IoT devices still communicate in plaintext. The weakest device can expose data for the whole home network.<\/li>\n\n\n\n<li>Small configuration changes (TLS for MQTT, VLANs, reverse proxy) drastically reduce risk.<\/li>\n\n\n\n<li>Auto-discovery features are useful, but they increase attack surface \u2014 be deliberate about what you allow.<\/li>\n\n\n\n<li>Defensive testing in a lab helps you explain risks to family and colleagues in a much clearer way than purely theoretical advice.<\/li>\n<\/ul>\n\n\n\n<p>My brother-in-law left thinking: \u201cI had no idea my smart plugs were talking in plain text.\u201d He implemented network segmentation and turned on TLS where possible \u2014 those two steps alone go a long way.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It\u2019s been a while \u2014 I was out sick and focused on getting better \u2014 but I\u2019m back and ready to post again. To get me warmed up I want to write about something practical and relevant: Home Assistant (HA) and how easy it is for poorly configured smart devices to leak sensitive data on [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-container-style":"default","site-container-layout":"default","site-sidebar-layout":"default","disable-article-header":"default","disable-site-header":"default","disable-site-footer":"default","disable-content-area-spacing":"default","footnotes":""},"categories":[20,9],"tags":[],"class_list":["post-388","post","type-post","status-publish","format-standard","hentry","category-cybersecurity","category-network-hacking"],"_links":{"self":[{"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts\/388","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=388"}],"version-history":[{"count":3,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts\/388\/revisions"}],"predecessor-version":[{"id":396,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts\/388\/revisions\/396"}],"wp:attachment":[{"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=388"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=388"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=388"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}