goshs: WebDAV listener ignores --read-only, --upload-only, and --no-delete mode flags
위협 신호 · CVSS · EPSS · KEV
이론적 심각도 점수
예측 데이터 없음
실측 악용 기록 없음
계획된 패치 주기 내 조치(60일 이내)
CVSS 벡터 · 메트릭
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N상세 설명
WebDAV listener ignores --read-only, --upload-only, and --no-delete mode flags
Ecosystem: Go
Package: goshs.de/goshs/v2 (github.com/patrickhener/goshs)
Affected: <= v2.0.9 (every release that ships the WebDAV handler)
Summary
When goshs is launched with WebDAV enabled (-w), the mode-restriction flags --read-only, --upload-only, and --no-delete are enforced only on the primary HTTP port. The WebDAV port is wired straight to golang.org/x/net/webdav.Handler with no equivalent guard, so an authenticated WebDAV client can PUT, DELETE, MKCOL, MOVE, and COPY despite the operator's stated intent.
Details
httpserver/server.go:207-238 — the WebDAV mux registers only IPWhitelistMiddleware, ServerHeaderMiddleware, and optionally BasicAuthMiddleware. There is no fs.ReadOnly || fs.UploadOnly || fs.NoDelete check on the WebDAV path. The HTTP mux in the same file (lines 134-204) does check these flags on every state-changing route.
Proof of concept
1mkdir -p /tmp/r && echo secret > /tmp/r/x.txt 2goshs -p 18000 -wp 18001 -w -ro -d /tmp/r -b admin:pw & 3 4curl -u admin:pw -X PUT http://localhost:18000/y.txt --data x # 403 (HTTP enforces -ro) 5curl -u admin:pw -X PUT http://localhost:18001/y.txt --data x # 201 (WebDAV writes anyway) 6curl -u admin:pw -X DELETE http://localhost:18001/x.txt # 204 (WebDAV deletes anyway) 7curl -u admin:pw -X MKCOL http://localhost:18001/pwned/ # 201 (WebDAV creates dir)Impact
- Integrity —
--read-onlyand--no-deleteare silently downgraded to "no protection" on the WebDAV port. Any WebDAV client (curl, cadaver, Windows Explorer, Finder) can overwrite/delete files. - Confidentiality —
--upload-onlyis also bypassed: WebDAV GET/PROPFIND still return file contents. - Trust — operators using
goshs -w -ro -d /srv/case-files -b reviewer:pwto deliver engagement artifacts believe the directory is immutable. It isn't.
Suggested fix
Add a small http.HandlerFunc in front of wdHandler that maps WebDAV verbs to the existing mode flags:
1wdGuard := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 2 switch r.Method { 3 case http.MethodPut, "MKCOL", "MOVE", "COPY": 4 if fs.ReadOnly || fs.UploadOnly { http.Error(w, "read-only", 403); return } 5 case http.MethodDelete: 6 if fs.ReadOnly || fs.UploadOnly || fs.NoDelete { http.Error(w, "delete disabled", 403); return } 7 case http.MethodGet, "PROPFIND", "HEAD": 8 if fs.UploadOnly { http.Error(w, "upload-only", 403); return } 9 }10 wdHandler.ServeHTTP(w, r)11})Add regression tests in integration/functions.go covering each mode flag × each WebDAV verb.
Reporter: Nishant Verma. Reproduced live against goshs v2.0.9 (commit 8fc1e91) on 2026-05-27.
AI 심층 분석
공격 시나리오 · 재현 가능한 PoC 페이로드 · 즉시 적용 가능한 차단 패치를 한 번에 받아 보세요. 보안 운영팀이 그대로 점검·티켓팅에 쓸 수 있는 형태로 정리해 드립니다.