## Jfinal cms Background directory traversal
### Introduction to Vulnerability
Jfinal cms, using the simple and powerful JFinal as the web framework, the template engine is beetl, the database uses mysql, front-end bootstrap, flat ui and other frameworks. Support multi-site, oauth2 authentication, account registration, password encryption, comments and replies, message prompts, website traffic statistics, article comments and pageview statistics, response management, rights management, etc. There is a directory traversal vulnerability in its background template management office.
### Vulnerability Impact
- <= v4.7.1
### Vulnerability Analysis
The vulnerability trigger point is in `com/jflyfox/modules/filemanager/FileManagerController.java`
```java
public void index() {
HttpServletRequest request = getRequest();
try {
request.setCharacterEncoding("UTF-8");
getResponse().setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
FileManager fm = new FileManager(getRequest());
JSONObject responseData = null;
String mode = "";
String path = "";
boolean needPath = false;
boolean putTextarea = false;
if (!auth()) {
fm.error(fm.lang("AUTHORIZATION_REQUIRED"));
} else {
String contextPath = request.getContextPath();
// 设置contextPath
fm.setGetVar("contextPath", contextPath);
mode = request.getParameter("mode");
path = request.getParameter("path");
if (path != null) {
try {
if (request.getMethod().equals("GET"))
path = new String(path.getBytes("ISO8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
needPath = fm.setGetVar("path", path);
}
if (request.getMethod().equals("GET")) {
if (mode != null && mode != "") {
if (mode.equals("getinfo")) {
if (needPath) {
responseData = fm.getInfo();
}
} else if (mode.equals("getfolder")) {
if (needPath) {
......
```
When the user's incoming mode is getfolder, you can call the `getfolder` method of `Filemanager` and follow `getFolder` of `com/jflyfox/modules/filemanager/FileManager.java`.
```java
public JSONObject getFolder() {
JSONObject array = null;
File dir = new File(getRealFilePath());
File file = null;
if (!dir.isDirectory()) {
this.error(sprintf(lang("DIRECTORY_NOT_EXIST"), this.get.get("path")));
} else {
if (!dir.canRead()) {
this.error(sprintf(lang("UNABLE_TO_OPEN_DIRECTORY"), this.get.get("path")));
} else {
array = new JSONObject();
String[] files = dir.list();
JSONObject data = null;
JSONObject props = null;
for (int i = 0; i < files.length; i++) {
data = new JSONObject();
props = new JSONObject();
file = new File(getRealFilePath() + files[i]);
if (file.isDirectory() && !contains(getConfig("unallowed_dirs"), files[i])) {
try {
props.put("Date Created", (String) null);
props.put("Date Modified", (String) null);
props.put("Height", (String) null);
props.put("Width", (String) null);
props.put("Size", (String) null);
data.put("Path", this.get.get("path") + files[i] + "/");
data.put("Filename", files[i]);
data.put("File Type", "dir");
data.put("Preview", getConfig("icons-path") + getConfig("icons-directory"));
// TODO 文件权限
data.put("Protected", 0);
data.put("Error", "");
data.put("Code", 0);
data.put("Properties", props);
array.put(this.get.get("path") + files[i] + "/", data);
} catch (JSONException e) {
this.error("JSONObject error");
}
} else if (!contains(getConfig("unallowed_files"), files[i])) {
this.item = new HashMap<String, Object>();
this.item.put("properties", this.properties);
this.getFileInfo(getFilePath() + files[i]);
if (this.params.get("type") == null
|| (this.params.get("type") != null && (!this.params.get("type").equals("Image") || this.params
.get("type").equals("Image")
&& contains(getConfig("images"), (String) this.item.get("filetype"))))) {
try {
data.put("Path", this.get.get("path") + files[i]);
data.put("Filename", this.item.get("filename"));
data.put("File Type", this.item.get("filetype"));
// TODO 文件权限
data.put("Protected", 0);
data.put("Preview", this.item.get("preview"));
data.put("Properties", this.item.get("properties"));
data.put("Error", "");
data.put("Code", 0);
array.put(this.get.get("path") + files[i], data);
} catch (JSONException e) {
this.error("JSONObject error");
}
}
}
}
}
}
return array;
}
```
There is no restriction on the path passed by the user, which leads to directory traversal.
### Vulnerability recurrence
1. Login to the background
2. Click on Template Management
Http://localhost:8080/jfinal_cms/admin/filemanager/list
Click home
![](https://images.seebug.org/1553855290207-w331s)
3. Use burpsuite to capture the path
![](https://images.seebug.org/1553855296681-w331s)
4. As you can see, the web directory has been jumped out.
![](https://images.seebug.org/1553855303664-w331s)
暂无评论