From 630ebbe6c2b15605c90b292249f93430f681a40b Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Mon, 26 Oct 2015 18:08:59 -0700 Subject: [PATCH] Sanitizing input to LDAP authentication module. --- modules/auth/ldap/ldap.go | 42 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/modules/auth/ldap/ldap.go b/modules/auth/ldap/ldap.go index 382b5b8699..74a36d5e65 100644 --- a/modules/auth/ldap/ldap.go +++ b/modules/auth/ldap/ldap.go @@ -9,6 +9,7 @@ package ldap import ( "crypto/tls" "fmt" + "strings" "github.com/gogits/gogs/modules/ldap" "github.com/gogits/gogs/modules/log" @@ -33,6 +34,28 @@ type Source struct { Enabled bool // if this source is disabled } +func (ls *Source) sanitizedUserQuery(username string) (string, bool) { + // See http://tools.ietf.org/search/rfc4515 + badCharacters := "\x00()*\\" + if strings.ContainsAny(username, badCharacters) { + log.Debug("'%s' contains invalid query characters. Aborting.", username) + return "", false + } + + return fmt.Sprintf(ls.Filter, username), true +} + +func (ls *Source) sanitizedUserDN(username string) (string, bool) { + // See http://tools.ietf.org/search/rfc4514: "special characters" + badCharacters := "\x00()*\\,='\"#+;<> " + if strings.ContainsAny(username, badCharacters) { + log.Debug("'%s' contains invalid DN characters. Aborting.", username) + return "", false + } + + return fmt.Sprintf(ls.UserDN, username), true +} + func (ls *Source) FindUserDN(name string) (string, bool) { l, err := ldapDial(ls) if err != nil { @@ -55,7 +78,11 @@ func (ls *Source) FindUserDN(name string) (string, bool) { } // A search for the user. - userFilter := fmt.Sprintf(ls.Filter, name) + userFilter, ok := ls.sanitizedUserQuery(name) + if !ok { + return "", false + } + log.Trace("Searching using filter %s", userFilter) search := ldap.NewSearchRequest( ls.UserBase, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, @@ -85,7 +112,12 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str var userDN string if directBind { log.Trace("LDAP will bind directly via UserDN template: %s", ls.UserDN) - userDN = fmt.Sprintf(ls.UserDN, name) + + var ok bool + userDN, ok = ls.sanitizedUserDN(name) + if !ok { + return "", "", "", false, false + } } else { log.Trace("LDAP will use BindDN.") @@ -112,7 +144,11 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str } log.Trace("Bound successfully with userDN: %s", userDN) - userFilter := fmt.Sprintf(ls.Filter, name) + userFilter, ok := ls.sanitizedUserQuery(name) + if !ok { + return "", "", "", false, false + } + search := ldap.NewSearchRequest( userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter, []string{ls.AttributeName, ls.AttributeSurname, ls.AttributeMail},