-
-
Save rajkosto/e2b2455d457cc2be82dbb5c85e22d708 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3 | |
# | |
# Nokia/Alcatel-Lucent router backup configuration tool | |
# G2425 support added by rajkosto on 20/11/2022 | |
# XS-2426G-B support added by rajkosto on 28/02/2023 | |
# | |
# Features: | |
# - Unpack/repack .cfg files generated from the backup and restore functionnality | |
# in order to modify the full router configuration | |
# - Decrypt/encrypt the passwords/secret values present in the configuration | |
# | |
# Original author blog post: https://0x41.cf/reversing/2019/10/08/unlocking-nokia-g240wa.html | |
# | |
# Released under the MIT License (http://opensource.org/licenses/MIT) | |
# Copyright (c) Sami Alaoui Kendil (thedroidgeek) | |
# Copyright (c) Rajko Stojadinovic (rajkosto) | |
# | |
import io | |
import sys | |
import zlib | |
import struct | |
import base64 | |
import binascii | |
import datetime | |
import hashlib | |
import secrets | |
big_endian = True | |
encrypted_cfg = False | |
def u32(val): | |
return struct.unpack('>I' if big_endian else '<I', val)[0] | |
def p32(val): | |
return struct.pack('>I' if big_endian else '<I', val) | |
def checkendian(cfg): | |
if (cfg[0:4] == b'\x00\x12\x31\x23'): | |
return True | |
elif (cfg[0:4] == b'\x23\x31\x12\x00'): | |
return False | |
else: | |
return None | |
class RouterCrypto: | |
def __init__(self): | |
from Crypto.Cipher import AES | |
# key and IV for AES | |
key = '3D A3 73 D7 DC 82 2E 2A 47 0D EC 37 89 6E 80 D7 2C 49 B3 16 29 DD C9 97 35 4B 84 03 91 77 9E A4' | |
iv = 'D0 E6 DC CD A7 4A 00 DF 76 0F C0 85 11 CB 05 EA' | |
# create AES-128-CBC cipher | |
self.cipher = AES.new(bytes(bytearray.fromhex(key)), AES.MODE_CBC, bytes(bytearray.fromhex(iv))) | |
def decrypt(self, data): | |
output = self.cipher.decrypt(data) | |
# verify and remove PKCS#7 padding | |
padLen = ord(output[-1:]) | |
if padLen <= 0 or padLen > 16: #cannot be 0 or > blocksize | |
return None | |
padBytes = output[-padLen:] | |
validPad = all(padByte == padLen for padByte in padBytes) | |
if validPad: | |
return output[:-padLen] | |
else: | |
return None | |
def encrypt(self, data): | |
# add PKCS#7 padding for 128-bit AES | |
pad_num = (16 - (len(data) % 16)) | |
data += chr(pad_num).encode() * pad_num | |
return self.cipher.encrypt(data) | |
class PKCSPassCrypto(RouterCrypto): | |
def __init__(self, pkcsPass, pkcsSalt): | |
from Crypto.Cipher import AES | |
from hashlib import pbkdf2_hmac | |
keyLen = 32 #AES-256 | |
ivLen = 16 #AES blocksize | |
if not isinstance(pkcsPass, bytes): | |
pkcsPass = pkcsPass.encode() | |
pkcs = pbkdf2_hmac('sha256', pkcsPass, pkcsSalt, 10, dklen=keyLen+ivLen) | |
keyBytes = pkcs[:keyLen] | |
ivBytes = pkcs[keyLen:] | |
self.cipher = AES.new(keyBytes, AES.MODE_CBC, ivBytes) | |
#G2425 and newer config pkcs password | |
PKCSPasswords = ["S23l7nZm47XyMGs6y6oJpN9CR4nbfIZHJ4VRwp7HcdV6o2YvUmeNYFlz08Otwz78"] | |
# | |
# unpack xml from cfg | |
# | |
if (len(sys.argv) == 3 and sys.argv[1] == '-u'): | |
# line feed | |
print('') | |
# read the cfg file | |
cf = open(sys.argv[2], 'rb') | |
cfg_data = cf.read() | |
# check cfg file magic (0x123123) and determine endianness | |
big_endian = checkendian(cfg_data) | |
if big_endian == None: | |
# check if config is encrypted | |
decrypted = None | |
try: | |
# decrypt and check validity | |
decrypted = RouterCrypto().decrypt(cfg_data) | |
big_endian = checkendian(decrypted) | |
except ValueError: | |
pass | |
# if decryption failed, or still invalid, bail out | |
if big_endian == None: | |
print('invalid cfg file/magic :(\n') | |
exit() | |
# set decrypted cfg buffer and encryption flag | |
print('-> encrypted cfg detected') | |
cfg_data = decrypted | |
encrypted_cfg = True | |
# log endianness | |
if big_endian: | |
print('-> big endian CPU detected') | |
else: | |
print('-> little endian CPU detected') | |
# get the size of the compressed data | |
data_size = u32(cfg_data[0x04:0x08]) | |
large_header = False | |
if data_size == 0: | |
data_size = u32(cfg_data[0x08:0x0C]) | |
large_header = True | |
if data_size == 0: | |
print('\nERROR: config data size is 0!\n') | |
exit() | |
# get fw_magic (unknown, could be fw version/compile time, hw serial number, etc.) | |
fw_magic = 0 | |
if large_header: | |
fw_magic = u32(cfg_data[0x20:0x24]) | |
else: | |
fw_magic = u32(cfg_data[0x10:0x14]) | |
print('-> fw_magic = ' + hex(fw_magic)) | |
# get the compressed data | |
compressed = [] | |
if large_header: | |
compressed = cfg_data[0x28 : 0x28 + data_size] | |
else: | |
compressed = cfg_data[0x14 : 0x14 + data_size] | |
# get the checksum of the compressed data | |
checksum = 0 | |
if large_header: | |
checksum = u32(cfg_data[0x10:0x14]) | |
else: | |
checksum = u32(cfg_data[0x08:0x0C]) | |
# verify the checksum | |
if (binascii.crc32(compressed) & 0xFFFFFFFF != checksum): | |
print('\nCRC32 checksum failed :(\n') | |
exit() | |
uncomp_size = 0 | |
if large_header: | |
uncomp_size = u32(cfg_data[0x18:0x1C]) | |
else: | |
uncomp_size = u32(cfg_data[0x0C:0x10]) | |
# unpack the config | |
xml_data = None | |
try: | |
xml_data = zlib.decompress(compressed) | |
pkcsPass = None | |
except zlib.error: | |
encData = None | |
pkcsSalt = None | |
tryPasswords = [] | |
if compressed[0] == 0xFF: #pkcs encrypted payload | |
tryPasswords = PKCSPasswords | |
with io.BytesIO(compressed) as payload: | |
payload.seek(1) | |
pkcsSalt = payload.read(8) | |
encData = payload.read() | |
for currPass in tryPasswords: | |
decryptor = PKCSPassCrypto(currPass,pkcsSalt) | |
compressed = decryptor.decrypt(encData) | |
if compressed is None: #pkcs padding verification failed, key is wrong | |
continue | |
try: | |
xml_data = zlib.decompress(compressed) | |
pkcsPass = currPass | |
except zlib.error: | |
pass | |
if xml_data is None: | |
if len(tryPasswords): | |
raise RuntimeError('Exhausted all known encryption passwords') | |
else: | |
raise | |
if len(xml_data) != uncomp_size: | |
print('WARNING: uncompressed size does not match value in header!') | |
# output the xml file | |
out_filename = 'config-%s.xml' % datetime.datetime.now().strftime('%d%m%Y-%H%M%S') | |
if xml_data[0] != ord('<'): | |
out_filename = out_filename.replace('.xml','.ini') | |
of = open(out_filename, 'wb') | |
of.write(xml_data) | |
print('\nunpacked as: ' + out_filename) | |
recompInfo = ('-pb' if big_endian else '-pl') | |
if large_header: | |
recompInfo += '64' | |
if encrypted_cfg or pkcsPass: | |
recompInfo += 'e' | |
if pkcsPass: | |
recompInfo += pkcsPass | |
print('\n# repack with:') | |
print('%s %s %s %s\n' % (sys.argv[0], recompInfo, out_filename, hex(fw_magic))) | |
cf.close() | |
of.close() | |
# | |
# generate cfg from xml | |
# | |
elif (len(sys.argv) == 4 and (sys.argv[1][:3] == '-pb' or sys.argv[1][:3] == '-pl')): | |
fw_magic = 0 | |
try: | |
# parse hex string | |
fw_magic = int(sys.argv[3], 16) | |
# 32-bit check | |
p32(fw_magic) | |
except: | |
print('\ninvalid magic value specified (32-bit hex)\n') | |
exit() | |
big_endian = sys.argv[1][:3] == '-pb' | |
large_header = False | |
param_len = 3 | |
if sys.argv[1][3:5] == '64': | |
large_header = True | |
param_len += 2 | |
elif sys.argv[1][3:5] == '32': | |
large_header = False | |
param_len += 2 | |
encrypted_cfg = False | |
if len(sys.argv[1]) > param_len and sys.argv[1][param_len] == 'e': | |
encrypted_cfg = True | |
param_len += 1 | |
pkcsPass = None | |
if encrypted_cfg and len(sys.argv[1]) > param_len: | |
pkcsPass = sys.argv[1][param_len:] | |
encrypted_cfg = False | |
out_filename = 'config-%s.cfg' % datetime.datetime.now().strftime('%d%m%Y-%H%M%S') | |
# read the xml file | |
xf = open(sys.argv[2], 'rb') | |
xml_data = xf.read() | |
xf.close() | |
# compress using default zlib compression | |
compressed = zlib.compress(xml_data) | |
# pkcs encrypt the inner data if needed | |
extraDecompLen = 1 #non pkcs encrypted configs have +1 to decomp len | |
if pkcsPass is not None: | |
extraDecompLen = 0 | |
with io.BytesIO() as payload: | |
payload.write(b'\xFF') | |
pkcsSalt = secrets.token_bytes(8) | |
payload.write(pkcsSalt) | |
cryptor = PKCSPassCrypto(pkcsPass,pkcsSalt) | |
payload.write(cryptor.encrypt(compressed)) | |
compressed = payload.getvalue() | |
## construct the header ## | |
# magic | |
cfg_data = p32(0x123123) | |
if large_header: | |
cfg_data += p32(0) | |
# size of compressed data | |
cfg_data += p32(len(compressed)) | |
if large_header: | |
cfg_data += p32(0) | |
# crc32 checksum | |
cfg_data += p32(binascii.crc32(compressed) & 0xFFFFFFFF) | |
if large_header: | |
cfg_data += p32(0) | |
# size of xml file | |
cfg_data += p32(len(xml_data) + extraDecompLen) | |
if large_header: | |
cfg_data += p32(0) | |
# fw_magic | |
cfg_data += p32(fw_magic) | |
if large_header: | |
cfg_data += p32(0) | |
# add the compressed xml | |
cfg_data += compressed | |
# encrypt overall file if necessary | |
if encrypted_cfg: | |
cfg_data = RouterCrypto().encrypt(cfg_data) | |
# write the cfg file | |
of = open(out_filename, 'wb') | |
of.write(cfg_data) | |
of.close() | |
print('\npacked as: ' + out_filename + '\n') | |
# | |
# decrypt/encrypt secret value | |
# | |
elif (len(sys.argv) == 3 and (sys.argv[1] == '-d' or sys.argv[1] == '-e')): | |
decrypt_mode = sys.argv[1] == '-d' | |
if decrypt_mode: | |
# base64 decode + AES decrypt | |
print('\ndecrypted: ' + RouterCrypto().decrypt(base64.b64decode(sys.argv[2])).decode('UTF-8') + '\n') | |
else: | |
# AES encrypt + base64 encode | |
print('\nencrypted: ' + base64.b64encode(RouterCrypto().encrypt(sys.argv[2].encode())).decode('UTF-8') + '\n') | |
else: | |
print('\n#\n# Nokia/Alcatel-Lucent router backup configuration tool\n#\n') | |
print('# unpack (cfg to xml)\n') | |
print(sys.argv[0] + ' -u config.cfg\n') | |
print('# pack (xml to cfg)\n') | |
print(sys.argv[0] + ' -pb config.xml 0x13377331 # big endian, no encryption, fw_magic = 0x13377331') | |
print(sys.argv[0] + ' -pl config.xml 0x13377331 # little endian, ...') | |
print(sys.argv[0] + ' -pbe config.xml 0x13377331 # big endian, with encryption, ...') | |
print(sys.argv[0] + ' -ple config.xml 0x13377331 # ...\n') | |
print('# decrypt/encrypt secret values within xml (ealgo="ab")\n') | |
print(sys.argv[0] + ' -d OYdLWUVDdKQTPaCIeTqniA==') | |
print(sys.argv[0] + ' -e admin\n') |
Hey! thanks for the awesome work. I have made the following changes in the config file, and restored it on the router:
<LimitAccount_ONTUSER rw="RW" t="boolean" v="true"></LimitAccount_ONTUSER>
<TelnetSshAccount. n="TelnetSshAccount" t="staticObject"> <Enable rw="RW" t="boolean" v="False"></Enable> <UserName ml="64" rw="RW" t="string" v="ONTUSER"></UserName> <Password ml="64" rw="RW" t="string" v="password"></Password> </TelnetSshAccount.>
Then when I do
telnet 192.168.1.1
in putty (This is my routers IP) and try to login usingONTUSER
,password
. I get incorrect password. Is there anything else that I need to do be able to login?I am using
G-2425G-A
with3FE49362JJIJ54
software version.
All your booleans are wrong...
you want LimitAccount_ONTUSER to be False so it will exist/be usable
and you want Enable on TelnetSshAccount to be true so SSH works
@rajkosto
ontuser is already enabled and password is set in firmware with md5crypt hash (that i cant decrypt password =$1$gN5WP2Fo$6B.xGzm6kfpDOpYlY89Wp. or $1$ojmCYQtx$ktc5DH0Kvu/jCpuUSAQB0. )
Try this in your config file
i just curious, anybody tried to find where the default data is been stored.
@Nepankaj inside .ubi volume
Hello sir @rajkosto i am getting an File invalid error! while importing config.cfg file to the router please help sir how to get rid of it or just help me to understand what is going on!!!
Possible support for Nokia XS-2426G-B? It's a new AX (WiFi 6) router.
Reverse engineered the firmware, it's in an encrypted file in /etc, keys for which differ for each fw ver, but this password is still consistent across firmwares and even newer models, if they change it I'll have to obtain newer firmware and reverse engineer it again
Olá, para a G-1425G-A/B, funcionou para de desencryptar o config.cfg porém não funciona para encryptar, creio que seja a chave PKCSPasswords = ["S23l7nZm47XyMGs6y6oJpN9CR4nbfIZHJ4VRwp7HcdV6o2YvUmeNYFlz08Otwz78"] que não é compativel com esse modelo. Você poderia descobrir a PKCSPasswords da G-1425G-Bm por favor? ou nos mostrar o caminho pra descobrir? Obrigado!
Unable to Upload the config file.
Hardware Version 3FE48299DEAC
Software Version 3FE49362JJIJ54
Config Edit:
<LimitAccount_ONTUSER rw="RW" t="boolean" v="false"></LimitAccount_ONTUSER>
<TelnetSshAccount. n="TelnetSshAccount" t="staticObject">
<Enable rw="RW" t="boolean" v="True"></Enable>
<UserName ml="64" rw="RW" t="string" v="ONTUSER"></UserName>
<Password ml="64" rw="RW" t="string" v="anyrandompassword"></Password>
</TelnetSshAccount.>
the bin/sh trick was patched after 3FE49362IJHK46 you can still change the password for
ONTUSER
by settingONTUSER
as the username inTelnetSshAccount
section, and whatever password you want, and then enablingONTUSER
to drop into busybox instead of vtysh by settingLimitAccount_ONTUSER
to false if you are getting invalid config when importing, make sure you are using the exact commandline the script tells you to use when you unpacked (important, because it contains the key to encrypt with) otherwise, you can try just naming itconfig.cfg
i tried to setup ONTUSER in telnet ssh and already set Boolean for LimitAccount_ONTUSER to false
but still won't be able to get the shell because it again asking for password2 please help me how can i find it or how can i get shell access for nokia G-2425G-A SERIAL NUMBER ALCLB3AD4352
SOFTWARE VERSION 3FE49362JJIJ54
@rajkosto
what is the password for shell? I've tried everything to get the root access but nothing worked for me. If anyone know the password2 please let us know.
I appreciate Your prompt response!
Thank You!
Hello sir @rajkosto i am getting an File invalid error! while importing config.cfg file to the router please help sir how to get rid of it or just help me to understand what is going on!!!
@Infmous0099 were you able to resolve this issue? I am facing same issue.
Hello sir @rajkosto i am getting an File invalid error! while importing config.cfg file to the router please help sir how to get rid of it or just help me to understand what is going on!!!
@Infmous0099 were you able to resolve this issue? I am facing same issue.
yes i am able to resolve the issue which router you are using?
all done, but after importing it says "Upload Failed: File Invalid!"
kindly help
all done, but after importing it says "Upload Failed: File Invalid!" kindly help
Did you try changing the filename to "config.cfg" before uploading? The router does not accept any other names for config file.
I am having the same "Upload Failed: File Invalid!" Issue can anyone share the Boolean values? I think that might be a problem.
What is the password2 for shell access?
Hello, I have a G-0425G-C, it uses the SW version 3FE49568IJJL06. I am able to use the decryption tool and managed to get the AdminGPON login, but the password for the PPPoE is base64 encoded. I tried changing the text on the base64 part to text, encrypt it back and upload to the ONT, but that didn't work. When I extract it and decrypt it, the string with base64 is back there and the password for the PPPoE is still encrypted. Feel like I am really close to getting internet access and replace the ONT. I managed to clone the information into the ONU and get O5, the last stage is getting the PPPoE password it seems.
the bin/sh trick was patched after 3FE49362IJHK46 you can still change the password for
ONTUSER
by settingONTUSER
as the username inTelnetSshAccount
section, and whatever password you want, and then enablingONTUSER
to drop into busybox instead of vtysh by settingLimitAccount_ONTUSER
to false if you are getting invalid config when importing, make sure you are using the exact commandline the script tells you to use when you unpacked (important, because it contains the key to encrypt with) otherwise, you can try just naming itconfig.cfg
Oh damn this worked. I'm kind of clueless now what commands do I do as aont root to get the PPPoE password?
Oh damn this worked. I'm kind of clueless now what commands do I do as aont root to get the PPPoE password?
cat /etc/ppp/options_ppp111
the ppp111 suffix might be different for you, but its not just /etc/ppp/options as that has just general information, not connection-specific like username/password
btw, you could have just decrypted the base64 password from the config using this exact script and the -d option as well (which someone put a screenshot of their attempt in the SECOND COMMENT).
Oh damn this worked. I'm kind of clueless now what commands do I do as aont root to get the PPPoE password?
cat /etc/ppp/options_ppp111
the ppp111 suffix might be different for you, but its not just /etc/ppp/options as that has just general information, not connection-specific like username/password btw, you could have just decrypted the base64 password from the config using this exact script and the -d option as well (which someone put a screenshot of their attempt in the SECOND COMMENT).
Oh great! Thank you. This worked for my G-0425-C, however, this just confirmed to me that your python script did, in fact, decrypt the encrypted PPPoE password and that what I was seeing was the already decrypted password. So I am left clueless as to how to solve this situation (I want to replace the ONT from my ISP, which has been causing issues with my access points), with an ONU of my own. I feel like I have come so far and am so close to getting to the solution, but I fell short. I cloned the ONT's settings into the new ONU and it now gives out O5, but trying a connection with the given PPPoE credentials just does not give internet access.
Could it maybe be that the ISP has locked down the access to the onboard router's MAC address? If so, what command could I use on AONT root to extract that?
Python -m venv venv
Pip install openssl secrets
In a fresh virtual environment you might have more luck?
SLT - Sri Lanka Telecom Nokia GPON G 1425 G B
-
Thank you for your work @rajkosto
-
I extracted two squashfs and a ubi partition in there (ubi partition with current modifications) etc/passwd and etc/shadow there is additional account administrator that's the one who connects with vtysh, How should I proceed?
-
administrator : AU121BM213CH38E5
-
ONTUSER and root passwords are unknown
Reverse engineered the firmware, it's in an encrypted file in /etc, keys for which differ for each fw ver, but this password is still consistent across firmwares and even newer models, if they change it I'll have to obtain newer firmware and reverse engineer it again
Hi @rajkosto !
Thank you for the great work done! I just wanted to ask you for a small guide/how-to about the process of PKCSPasswords extraction
from newer Nokia firmware (e.g. 3FE49568IJJK06(1.2203.406))... I have already dumped and extracted the firmware from a
locked Nokia ONT router (G-1425G-A, provided by my ISP) and have found the "config_encryption.cfg" file, but the script posted here
was not able to decrypt it and now I do not know how to move forward...
Can you, please, help with the reverse engineering process to find the new/suitable PKCSPasswords?
Also, the magic value/header in my config file is different (Hex 24 41 12 00). After correcting that (to Hex 23 31 12 00), I get this error:
Traceback (most recent call last):
File "C:\Users\taronhov\Downloads\mtd6_mtd7\nokia-router-cfg-tool.py", line 205, in
xml_data = zlib.decompress(compressed)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
zlib.error: Error -3 while decompressing data: incorrect header check
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\taronhov\Downloads\mtd6_mtd7\nokia-router-cfg-tool.py", line 232, in
raise RuntimeError('Exhausted all known encryption passwords')
RuntimeError: Exhausted all known encryption passwords
Thanks!
C:\Users\Yan\Downloads\Python 3>python nokia-router-cfg-tool.py -u config.cfg
-> little endian CPU detected
-> fw_magic = 0xffffffff
unpacked as: config-04112024-131752.xml
repack with:
nokia-router-cfg-tool.py -pleS23l7nZm47XyMGs6y6oJpN9CR4nbfIZHJ4VRwp7HcdV6o2YvUmeNYFlz08Otwz78 config-04112024-131752.xml 0xffffffff
C:\Users\Yan\Downloads\Python 3>nokia-router-cfg-tool.py -pleS23l7nZm47XyMGs6y6oJpN9CR4nbfIZHJ4VRwp7HcdV6o2YvUmeNYFlz08Otwz78 config-04112024-131752.xml 0xffffffff
C:\Users\Yan\Downloads\Python 3>
[main 2024-11-04T17:18:00.481Z] update#setState idle
[main 2024-11-04T17:18:01.953Z] Extension host with pid 5492 exited with code: 0, signal: unknown.
Hello, I am facing this issue trying to run the script recently. Any idea on how to fix it? It just opens VScode when I try repacking
Reverse engineered the firmware, it's in an encrypted file in /etc, keys for which differ for each fw ver, but this password is still consistent across firmwares and even newer models, if they change it I'll have to obtain newer firmware and reverse engineer it again
Hi @rajkosto !
Thank you for the great work done! I just wanted to ask you for a small guide/how-to about the process of PKCSPasswords extraction from newer Nokia firmware (e.g. 3FE49568IJJK06(1.2203.406))... I have already dumped and extracted the firmware from a locked Nokia ONT router (G-1425G-A, provided by my ISP) and have found the "config_encryption.cfg" file, but the script posted here was not able to decrypt it and now I do not know how to move forward... Can you, please, help with the reverse engineering process to find the new/suitable PKCSPasswords? Also, the magic value/header in my config file is different (Hex 24 41 12 00). After correcting that (to Hex 23 31 12 00), I get this error:
Traceback (most recent call last): File "C:\Users\taronhov\Downloads\mtd6_mtd7\nokia-router-cfg-tool.py", line 205, in xml_data = zlib.decompress(compressed) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ zlib.error: Error -3 while decompressing data: incorrect header check
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "C:\Users\taronhov\Downloads\mtd6_mtd7\nokia-router-cfg-tool.py", line 232, in raise RuntimeError('Exhausted all known encryption passwords') RuntimeError: Exhausted all known encryption passwords
Thanks!
@taronhov
Can you share the process for extracting the firmware, my isp also upgraded similar software version and currently completely locked
@mytot
Hi, I have dumped the firmware from NAND IC (SPI memory chip), using a programmer...
Then used binwalk tol to examine it, and information provided here to extract mtd6 and mtd7 partitions (search these names here),
Then ubidump and ubi-readerr tools can be used to extract file-systems...
For other partitions you may want ot use sqashfs tools, etc.
Is it Possible to Convert this ONT GPON to EPON, I have there is Huawei ONU can be changed from GPON to EPON Updating Firmware
model_name=Nokia WiFi Beacon 1.1
Username=superadmin
Password=Telc@Admin2#