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

[SECURITY] Excessive ranges in a single ACK frame causes an exception in python programs #549

Open
k4ra5u opened this issue Oct 25, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@k4ra5u
Copy link

k4ra5u commented Oct 25, 2024

Description

  • When aioquic accumulates too many frames to revert to ack, the index variable of the above code becomes very large, causing the push_uint_var function to report an error: Write out of bounds. I've put the error message at the bottom of the article
    def push_ack_frame(buf: Buffer, rangeset: RangeSet, delay: int) -> int:
    ranges = len(rangeset)
    index = ranges - 1
    r = rangeset[index]
    buf.push_uint_var(r.stop - 1)
    buf.push_uint_var(delay)
    buf.push_uint_var(index)
    buf.push_uint_var(r.stop - 1 - r.start)
    start = r.start
    while index > 0:
    index -= 1
    r = rangeset[index]
    buf.push_uint_var(start - r.stop - 1)
    buf.push_uint_var(r.stop - r.start - 1)
    start = r.start
    return ranges
  • Although aioquic uses async for asynchronous operation to avoid crashing the whole programme due to a single error, however, the server is unable to generate replies (as the thread generating the replies has crashed), resulting in the state of many quic connections not being updated in time; thus affecting the normal communication between the two sides.
  • At the same time, we observed that aioquic spends almost all of its time handling exceptions and writing data to the buf, and its CPU usage remains at 100%. This resulted in a denial-of-service attack as aioquic was unable to properly establish connections with new clients.
2024-10-25 14:45:23,262 ERROR asyncio Unhandled exception in event loop
Traceback (most recent call last):
  File "uvloop/handles/udp.pyx", line 373, in uvloop.loop.__uv_udp_on_receive
  File "uvloop/handles/udp.pyx", line 260, in uvloop.loop.UDPTransport._on_receive
  File "uvloop/loop.pyx", line 117, in uvloop.loop.run_in_context2
  File "/home/john/.local/lib/python3.10/site-packages/aioquic/asyncio/server.py", line 149, in datagram_received
    protocol.datagram_received(data, addr)
  File "/home/john/.local/lib/python3.10/site-packages/aioquic/asyncio/protocol.py", line 158, in datagram_received
    self.transmit()
  File "/home/john/.local/lib/python3.10/site-packages/aioquic/asyncio/protocol.py", line 121, in transmit
    for data, addr in self._quic.datagrams_to_send(now=self._loop.time()):
  File "/home/john/.local/lib/python3.10/site-packages/aioquic/quic/connection.py", line 600, in datagrams_to_send
    self._write_application(builder, network_path, now)
  File "/home/john/.local/lib/python3.10/site-packages/aioquic/quic/connection.py", line 3021, in _write_application
    self._write_ack_frame(builder=builder, space=space, now=now)
  File "/home/john/.local/lib/python3.10/site-packages/aioquic/quic/connection.py", line 3222, in _write_ack_frame
    ranges = push_ack_frame(buf, space.ack_queue, ack_delay_encoded)
  File "/home/john/.local/lib/python3.10/site-packages/aioquic/quic/packet.py", line 638, in push_ack_frame
    buf.push_uint_var(start - r.stop - 1)
aioquic._buffer.BufferWriteError: Write out of bounds
@k4ra5u
Copy link
Author

k4ra5u commented Oct 25, 2024

A simple way to trigger the vulnerability is to send ping data quickly, up to 2s you can see that aioquic triggered the exception, after which aioquic's CPU usage stays at 100% for a long time.
image

@rthalley rthalley added the bug Something isn't working label Oct 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants