Only allow IPv4 literals in strict form (#18656)

* Only allow IPv4 literals in strict form

The strict form as defined in RFC 6943, section 3.1.1 only allows the dotted
form ddd.ddd.ddd.ddd of IPv4 literals, where ddd is a one to three digit decimal
number between 0 and 255. Until now octal numbers (with a leading zero) were
interpreted as decimal numbers which has security implications, see
CVE-2021-29922 and CVE-2021-29923.

* Update lib/pure/net.nim

Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>
This commit is contained in:
Christian Ulrich 2021-08-08 20:11:07 +02:00 • committed by GitHub
commit 0d3af5454b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 106 additions and 44 deletions

View file

@ -281,14 +281,20 @@ proc parseIPv4Address(addressStr: string): IpAddress =
byteCount = 0
currentByte: uint16 = 0
separatorValid = false
leadingZero = false
result = IpAddress(family: IpAddressFamily.IPv4)
for i in 0 .. high(addressStr):
if addressStr[i] in strutils.Digits: # Character is a number
if leadingZero:
raise newException(ValueError,
"Invalid IP address. Octal numbers are not allowed")
currentByte = currentByte * 10 +
cast[uint16](ord(addressStr[i]) - ord('0'))
if currentByte > 255'u16:
if currentByte == 0'u16:
leadingZero = true
elif currentByte > 255'u16:
raise newException(ValueError,
"Invalid IP Address. Value is out of range")
separatorValid = true
@ -300,6 +306,7 @@ proc parseIPv4Address(addressStr: string): IpAddress =
currentByte = 0
byteCount.inc
separatorValid = false
leadingZero = false
else:
raise newException(ValueError,
"Invalid IP Address. Address contains an invalid character")
@ -388,10 +395,16 @@ proc parseIPv6Address(addressStr: string): IpAddress =
result.address_v6[groupCount*2+1] = cast[uint8](currentShort and 0xFF)
groupCount.inc()
else: # Must parse IPv4 address
var leadingZero = false
for i, c in addressStr[v4StartPos..high(addressStr)]:
if c in strutils.Digits: # Character is a number
if leadingZero:
raise newException(ValueError,
"Invalid IP address. Octal numbers not allowed")
currentShort = currentShort * 10 + cast[uint32](ord(c) - ord('0'))
if currentShort > 255'u32:
if currentShort == 0'u32:
leadingZero = true
elif currentShort > 255'u32:
raise newException(ValueError,
"Invalid IP Address. Value is out of range")
separatorValid = true
@ -402,6 +415,7 @@ proc parseIPv6Address(addressStr: string): IpAddress =
currentShort = 0
byteCount.inc()
separatorValid = false
leadingZero = false
else: # Invalid character
raise newException(ValueError,
"Invalid IP Address. Address contains an invalid character")
@ -431,7 +445,12 @@ proc parseIPv6Address(addressStr: string): IpAddress =
proc parseIpAddress*(addressStr: string): IpAddress =
## Parses an IP address
## Raises ValueError on error
##
## Raises ValueError on error.
##
## For IPv4 addresses, only the strict form as
## defined in RFC 6943 is considered valid, see
## https://datatracker.ietf.org/doc/html/rfc6943#section-3.1.1.
if addressStr.len == 0:
raise newException(ValueError, "IP Address string is empty")
if addressStr.contains(':'):