Introduction

Netgear Arlo is one of the most popular IoT camera vendors out there. According to their website, over 100 million videos are streamed daily for millions of registered users. Primarily geared towards general consumers, their ubiquitous product line draws in customers ranging from home users, small business owners, storage unit purveyors, rental property owners (such as an AirBnB), etc.

I bought one of their most popular devices — the standard Arlo camera and corresponding basestation— a few months ago and have been relatively impressed with its performance.

There doesn’t appear to be a lot of research out there on this product beyond a couple of CVEs back in 2015. Let’s dig in and see what’s going on.

TL;DR

The remainder of this post covers the general research process for this device. If you only care about the vulnerability details, check out TRA-2019–30 or skip to the end of the article. Please note that this blog post contains information that may not otherwise be included in the TRA.

Device Setup and Initial Recon

The Grand Unboxing

The setup for these devices is about as plug and play as you can get.

Take everything out of the box and plug it in. Download the Arlo app to a compatible mobile device. Register your account and let the app discover the equipment on your network. Press the “Sync” buttons on the basestation and cameras.

That’s it. Everything was up and running within 5 minutes.

Camera Sync

Network Segregation Diagram

Syncing the cameras with the basestation requires pushing a sync button on both the camera and the basestation. This indicates that there is some sort of pairing going on. After further investigation, it appears that the basestation broadcasts a dedicated WiFi network for the cameras to connect to. Authentication is done via WPS, with PIN authentication disabled to prevent brute force attempts at connecting to this internal network.

There appears to be some additional filtering that prevents non-Netgear devices from connecting to this network. This functionality was not explored further during this investigation.

As we’ll see later, while this internal network has limited security functionality enabled, the network is also not trivial to connect to.

Port Scan

The first point of active recon is to see what exactly the device exposes. Unfortunately… there isn’t much.

<…snip…>

PORT STATE SERVICE VERSION

5061/tcp open ssl/sip-tls?

MAC Address: 9CCENSOREDA2 (Netgear)

Device type: WAP

Running: AVM embedded

OS CPE: cpe:/h:avm:fritz%21box_fon_wlan_7240

OS details: AVM FRITZ!Box FON WLAN 7240 WAP

Network Distance: 1 hop

<…snip…>

It would appear that a SIP service (a communication scheme often seen in VOIP implementations) is running on port 5061 as the only externally exposed service that is accessible in any way. More on this service later.

Connection to the Cloud

All interactions with the devices happen through the Arlo cloud. That means that the basestation must always be connected to the internet in some fashion in order to operate as expected and that users are unable to view video streams or other features without first connecting to the cloud service themselves. This may be inconvenient for some users, but it does allow Arlo to reduce the attack surface of their equipment by maintaining this extra control over the traffic at the cost of flexibility for the end user.

At a glance, it looks like they’re doing everything more or less correctly. Traffic is properly encrypted, the expected certs are in place, etc. The only item of concern here is the desktop applications dependence on flash. A number of simple CSRFs were reported to Arlo through their Bugcrowd program but were noted as duplicate submissions. It is unclear if these issues were ever patched by the vendor. On that note, however, users are not required to use this interface if they instead opt for mobile applications.

Taking It Apart

Disassembling the Enclosure

Visible Serial Port (highlighted)

Connection to the Serial Console

Prior write-ups for this device indicate that this serial connection will drop us to a shell on the device. At this point, we need to connect to the device via a USB-to-Serial interface of some kind to verify that. Several options exist. I opted to use a buspirate as a passthrough device since I already had one lying around.

Rather than blindly trust 4-year-old blog posts… it’s probably a good idea to verify the pinout ourselves.

Luckily, 4-pin serial interfaces are relatively simple to figure out. The four expected pins here are:

Ground

Vcc

Rx

Tx

Screwing up ground or Vcc could potentially bork the device if power is supplied to the wrong pin. Screwing up Rx or Tx just means the output will look weird. This is a bit of an oversimplification, but it usually holds true.

Luckily, the ground pin is the easiest thing to figure out via a continuity test. Essentially, we’ll be using a multimeter to test the resistance between a known ground point on the board and each of the serial pins. If the multimeter emits a tone, that means there is effectively no resistance between the pin and the chosen ground point. This indicates that we’ve found the ground pin.

Shield cans (the metal enclosures on the board) are typically connected to ground. For cheap consumer devices like this, that’s generally a safe assumption. Please note that this test is performed with the device unplugged and powered off.

We’ll need to plug the device in and power it on in order to figure out the rest of the pinout. Measuring voltage across ground and each remaining pin will give us the remaining portion. This part can be a little tricky depending on how the board is designed and if there are any mitigations in place to prevent people from reversing the hardware (at a glance, no additional protections such as pull-up resistors are in place).

Vcc is the most import pin to figure out here. It will be the pin with a constant 3.3V output. Unfortunately, all three pins appear to show readings around this value. One trick I’ve picked up is to perform this measurement during device boot. As many serial consoles will output some sort of boot log and perform some basic input/output operations, you can usually see the voltage fluctuations more clearly at this stage. Rebooting the device a couple of times and monitoring each pin independently shows two of the three pins to fluctuate slightly and only one remaining constant. The constant pin is Vcc.

Now that the dangerous part is figured out, we need to determine Rx and Tx. Since there is little risk to getting these pins incorrect, we can simply guess and swap later if we turn out to be wrong. To start, however, I’m going to assume the rapidly fluctuating pin is Tx and the other is Rx. This is because Tx will likely fluctuate more based on console output whereas Rx pins are generally pulled up to Vcc or grounded and will only fluctuate based on input.

The below image shows our determined pinout and final connections.

Authentication Woes

Once connected and booted, the actual boot sequence gave us a wealth of information about the device.

<…snip…>

Found an ST compatible serial flash with 0 64KB blocks; total size 0MB

bcmsflash: found no supported devices

The first offset=200000, 2nd offset=2e00000

Boot partition size = 524288(0x80000)

lookup_nflash_rootfs_offset: offset = 0x200000 size = 0x2c00000

nflash: squash filesystem with lzma found at block 27

lookup_nflash_rootfs_offset: offset = 0x2e00000 size = 0x5a00000

nflash: squash filesystem with lzma found at block 379

Creating 11 MTD partitions on "nflash":

0x00000000–0x00080000 : "boot"

0x00080000–0x00200000 : "nvram"

0x00200000–0x02e00000 : "linux"

0x00360af4–0x02e00000 : "rootfs"

0x02e00000–0x05a00000 : "linux2"

0x02f60afc-0x05a00000 : "rootfs2"

0x05a00000–0x05b80000 : "nvram2"

0x05b80000–0x05bc0000 : "board_data"

0x05bc0000–0x05c00000 : "board_data2"

0x05c00000–0x05c40000 : "POT1"

0x05c40000–0x05c80000 : "POT2"

The first offset=200000, 2nd offset=2e00000

<…snip…>

Buuuuuut there’s a login prompt. And we don’t have the password.

Dumping a flash chip is a total pain, so let’s see if we can access the boot loader. This can be done by sending an interrupt early in the boot process (ctrl+c during device boot).

CFE for VZS3000 version: v1.1.5

Build Date: Mon Mar 21 11:21:01 CST 2016

Init Arena

Init Devs.

Boot partition size = 262144(0x40000)

NFLASH Boot partition size = 524288(0x80000)

flash_size=0x8000000,134217728,max_image_size=0x2C00000

left flash_size=0x3A00000,60817408,max_image_size=0x2C00000

et0: Broadcom BCM47XX 10/100/1000 Mbps Ethernet Controller 6.37.14.5501 (r428563)

CPU type 0x19749: 530MHz

Tot mem: 131072 KBytes

CFE> show devices

Device Name Description

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

uart0 NS16550 UART at 0x18000300

nflash0 AMD NAND flash size 131072KB

nflash0.boot AMD NAND flash offset 0 size 512KB

nflash0.nvram AMD NAND flash offset 80000 size 1536KB

nflash0.trx AMD NAND flash offset 200000 size 1KB

nflash0.os AMD NAND flash offset 20001C size 45056KB

nflash0.trx2 AMD NAND flash offset 2E00000 size 1KB

nflash0.os2 AMD NAND flash offset 2E0001C size 45056KB

nflash0.nvram2 AMD NAND flash offset 5A00000 size 1536KB

nflash0.board_data AMD NAND flash offset 5B80000 size 256KB

nflash0.board_data2 AMD NAND flash offset 5BC0000 size 256KB

nflash0.POT1 AMD NAND flash offset 5C00000 size 256KB

nflash0.POT2 AMD NAND flash offset 5C40000 size 256KB

nflash0.fs_rw AMD NAND flash offset 5C80000 size 32768KB

nflash1.boot AMD NAND flash offset 0 size 512KB

nflash1.nvram AMD NAND flash offset 80000 size 1536KB

nflash1.trx AMD NAND flash offset 200000 size 45056KB

nflash1.trx2 AMD NAND flash offset 2E00000 size 45056KB

nflash1.nvram2 AMD NAND flash offset 5A00000 size 1536KB

nflash1.board_data AMD NAND flash offset 5B80000 size 256KB

nflash1.board_data2 AMD NAND flash offset 5BC0000 size 256KB

nflash1.POT1 AMD NAND flash offset 5C00000 size 256KB

nflash1.POT2 AMD NAND flash offset 5C40000 size 256KB

nflash1.fs_rw AMD NAND flash offset 5C80000 size 32768KB

eth0 Broadcom BCM47XX 10/100/1000 Mbps Ethernet Controller

*** command status = 0%

That does the trick. Checking nvram we get some details and creds and whatnot… unfortunately the creds look encoded or encrypted somehow.

CFE> nvram get UART_username

0uWAcKrAwElsdekujfbELA==

*** command status = 0

CFE> nvram get UART_passwd

MNezCqaCs6z8TjZVf1X4Cg==

*** command status = 0

The boot loader seems to be modified version of CFE and doesn’t respond as expected to typical commands. Save-to-tftp appears modified, but functional. From the boot log earlier, we know which regions we’d like to try and dump. After a bit of trial and error, we got a successful transfer to a TFTP server in my lab environment containing the entire firmware image.

Running strings on the saved output gives us just what we need: the command that encrypts the password and username. Those values are there in plaintext too, but we may as well verify.

$ echo "0uWAcKrAwElsdekujfbELA==" | openssl enc -d -base64 -aes-256-cbc -nosalt -pass pass:GEARNET

ngroot

$ echo "MNezCqaCs6z8TjZVf1X4Cg==" | openssl enc -d -base64 -aes-256-cbc -nosalt -pass pass:GEARNET

ngbase

Boom. It works.

Login: ngroot

Password:

Username and Password is correct!

BusyBox v1.7.2 (2018–10–22 13:09:12 PDT) built-in shell (ash)

Enter 'help' for a list of built-in commands.

#

Under the hood

Much of the recon from this point forward is mostly poking around the filesystem or pretty self-explanatory.

Services running

# netstat -lant

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address Foreign Address State

tcp 0 0 172.14.1.1:4000 0.0.0.0:* LISTEN

tcp 0 0 127.0.0.1:4001 0.0.0.0:* LISTEN

tcp 0 0 127.0.0.1:14369 0.0.0.0:* LISTEN

tcp 0 0 127.0.0.1:4002 0.0.0.0:* LISTEN

tcp 0 0 172.14.1.1:4100 0.0.0.0:* LISTEN

tcp 0 0 0.0.0.0:5061 0.0.0.0:* LISTEN

tcp 0 0 127.0.0.1:4006 0.0.0.0:* LISTEN

tcp 0 0 172.14.1.1:4200 0.0.0.0:* LISTEN

tcp 0 0 172.14.1.1:80 0.0.0.0:* LISTEN

tcp 0 0 192.168.1.11:45327 35.163.123.134:443 ESTABLISHED

After some prodding of the above, we can see that our prior assumptions of port 5061 being the only thing exposed were correct. Everything else is either bound to a local port or the internal interface managing the camera network.

There are three primary services that run the Arlo feature set: vzdaemon, xagent, and xagent-watchdog. vzdaemon is the real central figure of this operation. This binary was heavily reversed over the course of this research, but unfortunately, given the scope of exposed attack surface, most findings are null and void since there is no way for an end user or attacker to actually access or trigger the potential issues.

Filesystem recon

At least we can see how the cameras work and view all the configs. For example, the primary basestation config looks like this:

# version

Release version : Netgear Wireless Router VZC3000

U12H29500/V1.0.2.68/1.0.67

Time : Sep 14 2018 09:49:28

CFE version : v1.1.5

# showconfig

LAN IP/Subnet: 172.14.1.1/255.255.255.0

WLAN SSID: NETGEAR33

WLAN Security: WPA2-PSK

WLAN passphrase: 68CXh7z+kj44NxmQcPiUDvVxpcWU40Pu

WLAN region: United States

Timezone: GMT-8

GUI login: admin/password

# routerinfo

Release version : Netgear Wireless Router VZC3000

U12H29500/V1.0.2.68/1.0.67

Time : Sep 14 2018 09:49:28

CFE version : v1.1.5

WSC PIN - 13064082

LAN mac address - 9CCENSOREDA2

WAN mac address - 9CCENSOREDA2

WLAN_G mac address - 9CCENSOREDA2

WLAN_N mac address - 9CCENSOREDA2

Board ID - U12H295T00_NETGEAR

serial number - 9CCENSOREDA2

Wifi security looks pretty solid. While it could be cracked by a dedicated attacker, not really worth our time. Internal camera configs are simple JSON files.

Nothing too interesting as far as filesystem and configs go, unfortunately. One quick thing to note, however, is this: Netgear Wireless Router VZC3000. It would appear that this device is based on an old wireless router or extender. This is the cause of checking for a certain vulnerability later.

SIP Service

From reversing the vzdaemon binary, it is clear that this binary contains and runs a pjsip-based service. It responds as expected to many voip commands when openssl and other encryption mechanisms are patched out, but I have no idea how this works or how to connect to it with the encryption in place.

It has a similar Passthru routine as the vzdaemon web interface (more on this momentarily), but it seems like it has slightly different functionality. It was enough of a pain that I gave up on this attack vector pretty quickly. Definitely worth looking at again in the future (myself or other researchers).

My analysis indicates that this SIP interface was once used for device enrollment, but has since been phased out of use. I could be completely wrong, but taking apart the android app and vzdaemon shows no indications that this functionality is in use any longer in this model. The hints in the Android app of “DoorbellCallInfo” might indicate that this functionality is specific to devices with doorbell-integration features.

If other researchers are interested in analyzing this service, the SIP credentials are hardcoded into the Android app as “1025 / 1025”:

.method static synthetic lambda$onItemClick$3()V

.locals 2

.line 702

new-instance v0, Lcom/netgear/android/sip/DoorbellCallInfo;

invoke-direct {v0}, Lcom/netgear/android/sip/DoorbellCallInfo;-><init>()V

const-string v1, "1025"

.line 703

invoke-virtual {v0, v1}, Lcom/netgear/android/sip/DoorbellCallInfo;->setId(Ljava/lang/String;)V

const-string v1, "1025"

.line 704

invoke-virtual {v0, v1}, Lcom/netgear/android/sip/DoorbellCallInfo;->setPassword(Ljava/lang/String;)V

The nitty gritty

Plaintext fun

The nvram entries used earlier to discover authentication details expose all sorts of other things as well. For example:

$ cat nvram_default | grep pass

super_passwd=Geardog

wla_passphrase_backup=

bpa_passwd=

http_passwd=password

password_answer1=

password_answer2=

wla_preset_passphrase=940C5EAE80072C56F465F73CC2AC938ABD3FF7E07D7C7EC30B1076AE99F4A0DD1457EC0189B6A1E403A1A42F33B9C288D40394529FB35814A4D08F559B6867D900000000000000000000000000000000

wlg_passphrase_2=

pppoe2_east_passwd=guest

wla_passphrase_2=

wla_passphrase_3=

wla_passphrase_4=

ddns_passwd=

pppoe_passwd=

parser_passwd=Gearucp

wla_passphrase=940C5EAE80072C56F465F73CC2AC938ABD3FF7E07D7C7EC30B1076AE99F4A0DD1457EC0189B6A1E403A1A42F33B9C288D40394529FB35814A4D08F559B6867D900000000000000000000000000000000

wla_temp_passphrase_2=

pppoe_tmp_passwd=

password_question1=0

password_question2=0

wlg_preset_passphrase=

passphrase_encrypt=1

pppoe2_passwd=

wlg_temp_passphrase=

enable_password_recovery=0

The usual Netgear suspects exist: Gearguy:Geardog, gearucp:gearpar, admin:password (unused without manually turning on certain services — ­ i.e. httpd).

Other credentials exist as well: flets:flets, flets:guest@flets, flets:flets@flets.

At a glance, these appear to be used for PPPoE infrastructure or AWS internal configurations. These don’t appear to be in use by anything by default on the device itself (sbin/acos_service and the dhcpd binaries show the only usage), but could potentially lead an attacker to access potentially sensitive infrastructure.

It is unclear whether or not these credentials are in use or have any security-related impact. These issues were reported to the vendor.

Using it as a “router”

As mentioned earlier, this basestation is based on a prior consumer routing device. This made me curious as to whether or not certain routing functionality was recycled without proper review.

Specify the router as your gateway (or simply add the appropriate route to your host machine) and boom, it forwards traffic between interfaces. In particular, the default http listener deployed by “vzdaemon” contains a “passthru” api endpoint that allows the arbitrary download or upload of files on the device.

For example, simply calling “http://<internal ip of interface>/passthru/tmp/system-log” allows an attacker to download the primary logfile used for the device.

While this proof of concept doesn’t illustrate the most significant impact this issue can have, it nicely illustrates the functionality and demonstrates an easy test case when patching.

This passthru api endpoint could allow an attacker to completely take over the device since it allows the arbitrary upload and download of files on the system, which means an attacker could replace a binary that is run automatically (such as “ping,” which is run periodically via vzdaemon) with something malicious.

Camera snooping and other internal issues

If an attacker is able to connect to the internal camera network (by obtaining the PSK from one of the aforementioned vulnerabilities or other means), probing of the internal network opens all manner of opportunity to probe additional services, snoop on other facets of cameras or base station, and attempt to submit configuration change requests. As illustrated in this 2015 article from NewSkySecurity­­ it is possible to snoop on camera streams via a man in the middle attack. While reported to the vendor, it is my opinion that this communication scheme is by design and within the realm of acceptable risk under normal circumstances given the other mitigations in place.

Decryption routines

The fwupgrade binaries contain the private keys and routines used to decrypt the software. This could be easily reversed and used to decrypt future firmware releases.

This works for decrypting camera firmware as well, which was not a focus of this research given that it is part of the internal network. This issue was reported on the off chance that Arlo wished to fix it, but we see no direct security impact here.

The private keys can be found in the fwupgrade utility directly and below:

----BEGIN RSA PRIVATE KEY----

MIIEpQIBAAKCAQEAxqsUswSN425Toar394cE3hf//+XlBfR5cZwpODHBj+X6UZRe

kJNlZoRH0c72D27blNf8dG2TjxsJOHm+gkoCbBz0a9ORenGNrZGZECJYDLH0MVcm

klyyh/z8cyBrMtqRiPoWzYaPN48snuUHFsF/JOVu3OIavFdu7MAGLRQ32dJeQ8Ou

ljlUK/hALVzzGseYuXHdVsj8TNIFqIvKlfMOB7T9biI8NxIoDNb8v3riHmkgSFbs

xlREkLi46Il+XGLIQeC4PzTicte14j7BUjetrurLTJWCac0VdHgKy5jU8xz4opLk

yDaHPCrqgZXQ6w4t/2qlW3n2J94CWMJv9ZC0BQIDAQABAoIBACw7JLWimvB6vLXu

uZxrfCLyVvWjOnUz8+HecbLoKP8fpbaKAO/RUS8c3lyQ5mmTNeISoEtPph2jWE8x

k7+wOI/XdneXN/l51KBDHT/hVZcl+4cMrzLA3qK2KYJ8QkGlNee4PmFtxu8Iuld6

CDUByYvuZNtan7c1BCZDrlxU9wZQkeC3bZDnn/gV8OXUJdKfK3w3H1vG0K3oGGjf

DvLqdQLnIFxGsFVmcfV4AaLigZ5Oe1BiRtDWjgnm5CsnCZ1D7/wcjrWNlfx/zGh4

z7oPPeQgE070b8A0ERV9fqGeiMbGKwDQwSBeddl/e5MJxUNAojAJd7baXGeNnE71

R6Q6q4ECgYEA+n+H5+9E/9VT2QhpAoxV7OkiLDTEC0eBjR3gP6Wx2QY/OwSHy1Jz

tenAfav8Ejmv21vFXbGPvngnBYVDZKgQacBYkgeCJs6t72aqBzKIxJZ0DK6SSMPX

jwOH9YerAuu6b2i7sN0aGnGvqW3EN6QodCNPBR/fSh9sb4LLW9C3xWUCgYEAywgg

pXf3I4z7F+W4PWzl40RTfTgEjCi5Zv9IrfD8BzTvTpcqvQl8KBA1woVysnlCKZdc

AgRNzG0Vvl7HV2exWo63WUEUYRt0scHc1XGVio5rfZg+p81wTOsugZqmvQofdxWq

vqCjtgrUtxgKgnfMGj2YJce8Oy9FRlRQelFEGiECgYEAjS2jIwyvDqDkiMU8qbr+

Em+yWsfCVbkPQsE7yaNRAMeMi26aOfVWUYhUfH+ZqYvpmO+35H5WTTragzoAKZKu

7WsCgArLR6PkU7DA0x2gB2vkK+GXgHsf2fJbhf3YW+UPRgr4/U0fkRfRsOO0Wsei

JRJhTroP1m6vZomIo06WxCECgYEAnli7ZXIX3LEykCPIupd4//QlDU8oNMv6NXs6

ivadCV3emjPJ0F9aZsClvQ1pNArgcCGtT6Fdr+cQA0ZWQDQOHWubUdAw/b91FsH0

4r9QexyyduTLUQIn6MWvosMj8eG4Qp8yaLROmkb+OcJVSAX4uCp7xFNv2dT3OW++

yHcjHyECgYEAtQYGaDBpyjIgEJvAVSy0awv3zik3Ks/c5Wz4nHBV/kTB0xo5SzvM

InLrrHPVa/7oa3NMzZ5140pWuwS62rvrF7JX2kRaJ7vi3UVqmwGxGf2s9MoocS98

iSAZXhQ21meqgu5KMiLIpshrEubd3CPtq6to+yicoqXvOQ0v3DaMndU=

----END RSA PRIVATE KEY----

----BEGIN PUBLIC KEY----

MIIDRjCCAjkGByqGSM44BAEwggIsAoIBAQCPJ9cjoVgpXihsTEvSM2Murt7KBLhd

+qE0YReJWuY2JD3KbHOv6iTXSIjFKmlUR31NGhJ1FTvak5c01/mt88OXkdzRhoFy

iM49kWyx0NRntnHk8gcJFKZ29/+c+2kCHR3H2qA9ldhPEgP5xuLttui8Bd2FNKla

bEn7jnZiJztf7iOmqsI+xTXplsKgpPglLObXNDPUxFjD3rOrGx05LX+eN34XqZjT

X9X3m4vmjGTGTDhij6LoMCvDD2cp44c2/EoCD+AHPBlHDh7YclyEbhAZ9rsOiDlI

XhJox4KMWKdn18s1/rf9RNsS44YYGFyTX+Tdl/6pq1NtGX8IeCIYrNMDAiEAlzKP

vGUirRyM2B/Rm1k1aRzWxCG9kU56E0nCnasA5iECggEAWqawuVSubieYTDs/whRp

5HcDELZJ2EBd0y3ADlxnlWr1OkzJueX3kP10A3g/pzet/d9+Yx7VeS9gxLHhJVFu

P6Xhruesm+Tgm+NYJEPbV6G1U6UJ3QxWiCrDRHUd93n+/UewQun3kc9sPkhbxcNO

k/aZXIKIGhHNQUkpgCQfTTIoxMTH+TxPCpzKSJXkpNuA4SSb3fKLJU77F6NYeNd7

zz0k51QZpX/UmvXku546+xScQj2IErPVmhl1g8wZusKZ+44GjV9L/CXMaEE/aylu

jbjfBjuIphccTNdOVpUbVLXSypxXAKUpGQaMHIJR0aClevZ+fq+MK9XkfodUu80f

sQOCAQUAAoIBAHggg0ZTZznLxuULaU15qrUW9op2vQnhXbZWEGl/+nsdQlwvDYIq

zZIlO6sNqrjnGBdcjmaU1N/pabNNsxwxFY/NtT5l3xInJEKUwBC/m0dUrOYqQ3pm

ljupxzfME60EEmitRXAPvgPcDyUYGqXpj9+P1vL2ANHT2tjNYk+dJJokgYmLryHs

kfHPzmcDKe0K3A7Ik/JN08TFeZZ1jkVGfwkU2Mygnkg+TU5Nc/S0irwavNf0yPdM

zv82QkIx0KB7c8mEoUTlHAnmP+cJN6yncpVAHEDgK+s+EHRHF6tYkN6V1bDgWbSd

e3jhuLWvHUjC+O9CWvekug/JjdkHJw40bUE=

----END PUBLIC KEY----

Conclusion

Honestly, this is one of the better IoT devices I’ve looked at in terms of security posture. While it isn’t without flaw, the device itself holds up to scrutiny. The biggest downsides here are the internet connection requirements and the submission of all captured data being sent to the Arlo cloud, which is out of your control and unable to be independently researched or evaluated.