Add warn logs on invalid authentications

This commit is contained in:
Thomas Miceli 2023-04-04 01:16:22 +02:00
parent 8cdcb58e95
commit 746d836b99
No known key found for this signature in database
GPG key ID: D86C6F6390AF050F
5 changed files with 27 additions and 8 deletions

View file

@ -2,6 +2,7 @@ package ssh
import ( import (
"errors" "errors"
"github.com/rs/zerolog/log"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"gorm.io/gorm" "gorm.io/gorm"
"io" "io"
@ -11,7 +12,7 @@ import (
"strings" "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) verb, args := parseCommand(gitCmd)
if !strings.HasPrefix(verb, "git-") { if !strings.HasPrefix(verb, "git-") {
verb = "" verb = ""
@ -40,6 +41,7 @@ func runGitCommand(ch ssh.Channel, gitCmd string, keyID uint) error {
user, err := models.GetUserBySSHKeyID(keyID) user, err := models.GetUserBySSHKeyID(keyID)
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
log.Warn().Msg("Invalid SSH authentication attempt from " + ip)
return errors.New("unauthorized") return errors.New("unauthorized")
} }
errorSsh("Failed to get user by SSH key id", err) 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 { if user.ID != gist.UserID {
log.Warn().Msg("Invalid SSH authentication attempt from " + ip)
return errors.New("unauthorized") return errors.New("unauthorized")
} }
} }

View file

@ -25,8 +25,13 @@ func Start() {
sshConfig := &ssh.ServerConfig{ sshConfig := &ssh.ServerConfig{
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
pkey, err := models.GetSSHKeyByContent(strings.TrimSpace(string(ssh.MarshalAuthorizedKey(key)))) pkey, err := models.GetSSHKeyByContent(strings.TrimSpace(string(ssh.MarshalAuthorizedKey(key))))
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { if err != nil {
return nil, err 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 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) go ssh.DiscardRequests(reqs)
keyID, _ := strconv.Atoi(sConn.Permissions.Extensions["key-id"]) 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 { for channel := range channels {
if channel.ChannelType() != "session" { if channel.ChannelType() != "session" {
_ = channel.Reject(ssh.UnknownChannelType, "Unknown channel type") _ = channel.Reject(ssh.UnknownChannelType, "Unknown channel type")
@ -104,7 +109,7 @@ func handleConnexion(channels <-chan ssh.NewChannel, keyID uint) {
payloadCmd = payloadCmd[i:] 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.Stderr().Write([]byte("Opengist: " + err.Error() + "\r\n"))
} }
_, _ = ch.SendRequest("exit-status", false, []byte{0, 0, 0, 0}) _, _ = ch.SendRequest("exit-status", false, []byte{0, 0, 0, 0})

View file

@ -1,7 +1,10 @@
package web package web
import ( import (
"errors"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
"gorm.io/gorm"
"opengist/internal/config" "opengist/internal/config"
"opengist/internal/models" "opengist/internal/models"
) )
@ -80,6 +83,10 @@ func processLogin(ctx echo.Context) error {
var user *models.User var user *models.User
if user, err = models.GetUserByUsername(dto.Username); err != nil { 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") addFlash(ctx, "Invalid credentials", "error")
return redirect(ctx, "/login") return redirect(ctx, "/login")
} }
@ -88,6 +95,7 @@ func processLogin(ctx echo.Context) error {
if err != nil { if err != nil {
return errorRes(500, "Cannot check for password", err) return errorRes(500, "Cannot check for password", err)
} }
log.Warn().Msg("Invalid HTTP authentication attempt from " + ctx.RealIP())
addFlash(ctx, "Invalid credentials", "error") addFlash(ctx, "Invalid credentials", "error")
return redirect(ctx, "/login") return redirect(ctx, "/login")
} }

View file

@ -6,6 +6,7 @@ import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
"net/http" "net/http"
"opengist/internal/git" "opengist/internal/git"
"opengist/internal/models" "opengist/internal/models"
@ -84,6 +85,7 @@ func gitHttp(ctx echo.Context) error {
if err != nil { if err != nil {
return errorRes(500, "Cannot verify password", err) return errorRes(500, "Cannot verify password", err)
} }
log.Warn().Msg("Invalid HTTP authentication attempt from " + ctx.RealIP())
return errorRes(403, "Unauthorized", nil) return errorRes(403, "Unauthorized", nil)
} }

View file

@ -107,11 +107,12 @@ func Start() {
Getter: middleware.MethodFromForm("_method"), Getter: middleware.MethodFromForm("_method"),
})) }))
e.Pre(middleware.RemoveTrailingSlash()) e.Pre(middleware.RemoveTrailingSlash())
e.Use(middleware.CORS()) e.Pre(middleware.CORS())
e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ e.Pre(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
LogURI: true, LogStatus: true, LogMethod: true, LogURI: true, LogStatus: true, LogMethod: true,
LogValuesFunc: func(ctx echo.Context, v middleware.RequestLoggerValues) error { LogValuesFunc: func(ctx echo.Context, v middleware.RequestLoggerValues) error {
log.Info().Str("URI", v.URI).Int("status", v.Status).Str("method", v.Method). log.Info().Str("URI", v.URI).Int("status", v.Status).Str("method", v.Method).
Str("ip", ctx.RealIP()).
Msg("HTTP") Msg("HTTP")
return nil return nil
}, },