CVE-2020-19005: Incorrect Authorization (CWE-863)
value: zrlog v2.1.0 has a vulnerability with the permission check. If admin account is logged in, other unauthorized users can download the database backup file directly.
CWE description: The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. This allows attackers to bypass intended access restrictions.
CVSS v3 base score: 5.7
Published: 2020-08-25T22:15Z
Repository: https://github.com/94fzb/zrlog
Language: Java
Files changed: common/src/main/java/com/zrlog/web/util/PluginHelper.java, pom.xml, service/src/main/java/com/zrlog/service/UploadService.java, web/src/main/java/com/zrlog/web/handler/PluginHandler.java
Commit date: 2019-04-22 23:40:35 +0800
Commit message: Fix #48 forget remove token from ThreadLocal

Diff: diff --git a/service/src/main/java/com/zrlog/service/PluginHelper.java b/common/src/main/java/com/zrlog/web/util/PluginHelper.java
similarity index 74%
rename from service/src/main/java/com/zrlog/service/PluginHelper.java
rename to common/src/main/java/com/zrlog/web/util/PluginHelper.java
index 6af8164..e295913 100644
--- a/service/src/main/java/com/zrlog/service/PluginHelper.java
+++ b/common/src/main/java/com/zrlog/web/util/PluginHelper.java
@@ -1,30 +1,26 @@
-package com.zrlog.service;
+package com.zrlog.web.util;
 
-import com.jfinal.core.JFinal;
 import com.zrlog.common.vo.AdminTokenVO;
-import com.zrlog.model.User;
+import com.zrlog.util.BlogBuildInfoUtil;
 import com.zrlog.util.I18nUtil;
 import com.zrlog.util.ZrLogUtil;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.HashMap;
 import java.util.Map;
 
 public class PluginHelper {
 
-    public static Map<String, String> genHeaderMapByRequest(HttpServletRequest request) {
+    public static Map<String, String> genHeaderMapByRequest(HttpServletRequest request, AdminTokenVO adminTokenVO) {
         Map<String, String> map = new HashMap<>();
-        AdminTokenVO adminTokenVO = AdminTokenThreadLocal.getUser();
         if (adminTokenVO != null) {
-            User user = User.dao.findById(adminTokenVO.getUserId());
-            map.put("LoginUserName", user.get("userName").toString());
             map.put("LoginUserId", adminTokenVO.getUserId() + "");
         }
         map.put("IsLogin", (adminTokenVO != null) + "");
         map.put("Current-Locale", I18nUtil.getCurrentLocale());
-        map.put("Blog-Version", ((Map) JFinal.me().getServletContext().getAttribute("zrlog")).get("version").toString());
+        map.put("Blog-Version", BlogBuildInfoUtil.getVersion());
         if (request != null) {
             String fullUrl = ZrLogUtil.getFullUrl(request);
             if (request.getQueryString() != null) {
                 fullUrl = fullUrl + "?" + request.getQueryString();
             }
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..4a34cca
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,104 @@
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.zrlog</groupId>
+    <artifactId>zrlog</artifactId>
+    <version>2.1.0</version>
+    <modules>
+        <module>web</module>
+        <module>service</module>
+        <module>common</module>
+        <module>data</module>
+    </modules>
+    <packaging>pom</packaging>
+    <name>zrlog</name>
+    <description>ZrLog是使用Java开发的博客/CMS程序，具有简约，易用，组件化，内存占用低等特点。自带Markdown编辑器，让更多的精力放在写作上，而不是花费大量时间在学习程序的使用上。
+    </description>
+    <url>https://www.zrlog.com</url>
+
+    <properties>
+        <java.version>1.8</java.version>
+        <jfinal.version>3.3</jfinal.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <servlet.version>3.1.0</servlet.version>
+    </properties>
+
+    <developers>
+        <developer>
+            <name>xiaochun</name>
+            <email>xchun90@163.com</email>
+            <url>http://blog.94fzb.com</url>
+            <roles>
+                <role>owner</role>
+            </roles>
+        </developer>
+        <developer>
+            <name>weekdragon</name>
+            <email>790774717@qq.com</email>
+            <url>https://www.weekdragon.cn</url>
+            <roles>
+                <role>developer</role>
+            </roles>
+        </developer>
+        <developer>
+            <name>e-lionel</name>
+            <email>lionel0724@163.com</email>
+            <url>https://github.com/e-lionel</url>
+            <roles>
+                <role>reporter</role>
+            </roles>
+        </developer>
+    </developers>
+
+    <issueManagement>
+        <system>Github Issue</system>
+        <url>http://github.com/94fzb/zrlog</url>
+    </issueManagement>
+
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://apache.org/licenses/LICENSE-2.0.txt</url>
+        </license>
+    </licenses>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.12</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.7.12</version>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.17</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <sourceDirectory>src/main/java</sourceDirectory>
+        <testSourceDirectory>src/test/java</testSourceDirectory>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+                <version>2.3.2</version>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/service/src/main/java/com/zrlog/service/UploadService.java b/service/src/main/java/com/zrlog/service/UploadService.java
index 09c4004..a027022 100644
--- a/service/src/main/java/com/zrlog/service/UploadService.java
+++ b/service/src/main/java/com/zrlog/service/UploadService.java
@@ -2,10 +2,11 @@ package com.zrlog.service;
 
 import com.hibegin.common.util.http.HttpUtil;
 import com.hibegin.common.util.http.handle.HttpJsonArrayHandle;
 import com.zrlog.common.Constants;
 import com.zrlog.common.response.UploadFileResponse;
+import com.zrlog.web.util.PluginHelper;
 import org.apache.log4j.Logger;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.HashMap;
 import java.util.List;
@@ -22,11 +23,11 @@ public class UploadService {
         map.put("fileInfo", new String[]{finalFilePath + "," + uri});
         map.put("name", new String[]{"uploadService"});
         String url;
         try {
             List<Map> urls = HttpUtil.getInstance().sendGetRequest(Constants.pluginServer + "/service", map
-                    , new HttpJsonArrayHandle<Map>(), PluginHelper.genHeaderMapByRequest(request)).getT();
+                    , new HttpJsonArrayHandle<Map>(), PluginHelper.genHeaderMapByRequest(request, AdminTokenThreadLocal.getUser())).getT();
             if (urls != null && !urls.isEmpty()) {
                 url = (String) urls.get(0).get("url");
                 if (!url.startsWith("https://") && !url.startsWith("http://")) {
                     String tUrl = url;
                     if (!url.startsWith("/")) {
diff --git a/web/src/main/java/com/zrlog/web/handler/PluginHandler.java b/web/src/main/java/com/zrlog/web/handler/PluginHandler.java
index 2beb4db..32f2237 100644
--- a/web/src/main/java/com/zrlog/web/handler/PluginHandler.java
+++ b/web/src/main/java/com/zrlog/web/handler/PluginHandler.java
@@ -8,12 +8,12 @@ import com.jfinal.handler.Handler;
 import com.zrlog.common.Constants;
 import com.zrlog.common.vo.AdminTokenVO;
 import com.zrlog.model.User;
 import com.zrlog.service.AdminTokenService;
 import com.zrlog.service.AdminTokenThreadLocal;
-import com.zrlog.service.PluginHelper;
 import com.zrlog.util.BlogBuildInfoUtil;
+import com.zrlog.web.util.PluginHelper;
 import org.apache.http.Header;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.log4j.Logger;
 
 import javax.servlet.http.HttpServletRequest;
@@ -50,12 +50,13 @@ public class PluginHandler extends Handler {
             if (target.startsWith(path)) {
                 isPluginPath = true;
             }
         }
         if (isPluginPath) {
+            Map.Entry<AdminTokenVO, User> entry = null;
             try {
-                Map.Entry<AdminTokenVO, User> entry = adminTokenService.getAdminTokenVOUserEntry(request);
+                entry = adminTokenService.getAdminTokenVOUserEntry(request);
                 if (entry != null) {
                     adminTokenService.setAdminToken(entry.getValue(), entry.getKey().getSessionId(), entry.getKey().getProtocol(), request, response);
                 }
                 if (target.startsWith("/admin/plugins/")) {
                     try {
@@ -70,10 +71,13 @@ public class PluginHandler extends Handler {
                         LOGGER.error(e);
                     }
                 }
             } finally {
                 isHandled[0] = true;
+                if (entry != null) {
+                    AdminTokenThreadLocal.remove();
+                }
             }
         } else {
             this.next.handle(target, request, response, isHandled);
         }
     }
@@ -151,17 +155,17 @@ public class PluginHandler extends Handler {
         CloseableHttpResponse httpResponse;
         CloseResponseHandle handle = new CloseResponseHandle();
         HttpUtil httpUtil = disableRedirect ? HttpUtil.getDisableRedirectInstance() : HttpUtil.getInstance();
         //GET请求不关心request.getInputStream() 的数据
         if (method.equals(request.getMethod()) && "GET".equalsIgnoreCase(method)) {
-            httpResponse = httpUtil.sendGetRequest(pluginServerHttp + uri, request.getParameterMap(), handle, PluginHelper.genHeaderMapByRequest(request)).getT();
+            httpResponse = httpUtil.sendGetRequest(pluginServerHttp + uri, request.getParameterMap(), handle, PluginHelper.genHeaderMapByRequest(request, AdminTokenThreadLocal.getUser())).getT();
         } else {
             //如果是表单数据提交不关心请求头，反之将所有请求头都发到插件服务
             if ("application/x-www-form-urlencoded".equals(request.getContentType())) {
-                httpResponse = httpUtil.sendPostRequest(pluginServerHttp + uri, request.getParameterMap(), handle, PluginHelper.genHeaderMapByRequest(request)).getT();
+                httpResponse = httpUtil.sendPostRequest(pluginServerHttp + uri, request.getParameterMap(), handle, PluginHelper.genHeaderMapByRequest(request, AdminTokenThreadLocal.getUser())).getT();
             } else {
-                httpResponse = httpUtil.sendPostRequest(pluginServerHttp + uri + "?" + request.getQueryString(), IOUtil.getByteByInputStream(request.getInputStream()), handle, PluginHelper.genHeaderMapByRequest(request)).getT();
+                httpResponse = httpUtil.sendPostRequest(pluginServerHttp + uri + "?" + request.getQueryString(), IOUtil.getByteByInputStream(request.getInputStream()), handle, PluginHelper.genHeaderMapByRequest(request, AdminTokenThreadLocal.getUser())).getT();
             }
         }
         //添加插件服务的HTTP响应头到调用者响应头里面
         if (httpResponse != null) {
             Map<String, String> headerMap = new HashMap<>();

Vulnerable code: package com.zrlog.service;
import com.jfinal.core.JFinal;
import com.zrlog.model.User;
    public static Map<String, String> genHeaderMapByRequest(HttpServletRequest request) {
        AdminTokenVO adminTokenVO = AdminTokenThreadLocal.getUser();
            User user = User.dao.findById(adminTokenVO.getUserId());
            map.put("LoginUserName", user.get("userName").toString());
        map.put("Blog-Version", ((Map) JFinal.me().getServletContext().getAttribute("zrlog")).get("version").toString());
                    , new HttpJsonArrayHandle<Map>(), PluginHelper.genHeaderMapByRequest(request)).getT();
import com.zrlog.service.PluginHelper;
                Map.Entry<AdminTokenVO, User> entry = adminTokenService.getAdminTokenVOUserEntry(request);
            httpResponse = httpUtil.sendGetRequest(pluginServerHttp + uri, request.getParameterMap(), handle, PluginHelper.genHeaderMapByRequest(request)).getT();
                httpResponse = httpUtil.sendPostRequest(pluginServerHttp + uri, request.getParameterMap(), handle, PluginHelper.genHeaderMapByRequest(request)).getT();
                httpResponse = httpUtil.sendPostRequest(pluginServerHttp + uri + "?" + request.getQueryString(), IOUtil.getByteByInputStream(request.getInputStream()), handle, PluginHelper.genHeaderMapByRequest(request)).getT();
Fixed code: package com.zrlog.web.util;
import com.zrlog.util.BlogBuildInfoUtil;
    public static Map<String, String> genHeaderMapByRequest(HttpServletRequest request, AdminTokenVO adminTokenVO) {
        map.put("Blog-Version", BlogBuildInfoUtil.getVersion());
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.zrlog</groupId>
    <artifactId>zrlog</artifactId>
    <version>2.1.0</version>
    <modules>
        <module>web</module>
        <module>service</module>
        <module>common</module>
        <module>data</module>
    </modules>
    <packaging>pom</packaging>
    <name>zrlog</name>
    <description>ZrLog是使用Java开发的博客/CMS程序，具有简约，易用，组件化，内存占用低等特点。自带Markdown编辑器，让更多的精力放在写作上，而不是花费大量时间在学习程序的使用上。
    </description>
    <url>https://www.zrlog.com</url>

    <properties>
        <java.version>1.8</java.version>
        <jfinal.version>3.3</jfinal.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <servlet.version>3.1.0</servlet.version>
    </properties>

    <developers>
        <developer>
            <name>xiaochun</name>
            <email>xchun90@163.com</email>
            <url>http://blog.94fzb.com</url>
            <roles>
                <role>owner</role>
            </roles>
        </developer>
        <developer>
            <name>weekdragon</name>
            <email>790774717@qq.com</email>
            <url>https://www.weekdragon.cn</url>
            <roles>
                <role>developer</role>
            </roles>
        </developer>
        <developer>
            <name>e-lionel</name>
            <email>lionel0724@163.com</email>
            <url>https://github.com/e-lionel</url>
            <roles>
                <role>reporter</role>
            </roles>
        </developer>
    </developers>

    <issueManagement>
        <system>Github Issue</system>
        <url>http://github.com/94fzb/zrlog</url>
    </issueManagement>

    <licenses>
        <license>
            <name>The Apache Software License, Version 2.0</name>
            <url>http://apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <testSourceDirectory>src/test/java</testSourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>UTF-8</encoding>
                </configuration>
                <version>2.3.2</version>
            </plugin>
        </plugins>
    </build>
</project>
import com.zrlog.web.util.PluginHelper;
                    , new HttpJsonArrayHandle<Map>(), PluginHelper.genHeaderMapByRequest(request, AdminTokenThreadLocal.getUser())).getT();
import com.zrlog.web.util.PluginHelper;
            Map.Entry<AdminTokenVO, User> entry = null;
                entry = adminTokenService.getAdminTokenVOUserEntry(request);
                if (entry != null) {
                    AdminTokenThreadLocal.remove();
                }
            httpResponse = httpUtil.sendGetRequest(pluginServerHttp + uri, request.getParameterMap(), handle, PluginHelper.genHeaderMapByRequest(request, AdminTokenThreadLocal.getUser())).getT();
                httpResponse = httpUtil.sendPostRequest(pluginServerHttp + uri, request.getParameterMap(), handle, PluginHelper.genHeaderMapByRequest(request, AdminTokenThreadLocal.getUser())).getT();
                httpResponse = httpUtil.sendPostRequest(pluginServerHttp + uri + "?" + request.getQueryString(), IOUtil.getByteByInputStream(request.getInputStream()), handle, PluginHelper.genHeaderMapByRequest(request, AdminTokenThreadLocal.getUser())).getT();