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

Strange Behavior When Unpickling #1081

Closed
TheTechromancer opened this issue May 4, 2024 · 4 comments
Closed

Strange Behavior When Unpickling #1081

TheTechromancer opened this issue May 4, 2024 · 4 comments

Comments

@TheTechromancer
Copy link

Hi, first off thanks for making such a useful library and for your quick responses in the past. This specific bug may not be in dnspython, but I'm still in the process of troubleshooting and hoping you might be able to shed some light on it:

Traceback (most recent call last):
  File "/home/bls/Downloads/code/bbot/dns_bug2.py", line 14, in <module>
    pickle.loads(pickle.dumps(answer))
  File "/usr/local/lib/python3.11/enum.py", line 767, in __getattr__
    raise AttributeError(name) from None
AttributeError: CLASS1232

This bug only triggers in very rare cases when an answer object is deserialized via pickle.loads().

We've only been able to reproduce it on Synack's internal infrastructure, which only adds to the strangeness. It seems to be dependent on the DNS server. The following code triggers the error (only on Synack's internal DNS):

from dns.resolver import Resolver
import pickle

r = Resolver()
r.lifetime = 1
r.timeout = 1

while 1:
    try:
        answer = r.resolve('net-199-36-133-136.ppsfibernet.com', rdtype="A")
    except Exception:
        pass
    try:
        pickle.loads(pickle.dumps(answer))
    except Exception:
        print(answer.response.to_text())
        raise

@liquidsec can you post the wireshark capture?

@TheTechromancer
Copy link
Author

I should add, the AttributeError isn't always the same. Sometimes it's CLASS1232 and sometimes it's CLASS65494, but the number always seems to correspond to the UDP Payload Size in wireshark:

image

@liquidsec
Copy link

Here is the output from @TheTechromancer 's PoC:

id 51415
opcode QUERY
rcode NOERROR
flags QR RD RA
edns 0
payload 65494
;QUESTION
net-199-36-133-136.ppsfibernet.com. IN A
;ANSWER
net-199-36-133-136.ppsfibernet.com. 4063 IN A 199.36.133.136
;AUTHORITY
;ADDITIONAL
Traceback (most recent call last):
  File "/home/[REDACTED]/bbot/dnstry.py", line 13, in <module>
    pickle.loads(pickle.dumps(answer))
  File "/usr/local/lib/python3.11/enum.py", line 767, in __getattr__
    raise AttributeError(name) from None
AttributeError: CLASS65494

Attached the pcap

bbotdebug4.pcapng.txt

@rthalley
Copy link
Owner

rthalley commented May 5, 2024

The payload value of an EDNS0 OPT record is stored in its class, and it seems to be having trouble unpickling the dns.rdataclass.RdataClass. I cannot reproduce this with Python 3.12.3. There were regressions involving various aspects of enums on some 3.11 releases before 3.11.5, and also with some 3.12 prereleases. See #972 and also probably more specifically this CPython issue. I'm betting your Python version is 3.11.3 or 3.11.4 but I can't tell from your report. If running on a newer CPython doesn't fix it, can you tell me what version of dnspython you're using as well?

@TheTechromancer
Copy link
Author

Wow, you're right. Updating to 3.11.5 fixed it. Thanks for your help!

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

3 participants