mirror of
https://git.yoctoproject.org/poky
synced 2026-01-29 21:08:42 +01:00
go: Fix CVE-2025-61729
Upstream-Status: Backport from 3a842bd5c6
(From OE-Core rev: 2d6d68e46a430a1dbba7bd8b7d37ff56f4f5a0e6)
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
This commit is contained in:
committed by
Steve Sakoman
parent
d3c87dc830
commit
795103a538
@@ -30,6 +30,7 @@ SRC_URI += "\
|
|||||||
file://CVE-2025-61723.patch \
|
file://CVE-2025-61723.patch \
|
||||||
file://CVE-2025-61724.patch \
|
file://CVE-2025-61724.patch \
|
||||||
file://CVE-2025-61727.patch \
|
file://CVE-2025-61727.patch \
|
||||||
|
file://CVE-2025-61729.patch \
|
||||||
"
|
"
|
||||||
SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
|
SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
|
||||||
|
|
||||||
|
|||||||
174
meta/recipes-devtools/go/go/CVE-2025-61729.patch
Normal file
174
meta/recipes-devtools/go/go/CVE-2025-61729.patch
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
From 3a842bd5c6aa8eefa13c0174de3ab361e50bd672 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Nicholas S. Husin" <nsh@golang.org>
|
||||||
|
Date: Mon, 24 Nov 2025 14:56:23 -0500
|
||||||
|
Subject: [PATCH] [release-branch.go1.24] crypto/x509: prevent
|
||||||
|
HostnameError.Error() from consuming excessive resource
|
||||||
|
|
||||||
|
Constructing HostnameError.Error() takes O(N^2) runtime due to using a
|
||||||
|
string concatenation in a loop. Additionally, there is no limit on how
|
||||||
|
many names are included in the error message. As a result, a malicious
|
||||||
|
attacker could craft a certificate with an infinite amount of names to
|
||||||
|
unfairly consume resource.
|
||||||
|
|
||||||
|
To remediate this, we will now use strings.Builder to construct the
|
||||||
|
error message, preventing O(N^2) runtime. When a certificate has 100 or
|
||||||
|
more names, we will also not print each name individually.
|
||||||
|
|
||||||
|
Thanks to Philippe Antoine (Catena cyber) for reporting this issue.
|
||||||
|
|
||||||
|
Updates #76445
|
||||||
|
Fixes #76460
|
||||||
|
Fixes CVE-2025-61729
|
||||||
|
|
||||||
|
Change-Id: I6343776ec3289577abc76dad71766c491c1a7c81
|
||||||
|
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3000
|
||||||
|
Reviewed-by: Neal Patel <nealpatel@google.com>
|
||||||
|
Reviewed-by: Damien Neil <dneil@google.com>
|
||||||
|
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3220
|
||||||
|
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||||
|
Reviewed-on: https://go-review.googlesource.com/c/go/+/725820
|
||||||
|
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||||
|
TryBot-Bypass: Dmitri Shuralyov <dmitshur@golang.org>
|
||||||
|
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
|
||||||
|
Reviewed-by: Mark Freeman <markfreeman@google.com>
|
||||||
|
|
||||||
|
Upstream-Status: Backport [https://github.com/golang/go/commit/3a842bd5c6aa8eefa13c0174de3ab361e50bd672]
|
||||||
|
CVE: CVE-2025-61729
|
||||||
|
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||||
|
---
|
||||||
|
src/crypto/x509/verify.go | 21 ++++++++++-----
|
||||||
|
src/crypto/x509/verify_test.go | 47 ++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 61 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
|
||||||
|
index 3fdf65f..0ae8aef 100644
|
||||||
|
--- a/src/crypto/x509/verify.go
|
||||||
|
+++ b/src/crypto/x509/verify.go
|
||||||
|
@@ -100,31 +100,38 @@ type HostnameError struct {
|
||||||
|
|
||||||
|
func (h HostnameError) Error() string {
|
||||||
|
c := h.Certificate
|
||||||
|
+ maxNamesIncluded := 100
|
||||||
|
|
||||||
|
if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) {
|
||||||
|
return "x509: certificate relies on legacy Common Name field, use SANs instead"
|
||||||
|
}
|
||||||
|
|
||||||
|
- var valid string
|
||||||
|
+ var valid strings.Builder
|
||||||
|
if ip := net.ParseIP(h.Host); ip != nil {
|
||||||
|
// Trying to validate an IP
|
||||||
|
if len(c.IPAddresses) == 0 {
|
||||||
|
return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
|
||||||
|
}
|
||||||
|
+ if len(c.IPAddresses) >= maxNamesIncluded {
|
||||||
|
+ return fmt.Sprintf("x509: certificate is valid for %d IP SANs, but none matched %s", len(c.IPAddresses), h.Host)
|
||||||
|
+ }
|
||||||
|
for _, san := range c.IPAddresses {
|
||||||
|
- if len(valid) > 0 {
|
||||||
|
- valid += ", "
|
||||||
|
+ if valid.Len() > 0 {
|
||||||
|
+ valid.WriteString(", ")
|
||||||
|
}
|
||||||
|
- valid += san.String()
|
||||||
|
+ valid.WriteString(san.String())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
- valid = strings.Join(c.DNSNames, ", ")
|
||||||
|
+ if len(c.DNSNames) >= maxNamesIncluded {
|
||||||
|
+ return fmt.Sprintf("x509: certificate is valid for %d names, but none matched %s", len(c.DNSNames), h.Host)
|
||||||
|
+ }
|
||||||
|
+ valid.WriteString(strings.Join(c.DNSNames, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
- if len(valid) == 0 {
|
||||||
|
+ if valid.Len() == 0 {
|
||||||
|
return "x509: certificate is not valid for any names, but wanted to match " + h.Host
|
||||||
|
}
|
||||||
|
- return "x509: certificate is valid for " + valid + ", not " + h.Host
|
||||||
|
+ return "x509: certificate is valid for " + valid.String() + ", not " + h.Host
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnknownAuthorityError results when the certificate issuer is unknown
|
||||||
|
diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
|
||||||
|
index df9b0a2..223c250 100644
|
||||||
|
--- a/src/crypto/x509/verify_test.go
|
||||||
|
+++ b/src/crypto/x509/verify_test.go
|
||||||
|
@@ -10,13 +10,16 @@ import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/rand"
|
||||||
|
+ "crypto/rsa"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/asn1"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"internal/testenv"
|
||||||
|
+ "log"
|
||||||
|
"math/big"
|
||||||
|
+ "net"
|
||||||
|
"os/exec"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
@@ -89,6 +92,26 @@ var verifyTests = []verifyTest{
|
||||||
|
|
||||||
|
errorCallback: expectHostnameError("certificate is valid for"),
|
||||||
|
},
|
||||||
|
+ {
|
||||||
|
+ name: "TooManyDNS",
|
||||||
|
+ leaf: generatePEMCertWithRepeatSAN(1677615892, 200, "fake.dns"),
|
||||||
|
+ roots: []string{generatePEMCertWithRepeatSAN(1677615892, 200, "fake.dns")},
|
||||||
|
+ currentTime: 1677615892,
|
||||||
|
+ dnsName: "www.example.com",
|
||||||
|
+ systemSkip: true, // does not chain to a system root
|
||||||
|
+
|
||||||
|
+ errorCallback: expectHostnameError("certificate is valid for 200 names, but none matched"),
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ name: "TooManyIPs",
|
||||||
|
+ leaf: generatePEMCertWithRepeatSAN(1677615892, 150, "4.3.2.1"),
|
||||||
|
+ roots: []string{generatePEMCertWithRepeatSAN(1677615892, 150, "4.3.2.1")},
|
||||||
|
+ currentTime: 1677615892,
|
||||||
|
+ dnsName: "1.2.3.4",
|
||||||
|
+ systemSkip: true, // does not chain to a system root
|
||||||
|
+
|
||||||
|
+ errorCallback: expectHostnameError("certificate is valid for 150 IP SANs, but none matched"),
|
||||||
|
+ },
|
||||||
|
{
|
||||||
|
name: "IPMissing",
|
||||||
|
leaf: googleLeaf,
|
||||||
|
@@ -595,6 +618,30 @@ func nameToKey(name *pkix.Name) string {
|
||||||
|
return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
|
||||||
|
}
|
||||||
|
|
||||||
|
+func generatePEMCertWithRepeatSAN(currentTime int64, count int, san string) string {
|
||||||
|
+ cert := Certificate{
|
||||||
|
+ NotBefore: time.Unix(currentTime, 0),
|
||||||
|
+ NotAfter: time.Unix(currentTime, 0),
|
||||||
|
+ }
|
||||||
|
+ if ip := net.ParseIP(san); ip != nil {
|
||||||
|
+ cert.IPAddresses = slices.Repeat([]net.IP{ip}, count)
|
||||||
|
+ } else {
|
||||||
|
+ cert.DNSNames = slices.Repeat([]string{san}, count)
|
||||||
|
+ }
|
||||||
|
+ privKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||||
|
+ if err != nil {
|
||||||
|
+ log.Fatal(err)
|
||||||
|
+ }
|
||||||
|
+ certBytes, err := CreateCertificate(rand.Reader, &cert, &cert, &privKey.PublicKey, privKey)
|
||||||
|
+ if err != nil {
|
||||||
|
+ log.Fatal(err)
|
||||||
|
+ }
|
||||||
|
+ return string(pem.EncodeToMemory(&pem.Block{
|
||||||
|
+ Type: "CERTIFICATE",
|
||||||
|
+ Bytes: certBytes,
|
||||||
|
+ }))
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
const gtsIntermediate = `-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFljCCA36gAwIBAgINAgO8U1lrNMcY9QFQZjANBgkqhkiG9w0BAQsFADBHMQsw
|
||||||
|
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
Reference in New Issue
Block a user