VYPR
High severityNVD Advisory· Published Jan 11, 2024· Updated Jun 17, 2025

Authenticated (user role) SQL injection in `OrderAndPaginate` (GHSL-2023-270)

CVE-2024-22196

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.

PackageAffected versionsPatched versions
github.com/0xJacky/Nginx-UIGo
< 2.0.0.beta.92.0.0.beta.9

Affected products

2

Patches

1
ec93ab05a3ec

fix: ensure the list sort query is validated to prevent SQL injection

https://github.com/0xJacky/nginx-uiHintayDec 19, 2023via ghsa
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

News mentions

0

No linked articles in our index yet.