gogs / gogs

Gogs is a painless self-hosted Git service

Home Page:https://gogs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Remote command execution

5alt opened this issue · comments

commented
  • 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.

gogs_admin_en

gogs_admin4_en

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?

This is a very serious issue @unknwon and this is the email u@gogs.io @5alt

Patch has pushed to fix this issue, please test on develop branch or https://try.gogs.io.

commented

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:

https://play.golang.org/p/z2QN4ReKbfT

commented

strings.ContainsAny checks any substring of second argument, so even ".." should work:

https://play.golang.org/p/z2QN4ReKbfT

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!