From 207e54631cb2df67a15ce8cc62f69559e6e2c332 Mon Sep 17 00:00:00 2001 From: nkorange Date: Tue, 30 Jul 2019 00:40:21 +0800 Subject: [PATCH] Fix namespace vulnerability --- .../alibaba/nacos/naming/web/AuthFilter.java | 22 ++++++++++++---- .../nacos/naming/web/NamingConfig.java | 2 +- .../nacos/test/naming/RestAPI_ITCase.java | 26 +++++++++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/naming/src/main/java/com/alibaba/nacos/naming/web/AuthFilter.java b/naming/src/main/java/com/alibaba/nacos/naming/web/AuthFilter.java index 696f807d8..3c679c894 100644 --- a/naming/src/main/java/com/alibaba/nacos/naming/web/AuthFilter.java +++ b/naming/src/main/java/com/alibaba/nacos/naming/web/AuthFilter.java @@ -15,10 +15,12 @@ */ package com.alibaba.nacos.naming.web; +import com.alibaba.nacos.api.naming.CommonParams; import com.alibaba.nacos.naming.acl.AuthChecker; import com.alibaba.nacos.naming.misc.SwitchDomain; import com.alibaba.nacos.naming.misc.UtilsAndCommons; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import javax.servlet.*; @@ -34,6 +36,8 @@ import java.security.AccessControlException; */ public class AuthFilter implements Filter { + private static final String[] NAMESPACE_FORBIDDEN_STRINGS = new String[]{"..", "/"}; + @Autowired private AuthChecker authChecker; @@ -64,11 +68,16 @@ public class AuthFilter implements Filter { } if (method.isAnnotationPresent(NeedAuth.class) && !switchDomain.isEnableAuthentication()) { + // leave it empty. + } - if (path.contains(UtilsAndCommons.NACOS_NAMING_RAFT_CONTEXT)) { - authChecker.doRaftAuth(req); - } else { - authChecker.doAuth(req.getParameterMap(), req); + // Check namespace: + String namespaceId = req.getParameter(CommonParams.NAMESPACE_ID); + + if (StringUtils.isNotBlank(namespaceId)) { + + if (namespaceId.contains(NAMESPACE_FORBIDDEN_STRINGS[0]) || namespaceId.contains(NAMESPACE_FORBIDDEN_STRINGS[1])) { + throw new IllegalArgumentException("forbidden namespace: " + namespaceId); } } @@ -78,9 +87,12 @@ public class AuthFilter implements Filter { } catch (NoSuchMethodException e) { resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, "no such api"); return; + } catch (IllegalArgumentException e) { + resp.sendError(HttpServletResponse.SC_BAD_REQUEST, UtilsAndCommons.getAllExceptionMsg(e)); + return; } catch (Exception e) { resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Server failed," + UtilsAndCommons.getAllExceptionMsg(e)); + "Server failed," + UtilsAndCommons.getAllExceptionMsg(e)); return; } filterChain.doFilter(req, resp); diff --git a/naming/src/main/java/com/alibaba/nacos/naming/web/NamingConfig.java b/naming/src/main/java/com/alibaba/nacos/naming/web/NamingConfig.java index e7df5ec4f..d18b10a7f 100644 --- a/naming/src/main/java/com/alibaba/nacos/naming/web/NamingConfig.java +++ b/naming/src/main/java/com/alibaba/nacos/naming/web/NamingConfig.java @@ -52,7 +52,7 @@ public class NamingConfig { FilterRegistrationBean registration = new FilterRegistrationBean<>(); registration.setFilter(authFilter()); - registration.addUrlPatterns("/api/*", "/raft/*"); + registration.addUrlPatterns("/v1/ns/*"); registration.setName("authFilter"); registration.setOrder(5); diff --git a/test/src/test/java/com/alibaba/nacos/test/naming/RestAPI_ITCase.java b/test/src/test/java/com/alibaba/nacos/test/naming/RestAPI_ITCase.java index 7f6f67014..e08b4f0bf 100644 --- a/test/src/test/java/com/alibaba/nacos/test/naming/RestAPI_ITCase.java +++ b/test/src/test/java/com/alibaba/nacos/test/naming/RestAPI_ITCase.java @@ -232,6 +232,32 @@ public class RestAPI_ITCase { namingServiceDelete(serviceName); } + @Test + public void testInvalidNamespace() { + + String serviceName = NamingBase.randomDomainName(); + ResponseEntity response = request(NamingBase.NAMING_CONTROLLER_PATH + "/service", + Params.newParams() + .appendParam("serviceName", serviceName) + .appendParam("protectThreshold", "0.6") + .appendParam("namespaceId", "..invalid-namespace") + .done(), + String.class, + HttpMethod.POST); + Assert.assertTrue(response.getStatusCode().is4xxClientError()); + + response = request(NamingBase.NAMING_CONTROLLER_PATH + "/service", + Params.newParams() + .appendParam("serviceName", serviceName) + .appendParam("protectThreshold", "0.6") + .appendParam("namespaceId", "/invalid-namespace") + .done(), + String.class, + HttpMethod.POST); + Assert.assertTrue(response.getStatusCode().is4xxClientError()); + + } + private void namingServiceDelete(String serviceName) { //delete service ResponseEntity response = request(NamingBase.NAMING_CONTROLLER_PATH + "/service",