From d403eb69b2a231aac94835b7acd556c6c8c1e99c Mon Sep 17 00:00:00 2001 From: Jay Mundrawala Date: Tue, 21 May 2024 03:23:50 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Assume=20connection=20reset=20me?= =?UTF-8?q?ans=20the=20server=20rejects=20all=20ciphersuites?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When testing for supported ciphersuites, some servers fail the check with: ``` read: connection reset by peer ``` This seems to consistently happen on these servers. And it seems to happen on requests where the only ciphersuites in the `ClientHello` are unsupported ones --- .../network/resources/tlsshake/tlsshake.go | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/providers/network/resources/tlsshake/tlsshake.go b/providers/network/resources/tlsshake/tlsshake.go index 6d6440b18d..f2e554245e 100644 --- a/providers/network/resources/tlsshake/tlsshake.go +++ b/providers/network/resources/tlsshake/tlsshake.go @@ -17,6 +17,7 @@ import ( "net" "net/http" "strconv" + "strings" "sync" "time" @@ -285,21 +286,21 @@ func (s *Tester) parseAlert(data []byte, conf *ScanConfig) error { // version is unsupported or just its ciphers. So we check if we found // it previously and if so, don't add it to the list of unsupported // versions. + s.sync.Lock() if _, ok := s.Findings.Versions["ssl3"]; !ok { - s.sync.Lock() s.Findings.Versions["ssl3"] = false - s.sync.Unlock() } + s.sync.Unlock() } names := cipherNames(conf.version, conf.ciphersFilter) for i := range names { name := names[i] + s.sync.Lock() if _, ok := s.Findings.Ciphers[name]; !ok { - s.sync.Lock() s.Findings.Ciphers[name] = false - s.sync.Unlock() } + s.sync.Unlock() } default: @@ -476,8 +477,22 @@ func (s *Tester) parseHello(conn net.Conn, conf *ScanConfig) (bool, error) { for !done { _, err := io.ReadFull(reader, header) if err != nil { + hasConnectionReset := strings.Contains(err.Error(), "connection reset by peer") if err == io.EOF { break + } else if hasConnectionReset { + // If we get a connection reset, we assume the server doesn't support + // any of the ciphers we are testing. + names := cipherNames(conf.version, conf.ciphersFilter) + for i := range names { + name := names[i] + s.sync.Lock() + if _, ok := s.Findings.Ciphers[name]; !ok { + s.Findings.Ciphers[name] = false + } + s.sync.Unlock() + } + return false, nil } return false, err }