-
-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[security] CVE-2021-29921: ipaddress Should not reject IPv4 addresses with leading zeroes as ambiguously octal #80565
Comments
I understand to a certain extent the logic in not allowing IPv4 octets that might ambiguously be octal, but in practice, it just seems like it creates additional parsing hassle needlessly. I have never in many years of working on many networked systems seen anyone use dotted octal format, it is actually specifically forbidden by RFC 3986 (https://tools.ietf.org/html/rfc3986#section-7.4), and it means that the ipaddress module throws exceptions on many perfectly valid IP addresses just because they have leading zeroes. Since the module doesn't support dotted octal or dotted hex anyway, this check seems a little pointless. If nothing else, there should be a way to disable this check by specifying that your IPs are in fact dotted decimal, otherwise it seems like it's just making you have to do extra parsing work or just write your own implementation. |
I agree that this is not a useful check. |
I've merged the change for Python 3.8 (thanks Joel!). I'm not sure whether to classify it as an enhancement or as an interoperability bug fix, though, so I've put the status to pending and added Ned to the nosy list to get his thoughts as the Python 3.7 RM. |
ipaddress is behaving as documented: "The following constitutes a valid IPv4 address: A string in decimal-dot notation, consisting of four decimal integers in the inclusive range 0–255, separated by dots (e.g. 192.168.0.1). Each integer represents an octet (byte) in the address. Leading zeroes are tolerated only for values less than 8 (as there is no ambiguity between the decimal and octal interpretations of such strings). [...]" https://docs.python.org/3/library/ipaddress.html I can sort of understand imposing that restriction in a Python 2 world where leading zeros implied octal and Python 3 outright rejects such forms of integers to avoid the ambiguity. That said, there's no particular reason why the components of an IPv4 string acceptable to ipaddress *have* to follow the same rules so I'm +0 on making the change at all. It's a bit of a stretch to consider it a bug when it appears to be behaving as documented but I would expect such a change to fix more problems than causing them so I'm OK if you want to backport it. But, in any case, the documentation for 3.8 and/or 3.7 needs to be updated. |
See also the article "Ping and FTP Resolve IP Address with Leading Zero as Octal" (https://web.archive.org/web/20061206211851/http://support.microsoft.com/kb/115388). This is still true in Windows 10. So it is safer to reject IPv4 addresses with leading zeros that can be ambiguously interpreted. Otherwise this can create a security hole. |
I think it should be 3.8 only, and the docs should be updated. Apologies for not catching that earlier: I searched via Google, which was a mistake. |
The recommended handling in the article that Serhiy mentions is to strip the leading zeroes, which the ipaddress module will still do - it's only being made more tolerant on input. That means it will become usable as a prefilter step (pass string with potentially leading zeroes to ipaddress, get string with no leading zeroes out). So that means the one part we missed is the docs update (together with a versionchanged note in the module docs themselves) |
Serhiy was right, this is a security issue. The patch should not have landed in 3.8. At a bare minimum the patch should have been postponed until documentation was updated. Since 3.8 the ipaddresss does not behave as documented. A similar security issue in NPM was published two days ago, CVE-2021-28918. I proposed to not only revert the change, but also tighten the check for leading zeros so it behaves like glibc's inet_pton(). It refuses any IPv4 string with a leading zero. >>> socket.inet_pton(socket.AF_INET, "01.1.1.1")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: illegal IP address string passed to inet_pton
>>> socket.inet_pton(socket.AF_INET, "1.1.1.01")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: illegal IP address string passed to inet_pton |
|
Deferred the blocker to the next regular release due to lack of activity in time for the current expedited releases. |
(Copied from my comment on the PR, following the one where I said this was ready to go.) Withdrawing the readiness - @ambv and I would prefer to see this behind a flag (probably "strict" parsing), on by default for 3.10, and maybe on by default for 3.9/earlier. The main reasoning being that this isn't our vulnerability, but an inconsistency with other vulnerable libraries. The current fix is the best it can be, but it doesn't prevent the vulnerability, it just causes Python to break first. So it ought to be relatively easy to retain the flexible (though admittedly non-sensical) behaviour for those who currently rely on it. |
Łukasz, thanks for pushing the PR over the finish line! |
Is there anything more to be done for this issue or can it be closed? |
I'm closing this, if someone thinks something is missing, please, reopen |
I created https://python-security.readthedocs.io/vuln/ipaddress-ipv4-leading-zeros.html to track this vulnerability. Python 3.8 is left unchanged (accept leading zeros). Python 3.7 and older are not affected. |
The timeline there is wrong. This issue's creation time isn't the disclosure time, it's when the bug was introduced. The disclosure was on 30th of May, when I emailed security@python.org and Christian Heimes commented here and made #25099. Even though Serhiy Storchaka commented that this could be a security issue back when the issue was new, the date would be 30th of March 2019, not 20th. |
George-Cristian Bîrzan: "The timeline there is wrong." Fixed: https://python-security.readthedocs.io/vuln/ipaddress-ipv4-leading-zeros.html#timeline The strange part is "2019-03-20 (-741 days): Python issue bpo-36384 reported by Joel Croteau". The problem is that this issue was "reused" for two different things: the initial change and the vulnerability. Maybe I can removed the reference to the bpo to remove it from the timeline (and put it in links). |
I think the only thing I'd improve would be to mention that this issue is the one that introduced the bug, otherwise it looks a bit weird. |
Ok, done: https://python-security.readthedocs.io/vuln/ipaddress-ipv4-leading-zeros.html#timeline |
Can we backport the security fix from this issue https://bugs.python.org/issue36384#msg392684 to version 3.8 |
What do you mean by this? Our understanding is that this is a low-severity CVE because in order for this to be a vulnerability, you'd have to have both:
Access to both then allows you at best to circumvent IP address-based access control or denial of service. However, access to just 1. allows you to input any IP address to achieve the same goals. Hence low-severity.
It is a bona fide breaking change. Any IP address configuration saved in files or databases which might have used leading zeroes would be rejected by 3.8.12. The same was true for 3.9.5 but since this release series has much higher exposure (still receiving binary installers and regular-cadence bugfixes), it was less controversial to include it. If you still feel this ought to be fixed in 3.8, please elaborate. |
Even though I agree with you assessment on the root cause of the issue itself, it is listed as critical in https://nvd.nist.gov/vuln/detail/CVE-2021-29921, which means most commercial scan tools will also flag python 3.8 as critical, and this could prevent users from going with python 3.8 on production. (our case too)
IMHO I still think this should be solved in 3.8, otherwise there is really no other alternative but to upgrade to python 3.9 which is a hassle, since all 3.8.x are "critically vulnerable", had the CVE in https://nvd.nist.gov/vuln/detail/CVE-2021-29921 not been marked as critical, then we could have used python 3.8 knowing the two conditions you mentioned earlier. |
I was unaware of the "CRITICAL" base score assigned by NIST to this. Alright, let's port this back then. There are a few things the PR will need. |
"CRITICAL" is a ridiculous high assessment for this bug. Somebody ticked all the scary boxes in the CVSS form like "total loss of control". |
The CVE was rated https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H&version=3.1, which is equivalent to a RCE with authentication bypass. I would rate the issue https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N&version=3.1, maybe A:L. |
New changeset 6ebfe8d by Łukasz Langa in branch '3.8': |
New changeset 0fd66e4 by Łukasz Langa in branch 'main': |
New changeset 1204dfc by Miss Islington (bot) in branch '3.10': |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: