Skip to content

Commit ab4c440

Browse files
committed
4.2.4
1 parent bd88a5b commit ab4c440

File tree

15 files changed

+223
-103
lines changed

15 files changed

+223
-103
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ Path : JDK安装目录\bin
111111

112112
```
113113
Linux: mkdir /home/nginxWebUI/
114-
wget -O /home/nginxWebUI/nginxWebUI.jar https://gitee.com/cym1102/nginxWebUI/releases/download/4.2.2/nginxWebUI-4.2.2.jar
114+
wget -O /home/nginxWebUI/nginxWebUI.jar https://gitee.com/cym1102/nginxWebUI/releases/download/4.2.4/nginxWebUI-4.2.4.jar
115115
116-
Windows: 直接使用浏览器下载 https://gitee.com/cym1102/nginxWebUI/releases/download/4.2.2/nginxWebUI-4.2.2.jar 到 D:/home/nginxWebUI/nginxWebUI.jar
116+
Windows: 直接使用浏览器下载 https://gitee.com/cym1102/nginxWebUI/releases/download/4.2.4/nginxWebUI-4.2.4.jar 到 D:/home/nginxWebUI/nginxWebUI.jar
117117
```
118118

119119
有新版本只需要修改路径中的版本即可

README_EN.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ reboot
107107

108108
```
109109
Linux: mkdir /home/nginxWebUI/
110-
wget -O /home/nginxWebUI/nginxWebUI.jar https://gitee.com/cym1102/nginxWebUI/releases/download/4.2.2/nginxWebUI-4.2.2.jar
110+
wget -O /home/nginxWebUI/nginxWebUI.jar https://gitee.com/cym1102/nginxWebUI/releases/download/4.2.4/nginxWebUI-4.2.4.jar
111111
112-
Windows: Download directly from your browser https://gitee.com/cym1102/nginxWebUI/releases/download/4.2.2/nginxWebUI-4.2.2.jar into D:/home/nginxWebUI/
112+
Windows: Download directly from your browser https://gitee.com/cym1102/nginxWebUI/releases/download/4.2.4/nginxWebUI-4.2.4.jar into D:/home/nginxWebUI/
113113
```
114114

115115
With a new version, you just need to change the version in the path

pom.xml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
1+
<project xmlns="http://maven.apache.org/POM/4.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
24

35
<parent>
46
<groupId>org.noear</groupId>
@@ -9,7 +11,7 @@
911
<modelVersion>4.0.0</modelVersion>
1012
<groupId>com.cym</groupId>
1113
<artifactId>nginxWebUI</artifactId>
12-
<version>4.2.2</version>
14+
<version>4.2.4</version>
1315

1416
<properties>
1517
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -27,7 +29,7 @@
2729
<easy-captcha.version>1.6.2</easy-captcha.version>
2830
<jackson-annotations.version>2.13.1</jackson-annotations.version>
2931
<maven-model.version>3.0</maven-model.version>
30-
<expiringmap.version>0.5.10</expiringmap.version>
32+
<expiringmap.version>0.5.11</expiringmap.version>
3133
</properties>
3234

3335
<dependencies>
@@ -67,7 +69,7 @@
6769
<artifactId>h2</artifactId>
6870
<version>${h2.version}</version>
6971
</dependency>
70-
72+
7173
<dependency>
7274
<groupId>org.xerial</groupId>
7375
<artifactId>sqlite-jdbc</artifactId>

src/main/java/com/cym/controller/adminPage/ConfController.java

Lines changed: 103 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package com.cym.controller.adminPage;
22

33
import java.io.File;
4-
import java.io.InputStream;
54
import java.nio.charset.StandardCharsets;
5+
import java.nio.file.Path;
6+
import java.nio.file.Paths;
67
import java.util.HashMap;
78
import java.util.List;
89
import java.util.Map;
@@ -31,11 +32,10 @@
3132

3233
import cn.hutool.core.codec.Base64;
3334
import cn.hutool.core.io.FileUtil;
34-
import cn.hutool.core.io.resource.ClassPathResource;
35+
import cn.hutool.core.io.file.PathUtil;
3536
import cn.hutool.core.util.CharsetUtil;
3637
import cn.hutool.core.util.RuntimeUtil;
3738
import cn.hutool.core.util.StrUtil;
38-
import cn.hutool.core.util.ZipUtil;
3939
import cn.hutool.json.JSONArray;
4040
import cn.hutool.json.JSONObject;
4141
import cn.hutool.json.JSONUtil;
@@ -269,22 +269,61 @@ public JsonResult check(String nginxPath, String nginxExe, String nginxDir, Stri
269269
@Mapping(value = "saveCmd")
270270
public JsonResult saveCmd(String nginxPath, String nginxExe, String nginxDir) {
271271
nginxPath = ToolUtils.handlePath(nginxPath);
272-
settingService.set("nginxPath", nginxPath);
273-
274272
nginxExe = ToolUtils.handlePath(nginxExe);
275-
settingService.set("nginxExe", nginxExe);
276-
277273
nginxDir = ToolUtils.handlePath(nginxDir);
278-
settingService.set("nginxDir", nginxDir);
274+
275+
if (StrUtil.isNotEmpty(nginxPath) && !isFile(nginxPath)) {
276+
nginxPath = null;
277+
}
278+
if (StrUtil.isNotEmpty(nginxDir) && !isFile(nginxDir)) {
279+
nginxDir = null;
280+
}
281+
if (StrUtil.isNotEmpty(nginxExe) && !isFile(nginxExe) && !isSafeCmd(nginxExe)) {
282+
nginxExe = null;
283+
}
284+
if (StrUtil.isNotEmpty(nginxExe) && isFile(nginxExe) && !isSafeEnd(nginxExe)) {
285+
nginxExe = null;
286+
}
287+
288+
if (nginxPath != null) {
289+
settingService.set("nginxPath", nginxPath);
290+
System.out.println("nginxPath -> " + nginxPath);
291+
}
292+
if (nginxExe != null) {
293+
settingService.set("nginxExe", nginxExe);
294+
System.out.println("nginxExe -> " + nginxExe);
295+
}
296+
if (nginxDir != null) {
297+
settingService.set("nginxDir", nginxDir);
298+
System.out.println("nginxDir -> " + nginxDir);
299+
}
279300

280301
Map<String, String> map = new HashMap<>();
281302
map.put("nginxPath", nginxPath);
282303
map.put("nginxExe", nginxExe);
283304
map.put("nginxDir", nginxDir);
284-
305+
System.out.println("");
285306
return renderSuccess(map);
286307
}
287308

309+
private boolean isSafeEnd(String nginxExe) {
310+
return nginxExe.endsWith("nginx") //
311+
|| nginxExe.endsWith("openresty") //
312+
|| nginxExe.endsWith("nginx.exe") //
313+
|| nginxExe.endsWith("openrestys.exe");
314+
}
315+
316+
private boolean isSafeCmd(String nginxExe) {
317+
return nginxExe.equals("nginx") //
318+
|| nginxExe.equals("openresty") //
319+
|| nginxExe.equals("nginx.exe") //
320+
|| nginxExe.equals("openrestys.exe");
321+
}
322+
323+
private boolean isFile(String path) {
324+
return FileUtil.isDirectory(path) || FileUtil.isFile(path);
325+
}
326+
288327
@Mapping(value = "reload")
289328
public synchronized JsonResult reload(String nginxPath, String nginxExe, String nginxDir) {
290329
if (nginxPath == null) {
@@ -308,7 +347,7 @@ public synchronized JsonResult reload(String nginxPath, String nginxExe, String
308347
String rs = RuntimeUtil.execForStr(cmd);
309348

310349
cmd = "<span class='blue'>" + cmd + "</span>";
311-
if (!rs.contains("[error]")) {
350+
if (!rs.contains("[error]") && !rs.contains("[emerg]")) {
312351
return renderSuccess(cmd + "<br>" + m.get("confStr.reloadSuccess") + "<br>" + rs.replace("\n", "<br>"));
313352
} else {
314353
if (rs.contains("The system cannot find the file specified") || rs.contains("nginx.pid") || rs.contains("PID")) {
@@ -331,7 +370,8 @@ public JsonResult runCmd(String cmd, String type) {
331370
}
332371

333372
// 仅执行nginx相关的命令,而不是其他的恶意命令
334-
if (!isAvailableCmd(cmd)) {
373+
cmd = buildRealCmd(cmd);
374+
if (StrUtil.isEmpty(cmd)) {
335375
return renderSuccess(m.get("confStr.notAvailableCmd"));
336376
}
337377

@@ -359,17 +399,12 @@ public JsonResult runCmd(String cmd, String type) {
359399
}
360400
}
361401

362-
// 仅执行nginx相关的命令,而不是其他的恶意命令
363-
private boolean isAvailableCmd(String cmd) {
364-
// 过滤数据库中的路径
365-
String nginxPath = ToolUtils.handleConf(settingService.get("nginxPath"));
366-
settingService.set("nginxPath", nginxPath);
367-
String nginxExe = ToolUtils.handleConf(settingService.get("nginxExe"));
368-
settingService.set("nginxExe", nginxExe);
369-
String nginxDir = ToolUtils.handleConf(settingService.get("nginxDir"));
370-
settingService.set("nginxDir", nginxDir);
402+
private String buildRealCmd(String cmd) {
403+
String dir = "";
404+
if (StrUtil.isNotEmpty(settingService.get("nginxDir"))) {
405+
dir = " -p " + settingService.get("nginxDir");
406+
}
371407

372-
// 检查命令格式
373408
switch (cmd) {
374409
case "net start nginx":
375410
case "service nginx start":
@@ -379,27 +414,58 @@ private boolean isAvailableCmd(String cmd) {
379414
case "systemctl stop nginx":
380415
case "taskkill /f /im nginx.exe":
381416
case "pkill nginx":
382-
return true;
383-
default:
384-
break;
385-
}
386-
387-
String dir = "";
388-
if (StrUtil.isNotEmpty(settingService.get("nginxDir"))) {
389-
dir = " -p " + settingService.get("nginxDir");
390-
}
417+
return cmd;
391418

392-
if (cmd.equals(settingService.get("nginxExe") + " -s stop" + dir)) {
393-
return true;
419+
case "stopNormal":
420+
return settingService.get("nginxExe") + " -s stop" + dir;
421+
case "startNormal":
422+
return settingService.get("nginxExe") + " -c " + settingService.get("nginxPath") + dir;
394423
}
395424

396-
if (cmd.equals(settingService.get("nginxExe") + " -c " + settingService.get("nginxPath") + dir)) {
397-
return true;
398-
}
399-
400-
return false;
425+
return null;
401426
}
402427

428+
// // 仅执行nginx相关的命令,而不是其他的恶意命令
429+
// private boolean isAvailableCmd(String cmd) {
430+
// // 过滤数据库中的路径
431+
// String nginxPath = ToolUtils.handleConf(settingService.get("nginxPath"));
432+
// settingService.set("nginxPath", nginxPath);
433+
// String nginxExe = ToolUtils.handleConf(settingService.get("nginxExe"));
434+
// settingService.set("nginxExe", nginxExe);
435+
// String nginxDir = ToolUtils.handleConf(settingService.get("nginxDir"));
436+
// settingService.set("nginxDir", nginxDir);
437+
//
438+
// // 检查命令格式
439+
// switch (cmd) {
440+
// case "net start nginx":
441+
// case "service nginx start":
442+
// case "systemctl start nginx":
443+
// case "net stop nginx":
444+
// case "service nginx stop":
445+
// case "systemctl stop nginx":
446+
// case "taskkill /f /im nginx.exe":
447+
// case "pkill nginx":
448+
// return true;
449+
// default:
450+
// break;
451+
// }
452+
//
453+
// String dir = "";
454+
// if (StrUtil.isNotEmpty(settingService.get("nginxDir"))) {
455+
// dir = " -p " + settingService.get("nginxDir");
456+
// }
457+
//
458+
// if (cmd.equals(settingService.get("nginxExe") + " -s stop" + dir)) {
459+
// return true;
460+
// }
461+
//
462+
// if (cmd.equals(settingService.get("nginxExe") + " -c " + settingService.get("nginxPath") + dir)) {
463+
// return true;
464+
// }
465+
//
466+
// return false;
467+
// }
468+
403469
@Mapping(value = "getLastCmd")
404470
public JsonResult getLastCmd(String type) {
405471
return renderSuccess(settingService.get(type));

src/main/java/com/cym/controller/adminPage/WwwController.java

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
package com.cym.controller.adminPage;
22

3+
import java.io.File;
4+
import java.io.FileInputStream;
5+
import java.io.IOException;
36
import java.net.URL;
47
import java.nio.charset.Charset;
8+
import java.util.zip.ZipEntry;
9+
import java.util.zip.ZipFile;
10+
import java.util.zip.ZipInputStream;
511

12+
import cn.hutool.core.util.CharsetUtil;
613
import cn.hutool.core.util.StrUtil;
714
import org.noear.solon.annotation.Controller;
815
import org.noear.solon.annotation.Inject;
@@ -43,12 +50,19 @@ public JsonResult addOver(Www www, String dirTemp) {
4350
}
4451

4552
try {
46-
// FileUtil.clean(www.getDir()); //太危险不要删了文件夹了
53+
try {
54+
if (!checkZipSafe(dirTemp, www.getDir(), CharsetUtil.defaultCharset())) {
55+
return renderError(m.get("wwwStr.zipNotSafe"));
56+
}
57+
} catch (IllegalArgumentException e) {
58+
if (!checkZipSafe(dirTemp, www.getDir(), Charset.forName("GBK"))) {
59+
return renderError(m.get("wwwStr.zipNotSafe"));
60+
}
61+
}
4762

4863
try {
4964
ZipUtil.unzip(dirTemp, www.getDir());
50-
} catch (Exception e) {
51-
// 默认UTF-8下不能解压中文字符, 尝试使用gbk
65+
} catch (IllegalArgumentException e) {
5266
ZipUtil.unzip(dirTemp, www.getDir(), Charset.forName("GBK"));
5367
}
5468

@@ -63,20 +77,69 @@ public JsonResult addOver(Www www, String dirTemp) {
6377

6478
return renderError(m.get("wwwStr.zipError"));
6579
}
66-
80+
81+
/**
82+
* 检查zip是否包含../目录
83+
*
84+
* @param dirTemp
85+
* @param dir
86+
* @param charset
87+
* @return
88+
*/
89+
private boolean checkZipSafe(String dirTemp, String dir, Charset charset) {
90+
File zipFile = new File(dirTemp);
91+
File outputFolder = new File(dir);
92+
ZipInputStream zis = null;
93+
94+
try {
95+
zis = new ZipInputStream(new FileInputStream(zipFile), charset);
96+
ZipEntry entry = null;
97+
while ((entry = zis.getNextEntry()) != null) {
98+
String name = entry.getName();
99+
// 检查并阻止任何尝试跳转到父目录的尝试
100+
if (name.contains("..") || name.startsWith("/") || name.startsWith("\\")) {
101+
return false;
102+
}
103+
104+
// 通常还需要检查解压后文件的完整路径,以确保它仍然位于输出文件夹内
105+
File file = new File(outputFolder, name);
106+
if (!file.getCanonicalPath().startsWith(outputFolder.getCanonicalPath())) {
107+
return false;
108+
}
109+
}
110+
} catch (IllegalArgumentException e) {
111+
logger.error(e.getMessage(), e);
112+
throw e;
113+
} catch (IOException e) {
114+
logger.error(e.getMessage(), e);
115+
return false;
116+
} finally {
117+
try {
118+
if (zis != null) {
119+
zis.close();
120+
}
121+
} catch (IOException e) {
122+
logger.error(e.getMessage(), e);
123+
}
124+
}
125+
126+
return true;
127+
128+
}
129+
67130
@Mapping("clean")
68131
public JsonResult clean(String id) {
69132
Www www = sqlHelper.findById(id, Www.class);
70-
133+
71134
FileUtil.clean(www.getDir());
72-
135+
73136
return renderSuccess();
74137
}
75138

76139
@Mapping("del")
77140
public JsonResult del(String id) {
78141
String[] ids = id.split(",");
79-
142+
80143
sqlHelper.deleteByIds(ids, Www.class);
81144

82145
return renderSuccess();

src/main/java/com/cym/service/ConfService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,15 +325,15 @@ public void buildDenyAllow(NgxBlock ngxBlock, String type, String id, ConfExt co
325325
List<String> strs = new ArrayList<>();
326326
if (denyAllowValue == 1) {
327327
// 黑名单
328-
strs.add("allow all;");
329-
330328
DenyAllow denyAllow = sqlHelper.findById(denyId, DenyAllow.class);
331329
if (denyAllow != null) {
332330
String[] ips = denyAllow.getIp().split("\n");
333331
for (String ip : ips) {
334332
strs.add("deny " + ip.trim() + ";");
335333
}
336334
}
335+
336+
strs.add("allow all;");
337337
}
338338
if (denyAllowValue == 2) {
339339
// 白名单

0 commit comments

Comments
 (0)