Skip to content

Commit 6fb224e

Browse files
committed
Fix webdav bug and address GHSA-jgfx-74g2-9r6g, a security bug where token can be used to bypass authentication and upload,delete files and run cli commands, if the module is activated. The attacker would need a valid share token beforehand.
1 parent c64a28d commit 6fb224e

4 files changed

Lines changed: 52 additions & 5 deletions

File tree

httpserver/handler.go

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,28 +103,46 @@ func (fs *FileServer) doFile(file *os.File, w http.ResponseWriter, req *http.Req
103103

104104
func (fs *FileServer) earlyBreakParameters(w http.ResponseWriter, req *http.Request) bool {
105105
if _, ok := req.URL.Query()["smtp"]; ok {
106+
if denyForTokenAccess(w, req) {
107+
return true
108+
}
106109
fs.handleSMTPAttachment(w, req)
107110
return true
108111
}
109112
if _, ok := req.URL.Query()["goshs-info"]; ok {
113+
if denyForTokenAccess(w, req) {
114+
return true
115+
}
110116
fs.handleInfo(w)
111117
return true
112118
}
113119
if _, ok := req.URL.Query()["mkdir"]; ok {
120+
if denyForTokenAccess(w, req) {
121+
return true
122+
}
114123
fs.handleMkdir(w, req)
115124
return true
116125
}
117126
if _, ok := req.URL.Query()["ws"]; ok {
127+
if denyForTokenAccess(w, req) {
128+
return true
129+
}
118130
fs.socket(w, req)
119131
return true
120132
}
121133
if _, ok := req.URL.Query()["cbDown"]; ok {
134+
if denyForTokenAccess(w, req) {
135+
return true
136+
}
122137
if !fs.NoClipboard && !fs.Invisible {
123138
fs.cbDown(w, req)
124139
return true
125140
}
126141
}
127142
if _, ok := req.URL.Query()["bulk"]; ok {
143+
if denyForTokenAccess(w, req) {
144+
return true
145+
}
128146
if !fs.Invisible {
129147
fs.bulkDownload(w, req)
130148
} else {
@@ -133,6 +151,9 @@ func (fs *FileServer) earlyBreakParameters(w http.ResponseWriter, req *http.Requ
133151
return true
134152
}
135153
if _, ok := req.URL.Query()["static"]; ok {
154+
if denyForTokenAccess(w, req) {
155+
return true
156+
}
136157
if !fs.Invisible {
137158
fs.static(w, req)
138159
} else {
@@ -141,6 +162,9 @@ func (fs *FileServer) earlyBreakParameters(w http.ResponseWriter, req *http.Requ
141162
return true
142163
}
143164
if _, ok := req.URL.Query()["embedded"]; ok {
165+
if denyForTokenAccess(w, req) {
166+
return true
167+
}
144168
if err := fs.embedded(w, req); err != nil {
145169
if !fs.Invisible {
146170
body := fs.emitCollabEvent(req, http.StatusNotFound)
@@ -155,6 +179,9 @@ func (fs *FileServer) earlyBreakParameters(w http.ResponseWriter, req *http.Requ
155179
return true
156180
}
157181
if _, ok := req.URL.Query()["delete"]; ok {
182+
if denyForTokenAccess(w, req) {
183+
return true
184+
}
158185
if !fs.ReadOnly && !fs.UploadOnly && !fs.NoDelete {
159186
fs.deleteFile(w, req)
160187
return true
@@ -164,6 +191,9 @@ func (fs *FileServer) earlyBreakParameters(w http.ResponseWriter, req *http.Requ
164191
}
165192
}
166193
if _, ok := req.URL.Query()["share"]; ok {
194+
if denyForTokenAccess(w, req) {
195+
return true
196+
}
167197
if !fs.Invisible {
168198
fs.CreateShareHandler(w, req)
169199
} else {
@@ -836,9 +866,11 @@ func (fs *FileServer) ShareHandler(w http.ResponseWriter, r *http.Request) {
836866
entry.Downloaded++
837867

838868
fs.SharedLinks[token] = entry
839-
if fs.SharedLinks[token].Downloaded >= fs.SharedLinks[token].DownloadLimit {
840-
// Remove the share link from map to keep it clean
841-
delete(fs.SharedLinks, token)
869+
if fs.SharedLinks[token].DownloadLimit != -1 {
870+
if fs.SharedLinks[token].Downloaded >= fs.SharedLinks[token].DownloadLimit {
871+
// Remove the share link from map to keep it clean
872+
delete(fs.SharedLinks, token)
873+
}
842874
}
843875
}
844876

httpserver/helper.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,11 @@ func GenerateQRCode(uri string) string {
7777

7878
return fmt.Sprintf("data:image/png;base64,%s", encoded)
7979
}
80+
81+
func denyForTokenAccess(w http.ResponseWriter, r *http.Request) bool {
82+
if r.URL.Query().Get("token") != "" {
83+
http.Error(w, "Forbidden", http.StatusForbidden)
84+
return true
85+
}
86+
return false
87+
}

httpserver/server.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,19 @@ func (fs *FileServer) SetupMux(mux *CustomMux, what string) string {
9393
// Define routes
9494
mux.HandleFunc("POST /", func(w http.ResponseWriter, r *http.Request) {
9595
if strings.HasSuffix(r.URL.Path, "/upload") {
96+
if denyForTokenAccess(w, r) {
97+
return
98+
}
9699
fs.upload(w, r)
97100
runtime.GC()
98101
} else {
99102
fs.logOnly(w, r)
100103
}
101104
})
102105
mux.HandleFunc("PUT /", func(w http.ResponseWriter, r *http.Request) {
106+
if denyForTokenAccess(w, r) {
107+
return
108+
}
103109
fs.put(w, r)
104110
})
105111
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

server/server.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ func StartAll(opts *options.Options) {
2828

2929
// webdav
3030
if opts.WebDav {
31-
httpSrv.Port = opts.WebDavPort
32-
go httpSrv.Start("webdav")
31+
webdavSrv := httpserver.NewHttpServer(opts, hub, clip, wl, *wh)
32+
webdavSrv.WebdavPort = opts.WebDavPort
33+
go webdavSrv.Start("webdav")
3334
}
3435

3536
if opts.SFTP {

0 commit comments

Comments
 (0)