Remote command execution
5alt opened this issue · comments
- Gogs version (or commit ref): newest(3a4c981)
- Can you reproduce the bug at https://try.gogs.io:
- [ x] Yes (provide example URL)
- No
- Not relevant
Description
I can login to arbitrary account. And when I logged in as admin, I can execute any command by git hooks.
I just tried login to Unknown's account but do not perform command execution.
As this is a very severe issue, I won't post details here.
@unknwon can you give me your email address and I send the details to you?
Patch has pushed to fix this issue, please test on develop
branch or https://try.gogs.io.
hi, the patch can be bypassed using ..\
in Windows. You should check ..
actually.
if strings.ContainsAny(sid, "..") {
return nil, errors.New("invalid 'sid': " + sid)
}
strings.ContainsAny
checks any substring of second argument, so even "..\" should work:
strings.ContainsAny
checks any substring of second argument, so even ".." should work:
In your patch, you checked ./
, but forget to check .\
func (m *Manager) Read(sid string) (RawStore, error) {
// No slashes or dots "./" should ever occur in the sid and to prevent session file forgery bug.
// See https://github.com/gogs/gogs/issues/5469
if strings.ContainsAny(sid, "./") {
return nil, errors.New("invalid 'sid': " + sid)
}
return m.provider.Read(sid)
}
If gogs runs on Windows, ..\
can be still used for directory traversal attack.
so check ..
is the best solution
strings.ContainsAny(sid, "./")
is equivalent to strings.Contains(sid, ".") || strings.Contains(sid, "/")
.Thus as long as the sid contains ".", it returns true.
Hmm. I think you're fixing things at the wrong level here. The issue is with the file session provider in file.go not necessarily the session.go.
Each session provider should be responsible for checking whether a session id is valid for it - therefore a check where the session id is valid should be in the Exists function of each of the providers.
For example, you may want to ensure that session IDs are a certain length on a database. Similarly if you're on ntfs and fat32 a session id with the path can't be more than 256 characters long due to filesystem constraints.
If there are global session id validity rules you need to check them before calling m.provider.Exists. As it stands the Exists if called before these are checked in Read - I'm not sure there's anything horrible you can do with just checking if a file exists but I'm fairly sure you shouldn't be able to do that.
Looking again at this the "Destory" (is this meant to be destroy?) and Regenerate methods basically allow arbitrary file creation and deletion through a similar fault. I'm not sure if these methods are available to end users to call arbitrarily but they almost certainly need checks placed on them too.
This issue should finally be solved go-macaron/session#24. Thanks to @zeripath!