【修复】漏洞修复(CVE-2025-7787),针对 httpJobHandler 支持配置URL白名单限制,防止服务器端请求伪造(SSRF)攻击。

3.2.0-release
xuxueli 4 weeks ago
parent bcccdf64f3
commit c741d8361e

@ -2545,7 +2545,9 @@ public void execute() {
### 7.40 版本 v3.2.0 Release Notes[规划中] ### 7.40 版本 v3.2.0 Release Notes[规划中]
- 1、【强化】AI任务ollamaJobHandler优化针对 “model” 模型配置信息,从执行器侧文件类配置调整至调度中心“任务参数”动态配置,支持集成多模型、并结合任务动态配置切换。 - 1、【强化】AI任务ollamaJobHandler优化针对 “model” 模型配置信息,从执行器侧文件类配置调整至调度中心“任务参数”动态配置,支持集成多模型、并结合任务动态配置切换。
- 2、【升级】升级多项maven依赖至较新版本如 spring-ai、dify 等; - 2、【修复】漏洞修复CVE-2025-7787针对 httpJobHandler 支持配置URL白名单限制防止服务器端请求伪造SSRF攻击。
- 3、【升级】升级多项maven依赖至较新版本如 spring-ai、dify 等;
- 3、【规划中】登录安全升级密码加密处理算法从Md5改为Sha256 - 3、【规划中】登录安全升级密码加密处理算法从Md5改为Sha256
``` ```
// 1、用户表password字段需要调整长度执行如下命令 // 1、用户表password字段需要调整长度执行如下命令

@ -149,7 +149,8 @@ VALUES (1, 1, '示例任务01', now(), now(), 'XXL', '', 'CRON', '0 0 0 * * ? *'
(2, 2, 'Ollama示例任务01', now(), now(), 'XXL', '', 'NONE', '', (2, 2, 'Ollama示例任务01', now(), now(), 'XXL', '', 'NONE', '',
'DO_NOTHING', 'FIRST', 'ollamaJobHandler', '{ 'DO_NOTHING', 'FIRST', 'ollamaJobHandler', '{
"input": "慢SQL问题分析思路", "input": "慢SQL问题分析思路",
"prompt": "你是一个研发工程师,擅长解决技术类问题。" "prompt": "你是一个研发工程师,擅长解决技术类问题。",
"model": "qwen3:0.6b"
}', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE', }', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE',
now(), ''), now(), ''),
(3, 2, 'Dify示例任务', now(), now(), 'XXL', '', 'NONE', '', (3, 2, 'Dify示例任务', now(), now(), 'XXL', '', 'NONE', '',

@ -12,8 +12,11 @@ import java.io.DataOutputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -83,7 +86,7 @@ public class SampleXxlJob {
BufferedReader bufferedReader = null; BufferedReader bufferedReader = null;
try { try {
// valid // valid
if (command==null || command.trim().length()==0) { if (command==null || command.trim().isEmpty()) {
XxlJobHelper.handleFail("command empty."); XxlJobHelper.handleFail("command empty.");
return; return;
} }
@ -168,15 +171,18 @@ public class SampleXxlJob {
} }
// param valid // param valid
if (url==null || url.trim().length()==0) { if (url==null || url.trim().isEmpty()) {
XxlJobHelper.log("url["+ url +"] invalid."); XxlJobHelper.log("url["+ url +"] invalid.");
XxlJobHelper.handleFail();
return;
}
if (!isValidDomain( url)) {
XxlJobHelper.log("url["+ url +"] not allowed.");
XxlJobHelper.handleFail(); XxlJobHelper.handleFail();
return; return;
} }
if (method==null || !Arrays.asList("GET", "POST").contains(method.toUpperCase())) { if (method==null || !Arrays.asList("GET", "POST").contains(method.toUpperCase())) {
XxlJobHelper.log("method["+ method +"] invalid."); XxlJobHelper.log("method["+ method +"] invalid.");
XxlJobHelper.handleFail(); XxlJobHelper.handleFail();
return; return;
} }
@ -206,9 +212,9 @@ public class SampleXxlJob {
connection.connect(); connection.connect();
// data // data
if (isPostMethod && data!=null && data.trim().length()>0) { if (isPostMethod && data!=null && !data.trim().isEmpty()) {
DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream()); DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
dataOutputStream.write(data.getBytes("UTF-8")); dataOutputStream.write(data.getBytes(StandardCharsets.UTF_8));
dataOutputStream.flush(); dataOutputStream.flush();
dataOutputStream.close(); dataOutputStream.close();
} }
@ -220,7 +226,7 @@ public class SampleXxlJob {
} }
// result // result
bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
String line; String line;
while ((line = bufferedReader.readLine()) != null) { while ((line = bufferedReader.readLine()) != null) {
@ -251,6 +257,25 @@ public class SampleXxlJob {
} }
// domain white-list, for httpJobHandler
private static Set<String> DOMAIN_WHITE_LIST = new HashSet<String>(Arrays.asList(
"http://www.baidu.com",
"http://cn.bing.com"
));
// valid if domain is in white-list
private boolean isValidDomain(String url) {
if (url == null || DOMAIN_WHITE_LIST.isEmpty()) {
return false;
}
for (String prefix : DOMAIN_WHITE_LIST) {
if (url.startsWith(prefix)) {
return true;
}
}
return false;
}
/** /**
* 5 * 5
*/ */

@ -13,8 +13,11 @@ import java.io.DataOutputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -170,15 +173,18 @@ public class SampleXxlJob {
} }
// param valid // param valid
if (url==null || url.trim().length()==0) { if (url==null || url.trim().isEmpty()) {
XxlJobHelper.log("url["+ url +"] invalid."); XxlJobHelper.log("url["+ url +"] invalid.");
XxlJobHelper.handleFail();
return;
}
if (!isValidDomain( url)) {
XxlJobHelper.log("url["+ url +"] not allowed.");
XxlJobHelper.handleFail(); XxlJobHelper.handleFail();
return; return;
} }
if (method==null || !Arrays.asList("GET", "POST").contains(method.toUpperCase())) { if (method==null || !Arrays.asList("GET", "POST").contains(method.toUpperCase())) {
XxlJobHelper.log("method["+ method +"] invalid."); XxlJobHelper.log("method["+ method +"] invalid.");
XxlJobHelper.handleFail(); XxlJobHelper.handleFail();
return; return;
} }
@ -208,9 +214,9 @@ public class SampleXxlJob {
connection.connect(); connection.connect();
// data // data
if (isPostMethod && data!=null && data.trim().length()>0) { if (isPostMethod && data!=null && !data.trim().isEmpty()) {
DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream()); DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
dataOutputStream.write(data.getBytes("UTF-8")); dataOutputStream.write(data.getBytes(StandardCharsets.UTF_8));
dataOutputStream.flush(); dataOutputStream.flush();
dataOutputStream.close(); dataOutputStream.close();
} }
@ -222,7 +228,7 @@ public class SampleXxlJob {
} }
// result // result
bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
String line; String line;
while ((line = bufferedReader.readLine()) != null) { while ((line = bufferedReader.readLine()) != null) {
@ -253,6 +259,24 @@ public class SampleXxlJob {
} }
// domain white-list, for httpJobHandler
private static Set<String> DOMAIN_WHITE_LIST = new HashSet<String>(Arrays.asList(
"http://www.baidu.com",
"http://cn.bing.com"
));
// valid if domain is in white-list
private boolean isValidDomain(String url) {
if (url == null || DOMAIN_WHITE_LIST.isEmpty()) {
return false;
}
for (String prefix : DOMAIN_WHITE_LIST) {
if (url.startsWith(prefix)) {
return true;
}
}
return false;
}
/** /**
* 5 * 5
*/ */

Loading…
Cancel
Save