漏洞简述
Apache IoTDB 是面向IoT场景存储时序数据的数据管理系统,具备跟Grafana、spark等系统的集成能力。
4月8日,IoTDB 修复了其中 grafana-connector 模块中的 SQL 注入漏洞。
由于 grafana-connector 模块中 BasicDaoImpl 类的 querySeriesInternal 方法存在拼接 SQL 语句,导致攻击者可以构造请求实现 SQL 注入。该漏洞受影响版本为 0.13.0,是上个月发布的新版本,对企业影响很小。
漏洞发现时间 | 2022-04-08 |
标题 | iotdb 0.13.0 存在 SQL 注入漏洞 |
漏洞编号 | MPS-2022-7877 |
发现方式 | 墨菲安全实验室情报预警监控 |
语言 | java |
影响组件及版本 | org.apache.iotdb:iotdb-grafana-connector(影响版本:0.13.0 版本) |
漏洞描述 | iotdb 是针对时序数据的数据管理系统。 grafana-connector 中的 BasicDaoImpl.querySeriesInternal 存在拼接 sql 语句的情况,导致产生了 SQL 注入漏洞。 攻击者可利用该漏洞获取数据库中的敏感数据。 |
漏洞类型 | SQL 注入漏洞 |
排查方式 | 获取 org.apache.iotdb:iotdb-grafana-connector 版本,判断其版本 = 0.13.0 |
处置建议 | 官方暂未发布新版本,但提供了修改补丁,参考链接:https://github.com/apache/iotdb/pull/5450/commits/ |
影响范围 | 中 |
漏洞级别 | 高危 |
漏洞时间线
- 4月8日,IoTDB的开发者表示在 grafana-connector 模块中存在 SQL 注入风险,8 小时后修复了该漏洞。
漏洞分析
从漏洞修复的 commit 确定漏洞点,querySeriesInternal 方法将 String s 的内容拼接到 sql 语句中。
通过 querySeriesInternal 向上溯源寻找漏洞触发点,可以确定调用逻辑
DatabaseConnectController.query --> DatabaseConnectController.setJsonTable / DatabaseConnectController.setJsonTimeseries --> DatabaseConnectServiceImpl.querySeries --> BasicDaoImpl.querySeries --> BasicDaoImpl.querySeriesInternal
从上图确定触发点是 query 方法,注入需要寻找 “/query” 的请求体结构。
@
RequestBody
作用是接收前端传递给后端的 json 字符串中数据,所以 query 方法的参数需要是 json 字符串。该方法对 json 请求体进行解析。
104行 getTimeFromAndTo 方法,json 字符串需要有 range 参数,range 内部需要有 from 和 to 两个参数,且为 Instant 类型。
105行得知 json 有 targets 参数,107行知道 targets 参数是列表结构,114和115行得知列表每项有 type 和 target 参数,且 type 是 “table”和“timeserie”其中之一,故能导致 sql 注入的结构是
{
"targets": [
{
"target": "payload",
"type": "table / timeserie"
}
],
"range": {
"from": "2022-04-08T18:35:24.00Z",
"to": "2022-04-08T18:36:24.00Z"
}
}
传入拼接 SQL 的参数是 target,接着从上文提到的调用逻辑寻找,target 参数直接传入 BasicDaoImpl.querySeriesInternal 的 s 参数。
该方法中将传入的 target 参数(即 s )以最后一个“.”分割,拼接到 SQL 语句中。
该漏洞出现的原因是使用 SQL 语句的拼接,这是 SQL 注入最常出现的原因。
从使用场景来看是期望通过输入查询字段和表名来查询对应数据,针对这类场景需要限制输入的字段和表名为相应的白名单内容。
漏洞验证
当以如下json请求query
接口时
{"targets": [{"target": "SLOT1.SLOT2","type": "table"}], "range": {"from": "1970-01-01T00:00:00.150Z", "to": "1970-01-01T00:00:00.400Z"}}
sql会被拼接为
SELECT SLOT2 FROM root.SLOT1 WHERE time > 150 and time < 400
但在利用上,由于调用jdbcTemplate.query(sql, new TimeValuesRowMapper(columnName))
,会限制只能执行select语法,而不能有select into等数据修改的逻辑,也无法堆叠语句,存在一定的限制。