先来看一个例子,对于 0177.0.0.1 这个 IP 地址不同的程序会解析出不同的结果:
curl
curl 0177.0.0.1 -v * Rebuilt URL to: 0177.0.0.1/ * Trying 177.0.0.1... * TCP_NODELAY set
ping
$ ping 0177.0.0.1 PING 0177.0.0.1 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.059 ms 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.084 ms ^C
可以看到,对于 0177.0.0.1 这个 IP 地址, curl 将它解析为 177.0.0.1 ,而 ping 却解析为了 127.0.0.1 。
之所以会有这种不一样的结果,是因为对于应该如何解析 IP 地址中数字前面的 0 并没有一个统一的标准, 有的程序将这种情况标记为无效 IP ,有些程序将 0xx 解析为 8 进制数字,有些程序将它解析为 10 进制数字。
正因为存在这种不统一的情况,也就导致应用程序对 IP 地址的校验逻辑存在安全隐患。
假设有一个服务的功能是访问用户输入的地址然后返回相应的响应信息,处于安全上的考虑, 会校验用户的输入,拦截访问服务内部 IP 的地址:
- 用户输入 http://0177.0.0.1:8080/path/to/secret
- 服务端的校验程序使用的 IP 解析库将地址中包含的 IP 地址解析为 177.0.0.1 ,然后放行了该请求
- 实际执行这个请求用户输入的服务,在请求这个地址时,使用的 IP 地址相关库将它解析为了 127.0.0.1 , 此时就会存在安全隐患,导致出现了非预期的结果。
基于 IP 黑名单的 ACL 或者过滤逻辑都有潜在的受这个问题影响的安全隐患, 这一问题的相关 CVE 可以参考【参考资料】中列出的部分 CVE 。
参考资料¶
- CVE-2021-29921 - python stdlib "ipaddress" - Improper Input Validation of octal literals in python 3.8.0 thru v3.10 results in indeterminate SSRF & RFI vulnerabilities. - "ipaddress leading zeros in IPv4 address" - Sick Codes - Security Research, Hardware & Software Hacking, Consulting, Linux, IoT, Cloud, Embedded, Arch, Tweaks & Tips!
- CVE-2021-29922 - rust standard library "net" - Improper Input Validation of octal literals in rust 1.52.0 std::net and below results in indeterminate SSRF & RFI vulnerabilities. - Sick Codes - Security Research, Hardware & Software Hacking, Consulting, Linux, IoT, Cloud, Embedded, Arch, Tweaks & Tips!
- CVE-2021-29923 - golang standard library "net" - Improper Input Validation of octal literals in golang 1.16.2 and below standard library "net" results in indeterminate SSRF & RFI vulnerabilities. - Sick Codes - Security Research, Hardware & Software Hacking, Consulting, Linux, IoT, Cloud, Embedded, Arch, Tweaks & Tips!
- CVE-2021-33571 – In Django 2.2 before 2.2.24, 3.x before 3.1.12, and 3.2 before 3.2.4, URLValidator, validate_ipv4_address, and validate_ipv46_address do not prohibit leading zero characters in octal literals. This may allow a bypass of access control that is based on IP addresses. (validate_ipv4_address and validate_ipv46_address are unaffected with Python 3.9.5+..) .
- CVE-2019-12161 – CVE-2019-12161 WPO WebPageTest 19.04 allows SSRF because ValidateURL in www/runtest.php does not consider octal encoding of IP addresses (such as 0300.0250 as a replacement for 192.168).
- CVE-2016-4029 – WordPress before 4.5 does not consider octal and hexadecimal IP address formats when determining an intranet address, which allows remote attackers to bypass an intended SSRF protection mechanism via a crafted address.
- Issue 36384: [security] CVE-2021-29921: ipaddress Should not reject IPv4 addresses with leading zeroes as ambiguously octal - Python tracker
- net: reject leading zeros in IP address parsers [freeze exception] · Issue #30999 · golang/go
- cve-2020-28360 - John J Hacking
- Universal "netmask" npm package, used by 270,000+ projects, vulnerable to octal input data: server-side request forgery, remote file inclusion, local file inclusion, and more (CVE-2021-28918) - Sick Codes - Security Research, Hardware & Software Hacking, Consulting, Linux, IoT, Cloud, Embedded, Arch, Tweaks & Tips!
Comments