fix: prevent indefinite hangs in TLS handshake and cipher enumeration#933
fix: prevent indefinite hangs in TLS handshake and cipher enumeration#933Bushi-gg wants to merge 3 commits intoprojectdiscovery:devfrom
Conversation
- Wrap pool.Acquire() with the same timeout context so connection pool acquisition cannot hang indefinitely on unresponsive hosts - Clone baseCfg per cipher iteration to prevent concurrent mutation of the shared CipherSuites slice - Applied consistently to both tls.go and ztls.go EnumerateCiphers
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Neo Security AuditNo security issues found Highlights
Hardening Notes
Comment |
45bad36 to
6477c2a
Compare
|
Hi, thanks for your interest in contributing! Just a heads up, we ask contributors to work on 1 active issue at a time (see). Also, we welcome AI-assisted development, but submissions must be complete, tested, and ready to merge. Please also make sure to fill out the PR template with proof that your changes work. We're closing this PR along with your other open submissions. Once you're ready, feel free to pick one issue to focus on and resubmit; we'd be happy to review it. Appreciate your understanding! |
Fixes #819
What's happening
tlsxhangs indefinitely on certain hosts during cipher enumeration. I traced it to a few things:tlsHandshakeWithTimeoutdoesn't actually time out (ztls.go)The select runs
Handshake()inline as the case expression, so if it blocks, the timeout case is never reached:Moved
Handshake()into a goroutine so the select can actually fire onctx.Done(). On timeout,tlsConn.Close()unblocks the goroutine.context.TODO()passed to the handshake (ztls.go)Even with the select fix,
EnumerateCipherswas passingcontext.TODO()which never cancels. Replaced with acontext.WithTimeoutper cipher iteration usingoptions.Timeout.No timeout at all in ctls path (tls.go)
The crypto/tls
EnumerateCipherscalledconn.Handshake()directly — no context, no timeout. Switched toconn.HandshakeContext(ctx)with the same per-iteration timeout.pool.Acquirehangs on unresponsive hostsBoth
EnumerateCipherspaths calledpool.Acquire(context.Background()), which can also block indefinitely if the host accepts TCP but stalls. Now uses the same timeout context for pool acquisition.Config mutation across loop iterations
baseCfg.CipherSuiteswas mutated in-place each iteration. AddedbaseCfg.Clone()per iteration to avoid sharing state.Both cipher enumeration paths include a guard for zero/negative timeout values — falls back to a cancelable context instead of failing immediately.
Files changed
pkg/tlsx/ztls/ztls.go— fix select, replace context.TODO, pool.Acquire timeout, config clonepkg/tlsx/tls/tls.go— HandshakeContext, pool.Acquire timeout, config clonepkg/tlsx/ztls/ztls_test.go— regression test with a TCP server that never respondsTest
The test starts a TCP listener that accepts but never sends data (simulating the hung handshake from #819). Before the fix it blocks forever. After the fix it returns within the configured timeout.
Checklist
dev)