Skip to content

Commit 09910ba

Browse files
committed
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$)
1 parent 3c6f0b1 commit 09910ba

File tree

2 files changed

+37
-9
lines changed

2 files changed

+37
-9
lines changed

copyparty/httpcli.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
sendfile_py,
108108
set_fperms,
109109
stat_resource,
110+
str_anchor,
110111
ub64dec,
111112
ub64enc,
112113
ujoin,
@@ -5369,9 +5370,9 @@ def tx_ups(self) -> bool:
53695370
raise Pebkac(500, "sqlite3 not found on server; unpost is disabled")
53705371
raise Pebkac(500, "server busy, cannot unpost; please retry in a bit")
53715372

5372-
zs = self.uparam.get("filter") or ""
5373-
filt = re.compile(zs, re.I) if zs else None
5374-
lm = "ups %r" % (zs,)
5373+
sfilt = self.uparam.get("filter") or ""
5374+
nfi, vfi = str_anchor(sfilt)
5375+
lm = "ups %d%r" % (nfi, sfilt)
53755376

53765377
if self.args.shr and self.vpath.startswith(self.args.shr1):
53775378
shr_dbv, shr_vrem = self.vn.get_dbv(self.rem)
@@ -5431,8 +5432,14 @@ def tx_ups(self) -> bool:
54315432
q = "select sz, rd, fn, at from up where ip=? and at>? order by at desc"
54325433
for sz, rd, fn, at in cur.execute(q, (self.ip, lim)):
54335434
vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x)
5434-
if filt and not filt.search(vp):
5435-
continue
5435+
if nfi == 0 or (nfi == 1 and vfi in vp):
5436+
pass
5437+
elif nfi == 2:
5438+
if not vp.startswith(vfi):
5439+
continue
5440+
elif nfi == 3:
5441+
if not vp.endswith(vfi):
5442+
continue
54365443

54375444
n -= 1
54385445
if not n:
@@ -5513,8 +5520,8 @@ def tx_rups(self) -> bool:
55135520
raise Pebkac(500, "server busy, cannot list recent uploads; please retry")
55145521

55155522
sfilt = self.uparam.get("filter") or ""
5516-
filt = re.compile(sfilt, re.I) if sfilt else None
5517-
lm = "ru %r" % (sfilt,)
5523+
nfi, vfi = str_anchor(sfilt)
5524+
lm = "ru %d%r" % (nfi, sfilt)
55185525
self.log(lm)
55195526

55205527
ret: list[dict[str, Any]] = []
@@ -5549,8 +5556,14 @@ def tx_rups(self) -> bool:
55495556
q = "select sz, rd, fn, ip, at from up where at>0 order by at desc"
55505557
for sz, rd, fn, ip, at in cur.execute(q):
55515558
vp = "/" + "/".join(x for x in [vol.vpath, rd, fn] if x)
5552-
if filt and not filt.search(vp):
5553-
continue
5559+
if nfi == 0 or (nfi == 1 and vfi in vp):
5560+
pass
5561+
elif nfi == 2:
5562+
if not vp.startswith(vfi):
5563+
continue
5564+
elif nfi == 3:
5565+
if not vp.endswith(vfi):
5566+
continue
55545567

55555568
if not dots and "/." in vp:
55565569
continue

copyparty/util.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,21 @@ def ujoin(rd: str, fn: str) -> str:
23962396
return rd or fn
23972397

23982398

2399+
def str_anchor(txt) -> tuple[int, str]:
2400+
if not txt:
2401+
return 0, ""
2402+
txt = txt.lower()
2403+
a = txt.startswith("^")
2404+
b = txt.endswith("$")
2405+
if not b:
2406+
if not a:
2407+
return 1, txt # ~
2408+
return 2, txt[1:] # ^
2409+
if not a:
2410+
return 3, txt[:-1] # $
2411+
return 4, txt[1:-1] # ^$
2412+
2413+
23992414
def log_reloc(
24002415
log: "NamedLogger",
24012416
re: dict[str, str],

0 commit comments

Comments
 (0)