CVE-2022-24124
Description
Casdoor before 1.13.1 has a SQL injection vulnerability in the query API's field parameter, allowing unauthorized database access.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Casdoor before 1.13.1 has a SQL injection vulnerability in the query API's field parameter, allowing unauthorized database access.
Vulnerability
Casdoor versions before 1.13.1 contain a SQL injection vulnerability in the query API, specifically in the GetSession function used for filtering results. The field and value parameters are directly concatenated into SQL queries without proper sanitization, as demonstrated in the api/get-organizations endpoint. The vulnerable code path is reachable when field and value parameters are supplied, and no authentication is required for this API endpoint. [1][2]
Exploitation
An attacker can exploit this vulnerability by sending crafted HTTP requests to the query API (e.g., api/get-organizations) with malicious input in the field parameter. The attacker does not need authentication or any special privileges. By injecting SQL commands into the field parameter, they can manipulate the underlying database query to extract arbitrary data. [1][3]
Impact
Successful exploitation allows an attacker to retrieve sensitive information from the Casdoor database, including user credentials, application configurations, and other stored data. This is a confidentiality impact, potentially leading to full compromise of the identity and access management system. [1][3]
Mitigation
The vulnerability is fixed in Casdoor version 1.13.1, released on January 26, 2022. The fix introduces a filterField validation function that restricts the field parameter to expected values, preventing direct SQL concatenation. Users should upgrade to version 1.13.1 or later. No workarounds were provided for earlier versions. [1][4]
- fix: fix the SQL injection vulnerability in field filter (#442) · casdoor/casdoor@5ec0c7a
- GitHub - casdoor/casdoor: An open-source Agent-first Identity and Access Management (IAM) /LLM MCP & agent gateway and auth server with web UI supporting OpenClaw, MCP, OAuth, OIDC, SAML, CAS, LDAP, SCIM, WebAuthn, TOTP, MFA, Face ID, Google Workspace, Azure AD
- NVD - CVE-2022-24124
- Comparing v1.13.0...v1.13.1 · casdoor/casdoor
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/casdoor/casdoorGo | < 1.13.1 | 1.13.1 |
Affected products
2Patches
15ec0c7a89005fix: fix the SQL injection vulnerability in field filter (#442)
14 files changed · +31 −59
object/adapter.go+8 −3 modified@@ -190,12 +190,17 @@ func (a *Adapter) createTable() { } func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session { - session := adapter.Engine.Limit(limit, offset).Where("1=1") + session := adapter.Engine.Prepare() + if offset != -1 && limit != -1 { + session.Limit(limit, offset) + } if owner != "" { session = session.And("owner=?", owner) } if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) + if filterField(field) { + session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) + } } if sortField == "" || sortOrder == "" { sortField = "created_time" @@ -206,4 +211,4 @@ func GetSession(owner string, offset, limit int, field, value, sortField, sortOr session = session.Desc(util.SnakeString(sortField)) } return session -} +} \ No newline at end of file
object/application.go+1 −4 modified@@ -56,10 +56,7 @@ type Application struct { } func GetApplicationCount(owner, field, value string) int { - session := adapter.Engine.Where("owner=?", owner) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession(owner, -1, -1, field, value, "", "") count, err := session.Count(&Application{}) if err != nil { panic(err)
object/cert.go+1 −4 modified@@ -53,10 +53,7 @@ func GetMaskedCerts(certs []*Cert) []*Cert { } func GetCertCount(owner, field, value string) int { - session := adapter.Engine.Where("owner=?", owner) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession(owner, -1, -1, field, value, "", "") count, err := session.Count(&Cert{}) if err != nil { panic(err)
object/check.go+9 −1 modified@@ -23,10 +23,14 @@ import ( goldap "github.com/go-ldap/ldap/v3" ) -var reWhiteSpace *regexp.Regexp +var ( + reWhiteSpace *regexp.Regexp + reFieldWhiteList *regexp.Regexp +) func init() { reWhiteSpace, _ = regexp.Compile(`\s`) + reFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`) } func CheckUserSignup(application *Application, organization *Organization, username string, password string, displayName string, email string, phone string, affiliation string) string { @@ -179,3 +183,7 @@ func CheckUserPassword(organization string, username string, password string) (* return user, "" } + +func filterField(field string) bool { + return reFieldWhiteList.MatchString(field) +} \ No newline at end of file
object/organization.go+1 −6 modified@@ -15,8 +15,6 @@ package object import ( - "fmt" - "github.com/casdoor/casdoor/cred" "github.com/casdoor/casdoor/util" "xorm.io/core" @@ -39,10 +37,7 @@ type Organization struct { } func GetOrganizationCount(owner, field, value string) int { - session := adapter.Engine.Where("owner=?", owner) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession(owner, -1, -1, field, value, "", "") count, err := session.Count(&Organization{}) if err != nil { panic(err)
object/permission.go+1 −4 modified@@ -39,10 +39,7 @@ type Permission struct { } func GetPermissionCount(owner, field, value string) int { - session := adapter.Engine.Where("owner=?", owner) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession(owner, -1, -1, field, value, "", "") count, err := session.Count(&Permission{}) if err != nil { panic(err)
object/provider.go+1 −4 modified@@ -81,10 +81,7 @@ func GetMaskedProviders(providers []*Provider) []*Provider { } func GetProviderCount(owner, field, value string) int { - session := adapter.Engine.Where("owner=?", owner) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession(owner, -1, -1, field, value, "", "") count, err := session.Count(&Provider{}) if err != nil { panic(err)
object/record.go+1 −4 modified@@ -102,10 +102,7 @@ func AddRecord(record *Record) bool { } func GetRecordCount(field, value string) int { - session := adapter.Engine.Where("1=1") - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession("", -1, -1, field, value, "", "") count, err := session.Count(&Record{}) if err != nil { panic(err)
object/resource.go+2 −5 modified@@ -40,11 +40,8 @@ type Resource struct { } func GetResourceCount(owner, user, field, value string) int { - session := adapter.Engine.Where("owner=? and user=?", owner, user) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } - count, err := session.Count(&Resource{}) + session := GetSession(owner, -1, -1, field, value, "", "") + count, err := session.Count(&Resource{User: user}) if err != nil { panic(err) }
object/role.go+1 −4 modified@@ -33,10 +33,7 @@ type Role struct { } func GetRoleCount(owner, field, value string) int { - session := adapter.Engine.Where("owner=?", owner) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession(owner, -1, -1, field, value, "", "") count, err := session.Count(&Role{}) if err != nil { panic(err)
object/syncer.go+1 −4 modified@@ -56,10 +56,7 @@ type Syncer struct { } func GetSyncerCount(owner, field, value string) int { - session := adapter.Engine.Where("owner=?", owner) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession(owner, -1, -1, field, value, "", "") count, err := session.Count(&Syncer{}) if err != nil { panic(err)
object/token.go+1 −4 modified@@ -57,10 +57,7 @@ type TokenWrapper struct { } func GetTokenCount(owner, field, value string) int { - session := adapter.Engine.Where("owner=?", owner) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession(owner, -1, -1, field, value, "", "") count, err := session.Count(&Token{}) if err != nil { panic(err)
object/user.go+2 −8 modified@@ -89,10 +89,7 @@ type User struct { } func GetGlobalUserCount(field, value string) int { - session := adapter.Engine.Where("1=1") - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession("", -1, -1, field, value, "", "") count, err := session.Count(&User{}) if err != nil { panic(err) @@ -123,10 +120,7 @@ func GetPaginationGlobalUsers(offset, limit int, field, value, sortField, sortOr } func GetUserCount(owner, field, value string) int { - session := adapter.Engine.Where("owner=?", owner) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession(owner, -1, -1, field, value, "", "") count, err := session.Count(&User{}) if err != nil { panic(err)
object/webhook.go+1 −4 modified@@ -43,10 +43,7 @@ type Webhook struct { } func GetWebhookCount(owner, field, value string) int { - session := adapter.Engine.Where("owner=?", owner) - if field != "" && value != "" { - session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value)) - } + session := GetSession(owner, -1, -1, field, value, "", "") count, err := session.Count(&Webhook{}) if err != nil { panic(err)
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-m358-g4rp-533rghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-24124ghsaADVISORY
- packetstormsecurity.com/files/166163/Casdoor-1.13.0-SQL-Injection.htmlghsax_refsource_MISCWEB
- github.com/casdoor/casdoor/commit/5ec0c7a89005819960d8fe07f5ddda13d1371b8cghsaWEB
- github.com/casdoor/casdoor/compare/v1.13.0...v1.13.1ghsax_refsource_MISCWEB
- github.com/casdoor/casdoor/issues/439ghsax_refsource_MISCWEB
- github.com/casdoor/casdoor/pull/442ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.