Lucene search

K
hackeroneV6akH1:1069487
HistoryDec 31, 2020 - 11:31 p.m.

Node.js: DNS rebinding in --inspect (insufficient fix of CVE-2018-7160)

2020-12-3123:31:42
v6ak
hackerone.com
$500
133

8.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

REQUIRED

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

6.8 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:N/C:P/I:P/A:P

0.044 Low

EPSS

Percentile

91.2%

Summary: While the debugger (i.e., the --inspect option) tries to prevent DNS rebinding, the whitelist is excessive.

Description: The whitelist includes “localhost6”, which is not that widespread. When “localhost6” is not present in /etc/hosts, it is just an ordinary domain that is resolved via DNS, i.e., over network. If the attacker controls victim’s DNS server or can spoof its responses, the DNS rebinding protection can be bypassed by using the “localhost6” domain. As long as the attacker uses the “localhost6” domain, they can still apply the attack described in CVE-2018-7160.

Reasoning why localhost6 is not so common and Node.js should not rely on its presence in the hosts file:

Steps To Reproduce:

Preconditions: Victim has no entry for localhost6 in hosts and attacker controls DNS responses. (It does not matter if the attacker control the DNS server or the network communication between the DNS server and the victim.)

  1. Victim runs node with --inspect option
  2. Victim visits attacker’s webpage
  3. The attacker’s webpage opens http://localhost6:9229
  4. Victim finds no “localhost6” entry in hosts file, so it asks the DNS server and gets <attacker’s-IP>. (Maybe the response will have a short TTL. There are multiple tricks to make DNS rebinding successful in a short time, but I am not going to be exhaustive.)
  5. Victim loads webpage http://localhost6:9229 from <attacker’s-IP>.
  6. The webpage http://localhost6:9229 tries to load http://localhost6:9229/json from attacker’s server. (If the IP address of “localhost6” is still cached, attacker needs to retry. There are techniques that can speed it up, like using RST packet.)
  7. Due to a short TTL, the DNS server will be soon asked again about an entry for “localhost6”. This time, the DNS server responds “127.0.0.1”.
  8. The http://localhost6:9229 website (i.e., the one hosted on <attacker’s IP>) will retrieve http://localhost6:9229/json from 127.0.0.1, including webSocketDebuggerUrl.
  9. Now, the attacker knows the webSocketDebuggerUrl and can connect to is using WebSocket. Note that WebSocket is not restricted by same-origin-policy. By doing so, they can gain the privileges of the Node.js instance.

Vulnerable code: https://github.com/nodejs/node/blob/fdf0a84e826d3a9ec0ce6f5a3f5adc967fe99408/src/inspector_socket.cc#L584

Impact:

Attacker can gain access to the Node.js debugger, which can result in remote code execution.

Supporting Material/References:

Impact

Attacker can gain access to the Node.js debugger, which can result in remote code execution.

8.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

REQUIRED

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

6.8 Medium

CVSS2

Access Vector

NETWORK

Access Complexity

MEDIUM

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:M/Au:N/C:P/I:P/A:P

0.044 Low

EPSS

Percentile

91.2%