From 746d836b9915192d1d46e65408d8827feff3a421 Mon Sep 17 00:00:00 2001 From: Thomas Miceli Date: Tue, 4 Apr 2023 01:16:22 +0200 Subject: [PATCH] Add warn logs on invalid authentications --- internal/ssh/git_ssh.go | 5 ++++- internal/ssh/run.go | 15 ++++++++++----- internal/web/auth.go | 8 ++++++++ internal/web/git_http.go | 2 ++ internal/web/run.go | 5 +++-- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/internal/ssh/git_ssh.go b/internal/ssh/git_ssh.go index dadf937..3724d4c 100644 --- a/internal/ssh/git_ssh.go +++ b/internal/ssh/git_ssh.go @@ -2,6 +2,7 @@ package ssh import ( "errors" + "github.com/rs/zerolog/log" "golang.org/x/crypto/ssh" "gorm.io/gorm" "io" @@ -11,7 +12,7 @@ import ( "strings" ) -func runGitCommand(ch ssh.Channel, gitCmd string, keyID uint) error { +func runGitCommand(ch ssh.Channel, gitCmd string, keyID uint, ip string) error { verb, args := parseCommand(gitCmd) if !strings.HasPrefix(verb, "git-") { verb = "" @@ -40,6 +41,7 @@ func runGitCommand(ch ssh.Channel, gitCmd string, keyID uint) error { user, err := models.GetUserBySSHKeyID(keyID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { + log.Warn().Msg("Invalid SSH authentication attempt from " + ip) return errors.New("unauthorized") } errorSsh("Failed to get user by SSH key id", err) @@ -47,6 +49,7 @@ func runGitCommand(ch ssh.Channel, gitCmd string, keyID uint) error { } if user.ID != gist.UserID { + log.Warn().Msg("Invalid SSH authentication attempt from " + ip) return errors.New("unauthorized") } } diff --git a/internal/ssh/run.go b/internal/ssh/run.go index ef9a4d1..580bfe1 100644 --- a/internal/ssh/run.go +++ b/internal/ssh/run.go @@ -25,8 +25,13 @@ func Start() { sshConfig := &ssh.ServerConfig{ PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { pkey, err := models.GetSSHKeyByContent(strings.TrimSpace(string(ssh.MarshalAuthorizedKey(key)))) - if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { - return nil, err + if err != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err + } + + log.Warn().Msg("Invalid SSH authentication attempt from " + conn.RemoteAddr().String()) + return nil, errors.New("unknown public key") } return &ssh.Permissions{Extensions: map[string]string{"key-id": strconv.Itoa(int(pkey.ID))}}, nil }, @@ -67,12 +72,12 @@ func listen(serverConfig *ssh.ServerConfig) { go ssh.DiscardRequests(reqs) keyID, _ := strconv.Atoi(sConn.Permissions.Extensions["key-id"]) - go handleConnexion(channels, uint(keyID)) + go handleConnexion(channels, uint(keyID), sConn.RemoteAddr().String()) }() } } -func handleConnexion(channels <-chan ssh.NewChannel, keyID uint) { +func handleConnexion(channels <-chan ssh.NewChannel, keyID uint, ip string) { for channel := range channels { if channel.ChannelType() != "session" { _ = channel.Reject(ssh.UnknownChannelType, "Unknown channel type") @@ -104,7 +109,7 @@ func handleConnexion(channels <-chan ssh.NewChannel, keyID uint) { payloadCmd = payloadCmd[i:] } - if err = runGitCommand(ch, payloadCmd, keyID); err != nil { + if err = runGitCommand(ch, payloadCmd, keyID, ip); err != nil { _, _ = ch.Stderr().Write([]byte("Opengist: " + err.Error() + "\r\n")) } _, _ = ch.SendRequest("exit-status", false, []byte{0, 0, 0, 0}) diff --git a/internal/web/auth.go b/internal/web/auth.go index 8fcef1c..d284024 100644 --- a/internal/web/auth.go +++ b/internal/web/auth.go @@ -1,7 +1,10 @@ package web import ( + "errors" "github.com/labstack/echo/v4" + "github.com/rs/zerolog/log" + "gorm.io/gorm" "opengist/internal/config" "opengist/internal/models" ) @@ -80,6 +83,10 @@ func processLogin(ctx echo.Context) error { var user *models.User if user, err = models.GetUserByUsername(dto.Username); err != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + return errorRes(500, "Cannot get user", err) + } + log.Warn().Msg("Invalid HTTP authentication attempt from " + ctx.RealIP()) addFlash(ctx, "Invalid credentials", "error") return redirect(ctx, "/login") } @@ -88,6 +95,7 @@ func processLogin(ctx echo.Context) error { if err != nil { return errorRes(500, "Cannot check for password", err) } + log.Warn().Msg("Invalid HTTP authentication attempt from " + ctx.RealIP()) addFlash(ctx, "Invalid credentials", "error") return redirect(ctx, "/login") } diff --git a/internal/web/git_http.go b/internal/web/git_http.go index 1b2acbf..6617dec 100644 --- a/internal/web/git_http.go +++ b/internal/web/git_http.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "fmt" "github.com/labstack/echo/v4" + "github.com/rs/zerolog/log" "net/http" "opengist/internal/git" "opengist/internal/models" @@ -84,6 +85,7 @@ func gitHttp(ctx echo.Context) error { if err != nil { return errorRes(500, "Cannot verify password", err) } + log.Warn().Msg("Invalid HTTP authentication attempt from " + ctx.RealIP()) return errorRes(403, "Unauthorized", nil) } diff --git a/internal/web/run.go b/internal/web/run.go index 9a83386..5aafa87 100644 --- a/internal/web/run.go +++ b/internal/web/run.go @@ -107,11 +107,12 @@ func Start() { Getter: middleware.MethodFromForm("_method"), })) e.Pre(middleware.RemoveTrailingSlash()) - e.Use(middleware.CORS()) - e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ + e.Pre(middleware.CORS()) + e.Pre(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ LogURI: true, LogStatus: true, LogMethod: true, LogValuesFunc: func(ctx echo.Context, v middleware.RequestLoggerValues) error { log.Info().Str("URI", v.URI).Int("status", v.Status).Str("method", v.Method). + Str("ip", ctx.RealIP()). Msg("HTTP") return nil },