
golang.org/x/crypto/ssh में CVE-2026-46595 को प्रदर्शित करने वाला Go proof-of-concept, जो stripped binaries के symbol inspection और image scans का उपयोग करके vulnerable NewServerConn उपयोग को सत्यापित करता है।
https://www.cve.org/CVERecord?id=CVE-2026-46595 है https://pkg.go.dev/vuln/GO-2026-5023 golang.org/x/crypto/ssh NewServerConn सिंबल में एक भेद्यता जैसा कि दूसरे लिंक में उल्लेख किया गया है।
इस रेपो में एक सरल प्रोग्राम है जो एक सकारात्मक भेद्यता जाँच प्रदर्शित करता है।
एक न्यूनतम golang.org/x/crypto/ssh सर्वर जो x/crypto v0.51.0 (< v0.52.0) पर पिन किया गया है,
जिसका उपयोग यह प्रदर्शित करने के लिए किया जाता है कि अनस्ट्रिप्ड बाइनरीज़ पर go tool nm दोनों सकारात्मक और
नकारात्मक जाँच प्रदान करता है
go mod tidy
go build ./...
चूँकि हम भेद्य सिंबल जानते हैं, इसके लिए जाँच करें। अभी यह अनस्ट्रिप्ड बाइनरी है लेकिन हम इसे स्ट्रिप करेंगे ताकि सिंबल टेबल्स हटा दी जाएँ और साबित हो कि भेद्य सिंबल आउटपुट में बना रहता है।
file cve-2026-46595-proof
cve-2026-46595-proof: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=kUaZmGWICI6Buw0K_I7t/L4jXRd3fy2BJy8zNlSYd/lB1_6wYHZLaOLsG0tE26/-FieQlhThdl7AkRj7rl0, BuildID[sha1]=c7ac1dd881dfcaef88a2dd180a8ccb3c5e751e32, with debug_info, not stripped
strings cve-2026-46595-proof | grep golang.org/x/crypto/ssh.NewServerConn
golang.org/x/crypto/ssh.NewServerConn
# ok, now strip it and repeat
strip cve-2026-46595-proof
file cve-2026-46595-proof
cve-2026-46595-proof: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=kUaZmGWICI6Buw0K_I7t/L4jXRd3fy2BJy8zNlSYd/lB1_6wYHZLaOLsG0tE26/-FieQlhThdl7AkRj7rl0, BuildID[sha1]=c7ac1dd881dfcaef88a2dd180a8ccb3c5e751e32, stripped
strings cve-2026-46595-proof | grep -E 'ssh\.(Dial|NewServerConn|NewClientConn|NewControlClientConn)'
golang.org/x/crypto/ssh.NewServerConn
अब, आइए OpenShift पेलोड इमेज में शिप किए गए बाइनरीज़ की जाँच करें।
इमेज से /usr/bin निकालें। --only-files आवश्यक है, अन्यथा oc image extract
लेयर के बीच में निकलते समय /usr/bin/ld.so जैसे सिमलिंक पर पहुँचकर रुक जाता है।
IMG=quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:b4dde8227fb99134f71b50f0707eb7f695cfade43b017da3cbc486c2db854fe1
mkdir -p /tmp/cveimg
oc image extract "$IMG" --path /usr/bin/:/tmp/cveimg/ --only-files
ls -laS /tmp/cveimg | head
इस डाइजेस्ट के लिए यह 4.21 cluster-config-operator इमेज है:
-rw-r-----. 1 sdodson sdodson 117899168 Feb 24 2026 cluster-config-operator
-rw-r-----. 1 sdodson sdodson 10639741 Feb 24 2026 cluster-config-operator-tests-ext.gz
देखें कि यह x/crypto के किस संस्करण के विरुद्ध बनाया गया था:
$ go version -m /tmp/cveimg/cluster-config-operator | grep -E 'go1|x/crypto'
/tmp/cveimg/cluster-config-operator: go1.24.13 (Red Hat 1.24.13-1.el9_6) X:strictfipsruntime
dep golang.org/x/crypto v0.40.0
v0.40.0 हर फिक्स्ड संस्करण से नीचे है, इसलिए मॉड्यूल-संस्करण स्कैनर इसे फ्लैग करते हैं। अब सिंबल जाँच लागू करें। GO-2026-5023 के अलावा golang.org/x/crypto की अन्य भेद्यताएँ भी हैं जो v0.55.0 और v0.56.0 में फिक्स की गई हैं, इसलिए उनके सभी भेद्य सिंबल्स को एक साथ जाँचें:
GO-2026-5023 => ssh.NewServerConn GO-2026-6303 => ssh.NewServerConn फिर से GO-2026-6354 => ssh.Dial ssh.NewClientConn ssh.NewControlClientConn ssh.NewServerConn GO-2026-6355 => ssh.Dial ssh.NewClientConn ssh.NewControlClientConn ssh.NewServerConn
tests-ext बाइनरी gzipped शिप होती है, इसलिए पहले इसे डीकंप्रेस करें और दोनों की जाँच करें:
gzip -dc /tmp/cveimg/cluster-config-operator-tests-ext.gz > /tmp/cveimg/cluster-config-operator-tests-ext
strings /tmp/cveimg/cluster-config-operator{,-tests-ext} \
| grep -E 'ssh\.(Dial|NewServerConn|NewClientConn|NewControlClientConn)'
कोई आउटपुट नहीं, वाह कोई भेद्यता नहीं! सैनिटी चेक करें कि grep किसी उबाऊ कारण से चुप नहीं है जैसे कि मैच करने के लिए कोई सिंबल ही न हो:
$ go tool nm /tmp/cveimg/cluster-config-operator | wc -l
150240
$ go tool nm /tmp/cveimg/cluster-config-operator | grep -c golang.org/x/crypto/ssh
0
$ go tool nm /tmp/cveimg/cluster-config-operator-tests-ext | wc -l
24607
$ go tool nm /tmp/cveimg/cluster-config-operator-tests-ext | grep -c golang.org/x/crypto
39
तो x/crypto वास्तव में लिंक किया गया है, लिंकर ने बस पूरे x/crypto/ssh को हटा दिया क्योंकि
कोई भी उस तक नहीं पहुँचता।
यह अन्य पेलोड इमेजों में भी दोहराने योग्य होना चाहिए; प्रति-इमेज एकमात्र भिन्नता यह है कि
बाइनरीज़ कहाँ रहती हैं और क्या वे ऊपर दिए गए -tests-ext.gz की तरह कंप्रेस्ड हैं।
ध्यान दें कि *-tests-ext जैसी टेस्ट बाइनरीज़ इमेजों में शिप की जाती हैं भले ही वे
किसी निष्पादन पथ पर न हों। जहाँ वे x/crypto/ssh को शामिल करती हैं (kubernetes की k8s-tests-ext
अपने e2e SSH हेल्पर्स के लिए ssh.NewClientConn लिंक करती है) वहाँ भी यह चल रहे कंपोनेंट के
निष्पादन पथ से बाहर है। फिर भी हम इमेजों से टेस्ट बाइनरीज़ को हटाने पर काम करेंगे क्योंकि वे
उन्हें बड़ा बनाती हैं और इमेज पुल जैसी चीज़ों को धीमा करती हैं।
निम्नलिखित Claude द्वारा सकारात्मक टेस्ट केस बाइनरीज़ बनाते समय उत्पन्न किया गया था, प्रमाण के लिए आवश्यक नहीं है लेकिन मैंने इसे छोड़ दिया है।
भेद्यता के अस्तित्व को साबित करने के लिए यह आवश्यक नहीं है, ऊपर वाला पहले ही यह प्रदर्शित कर चुका है लेकिन बेझिझक यह भी करें।
go run . -addr 127.0.0.1:2222 -user demo -password demo
फिर, दूसरे टर्मिनल में:
ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected]
पासवर्ड demo है। सेशन एक अभिवादन प्रिंट करता है और इनपुट को वापस इको करता है।
हर बार शुरू होने पर एक नई ed25519 होस्ट की जनरेट होती है, इसलिए डिस्क पर कुछ नहीं लिखा जाता।
v0.51.0 पर, govulncheck golang.org/x/crypto/ssh में 10 पहुँचने योग्य भेद्यताएँ रिपोर्ट करता है,
सभी main.go → ssh.NewServerConn के माध्यम से ट्रेस की गईं (GO-2026-5018 भी
ssh.NewSignerFromKey के माध्यम से ट्रेस होता है)।
go get golang.org/x/[email protected]
go mod tidy
govulncheck ./...
v0.52.0 उनमें से अधिकांश को साफ़ कर देता है, लेकिन तीन को नए रिलीज़ चाहिए: GO-2026-6303 v0.55.0 में फिक्स होता है, और GO-2026-6354 / GO-2026-6355 v0.56.0 में। v0.56.0 पर स्कैनिंग साफ़ आनी चाहिए।