From dd4f40ad5ef173dacd751b0ee14484cbe1975f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Wed, 8 Jul 2026 18:51:29 +0200 Subject: [PATCH] Adding max reponse size for HTTP2 --- lib/core/settings.py | 2 +- lib/request/http2.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/core/settings.py b/lib/core/settings.py index 1cb6c5ddf..0a35a7fce 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from lib.core.enums import OS from thirdparty import six # sqlmap version (...) -VERSION = "1.10.7.46" +VERSION = "1.10.7.47" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) diff --git a/lib/request/http2.py b/lib/request/http2.py index 17c768068..a8aa6287f 100644 --- a/lib/request/http2.py +++ b/lib/request/http2.py @@ -377,6 +377,12 @@ class Encoder(object): SETTINGS_INITIAL_WINDOW_SIZE = 0x4 BIG_WINDOW = (1 << 31) - 1 +# Upper bound on the response bytes (body or header block) buffered per stream. The client advertises a +# ~2GB flow-control window, so without this a large (or hostile) server would drive the whole body into +# memory and OOM the process. Mirrors the HTTP/1.1 path's MAX_CONNECTION_TOTAL_SIZE (100MB) cap in +# connect.py; a stream that exceeds it is truncated (body) or abandoned (headers) and its connection retired. +MAX_RESPONSE_SIZE = 100 * 1024 * 1024 + def _recv_exact(sock, n): buf = b"" while len(buf) < n: @@ -524,6 +530,9 @@ class _H2Connection(object): if flags & FLAG_PRIORITY: p = p[5:] header_block += p + if len(header_block) > MAX_RESPONSE_SIZE: # hostile/endless header block -> bail rather than OOM + self.usable = False + raise IOError("oversized HTTP/2 header block") if flags & FLAG_END_HEADERS: resp_headers = self.dec.decode(header_block) if flags & FLAG_END_STREAM: @@ -533,6 +542,9 @@ class _H2Connection(object): if flags & FLAG_PADDED: p = p[1:len(p) - bytearray(payload)[0]] resp_body += p + if len(resp_body) > MAX_RESPONSE_SIZE: # cap like the HTTP/1.1 path; stop reading and retire the + self.usable = False # connection (leftover frames abandoned) instead of OOM + break if payload: # replenish stream + connection windows self.sock.sendall(encode_frame(WINDOW_UPDATE, 0, sid, struct.pack("!I", len(payload)))) self.sock.sendall(encode_frame(WINDOW_UPDATE, 0, 0, struct.pack("!I", len(payload)))) @@ -603,6 +615,9 @@ class _H2Connection(object): if flags & FLAG_PRIORITY: p = p[5:] state[fsid]["hb"] += p + if len(state[fsid]["hb"]) > MAX_RESPONSE_SIZE: + self.usable = False + raise IOError("oversized HTTP/2 header block during timeless pair") if flags & FLAG_END_HEADERS: state[fsid]["headers"] = self.dec.decode(state[fsid]["hb"]) if flags & FLAG_END_STREAM and fsid in remaining: @@ -612,6 +627,9 @@ class _H2Connection(object): if flags & FLAG_PADDED: p = p[1:len(p) - bytearray(payload)[0]] state[fsid]["body"] += p + if len(state[fsid]["body"]) > MAX_RESPONSE_SIZE: # cap the buffered body (mirrors exchange()) + self.usable = False + raise IOError("oversized response during timeless pair") if payload: self.sock.sendall(encode_frame(WINDOW_UPDATE, 0, fsid, struct.pack("!I", len(payload)))) self.sock.sendall(encode_frame(WINDOW_UPDATE, 0, 0, struct.pack("!I", len(payload))))