mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-13 10:00:41 +02:00
sftp: url-encode the upload path so filenames can't inject filer query commands
The SFTP put handler concatenated the user-controlled filename straight into
the filer upload URL, so a name containing "?" was parsed as a query string.
Build the URL via url.URL{Path: ...} so "?" becomes %3F and stays a literal
path character.
40 lines
1.2 KiB
Go
40 lines
1.2 KiB
Go
package sftpd
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/pb"
|
|
)
|
|
|
|
// TestPutFileEscapesQueryInjection ensures a filename containing "?" cannot be
|
|
// reinterpreted by the filer as a query string that injects cp.from/mv.from
|
|
// commands, which would let an SFTP user escape their home directory.
|
|
func TestPutFileEscapesQueryInjection(t *testing.T) {
|
|
var gotPath, gotRawQuery string
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotPath = r.URL.Path
|
|
gotRawQuery = r.URL.RawQuery
|
|
if _, err := w.Write([]byte(`{}`)); err != nil {
|
|
t.Errorf("write response: %v", err)
|
|
}
|
|
}))
|
|
defer ts.Close()
|
|
|
|
fs := &SftpServer{filerAddr: pb.ServerAddress(strings.TrimPrefix(ts.URL, "http://"))}
|
|
|
|
malicious := "/home/alice/steal?cp.from=/home/bob/secret.txt"
|
|
if err := fs.putFile(malicious, strings.NewReader("dummy"), nil); err != nil {
|
|
t.Fatalf("putFile: %v", err)
|
|
}
|
|
|
|
if gotRawQuery != "" {
|
|
t.Errorf("filename leaked into query string: RawQuery=%q", gotRawQuery)
|
|
}
|
|
if gotPath != malicious {
|
|
t.Errorf("path not delivered literally: got %q, want %q", gotPath, malicious)
|
|
}
|
|
}
|