diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SessionCacheParamsChecker.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SessionCacheParamsChecker.java index 136ee9d..3ba3571 100644 --- a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SessionCacheParamsChecker.java +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SessionCacheParamsChecker.java @@ -7,7 +7,15 @@ package com.keyware.sonar.java.rules.checkers; import org.sonar.check.Rule; +import org.sonar.java.ast.parser.ArgumentListTreeImpl; +import org.sonar.java.model.expression.LiteralTreeImpl; +import org.sonar.java.model.expression.MemberSelectExpressionTreeImpl; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.semantic.Symbol; +import org.sonar.plugins.java.api.semantic.Type; +import org.sonar.plugins.java.api.tree.Arguments; +import org.sonar.plugins.java.api.tree.ExpressionTree; +import org.sonar.plugins.java.api.tree.MethodInvocationTree; import org.sonar.plugins.java.api.tree.Tree; import javax.annotation.Nonnull; @@ -22,11 +30,15 @@ import java.util.List; */ @Rule(key = "SessionCacheParamsChecker") public class SessionCacheParamsChecker extends IssuableSubscriptionVisitor { + + //违规集合 private static final List HIDED_PARAMS = List.of( - "id", - "token" + "userid", + "token", + "url", + "userpassword" ); - + private static final String requestType = "javax.servlet.http.HttpServletRequest"; @Override public List nodesToVisit() { @@ -35,8 +47,44 @@ public class SessionCacheParamsChecker extends IssuableSubscriptionVisitor { @Override public void visitNode(@Nonnull Tree tree) { - + // ((MemberSelectExpressionTree)methodInvocationTree.methodSelect()).expression().symbolType() + MethodInvocationTree methodInvocationTree = (MethodInvocationTree) tree; + Symbol.MethodSymbol methodSymbol = methodInvocationTree.methodSymbol(); + if(methodSymbol.isMethodSymbol()) { + //获取参数 + ExpressionTree expressionTree = methodInvocationTree.methodSelect(); + if(expressionTree instanceof MemberSelectExpressionTreeImpl){ + MemberSelectExpressionTreeImpl selectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree; + //获取参数类型 + Type type = selectExpressionTree.expression().symbolType(); + if(type != null){ + //判断参数类型和调用方法符不符合要求 + if(requestType.equals(type.fullyQualifiedName()) + && ("getParameter".equals(methodSymbol.name()) || "getCookies".equals(methodSymbol.name()))) { + //如果是getCookies方法直接抛错 + if("getCookies".equals(methodSymbol.name())){ + reportIssue(methodInvocationTree, "页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取"); + }else { + //获取参数 + Arguments arguments = methodInvocationTree.arguments(); + if(arguments instanceof ArgumentListTreeImpl){ + for (ExpressionTree argument : (ArgumentListTreeImpl) arguments) { + if(argument instanceof LiteralTreeImpl){ + LiteralTreeImpl literalTree = (LiteralTreeImpl) argument; + //获取参数值 + String name = literalTree.token().text().replace("\"", "").toLowerCase(); + //判断是否是违规项 + if(HIDED_PARAMS.contains(name)){ + reportIssue(methodInvocationTree, "页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取"); + break; + } + } + } + } + } + } + } + } + } } - - } diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SessionCacheParamsChecker.html b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SessionCacheParamsChecker.html new file mode 100644 index 0000000..cd92f6f --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SessionCacheParamsChecker.html @@ -0,0 +1,16 @@ + + +

页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取

+

页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取

+
+
+
+

合规解决方案

+
+
+
diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SessionCacheParamsChecker.json b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SessionCacheParamsChecker.json new file mode 100644 index 0000000..164cbab --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SessionCacheParamsChecker.json @@ -0,0 +1,13 @@ +{ + "title": "页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "28suo" + ], + "defaultSeverity": "Minor" +} \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/files/SessionCacheParamsChecker.java b/sonar-keyware-plugins-java/src/test/files/SessionCacheParamsChecker.java index 34f4d6a..55bac41 100644 --- a/sonar-keyware-plugins-java/src/test/files/SessionCacheParamsChecker.java +++ b/sonar-keyware-plugins-java/src/test/files/SessionCacheParamsChecker.java @@ -1,22 +1,31 @@ -package com.example; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.*; + public class ExampleServlet extends HttpServlet { + private static final long serialVersionUID = 1391640560504378168L; + public void doGet(HttpServletRequest request, HttpServletResponse response) { // 直接从request获取参数 - String param = request.getParameter("userId"); // Noncompliant {{建议将页面隐藏域字段、Cookie、URL等关键参数缓存到服务器端的会话中,并通过会话获取}} - + String param = request.getParameter("userId"); // Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}} + request.getParameter("userpassword");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}} + request.getParameter("token");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}} + request.getParameter("url");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}} // 直接从request获取Cookies - Cookie[] cookies = request.getCookies(); + Cookie[] cookies = request.getCookies();// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}} // 将参数存储到session HttpSession session = request.getSession(); session.setAttribute("sessionParam", param); // 其他代码... } - private void get(HttpServletRequest request, HttpServletResponse response){ + @RestController + class TestController{ + @GetMapping("/get") + public void get(HttpServletRequest request){ + String userId = request.getParameter("userId");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}} + } } } \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/SessionCacheParamsCheckerTest.java b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/SessionCacheParamsCheckerTest.java new file mode 100644 index 0000000..6a17a9a --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/SessionCacheParamsCheckerTest.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ + +package com.keyware.sonar.java.rules.checkers; + +import com.keyware.sonar.java.utils.FilesUtils; +import org.junit.jupiter.api.Test; +import org.sonar.java.checks.verifier.CheckVerifier; + +/** + * TODO SessionCacheParamsCheckerTest + * + * @author RenFengJiang + * @date 2024/1/24 + */ +public class SessionCacheParamsCheckerTest { + @Test + public void test() { + CheckVerifier.newVerifier() + .onFile("src/test/files/SessionCacheParamsChecker.java") + .withCheck(new SessionCacheParamsChecker()) + .withClassPath(FilesUtils.getClassPath("target/test-jars")) + .verifyIssues(); + } +}