mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Use cryptographic hash functions for TCP
gVisor used to use jenkins for generating initial sequence number and timestamp offset. Since it is not a cryptographic hash function and easily reversible, it can cause security concerns. Replaced it with sha256 which is a secure hash function. Discovered by Inon Kaplan (PhD candidate in the Hebrew University School of Computer Science and Engineering), Ron Even (BSc graduate of Bar Ilan University) and Amit Klein (faculty member in the Hebrew University School of Computer Science and Engineering). Details will be provided in their paper, to be presented in a forthcoming academic conference. Fixes #6473 PiperOrigin-RevId: 584211221
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
@@ -23,7 +24,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/checksum"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/hash/jenkins"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/seqnum"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
@@ -236,10 +236,14 @@ func (h *handshake) resetState() {
|
||||
// generateSecureISN generates a secure Initial Sequence number based on the
|
||||
// recommendation here https://tools.ietf.org/html/rfc6528#page-3.
|
||||
func generateSecureISN(id stack.TransportEndpointID, clock tcpip.Clock, seed uint32) seqnum.Value {
|
||||
isnHasher := jenkins.Sum32(seed)
|
||||
isnHasher := sha256.New()
|
||||
|
||||
seedBuf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(seedBuf, seed)
|
||||
// Per hash.Hash.Writer:
|
||||
//
|
||||
// It never returns an error.
|
||||
_, _ = isnHasher.Write(seedBuf)
|
||||
_, _ = isnHasher.Write(id.LocalAddress.AsSlice())
|
||||
_, _ = isnHasher.Write(id.RemoteAddress.AsSlice())
|
||||
portBuf := make([]byte, 2)
|
||||
@@ -257,7 +261,8 @@ func generateSecureISN(id stack.TransportEndpointID, clock tcpip.Clock, seed uin
|
||||
//
|
||||
// Which sort of guarantees that we won't reuse the ISN for a new
|
||||
// connection for the same tuple for at least 274s.
|
||||
isn := isnHasher.Sum32() + uint32(clock.NowMonotonic().Sub(tcpip.MonotonicTime{}).Nanoseconds()>>6)
|
||||
hash := binary.LittleEndian.Uint32(isnHasher.Sum(nil)[:4])
|
||||
isn := hash + uint32(clock.NowMonotonic().Sub(tcpip.MonotonicTime{}).Nanoseconds()>>6)
|
||||
return seqnum.Value(isn)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/hash/jenkins"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header/parse"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/internal/tcp"
|
||||
@@ -178,16 +179,17 @@ func (p *protocol) tsOffset(src, dst tcpip.Address) tcp.TSOffset {
|
||||
//
|
||||
// See https://tools.ietf.org/html/rfc7323#section-5.4 for details on
|
||||
// why this is required.
|
||||
//
|
||||
// TODO(https://gvisor.dev/issues/6473): This is not really secure as
|
||||
// it does not use the recommended algorithm linked above.
|
||||
h := jenkins.Sum32(p.tsOffsetSecret)
|
||||
h := sha256.New()
|
||||
|
||||
secretBuf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(secretBuf, p.tsOffsetSecret)
|
||||
// Per hash.Hash.Writer:
|
||||
//
|
||||
// It never returns an error.
|
||||
_, _ = h.Write(secretBuf)
|
||||
_, _ = h.Write(src.AsSlice())
|
||||
_, _ = h.Write(dst.AsSlice())
|
||||
return tcp.NewTSOffset(h.Sum32())
|
||||
return tcp.NewTSOffset(binary.LittleEndian.Uint32(h.Sum(nil)[:4]))
|
||||
}
|
||||
|
||||
// replyWithReset replies to the given segment with a reset segment.
|
||||
|
||||
Reference in New Issue
Block a user