summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPoonam Jadhav <Poonam.Jadhav@kpit.com>2023-03-03 18:02:14 +0530
committerArmin Kuster <akuster808@gmail.com>2023-03-18 16:16:42 -0400
commit9291a8873887ce36d4e394dcde7b28a0889b35b3 (patch)
treeb4f200c6c2de386602650c161e11583012bc0cc9
parentb691797f7768378a8caf36812312848add77377a (diff)
downloadmeta-openembedded-9291a8873887ce36d4e394dcde7b28a0889b35b3.tar.gz
nodejs: Fix CVE-2022-43548
Add patch to fix CVE-2022-43548 Link: https://sources.debian.org/src/nodejs/12.22.12~dfsg-1~deb11u3/debian/patches/cve-2022-43548.patch Signed-off-by: Poonam Jadhav <Poonam.Jadhav@kpit.com> Signed-off-by: Omkar Patil <omkarpatil10.93@gmail.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--meta-oe/recipes-devtools/nodejs/nodejs/CVE-2022-43548.patch214
-rw-r--r--meta-oe/recipes-devtools/nodejs/nodejs_12.22.12.bb1
2 files changed, 215 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/nodejs/nodejs/CVE-2022-43548.patch b/meta-oe/recipes-devtools/nodejs/nodejs/CVE-2022-43548.patch
new file mode 100644
index 0000000000..54da1fba99
--- /dev/null
+++ b/meta-oe/recipes-devtools/nodejs/nodejs/CVE-2022-43548.patch
@@ -0,0 +1,214 @@
1commit 2b433af094fb79cf80f086038b7f36342cb6826f
2Author: Tobias Nießen <tniessen@tnie.de>
3Date: Sun Sep 25 12:34:05 2022 +0000
4
5 inspector: harden IP address validation again
6
7 Use inet_pton() to parse IP addresses, which restricts IP addresses
8 to a small number of well-defined formats. In particular, octal and
9 hexadecimal number formats are not allowed, and neither are leading
10 zeros. Also explicitly reject 0.0.0.0/8 and ::/128 as non-routable.
11
12 Refs: https://hackerone.com/reports/1710652
13 CVE-ID: CVE-2022-43548
14 PR-URL: https://github.com/nodejs-private/node-private/pull/354
15 Reviewed-by: Michael Dawson <midawson@redhat.com>
16 Reviewed-by: Rafael Gonzaga <rafael.nunu@hotmail.com>
17 Reviewed-by: Rich Trott <rtrott@gmail.com>
18
19CVE: CVE-2022-43548
20Upstream-Status: Backport [https://sources.debian.org/src/nodejs/12.22.12~dfsg-1~deb11u3/debian/patches/cve-2022-43548.patch]
21Comment: No hunks refreshed
22Signed-off-by: Poonam Jadhav <Poonam.Jadhav@kpit.com>
23
24Index: nodejs-12.22.12~dfsg/src/inspector_socket.cc
25===================================================================
26--- nodejs-12.22.12~dfsg.orig/src/inspector_socket.cc
27+++ nodejs-12.22.12~dfsg/src/inspector_socket.cc
28@@ -10,6 +10,7 @@
29
30 #include "openssl/sha.h" // Sha-1 hash
31
32+#include <algorithm>
33 #include <cstring>
34 #include <map>
35
36@@ -166,25 +167,71 @@ static std::string TrimPort(const std::s
37 }
38
39 static bool IsIPAddress(const std::string& host) {
40- if (host.length() >= 4 && host.front() == '[' && host.back() == ']')
41+ // TODO(tniessen): add CVEs to the following bullet points
42+ // To avoid DNS rebinding attacks, we are aware of the following requirements:
43+ // * the host name must be an IP address,
44+ // * the IP address must be routable, and
45+ // * the IP address must be formatted unambiguously.
46+
47+ // The logic below assumes that the string is null-terminated, so ensure that
48+ // we did not somehow end up with null characters within the string.
49+ if (host.find('\0') != std::string::npos) return false;
50+
51+ // All IPv6 addresses must be enclosed in square brackets, and anything
52+ // enclosed in square brackets must be an IPv6 address.
53+ if (host.length() >= 4 && host.front() == '[' && host.back() == ']') {
54+ // INET6_ADDRSTRLEN is the maximum length of the dual format (including the
55+ // terminating null character), which is the longest possible representation
56+ // of an IPv6 address: xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd
57+ if (host.length() - 2 >= INET6_ADDRSTRLEN) return false;
58+
59+ // Annoyingly, libuv's implementation of inet_pton() deviates from other
60+ // implementations of the function in that it allows '%' in IPv6 addresses.
61+ if (host.find('%') != std::string::npos) return false;
62+
63+ // Parse the IPv6 address to ensure it is syntactically valid.
64+ char ipv6_str[INET6_ADDRSTRLEN];
65+ std::copy(host.begin() + 1, host.end() - 1, ipv6_str);
66+ ipv6_str[host.length()] = '\0';
67+ unsigned char ipv6[sizeof(struct in6_addr)];
68+ if (uv_inet_pton(AF_INET6, ipv6_str, ipv6) != 0) return false;
69+
70+ // The only non-routable IPv6 address is ::/128. It should not be necessary
71+ // to explicitly reject it because it will still be enclosed in square
72+ // brackets and not even macOS should make DNS requests in that case, but
73+ // history has taught us that we cannot be careful enough.
74+ // Note that RFC 4291 defines both "IPv4-Compatible IPv6 Addresses" and
75+ // "IPv4-Mapped IPv6 Addresses", which means that there are IPv6 addresses
76+ // (other than ::/128) that represent non-routable IPv4 addresses. However,
77+ // this translation assumes that the host is interpreted as an IPv6 address
78+ // in the first place, at which point DNS rebinding should not be an issue.
79+ if (std::all_of(ipv6, ipv6 + sizeof(ipv6), [](auto b) { return b == 0; })) {
80+ return false;
81+ }
82+
83+ // It is a syntactically valid and routable IPv6 address enclosed in square
84+ // brackets. No client should be able to misinterpret this.
85 return true;
86- uint_fast16_t accum = 0;
87- uint_fast8_t quads = 0;
88- bool empty = true;
89- auto endOctet = [&accum, &quads, &empty](bool final = false) {
90- return !empty && accum <= 0xff && ++quads <= 4 && final == (quads == 4) &&
91- (empty = true) && !(accum = 0);
92- };
93- for (char c : host) {
94- if (isdigit(c)) {
95- if ((accum = (accum * 10) + (c - '0')) > 0xff) return false;
96- empty = false;
97- } else if (c != '.' || !endOctet()) {
98- return false;
99- }
100- }
101- return endOctet(true);
102-}
103+ }
104+
105+ // Anything not enclosed in square brackets must be an IPv4 address. It is
106+ // important here that inet_pton() accepts only the so-called dotted-decimal
107+ // notation, which is a strict subset of the so-called numbers-and-dots
108+ // notation that is allowed by inet_aton() and inet_addr(). This subset does
109+ // not allow hexadecimal or octal number formats.
110+ unsigned char ipv4[sizeof(struct in_addr)];
111+ if (uv_inet_pton(AF_INET, host.c_str(), ipv4) != 0) return false;
112+
113+ // The only strictly non-routable IPv4 address is 0.0.0.0, and macOS will make
114+ // DNS requests for this IP address, so we need to explicitly reject it. In
115+ // fact, we can safely reject all of 0.0.0.0/8 (see Section 3.2 of RFC 791 and
116+ // Section 3.2.1.3 of RFC 1122).
117+ // Note that inet_pton() stores the IPv4 address in network byte order.
118+ if (ipv4[0] == 0) return false;
119+
120+ // It is a routable IPv4 address in dotted-decimal notation.
121+ return true;
122+ }
123
124 // Constants for hybi-10 frame format.
125
126Index: nodejs-12.22.12~dfsg/test/cctest/test_inspector_socket.cc
127===================================================================
128--- nodejs-12.22.12~dfsg.orig/test/cctest/test_inspector_socket.cc
129+++ nodejs-12.22.12~dfsg/test/cctest/test_inspector_socket.cc
130@@ -925,4 +925,84 @@ TEST_F(InspectorSocketTest, HostIpTooMan
131 expect_handshake_failure();
132 }
133
134+TEST_F(InspectorSocketTest, HostIpInvalidOctalOctetStartChecked) {
135+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
136+ "Host: 08.1.1.1:9229\r\n\r\n";
137+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
138+ INVALID_HOST_IP_REQUEST.length());
139+ expect_handshake_failure();
140+}
141+
142+TEST_F(InspectorSocketTest, HostIpInvalidOctalOctetMidChecked) {
143+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
144+ "Host: 1.09.1.1:9229\r\n\r\n";
145+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
146+ INVALID_HOST_IP_REQUEST.length());
147+ expect_handshake_failure();
148+}
149+
150+TEST_F(InspectorSocketTest, HostIpInvalidOctalOctetEndChecked) {
151+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
152+ "Host: 1.1.1.009:9229\r\n\r\n";
153+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
154+ INVALID_HOST_IP_REQUEST.length());
155+ expect_handshake_failure();
156+}
157+
158+TEST_F(InspectorSocketTest, HostIpLeadingZeroStartChecked) {
159+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
160+ "Host: 01.1.1.1:9229\r\n\r\n";
161+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
162+ INVALID_HOST_IP_REQUEST.length());
163+ expect_handshake_failure();
164+}
165+
166+TEST_F(InspectorSocketTest, HostIpLeadingZeroMidChecked) {
167+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
168+ "Host: 1.1.001.1:9229\r\n\r\n";
169+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
170+ INVALID_HOST_IP_REQUEST.length());
171+ expect_handshake_failure();
172+}
173+
174+TEST_F(InspectorSocketTest, HostIpLeadingZeroEndChecked) {
175+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
176+ "Host: 1.1.1.01:9229\r\n\r\n";
177+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
178+ INVALID_HOST_IP_REQUEST.length());
179+ expect_handshake_failure();
180+}
181+
182+TEST_F(InspectorSocketTest, HostIPv6NonRoutable) {
183+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
184+ "Host: [::]:9229\r\n\r\n";
185+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
186+ INVALID_HOST_IP_REQUEST.length());
187+ expect_handshake_failure();
188+}
189+
190+TEST_F(InspectorSocketTest, HostIPv6NonRoutableDual) {
191+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
192+ "Host: [::0.0.0.0]:9229\r\n\r\n";
193+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
194+ INVALID_HOST_IP_REQUEST.length());
195+ expect_handshake_failure();
196+}
197+
198+TEST_F(InspectorSocketTest, HostIPv4InSquareBrackets) {
199+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
200+ "Host: [127.0.0.1]:9229\r\n\r\n";
201+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
202+ INVALID_HOST_IP_REQUEST.length());
203+ expect_handshake_failure();
204+}
205+
206+TEST_F(InspectorSocketTest, HostIPv6InvalidAbbreviation) {
207+ const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n"
208+ "Host: [:::1]:9229\r\n\r\n";
209+ send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(),
210+ INVALID_HOST_IP_REQUEST.length());
211+ expect_handshake_failure();
212+}
213+
214 } // anonymous namespace
diff --git a/meta-oe/recipes-devtools/nodejs/nodejs_12.22.12.bb b/meta-oe/recipes-devtools/nodejs/nodejs_12.22.12.bb
index df9c6010eb..70f23de7b4 100644
--- a/meta-oe/recipes-devtools/nodejs/nodejs_12.22.12.bb
+++ b/meta-oe/recipes-devtools/nodejs/nodejs_12.22.12.bb
@@ -24,6 +24,7 @@ SRC_URI = "http://nodejs.org/dist/v${PV}/node-v${PV}.tar.xz \
24 file://0001-Remove-use-of-register-r7-because-llvm-now-issues-an.patch \ 24 file://0001-Remove-use-of-register-r7-because-llvm-now-issues-an.patch \
25 file://CVE-2022-32212.patch \ 25 file://CVE-2022-32212.patch \
26 file://CVE-2022-35255.patch \ 26 file://CVE-2022-35255.patch \
27 file://CVE-2022-43548.patch \
27 " 28 "
28SRC_URI_append_class-target = " \ 29SRC_URI_append_class-target = " \
29 file://0002-Using-native-binaries.patch \ 30 file://0002-Using-native-binaries.patch \