Update SFTP logic for authentication to avoid brute forces; replicates logic from #9
Co-Authored-By: Stepan Fedotov <trixterthetux@users.noreply.github.com>
This commit is contained in:
parent
65809b5731
commit
82912595b7
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/pterodactyl/sftp-server"
|
"github.com/pterodactyl/sftp-server"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *PanelRequest) ValidateSftpCredentials(request sftp_server.AuthenticationRequest) (*sftp_server.AuthenticationResponse, error) {
|
func (r *PanelRequest) ValidateSftpCredentials(request sftp_server.AuthenticationRequest) (*sftp_server.AuthenticationResponse, error) {
|
||||||
|
@ -23,13 +22,10 @@ func (r *PanelRequest) ValidateSftpCredentials(request sftp_server.Authenticatio
|
||||||
|
|
||||||
if r.HasError() {
|
if r.HasError() {
|
||||||
if r.HttpResponseCode() >= 400 && r.HttpResponseCode() < 500 {
|
if r.HttpResponseCode() >= 400 && r.HttpResponseCode() < 500 {
|
||||||
zap.S().Debugw("failed to validate server credentials for SFTP", zap.String("error", r.Error().String()))
|
|
||||||
|
|
||||||
return nil, new(sftp_server.InvalidCredentialsError)
|
return nil, new(sftp_server.InvalidCredentialsError)
|
||||||
}
|
}
|
||||||
|
|
||||||
rerr := errors.New(r.Error().String())
|
rerr := errors.New(r.Error().String())
|
||||||
zap.S().Warnw("error validating SFTP credentials", zap.Error(rerr))
|
|
||||||
|
|
||||||
return nil, rerr
|
return nil, rerr
|
||||||
}
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -56,7 +56,7 @@ require (
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/pkg/profile v1.4.0
|
github.com/pkg/profile v1.4.0
|
||||||
github.com/pkg/sftp v1.11.0 // indirect
|
github.com/pkg/sftp v1.11.0 // indirect
|
||||||
github.com/pterodactyl/sftp-server v1.1.2
|
github.com/pterodactyl/sftp-server v1.1.4
|
||||||
github.com/remeh/sizedwaitgroup v0.0.0-20180822144253-5e7302b12cce
|
github.com/remeh/sizedwaitgroup v0.0.0-20180822144253-5e7302b12cce
|
||||||
github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94
|
github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94
|
||||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -263,6 +263,8 @@ github.com/pterodactyl/sftp-server v1.1.1 h1:IjuOy21BNZxfejKnXG1RgLxXAYylDqBVpbK
|
||||||
github.com/pterodactyl/sftp-server v1.1.1/go.mod h1:b1VVWYv0RF9rxSZQqaD/rYXriiRMNPsbV//CKMXR4ag=
|
github.com/pterodactyl/sftp-server v1.1.1/go.mod h1:b1VVWYv0RF9rxSZQqaD/rYXriiRMNPsbV//CKMXR4ag=
|
||||||
github.com/pterodactyl/sftp-server v1.1.2 h1:5bI9upe0kBRn9ALDabn9S2GVU5gkYvSErYgs32dAKjk=
|
github.com/pterodactyl/sftp-server v1.1.2 h1:5bI9upe0kBRn9ALDabn9S2GVU5gkYvSErYgs32dAKjk=
|
||||||
github.com/pterodactyl/sftp-server v1.1.2/go.mod h1:KjSONrenRr1oCh94QIVAU6yEzMe+Hd7r/JHrh5/oQHs=
|
github.com/pterodactyl/sftp-server v1.1.2/go.mod h1:KjSONrenRr1oCh94QIVAU6yEzMe+Hd7r/JHrh5/oQHs=
|
||||||
|
github.com/pterodactyl/sftp-server v1.1.4 h1:JESuEuZ+d2tajMjuQblPOlGISM9Uc2xOzk7irVF9PQ0=
|
||||||
|
github.com/pterodactyl/sftp-server v1.1.4/go.mod h1:KjSONrenRr1oCh94QIVAU6yEzMe+Hd7r/JHrh5/oQHs=
|
||||||
github.com/remeh/sizedwaitgroup v0.0.0-20180822144253-5e7302b12cce h1:aP+C+YbHZfOQlutA4p4soHi7rVUqHQdWEVMSkHfDTqY=
|
github.com/remeh/sizedwaitgroup v0.0.0-20180822144253-5e7302b12cce h1:aP+C+YbHZfOQlutA4p4soHi7rVUqHQdWEVMSkHfDTqY=
|
||||||
github.com/remeh/sizedwaitgroup v0.0.0-20180822144253-5e7302b12cce/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
|
github.com/remeh/sizedwaitgroup v0.0.0-20180822144253-5e7302b12cce/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Initialize(config *config.Configuration) error {
|
func Initialize(config *config.Configuration) error {
|
||||||
|
@ -70,13 +71,36 @@ func validateDiskSpace(fs sftp_server.FileSystem) bool {
|
||||||
return s.Filesystem.HasSpaceAvailable()
|
return s.Filesystem.HasSpaceAvailable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var validUsernameRegexp = regexp.MustCompile(`^(?i)(.+)\.([a-z0-9]{8})$`)
|
||||||
|
|
||||||
// Validates a set of credentials for a SFTP login aganist Pterodactyl Panel and returns
|
// Validates a set of credentials for a SFTP login aganist Pterodactyl Panel and returns
|
||||||
// the server's UUID if the credentials were valid.
|
// the server's UUID if the credentials were valid.
|
||||||
func validateCredentials(c sftp_server.AuthenticationRequest) (*sftp_server.AuthenticationResponse, error) {
|
func validateCredentials(c sftp_server.AuthenticationRequest) (*sftp_server.AuthenticationResponse, error) {
|
||||||
resp, err := api.NewRequester().ValidateSftpCredentials(c)
|
|
||||||
|
|
||||||
log.WithFields(log.Fields{"subsystem": "sftp", "username": c.User}).Debug("validating credentials for SFTP connection")
|
log.WithFields(log.Fields{"subsystem": "sftp", "username": c.User}).Debug("validating credentials for SFTP connection")
|
||||||
|
|
||||||
|
f := log.Fields{
|
||||||
|
"subsystem": "sftp",
|
||||||
|
"username": c.User,
|
||||||
|
"ip": c.IP,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the username doesn't meet the expected format that the Panel would even recognize just go ahead
|
||||||
|
// and bail out of the process here to avoid accidentially brute forcing the panel if a bot decides
|
||||||
|
// to connect to spam username attempts.
|
||||||
|
if !validUsernameRegexp.MatchString(c.User) {
|
||||||
|
log.WithFields(f).Warn("failed to validate user credentials (invalid format)")
|
||||||
|
|
||||||
|
return nil, new(sftp_server.InvalidCredentialsError)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := api.NewRequester().ValidateSftpCredentials(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if sftp_server.IsInvalidCredentialsError(err) {
|
||||||
|
log.WithFields(f).Warn("failed to validate user credentials (invalid username or password)")
|
||||||
|
} else {
|
||||||
|
log.WithFields(f).Error("encountered an error while trying to validate user credentials")
|
||||||
|
}
|
||||||
|
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +112,7 @@ func validateCredentials(c sftp_server.AuthenticationRequest) (*sftp_server.Auth
|
||||||
return resp, errors.New("no matching server with UUID found")
|
return resp, errors.New("no matching server with UUID found")
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Log().WithFields(log.Fields{"subsystem": "sftp", "username": c.User}).Debug("matched user to server instance, credentials successfully validated")
|
s.Log().WithFields(f).Debug("credentials successfully validated and matched user to server instance")
|
||||||
|
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user