Adtran 411 Security Audit
Adtran produces equipment for fiber ISPs. I was provided an Adtran 411 by my current ISP for Internet access and decided to take a deep look into it.
Hardware
The Adtran 411 is a small GPON fiber ONT (Optical Network Terminal) designed to give symmetrical gigabit fiber Internet to SOHO users. It connects to the ISP via a GPON uplink and provides the user a normal ethernet RJ-45 connector to plug their router into and a RJ-11 port for a landline to be tunneled over VOIP.
The fiber ONT has a Broadcom MIPS CPU that also provides the network card as well.
The first step to learning more about the device is to look for any possible UART connections to grab serial logs. If present, the UART can provide boot logs and allow interacting with the device at a low level. Ideally this could also provide access to the bootloader and interact with the OS.
A UART can be identified by 3-4 pins, which will include Ground, Tx, Rx, and possibly a VCC. The Adtran just happened to have a hidden 4 pin header inside the device. Using a multimeter and logic analyzer revealed the pinout, and was able to provide the boot logs from the device. Amusingly, it can be accessed entirely externally by pushing wires through the vent holes!
The UART boot logs revealed that the device uses the uBoot boot loader and runs Linux. Once booted, it prompts for login credentials.
Dumping the Filesystem
The hardware contains a NAND flash chip. This acts as the persistent storage for the device. The ideal way is to desolder the NAND flash storage and use an external NAND dumper, however that can risk damaging the device when removing or re-adding the NAND flash from the board.
The NAND flash can also be dumped on-device using a much slower method through uBoot. This method involves using the UART serial connection to tell uBoot to load the entire contents of the NAND flash into memory, then read the memory that contains the NAND flash and print the output as hex over the UART serial. While this is running, log all of the serial output and later parse this hex output and reconstruct the binary from flash.
This can be done using tools like screen, grep, sed, xxd, etc. Converting from binary to hex+ASCII over a serial connection is incredibly slow. This can be automated with the Python tool bcm-cfedump. It took 15.5 hours to dump 128MB.
Exploring the Filesystem
The boot logs contained the partition layout for the NAND flash. We can use dd
to carve out the individual partitions from the dump.
dd bs=1 if=nand.bin of=nvram.bin skip=0 count=131072
dd bs=1 if=nand.bin of=update.bin count=64356352 skip=131072
dd bs=1 if=nand.bin of=rootfs.bin count=64356352 skip=64487424
dd bs=1 if=nand.bin of=data.bin count=4194304 skip=128974848
Next the files from the embedded JFFS2 filesystem can be extracted with the jefferson tool.
Users & Passwords
With access to the entire flash filesystem, it is possible to read /etc/passwd
to get a list of users. Surprisingly this also contained password hashes. On modern Linux systems, passwords are saved in /etc/shadow
, but this system had all of the hashes in the passwd file.
admin:$1$fiLRvAiv$WhZdXwZIDJ4QvO0XB1fdk0:0:0:Administrator:/:/bin/sh
support:$1$g0vSrd8Z$gBnlXTkhvDr4dJrFP0I1n1:0:0:Technical Support:/:/bin/sh
user:$1$7GYEnL0B$MbHFofzaMetppUwgKmvfv0:0:0:Normal User:/:/bin/sh
nobody:$1$cd1QZr5m$TUd00gjlgEa8C/WZ0RMa9.:0:0:nobody for ftp:/:/bin/sh
There were four users, all of which belonged to the root
group, gid 0. The password hashes are hashed using the MD5 algorithm as specified by the prefix $1$
.
I was able to crack two of the password hashes using cheap online hash cracking services. This revealed the following two passwords:
user
:user
support
:support
I’m a little embarrassed that I did not guess these passwords initially. It’s also very unusual that the nobody
user has a password, and has a shell assigned to it. Especially if it’s just meant for FTP as designated by the user account name.
These credentials worked to login on the UART shell, but more on that later…
SysRq
There was this SysRq message in the boot logs. SysRq is an abbreviation for System Rq. What is System Rq?
The magic SysRq key is a key combination understood by the Linux kernel, which allows the user to perform various low-level commands regardless of the system’s state. It is often used to recover from freezes. This key combination provides access to features for disaster recovery.
The keystrokes are: [Alt]
+ [SysRq]
+ [Command Key]
, however, over UART in screen: [Ctrl-A]
+ [Ctrl-B]
+ [Command Key]
. On systems that have SysRq enabled, it’s possible to enter a root shell at any time by sending a special keystroke to the device. Sending the command for SIGKILL drops to root shell!
Network Scan
The boot logs revealed the device assigns itself a static IP of 192.168.1.1
. Statically adding an IP on the same subnet to your machine connected to the ONT over ethernet allows direct network communication. A port scan reveals that there are two services running, HTTP and Telnet.
Telnet Service
The telnet interface drops you into the same restricted shell as UART that requires auth. The passwords collected previously from the filesystem work!
After logging in, you are dropped to a very limited custom CLI. It’s not a traditional shell. There are only a few limited debugging commands available like ping. Is it possible to escape this limited shell? Yes!
Telnet Command Injection
The ping command allows for command injection via semicolon (;
).
Web HTTP Service
Accessing the device over the network on port 80 presents a HTTP login form, which the previously collected credentials worked on.
Logging in as user
provides some limited viewing of settings in the web interface. The access control page makes it clear the admin
user has more permissions…
From the filesystem exploration, it was possible to identify additional hidden web pages that were not linked to in the menus.
/engdebug.html
allows for mirroring network port traffic for debugging
/packatcapture.html
allows for creating PCAP files for any interface.
These debug pages provided very privileged access for a non-admin user.
Web Command Injection
The ping utility has a similar command injection vulnerability as the CLI. You need to use two requests: one to run the command, and another to read the response.
Sending a HTTP GET request to /ping.txt?action=ping&command=cat%20/proc/cpuinfo
will initiate the “ping” command that will actually run the PoC command cat /proc/cpuinfo
. The response from that command can later be received by requesting /ping.txt?action=refresh
.
Dumping More Credentials
There was another hidden HTTP endpoint at dumpsysinfo.html
that was accessible from the non-admin user that allows for the creation of a “system information dump”. This dumps all config with all user passwords to a plain text XML file. Now I have the admin
password! The dump also includes SIP and other passwords too.
Control Plane
With live shell access to the device, when plugged in and online, there are lots of internal interfaces online including internal network interfaces, VLANs, and bridges. One of these interfaces is the control plane interface that provides some limited access to the ISP’s management network.
The main bridge br0
is the customer facing ethernet connection with the 192.168.1.1
IP address. There is also an IP on VLAN 702
on the GPON Fiber interface of 10.8.128.0/19
. This is a huge subnet with >8k IPs, likely containing all of the other ISP’s customers in this area. I was able to confirm other customers of this ISP could ping hosts on the control plane from behind their ONT.
All of the network services (Telnet, HTTP) are listening on all interfaces, including the control-plane. In theory this could allow a customer behind a compromised ONT to compromise other customers remotely. With permission from my ISP I tested this and it does appear that customer to customer ONT traffic is blocked. However, some limited access to other devices on the control plane was accessible, including the gateway, DNS and VOIP server.
Disclosure
None of these findings were the ISP’s fault. All issues reside in the firmware for the Adtran ONT. As soon as the ISP was made aware they took steps to make Adtran fix the issues and worked with me to do further testing. This is a security success story.
- February 6, 2024
- submitted a support request to Adtran to disclose to
- February 9, 2024
- submitted a 2nd support request to Adtran
- February 26, 2024
- email ISP support to disclose
- February 29, 2024
- heard back from ISP and provided all technical details of all findings
- ISP acknowledges receiving findings
- March 1, 2024
- ISP gives me permission and access to a test setup to test attacking other ONTs
- Tests successfully fail.
- March 7th, 2024
- ISP confirms Adtran is addressing the issues
- October 17th, 2024
- Adtran test firmware is pushed to my home ONT for testing
- I am given preview access to the new firmware and confirm all issues mitigated
- UART/telnet/HTTP services are all disabled
- December 30th, 2024
- Fixes start rolling out to customers.
CVEs (Common Vulnerabilities and Exposures)
- CVE-2025-22937
- debug serial console in Adtran 411 allows SysRq escape to root shell
- CVE-2025-22938
- Weak default passwords in Adtran 411
- CVE-2025-22939
- command injection in telnet server in Adtran 411 allows remote attacker arbitrary root command execution
- CVE-2025-22940
- web server in Adtran 411 allows unprivileged user to set/read admin password
- CVE-2025-22941
- command injection in web server in Adtran 411 allows remote attacker arbitrary root command execution
BSidesSF: Adventures & Findings in ISP Hacking
This content was covered in a talk I gave at BSidesSF 2025.