Skip to content

Slow IDNA decoding with large strings [CVE-2022-45061] #98433

Closed

Description

@guidovranken

Bug report

Originally reported to the security address on September 9.

('xn--016c'+'a'*5000).encode('utf-8').decode('idna')

The execution time is not linear in relation to the input string size, which can cause slowness with large inputs:

10 chars = 0.016 seconds
100 chars = 0.047 seconds
1000 chars = 2.883 seconds
2500 chars = 17.724 seconds
5000 chars = 1 min 10 seconds

Comment by @tiran:

According to spec https://unicode.org/reports/tr46/ an IDNA label must not be longer than 63 characters. Python's idna module enforces the restriction, but too late.

This may be abused in some cases, for example by passing a crafted host name to asyncio create_connection:

import asyncio

async def main():
    loop = asyncio.get_running_loop()

    await loop.create_connection(
        lambda: [], ('xn--016c'+'a'*5000).encode('utf-8'), 443
    )

asyncio.run(main())

Your environment

  • CPython versions tested on: CPython repository 'main' branch checkout, version 3.8.12, version 2.7.18
  • Operating system and architecture: Ubuntu Linux x64

Activity

  1. gpshead commented on Nov 4, 2022

    @gpshead
    Member

    This is probably in ToUnicode and ToASCII of https://github.com/python/cpython/blob/main/Lib/encodings/idna.py and/or in https://github.com/python/cpython/blob/main/Lib/encodings/punycode.py itself, where we could presumably just do an up front length check and reject inputs that are obviously too long to possibly decode into a label length that DNS standards will accept.

    If there are libraries that allow an attacker controlled hostname without a reasonable length check on it to get into a connect or similar call that tries idna decoding, that'd make this remotely exploitable. Based solely on code inspection, the urllib.request.HTTPRedirectHandler class is probably vulnerable to this - https://github.com/python/cpython/blob/main/Lib/urllib/request.py#L652 - the location or uri headers it consumes on a HTTP 302 redirect reponse to construct the new URL are not obviously limited, nor is the host that ultimately winds it way down into the socket module. (I didn't test this, I was just reading code) A test case would be to point urllib at a malicious server that sends a 2000 byte idna hostname in a 302 redirect header...

  2. vstinner commented on Nov 4, 2022

    @vstinner
    Member

    The issue #99083 was marked as a duplicate of this issue.

  3. added 2 commits that reference this issue on Nov 4, 2022
  4. added a commit that references this issue on Nov 8, 2022
  5. added a commit that references this issue on Nov 8, 2022
  6. added 2 commits that reference this issue on Nov 8, 2022
  7. 15 remaining items

  8. added a commit that references this issue on Dec 21, 2022
  9. added a commit that references this issue on Oct 6, 2023
  10. added 2 commits that reference this issue on Mar 11, 2024
  11. added 5 commits that reference this issue on Mar 20, 2024
  12. added a commit that references this issue on Mar 26, 2024
  13. added a commit that references this issue on Apr 2, 2024
  14. added a commit that references this issue on Apr 23, 2025
  15. added a commit that references this issue on Jul 4, 2025
  16. added a commit that references this issue on Aug 12, 2025
  17. added a commit that references this issue on Feb 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.10 (EOL)end of life3.11only security fixes3.12only security fixes3.7 (EOL)end of life3.8 (EOL)end of life3.9 (EOL)end of lifetype-bugAn unexpected behavior, bug, or errortype-securityA security issue

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions