diff options
| author | Poonam Jadhav <Poonam.Jadhav@kpit.com> | 2023-03-03 18:02:14 +0530 |
|---|---|---|
| committer | Armin Kuster <akuster808@gmail.com> | 2023-03-18 16:16:42 -0400 |
| commit | 9291a8873887ce36d4e394dcde7b28a0889b35b3 (patch) | |
| tree | b4f200c6c2de386602650c161e11583012bc0cc9 /meta-oe/recipes-devtools | |
| parent | b691797f7768378a8caf36812312848add77377a (diff) | |
| download | meta-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>
Diffstat (limited to 'meta-oe/recipes-devtools')
| -rw-r--r-- | meta-oe/recipes-devtools/nodejs/nodejs/CVE-2022-43548.patch | 214 | ||||
| -rw-r--r-- | meta-oe/recipes-devtools/nodejs/nodejs_12.22.12.bb | 1 |
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 @@ | |||
| 1 | commit 2b433af094fb79cf80f086038b7f36342cb6826f | ||
| 2 | Author: Tobias Nießen <tniessen@tnie.de> | ||
| 3 | Date: 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 | |||
| 19 | CVE: CVE-2022-43548 | ||
| 20 | Upstream-Status: Backport [https://sources.debian.org/src/nodejs/12.22.12~dfsg-1~deb11u3/debian/patches/cve-2022-43548.patch] | ||
| 21 | Comment: No hunks refreshed | ||
| 22 | Signed-off-by: Poonam Jadhav <Poonam.Jadhav@kpit.com> | ||
| 23 | |||
| 24 | Index: 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 | |||
| 126 | Index: 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 | " |
| 28 | SRC_URI_append_class-target = " \ | 29 | SRC_URI_append_class-target = " \ |
| 29 | file://0002-Using-native-binaries.patch \ | 30 | file://0002-Using-native-binaries.patch \ |
