From 92b5ce37224a9eaf8e3409517f85b34396868a25 Mon Sep 17 00:00:00 2001 From: Coki <92775570+HashCookie@users.noreply.github.com> Date: Wed, 29 Jan 2025 18:30:06 +0800 Subject: [PATCH] feat: add identifier validation for security in RunCasbinCommand (#3535) * feat: add identifier validation for security in RunCasbinCommand * refactor: update identifier validation to use SHA-256 hash and timestamp --- controllers/casbin_cli_api.go | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/controllers/casbin_cli_api.go b/controllers/casbin_cli_api.go index 1d7f227a..c04ccc80 100644 --- a/controllers/casbin_cli_api.go +++ b/controllers/casbin_cli_api.go @@ -15,11 +15,15 @@ package controllers import ( + "crypto/sha256" + "encoding/hex" "encoding/json" "fmt" "os" "os/exec" + "sort" "strings" + "time" ) func processArgsToTempFiles(args []string) ([]string, []string, error) { @@ -57,6 +61,11 @@ func processArgsToTempFiles(args []string) ([]string, []string, error) { // @Success 200 {object} controllers.Response The Response object // @router /run-casbin-command [get] func (c *ApiController) RunCasbinCommand() { + if err := validateIdentifier(c); err != nil { + c.ResponseError(err.Error()) + return + } + language := c.Input().Get("language") argString := c.Input().Get("args") @@ -112,3 +121,58 @@ func (c *ApiController) RunCasbinCommand() { output = strings.TrimSuffix(output, "\n") c.ResponseOk(output) } + +// validateIdentifier +// @Title validateIdentifier +// @Description Validate the request hash and timestamp +// @Param hash string The SHA-256 hash string +// @Return error Returns error if validation fails, nil if successful +func validateIdentifier(c *ApiController) error { + language := c.Input().Get("language") + args := c.Input().Get("args") + hash := c.Input().Get("m") + timestamp := c.Input().Get("t") + + if hash == "" || timestamp == "" || language == "" || args == "" { + return fmt.Errorf("invalid identifier") + } + + requestTime, err := time.Parse(time.RFC3339, timestamp) + if err != nil { + return fmt.Errorf("invalid identifier") + } + timeDiff := time.Since(requestTime) + if timeDiff > 5*time.Minute || timeDiff < -5*time.Minute { + return fmt.Errorf("invalid identifier") + } + + params := map[string]string{ + "language": language, + "args": args, + } + + keys := make([]string, 0, len(params)) + for k := range params { + keys = append(keys, k) + } + sort.Strings(keys) + + var paramParts []string + for _, k := range keys { + paramParts = append(paramParts, fmt.Sprintf("%s=%s", k, params[k])) + } + paramString := strings.Join(paramParts, "&") + + version := "casbin-editor-v1" + rawString := fmt.Sprintf("%s|%s|%s", version, timestamp, paramString) + + hasher := sha256.New() + hasher.Write([]byte(rawString)) + + calculatedHash := strings.ToLower(hex.EncodeToString(hasher.Sum(nil))) + if calculatedHash != strings.ToLower(hash) { + return fmt.Errorf("invalid identifier") + } + + return nil +}