Skip to content
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

Potential DoS via the Tudoor mechanism (CVE-2023-29483) #1045

Closed
rthalley opened this issue Feb 9, 2024 · 8 comments
Closed

Potential DoS via the Tudoor mechanism (CVE-2023-29483) #1045

rthalley opened this issue Feb 9, 2024 · 8 comments

Comments

@rthalley
Copy link
Owner

rthalley commented Feb 9, 2024

As mentioned in the "Tudoor" paper, and presumably in the CVE assigned to dnspython by the authors (CVE-2023-29483) the dnspython stub resolver is vulnerable to a potential DoS if a bad-in-some-way response from the right address and port forged by an attacker arrives before a legitimate one on the UDP port dnspython happens to be using for that single query.

While we don't think this is a huge practical threat for dnspython, we will nevertheless address the issue by adopting the recommended mitigation, which is ignoring the bad packets and continuing to listen for a legitimate response or until the allotted timeout for the query has expired.

We will issue a 2.6.0 release in the near future to address this. Because there is a small backwards compatible API change, we are not making a 2.5.1 release with this fix.

@rthalley rthalley changed the title DoS via the Tudoor mechanism (CVE-2023-29483) Potential DoS via the Tudoor mechanism (CVE-2023-29483) Feb 9, 2024
@rthalley
Copy link
Owner Author

rthalley commented Feb 9, 2024

Changes have been merged.

@kelvin-j-li
Copy link

kelvin-j-li commented Feb 14, 2024

hi @rthalley ,
Thank you for your fix for CVE-2023-29483.

We tried the latest dnspython-2.6.0rc1 to fix CVE-2023-29483. It fixes the skny monitor error, however, it seems to break the dns lookup in k8s environment, keep getting timeout errors:

[2024-02-14 04:20:12,780] ERROR in:25:MainThread: Failed to create MONGO_CLIENT with exception: **mongo-db.ns-mongo-db:27017**: [Errno -3] Lookup timed out (configured timeouts: socketTimeoutMS: 5000.0ms, connectTimeoutMS: 5000.0ms), Timeout: 30s, Topology Description: <TopologyDescription id: 65cc3f5e1adb6db858740ddb, topology_type: Unknown, servers: [<ServerDescription ('mongo-db.ns-mongo-db', 27017) server_type: Unknown, rtt: None, error=AutoReconnect('mongo-db.ns-mongo-db:27017: [Errno -3] Lookup timed out (configured timeouts: socketTimeoutMS: 5000.0ms, connectTimeoutMS: 5000.0ms)')>]>

when I used 'nc' or 'curl', I can see that the mongo db is actually running/listening:

$ nc -vz mongo-db.ns-mongo-db 27017
mongo-db.ns-mongo-db [192.168.152.52] 27017 open
$ curl mongo-db.ns-mongo-db:27017
It looks like you are trying to access MongoDB over HTTP on the native driver port.

Does dnspython stop supporting $app.$namespace:$port convention? Is there a get around for this timeout/dns lookup error? ex: $svc.$namespace.svc.cluster.local $port

Thanks in advance!

@kelvin-j-li
Copy link

kelvin-j-li commented Feb 14, 2024

i ran the test code for dnspython (2.5.0) inside k8s container:

$ test-dns.py
**test-dns.py:8: DeprecationWarning: please use dns.resolver.resolve() instead**
  ans = dns.resolver.query(hostname, "A")

qname: mongo-db.ns-mongo-db.svc.cluster.local.
reclass: RdataClass.IN
rdtype: RdataType.A
rrset: mongo-db.ns-mongo-db.svc.cluster.local. 30 IN A 192.168.152.52
response: id 36376
opcode QUERY
rcode NOERROR
flags QR AA RD
;QUESTION
mongo-db.ns-mongo-db.svc.cluster.local. IN A
;ANSWER
mongo-db.ns-mongo-db.svc.cluster.local. 30 IN A 192.168.152.52
;AUTHORITY
;ADDITIONAL

The timeout issue might be sth to do with eventlet-0.35.1. I have the below 2 lines at the beginning:

import eventlet
eventlet.monkey_patch()

After falling back to dnspython-2.5.0, the timeout issue does not occur. However, snyk would fail due to the existence of CVE-2023-29483 in 2.5.0.

@kelvin-j-li
Copy link

kelvin-j-li commented Feb 14, 2024

ok, i re-produced the issue in the container with dnspython-2.6.0rc1:

>>> import eventlet
>>> eventlet.monkey_patch()
>>> import dns.resolver
>>> hostname='localhost'
>>> ans = dns.resolver.resolve(hostname, "A")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pyuser/app/dist-packages/dns/resolver.py", line 1565, in resolve
    return get_default_resolver().resolve(
  File "/home/pyuser/app/dist-packages/dns/resolver.py", line 1321, in resolve
    timeout = self._compute_timeout(start, lifetime, resolution.errors)
  File "/home/pyuser/app/dist-packages/dns/resolver.py", line 1075, in _compute_timeout
    raise LifetimeTimeout(timeout=duration, errors=errors)
dns.resolver.LifetimeTimeout: The resolution lifetime expired after 5.107 seconds: Server Do53:10.235.12.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.128.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.12.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.128.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.12.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.128.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.12.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.128.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.12.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.128.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.12.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'; Server Do53:10.235.128.20@53 answered udp() got an unexpected keyword argument 'ignore_errors'
>>>

It's nothing to do with k8s. with hostname 'localhost' and eventlet activated, I got the same timeout issue (about 5s).

If I tested without eventlet monkey patching, it's working as expected:

$ python3
Python 3.8.10 (default, May 26 2023, 14:05:08)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dns.resolver
>>> hostname='localhost'
>>> ans = dns.resolver.query(hostname, "A")
<stdin>:1: DeprecationWarning: please use dns.resolver.resolve() instead
>>> print ("rrset:",ans.rrset)
rrset: localhost. 600 IN A 127.0.0.1

This issue does not occur in dnspython-2.5.0 with eventlet monkey_patch() enabled. :

VERSION
    2.5.0

FILE
    /home/pyuser/app/dist-packages/dns/__init__.py


>>>
$ python3
Python 3.8.10 (default, May 26 2023, 14:05:08)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import eventlet
>>> eventlet.monkey_patch()
>>> import dns.resolver
>>>
>>> hostname='localhost'
>>> ans = dns.resolver.query(hostname, "A")
<stdin>:1: DeprecationWarning: please use dns.resolver.resolve() instead
>>> ans = dns.resolver.resolve(hostname, "A")
>>> print("qname:",ans.qname)
qname: localhost.
>>>

@kelvin-j-li
Copy link

kelvin-j-li commented Feb 14, 2024

Here's the test code I use:

#!/usr/bin/env python3

import eventlet
eventlet.monkey_patch()

# from dns import resolver
import dns.resolver

hostname='localhost'
# ans = dns.resolver.query(hostname, "A")
ans = dns.resolver.resolve(hostname, "A")

print("")
print("qname:",ans.qname)
print ("reclass:",ans.rdclass)
print ("rdtype:",ans.rdtype)
print ("rrset:",ans.rrset)
print ("response:",ans.response)

we can re-produce the timeout error by the below version:

pip3 install dnspython==2.6.0rc1

After reverting back to 2.5.0, the timeout issue is gone:

pip3 install dnspython==2.5.0

@rthalley
Copy link
Owner Author

This is not a dnspython issue, but rather an eventlet issue as it monkey patches a function whose API has been extended in 2.6 to deal with the CVE, and which the resolver uses. I opened an issue there when I released the RC. Note that eventlet must replicate the fix in their monkey patched code in order to be protected against the CVE.

@kelvin-j-li
Copy link

Thank you so much for your quick response! @rthalley

@rthalley
Copy link
Owner Author

Dnspython 2.6.0 is now out. Note that testing in between the RC and the final release found an uncovered area of the CVE, so anyone using the RC should update to get the official fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants