Skip to content

Commit 5153baf

Browse files
ivgfujita
authored andcommitted
pkg/packet/mrt: fix parser to check the input length
1 func (m *BGP4MPHeader) decodeFromBytes(data []byte) ([]byte, error) { 2 if m.isAS4 && len(data) < 8 { 3 return nil, errors.New("not all BGP4MPMessageAS4 bytes available") 4 } else if !m.isAS4 && len(data) < 4 { 5 return nil, errors.New("not all BGP4MPMessageAS bytes available") 6 } 7 8 if m.isAS4 { 9 m.PeerAS = binary.BigEndian.Uint32(data[:4]) 10 m.LocalAS = binary.BigEndian.Uint32(data[4:8]) 11 data = data[8:] 12 } else { 13 m.PeerAS = uint32(binary.BigEndian.Uint16(data[:2])) 14 m.LocalAS = uint32(binary.BigEndian.Uint16(data[2:4])) 15 data = data[4:] 16 } 17 m.InterfaceIndex = binary.BigEndian.Uint16(data[:2]) 18 m.AddressFamily = binary.BigEndian.Uint16(data[2:4]) 19 switch m.AddressFamily { 20 case bgp.AFI_IP: 21 m.PeerIpAddress = net.IP(data[4:8]).To4() 22 m.LocalIpAddress = net.IP(data[8:12]).To4() 23 data = data[12:] 24 case bgp.AFI_IP6: 25 m.PeerIpAddress = net.IP(data[4:20]) 26 m.LocalIpAddress = net.IP(data[20:36]) 27 data = data[36:] 28 default: 29 return nil, fmt.Errorf("unsupported address family: %d", m.AddressFamily) 30 } 31 return data, nil 32 } The check at lines 2-6 is sufficient only to safely extract `PeerAS` and `LocalAS`, after that slice is rebound to the leftover bytes, i.e., the length of the slice is not 8 or 4 bytes less, depending on the it is AS4 or not. That means that it could be empty, therefore any line beyond 16 is vulnerable. E.g., we need to check for at least 4 bytes for lines 17 and 18, and then depending on the address family, for 12 or 36 bytes.
1 parent 56e6b10 commit 5153baf

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

Diff for: pkg/packet/mrt/mrt.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -677,9 +677,9 @@ type BGP4MPHeader struct {
677677
}
678678

679679
func (m *BGP4MPHeader) decodeFromBytes(data []byte) ([]byte, error) {
680-
if m.isAS4 && len(data) < 8 {
680+
if m.isAS4 && len(data) < 12 {
681681
return nil, errors.New("not all BGP4MPMessageAS4 bytes available")
682-
} else if !m.isAS4 && len(data) < 4 {
682+
} else if !m.isAS4 && len(data) < 8 {
683683
return nil, errors.New("not all BGP4MPMessageAS bytes available")
684684
}
685685

@@ -696,10 +696,16 @@ func (m *BGP4MPHeader) decodeFromBytes(data []byte) ([]byte, error) {
696696
m.AddressFamily = binary.BigEndian.Uint16(data[2:4])
697697
switch m.AddressFamily {
698698
case bgp.AFI_IP:
699+
if len(data) < 12 {
700+
return nil, errors.New("not all IPv4 peer bytes available")
701+
}
699702
m.PeerIpAddress = net.IP(data[4:8]).To4()
700703
m.LocalIpAddress = net.IP(data[8:12]).To4()
701704
data = data[12:]
702705
case bgp.AFI_IP6:
706+
if len(data) < 36 {
707+
return nil, errors.New("not all IPv6 peer bytes available")
708+
}
703709
m.PeerIpAddress = net.IP(data[4:20])
704710
m.LocalIpAddress = net.IP(data[20:36])
705711
data = data[36:]

0 commit comments

Comments
 (0)