An Analysis of Arlo

James Sebree
Jul 2 · 13 min read

Introduction

TL;DR

Device Setup and Initial Recon

The Grand Unboxing

Camera Sync

Network Segregation Diagram

Port Scan

<…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…>

Connection to the Cloud

Taking It Apart

Disassembling the Enclosure
Visible Serial Port (highlighted)

Connection to the Serial Console

Authentication Woes

<…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…>
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%
CFE> nvram get UART_username
0uWAcKrAwElsdekujfbELA==
*** command status = 0
CFE> nvram get UART_passwd
MNezCqaCs6z8TjZVf1X4Cg==
*** command status = 0
$ 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
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

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

Filesystem recon

# 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

SIP Service

.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

$ 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

Using it as a “router”

Camera snooping and other internal issues

Decryption routines

----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

Tenable TechBlog

Learn how Tenable finds new vulnerabilities and writes the software to help you find them

Thanks to Claire Tills.

James Sebree

Written by

Tenable TechBlog

Learn how Tenable finds new vulnerabilities and writes the software to help you find them