Changing the GPON Serial on the Ubiquiti UFiber Nano G – Part One

Published on January 5th, 2018
by Dylanger Daly

Hey Guys,

I’ve recently been getting into GPON networks recently, well not networks, but how the CPE works etc.

It turns out Ubiquiti offer a super cheap, cute little OLT/OLU – The Nano G


You can probably guess where UART is 😛

Temporarily Change the GPON Serial Number

After some playing around in the bins, I figured out how to (at least I think so, I don’t have an OLT to test) change the GPON Serial Number Temporarily:

SSH into the device and run ‘sh’, this should drop you into a shell:

login as: ubnt
ubnt@'s password:
BCM96838 Broadband Router
> sh

BusyBox v1.17.2 (2017-09-19 08:54:11 UTC) built-in shell (ash)
Enter 'help' for a list of built-in commands.

# cd bin
# ./gponctl getSnPwd

======== Serial Number & Password ========

Serial Number: 55-42-4E-54-xx-xx-xx-xx
Password : 20-20-20-20-20-20-20-20-20-20


# ./gponctl stop

Stop ONU without sending dying gasp messages

# ./gponctl setSnPwd --sn 41-4c-43-4c-xx-xx-xx-xx --pwd 20-20-20-20-20-20-20-20-20-20

======== Serial Number & Password ========

Serial Number: 41-4C-43-4C-xx-xx-xx-xx
Password : 20-20-20-20-20-20-20-20-20-20


# ./gponctl init
# ./gponctl start

Start ONU with operational state: INIT (01)

# ./gponctl getSnPwd

======== Serial Number & Password ========

Serial Number: 41-4C-43-4C-xx-xx-xx-xx
Password : 20-20-20-20-20-20-20-20-20-20




Now this value will not survive a reboot, upon rebooting and running `./gponctl getSnPwd` you’ll notice its switched back to the original UBNT Vendor ID.

Also, I don’t have an OLT so I can’t test that this actually changing the Serial Number of the device.

 On another note, gponctl is pretty powerful

Here’s a list of commands it can take:

# ./gponctl

GPON Control Utility:

Proc FileSystem: /proc/ploam /proc/omci

::: Usage:

./gponctl --help

:::::: System ::::::
./gponctl init
./gponctl start
[ --oper <1..8> ]
./gponctl stop
[ --gasp <0=FALSE|1=TRUE> ]
./gponctl setTO1TO2 --to1 <ms> --to2 <ms>
./gponctl getTO1TO2
./gponctl getState
./gponctl getSnPwd
./gponctl setSnPwd
[ --sn <xx-xx-xx-xx-xx-xx-xx-xx>
--pwd <xx-xx-xx-xx-xx-xx-xx-xx-xx-xx> ]
./gponctl getVersion
./gponctl ackOffset [ --offset <bytes>]

:::::: Event ::::::
./gponctl getEvent
./gponctl maskEvent
[ --state <0=OFF|1=ON> --alarm <0=OFF|1=ON>
--port <0=OFF|1=ON> --rxo <0=OFF|1=ON>
--txo <0=OFF|1=ON> --gem <0=OFF|1=ON>]

:::::: Alarm ::::::
./gponctl getAlarm
./gponctl maskAlarm
[ --los <0=OFF|1=ON> --lof <0=OFF|1=ON>
--sf <0=OFF|1=ON> --sd <0=OFF|1=ON>
--lcdg <0=OFF|1=ON> --suf <0=OFF|1=ON>
--mem <0=OFF|1=ON> --dact <0=OFF|1=ON>
--dis <0=OFF|1=ON> --lol <0=OFF|1=ON>
--apc <0=OFF|1=ON> --pee <0=OFF|1=ON> ]
./gponctl getSfSdThreshold
./gponctl setSfSdThreshold
[ --sf <3..8> --sd <sf+1..9> ]
./gponctl setSoakTime --alarm <los|lof|lcdg|lol|apc>
--decl <100ms unit> --retire <100ms unit>
./gponctl getSoakTime --alarm <los|lof|lcdg|lol|apc>

:::::: Message ::::::
./gponctl transmitMsg
[ --id <0..255>
--data <xx-xx-..-xx (up to 10)> ]
--block (blocking bcm_dev_write) ]
./gponctl registerMsg
[ --all <0=FALSE|1=TRUE> --dir <0=UP|1=DOWN>
--id <0..255> ]
./gponctl unregisterMsg
[ --all <0=FALSE|1=TRUE> --dir <0=UP|1=DOWN>
--id <0..255> ]
./gponctl getRegisteredMsg

:::::: Counters ::::::
./gponctl getMsgCounters
[ --reset <0=FALSE|1=TRUE> ]
./gponctl getGtcCounters
[ --reset <0=FALSE|1=TRUE> ]
./gponctl getGemPortCounters
[ --reset <0=FALSE|1=TRUE>
--index <0..255|BCM_PLOAM_GEM_PORT_IDX_ALL(0xfffe)|BCM_PLOAM_GEM_PORT_IDX_ETH_ALL(0xfffd)>
--id <0..BCM_PLOAM_MAX_GEM_ID(0x0fff)> ]

:::::: GEM Port Provisioning ::::::
./gponctl configGemPort
[ --index <0..31|BCM_PLOAM_GEM_PORT_IDX_UNASSIGNED(0xffff)>
--id <0..BCM_PLOAM_MAX_GEM_ID(0x0fff)>
./gponctl getUsQueueCfg
[ --queue <0..63>
./gponctl configUsQos
[ --queue <0..63>
--spEnabled <0=FALSE|1=TRUE>
--priority <0..31> --weight <0..127> ]
./gponctl configGemtoDsMibIdx
[ --index <0..128|BCM_PLOAM_GEM_PORT_IDX_UNASSIGNED(0xffff)
--id <0..BCM_PLOAM_MAX_GEM_ID(0x0fff)>
--mibidx <0..31> ]
./gponctl configGemPortGtcDs
[ --index <0..31|BCM_PLOAM_GEM_PORT_IDX_UNASSIGNED(0xffff)>
--id <0..BCM_PLOAM_MAX_GEM_ID(0x0fff)>
--queue <0..7> --mode <0..3>
--dsQPbit <0=FALSE|1=TRUE> --useTag1 <0=FALSE|1=TRUE> ]
./gponctl deconfigGemPort
[ --index <0..31|BCM_PLOAM_GEM_PORT_IDX_UNASSIGNED(0xffff)|
--id <0..BCM_PLOAM_MAX_GEM_ID(0x0fff)> ]
./gponctl enableGemPort
[ --index <0..31|BCM_PLOAM_GEM_PORT_IDX_UNASSIGNED(0xffff)>
--id <0..BCM_PLOAM_MAX_GEM_ID(0x0fff)>
--enable <0=FALSE|1=TRUE> ]
./gponctl getGemPort
[ --index <0..31|BCM_PLOAM_GEM_PORT_IDX_UNASSIGNED(0xffff)>
--id <0..BCM_PLOAM_MAX_GEM_ID(0x0fff)> ]
./gponctl getOmciPort
./gponctl getAllocIds

./gponctl configDsGemPortEncryByIx
--encryption <0..1> ]
./gponctl configDsGemPortEncryById
[ --gemPortId <0..BCM_PLOAM_MAX_GEM_ID(0x0fff)>
--encryption <0..1> ]
./gponctl configUsShaper
[--queue <0..63>]
[--beDisabled <0=FALSE|1=TRUE>]
[--cir <0=FALSE|1=TRUE>]
[--cirRate <Kbps> ]
[--eir <0=FALSE|1=TRUE>]
[--eirRate <Kbps> ]
./gponctl configTcontQueueMap
[--tcontIdx <0..7>]
[--queueIdx <0..63> ...]
./gponctl configTcontAllocId
[--tcontIdx <0..7>]
./gponctl configTcontSchdPolicy
[--tcontIdx <0..7>]
--policy <1(SP_WRR) 2(SP_WFQ)>]
./gponctl configGemBlkLen
[--len <Bytes>]
./gponctl configTod
[--enable <0=FALSE|1=TRUE>]
[--usrEvent <0=FALSE|1=TRUE>]
[--pulseWidth <0...255>]
[--sf <0...0x3FFFFFFF>]
[--timeNs <0...0xFFFFFFFF>]
[--timeSecMSB <0...0xFFFFF>]
[--timeSecLSB <0...0xFFFFFFFF>]
./gponctl configGtcDsSchd
[--thld <0x20...0x480>]...
./gponctl deconfigUsShaper
[--queue <0..63>]
./gponctl deconfigTcontSchdPolicy
[--tcontIdx <0..7>]
./gponctl deconfigUsQos
[ --queue <0..63>
./gponctl getTcontCfg
[--tcontIdx <0..7>]
:::::: GTC parameters ::::::
./gponctl setSnPreamble
[ --enable <0=FALSE|1=TRUE>
--len1 <0..255>
--len2 <0..255> ]
./gponctl getGtcParam
./gponctl getOnuId
./gponctl getFecMode
./gponctl getEncryptionKey
./gponctl configGtcDs
[ --inner <tpid1> <tpid2> <tpid3> <tpid4>
--outer <tpid1> <tpid2> <tpid3> <tpid4> ]
./gponctl configMCastFilter
--inner <0..4095|BCM_PLOAM_VID_NOT_USED>
--outer <0..4095|BCM_PLOAM_VID_NOT_USED>
--mac <xx:xx:xx:xx:xx:xx> ]
./gponctl generatePrbs
[ --enable <0=FALSE|1=TRUE>

:::::: Optical Module Interface parameters ::::::
./gponctl configOpticalModule
[ --los <0=FALSE|1=TRUE>
--burst <0=FALSE|1=TRUE>
--lvds <0=FALSE|1=TRUE>
--lvttl <0=FALSE|1=TRUE>
--lon <0..31> ]
--loff <0..31> ]
--idlePat <0..4294967295> ]

./gponctl getOpticalModuleConfig
:::::: Active Ethernet Mode ::::::
./gponctl aeSetMode
[ --sgmii ][ --1000bx ]

./gponctl aeGetMode
./gponctl aeStart
./gponctl aeStop
./gponctl aeStatus
./gponctl aeMode
[ --sgmii ]

:::::: OMCI ::::::
./gponctl transmitOmciMsg
[ --len <1..2040>
--data <xx-xx-..-xx (up to len or 512, whichever comes first.
If len>512, byte pattern 00-01-02-... is used for
data items 512 and up.)>
--block (blocking bcm_dev_write) ]
./gponctl getOmciCounters
[ --reset <0=FALSE|1=TRUE> ]
./gponctl getOmciVersion

OLT fuzzing anyone? No?


Next Steps

In the next post, we’ll look into Broadcom’s CFE NVRAM, this is where I think the GPON Serial and Password are permanatly stored, we’ll reverse engineer the httpd daemon to see how it sets the OLT Vendor ID (Profile ID, of which there are 4 – UBNT, Huawei, Some other vendor and ZTE) and GPON Password.

Dylanger Daly

If its Security, I'm there. I mainly work in the Security Research Field, most of my focus is Mobile Security, anything from the hardware to TrustZone to the Modem. Bypassing checks one NOP at a time.

You've reached the end!

back to top