fix GHSA-5662-2rj7-f2v6 ;

an unauthenticated user could make the server inaccessible by
accessing the recent-uploads page and using an expensive filter

fixed by making the filter not regex-based,
only supporting bare-minimum anchoring (^foo bar$)
This commit is contained in:
ed 2025-08-01 20:42:49 +00:00
parent 3c6f0b17d0
commit 09910ba807
2 changed files with 37 additions and 9 deletions

View file

@ -107,6 +107,7 @@ from .util import (
sendfile_py, sendfile_py,
set_fperms, set_fperms,
stat_resource, stat_resource,
str_anchor,
ub64dec, ub64dec,
ub64enc, ub64enc,
ujoin, ujoin,
@ -5369,9 +5370,9 @@ class HttpCli(object):
raise Pebkac(500, "sqlite3 not found on server; unpost is disabled") raise Pebkac(500, "sqlite3 not found on server; unpost is disabled")
raise Pebkac(500, "server busy, cannot unpost; please retry in a bit") raise Pebkac(500, "server busy, cannot unpost; please retry in a bit")
zs = self.uparam.get("filter") or "" sfilt = self.uparam.get("filter") or ""
filt = re.compile(zs, re.I) if zs else None nfi, vfi = str_anchor(sfilt)
lm = "ups %r" % (zs,) lm = "ups %d%r" % (nfi, sfilt)
if self.args.shr and self.vpath.startswith(self.args.shr1): if self.args.shr and self.vpath.startswith(self.args.shr1):
shr_dbv, shr_vrem = self.vn.get_dbv(self.rem) shr_dbv, shr_vrem = self.vn.get_dbv(self.rem)
@ -5431,7 +5432,13 @@ class HttpCli(object):
q = "select sz, rd, fn, at from up where ip=? and at>? order by at desc" q = "select sz, rd, fn, at from up where ip=? and at>? order by at desc"
for sz, rd, fn, at in cur.execute(q, (self.ip, lim)): for sz, rd, fn, at in cur.execute(q, (self.ip, lim)):
vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x) vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x)
if filt and not filt.search(vp): if nfi == 0 or (nfi == 1 and vfi in vp):
pass
elif nfi == 2:
if not vp.startswith(vfi):
continue
elif nfi == 3:
if not vp.endswith(vfi):
continue continue
n -= 1 n -= 1
@ -5513,8 +5520,8 @@ class HttpCli(object):
raise Pebkac(500, "server busy, cannot list recent uploads; please retry") raise Pebkac(500, "server busy, cannot list recent uploads; please retry")
sfilt = self.uparam.get("filter") or "" sfilt = self.uparam.get("filter") or ""
filt = re.compile(sfilt, re.I) if sfilt else None nfi, vfi = str_anchor(sfilt)
lm = "ru %r" % (sfilt,) lm = "ru %d%r" % (nfi, sfilt)
self.log(lm) self.log(lm)
ret: list[dict[str, Any]] = [] ret: list[dict[str, Any]] = []
@ -5549,7 +5556,13 @@ class HttpCli(object):
q = "select sz, rd, fn, ip, at from up where at>0 order by at desc" q = "select sz, rd, fn, ip, at from up where at>0 order by at desc"
for sz, rd, fn, ip, at in cur.execute(q): for sz, rd, fn, ip, at in cur.execute(q):
vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x) vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x)
if filt and not filt.search(vp): if nfi == 0 or (nfi == 1 and vfi in vp):
pass
elif nfi == 2:
if not vp.startswith(vfi):
continue
elif nfi == 3:
if not vp.endswith(vfi):
continue continue
if not dots and "/." in vp: if not dots and "/." in vp:

View file

@ -2396,6 +2396,21 @@ def ujoin(rd: str, fn: str) -> str:
return rd or fn return rd or fn
def str_anchor(txt) -> tuple[int, str]:
if not txt:
return 0, ""
txt = txt.lower()
a = txt.startswith("^")
b = txt.endswith("$")
if not b:
if not a:
return 1, txt # ~
return 2, txt[1:] # ^
if not a:
return 3, txt[:-1] # $
return 4, txt[1:-1] # ^$
def log_reloc( def log_reloc(
log: "NamedLogger", log: "NamedLogger",
re: dict[str, str], re: dict[str, str],