Authenticated (user role) SQL injection in `OrderAndPaginate` (GHSL-2023-270)
Description
Nginx-UI is an online statistics for Server Indicators Monitor CPU usage, memory usage, load average, and disk usage in real-time. This issue may lead to information disclosure. By using DefaultQuery, the "desc" and "id" values are used as default values if the query parameters are not set. Thus, the order and sort_by query parameter are user-controlled and are being appended to the order variable without any sanitization. This issue has been patched in version 2.0.0.beta.9.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Nginx-UI before 2.0.0.beta.9 is vulnerable to SQL injection via unsanitized 'order' and 'sort_by' query parameters, leading to information disclosure.
Vulnerability
CVE-2024-22196 is a SQL injection vulnerability in Nginx-UI, a web interface for Nginx. The OrderAndPaginate and SortOrder functions construct database queries by directly appending user-controlled order and sort_by query parameters without sanitization [1][2]. This occurs in the cosy package, where DefaultQuery is used to supply default values, but the parameters are concatenated into a raw SQL ORDER BY clause [4].
Exploitation
An authenticated attacker can exploit this by sending a crafted sort_by parameter to endpoints that use OrderAndPaginate, such as GET /api/dns_credentials [4]. For example, a request like ?sort_by=(CASE WHEN (SELECT 1)=1 THEN id ELSE updated_at END) ASC -- allows the attacker to infer information based on the ordering of results, effectively performing a blind SQL injection [4]. No special privileges beyond a valid user role are required.
Impact
Successful exploitation allows an attacker to retrieve arbitrary data from the database, leading to information disclosure [2][4]. The attacker can enumerate records, extract credentials, or other sensitive information stored in the application's database.
Mitigation
The issue has been patched in version 2.0.0.beta.9 [1][2]. The fix validates that the sort_by parameter corresponds to an existing database column and restricts the order parameter to only asc or desc [3]. Users should upgrade immediately. There is no known workaround; the KEV catalog does not list this CVE as of publication.
AI Insight generated on May 20, 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/0xJacky/Nginx-UIGo | < 2.0.0.beta.9 | 2.0.0.beta.9 |
Affected products
2- 0xJacky/nginx-uiv5Range: < 2.0.0.beta.9
Patches
1ec93ab05a3ecfix: ensure the list sort query is validated to prevent SQL injection
2 files changed · +34 −10
api/cosy/sort.go+20 −8 modified@@ -2,27 +2,39 @@ package cosy import ( "fmt" + "github.com/0xJacky/Nginx-UI/internal/logger" "github.com/gin-gonic/gin" "gorm.io/gorm" + "gorm.io/gorm/schema" + "sync" ) func (c *Ctx[T]) SortOrder() func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB { sort := c.ctx.DefaultQuery("order", "desc") - order := fmt.Sprintf("%s %s", DefaultQuery(c.ctx, "sort_by", c.itemKey), sort) - return db.Order(order) + if sort != "desc" && sort != "asc" { + sort = "desc" + } + + // check if the order field is valid + // todo: maybe we can use more generic way to check if the sort_by is valid + order := DefaultQuery(c.ctx, "sort_by", c.itemKey) + s, _ := schema.Parse(c.Model, &sync.Map{}, schema.NamingStrategy{}) + if _, ok := s.FieldsByDBName[order]; ok { + order = fmt.Sprintf("%s %s", order, sort) + return db.Order(order) + } else { + logger.Error("invalid order field:", order) + } + + return db } } func (c *Ctx[T]) OrderAndPaginate() func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB { - sort := c.ctx.DefaultQuery("order", "desc") - - order := fmt.Sprintf("%s %s", DefaultQuery(c.ctx, "sort_by", c.itemKey), sort) - db = db.Order(order) - + db = c.SortOrder()(db) _, offset, pageSize := GetPagingParams(c.ctx) - return db.Offset(offset).Limit(pageSize) } }
model/model.go+14 −2 modified@@ -10,8 +10,10 @@ import ( "gorm.io/gen" "gorm.io/gorm" gormlogger "gorm.io/gorm/logger" + "gorm.io/gorm/schema" "path" "strings" + "sync" "time" ) @@ -100,9 +102,19 @@ func SortOrder(c *gin.Context) func(db *gorm.DB) *gorm.DB { func OrderAndPaginate(c *gin.Context) func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB { sort := c.DefaultQuery("order", "desc") + if sort != "desc" && sort != "asc" { + sort = "desc" + } - order := fmt.Sprintf("`%s` %s", DefaultQuery(c, "sort_by", "id"), sort) - db = db.Order(order) + // check if the order field is valid + order := c.DefaultQuery("sort_by", "id") + s, _ := schema.Parse(db.Model, &sync.Map{}, schema.NamingStrategy{}) + if _, ok := s.FieldsByName[order]; ok { + order = fmt.Sprintf("%s %s", order, sort) + db = db.Order(order) + } else { + logger.Error("invalid order field: ", order) + } page := cast.ToInt(c.Query("page")) if page == 0 {
Vulnerability mechanics
Synthesis attempt was rejected by the grounding validator. Re-run pending.
References
7- github.com/advisories/GHSA-h374-mm57-879cghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-22196ghsaADVISORY
- github.com/0xJacky/nginx-ui/commit/ec93ab05a3ecbb6bcf464d9dca48d74452df8a5bghsax_refsource_MISCWEB
- github.com/0xJacky/nginx-ui/security/advisories/GHSA-h374-mm57-879cghsax_refsource_CONFIRMWEB
- github.com/0xjacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/model/model.goghsaWEB
- github.com/0xjacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/model/model.goghsaWEB
- github.com/0xjacky/nginx-ui/blob/04bf8ec487f06ab17a9fb7f34a28766e5f53885e/model/model.goghsaWEB
News mentions
0No linked articles in our index yet.