Too much confidence in user input: the Gemtek WLTXFSQ-102N case
Yesterday I was having a break from studying for next exam. I had few minutes of free time, so I decided to spend that time going around inside the web interface of Gemtek WiMax/4G router that my ISP installed here. I had a "guest" account, as specified in the router's manual.
During my "exploration" of router's web interface I landed into "utility" web page. As usual, "utility" means "ping" and "traceroute", nothing more. Usually, these utilities are installed as executable in router's firmware (sometimes with busybox package), and very often web developers use these executables instead of reinventing the wheel.
Both tests ("ping" and "traceroute") need a destination: host name or IP address. What if I insert a different thing?
Input sanitization
The golden rule for web programming is: don't trust user's input (actually I think that is the golden rule for everything in IT...).
I choose "ping" test. The "destination" input is protected by a Javascript that doesn't allow me to proceed if the field doesn't match a specific set of regular expressions. Let's disable that check (very easy to do with Firefox/Chrome developer tools) and test some inputs:
www.google.it;ls
It doesn't work (the output shows: "unknown host www.google.it;ls"). I was hoping that the field was appended as raw text to ping CLI utility. That's not the case: apparently, the field is quoted with single or double quote. So let's try with:
www.google.it';ls
Nope. Even with double-quote. Apparently the double-quote gets replaced (from server) with single-quote. So, we can assume that the web interface is launching the ping utility with destination into double-quote. Let me try something stupid:
www.google.it$(ls)
Bingo! "ls" is executed, and the output is appended to ping as destination argument. That's not a problem, because we can see the error message ("unknown host: ...") with the full output of "ls". Ok, let's check how the web interface is running these commands:
www.google.it$(ps)
the output is
1399 root sh -c (ping -4 -c 5 -s 64 -W 10 "www.google.it$(ps)" > /tmp/mon_diag.log 2>&1)&
Wait a moment! We're running as root! In fact, I was able to launch a telnet daemon and acquire a full root shell access. Then, I was able to download and decrypt some critical files, such as /etc/passwd and /etc/shadow.
How to avoid that?
The key concept is "input sanitization". You should clean (or reject) user input server-side with a very specific filter. Are you planning to have an hostname? You should remove all chars that are not in DNS specifications. Then remote all problematic characters (if any) such as $ (dollar sign), ` (backtick) and others.
Another layer of security is executing programs with the "least-privilege" concept: you should enforce software to run with the minimum subset of privileges. If you don't need to be root to ping, don't be. If you don't need "telnetd", negate execution/access/remove from firmware.
Implementing both these best pratices will render this attack impossible.
A word about NSA/CIA
Yes, this kind of attack can be useful to NSA/CIA/hackers to hack your router and install a spyware into it. You should reduce your attack surface: change router default passwords and parameters, learn how to do it. Protect your own PC even in home network. Install a firewall, configure it. Keep your PC's software up-to-date.