diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/RulesList.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/RulesList.java index c642a0e..ea2e248 100644 --- a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/RulesList.java +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/RulesList.java @@ -6,10 +6,7 @@ */ package com.keyware.sonar.java.rules; -import com.keyware.sonar.java.rules.checkers.ABCVarNameChecker; -import com.keyware.sonar.java.rules.checkers.AbsolutePathDetectorChecker; -import com.keyware.sonar.java.rules.checkers.DynamicCodeChecker; -import com.keyware.sonar.java.rules.checkers.PathAndKeywordCheck; +import com.keyware.sonar.java.rules.checkers.*; import org.sonar.plugins.java.api.JavaCheck; import java.util.ArrayList; @@ -37,7 +34,8 @@ public final class RulesList { ABCVarNameChecker.class, AbsolutePathDetectorChecker.class, PathAndKeywordCheck.class, - DynamicCodeChecker.class + DynamicCodeChecker.class, + SystemFunctionChecker.class /*SpringControllerRequestMappingEntityRule.class, AvoidAnnotationRule.class, AvoidBrandInMethodNamesRule.class, diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SystemFunctionChecker.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SystemFunctionChecker.java new file mode 100644 index 0000000..dd9445e --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SystemFunctionChecker.java @@ -0,0 +1,93 @@ +package com.keyware.sonar.java.rules.checkers;/* + *@title SystemFunctionChecker + *@description + *@author Admin + *@version 1.0 + *@create 2024/1/11 9:29 + */ + +import org.sonar.check.Rule; +import org.sonar.java.checks.helpers.ExpressionsHelper; +import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.semantic.Symbol; +import org.sonar.plugins.java.api.tree.*; + +import java.util.*; + +/** + * 在构建命令前对输入数据进行“白名单”机制验证 + * + * @author WuHaoYang + * @date 2024/1/10 + */ +@Rule(key = "SystemFunctionChecker") +public class SystemFunctionChecker extends IssuableSubscriptionVisitor { + + private static final Set SYSTEM_FUNCTION_NAMES = new HashSet<>(Arrays.asList( + "exec", + "getRuntime().exec", + "ProcessBuilder.command" + )); + + @Override + public List nodesToVisit() { + return Arrays.asList(Tree.Kind.METHOD_INVOCATION, Tree.Kind.NEW_CLASS); + } + + @Override + public void visitNode(Tree tree) { + if (tree.is(Tree.Kind.METHOD_INVOCATION)) { + MethodInvocationTree methodInvocationTree = (MethodInvocationTree) tree; + + ExpressionTree methodSelect = methodInvocationTree.methodSelect(); + if (methodSelect.is(Tree.Kind.MEMBER_SELECT)) { + MemberSelectExpressionTree memberSelect = (MemberSelectExpressionTree) methodSelect; + String methodName = memberSelect.identifier().name(); + + if (SYSTEM_FUNCTION_NAMES.contains(methodName)) { + checkSystemCommand(methodInvocationTree.arguments(), methodInvocationTree); + } + } + } else if (tree.is(Tree.Kind.NEW_CLASS)) { + NewClassTree newClassTree = (NewClassTree) tree; + String className = newClassTree.symbolType().name(); + + if (className.equals("ProcessBuilder")) {//判断是否为ProcessBuilder + checkSystemCommand(newClassTree.arguments(), newClassTree); + } + } + } + + private void checkSystemCommand(List arguments, Tree tree) { + for (int i = 0; i < arguments.size(); i++) { + ExpressionTree argument = arguments.get(i); + + // 获取方法的参数 + Tree parentMethod = findEnclosingMethod(tree); + if (parentMethod != null && parentMethod.is(Tree.Kind.METHOD)) { + MethodTree methodTree = (MethodTree) parentMethod; + List parameters = methodTree.parameters(); + + // 检查执行系统命令对象的参数是否与方法的入参相等 + if (i < parameters.size()) { + String parameterName = parameters.get(i).simpleName().name(); + if (argument.is(Tree.Kind.IDENTIFIER) && ((IdentifierTree) argument).name().equals(parameterName)) { + System.out.println("参数"+parameterName); + reportIssue(tree, "在构建命令前对输入数据进行验证"); + } + } + } + } + } + + public void reportIssue(Tree tree, String message) { + context.reportIssue(this, tree, message); + } + + private Tree findEnclosingMethod(Tree tree) { + while (tree != null && !tree.is(Tree.Kind.METHOD)) { + tree = tree.parent(); + } + return tree; + } +} diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SystemFunctionChecker.html b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SystemFunctionChecker.html new file mode 100644 index 0000000..90a9af4 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SystemFunctionChecker.html @@ -0,0 +1,9 @@ +

在构建命令前对输入数据进行验证

+

在构建命令前对输入数据进行验证

+
+
+
+

合规解决方案

+
+
+
diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SystemFunctionChecker.json b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SystemFunctionChecker.json new file mode 100644 index 0000000..45c653b --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SystemFunctionChecker.json @@ -0,0 +1,13 @@ +{ + "title": "在构建命令前对输入数据进行验证", + "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/SystemFunctionChecker.java b/sonar-keyware-plugins-java/src/test/files/SystemFunctionChecker.java new file mode 100644 index 0000000..905f001 --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/files/SystemFunctionChecker.java @@ -0,0 +1,13 @@ + + +class SystemFunctionChecker{ + public void add(String command){ + Process process = Runtime.getRuntime().exec(command); // Noncompliant {{在构建命令前对输入数据进行验证}} + + } + + public void det(String commands){ + + ProcessBuilder pb = new ProcessBuilder(commands);// Noncompliant {{在构建命令前对输入数据进行验证}} + } +} \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/SystemFunctionCheckerTest.java b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/SystemFunctionCheckerTest.java new file mode 100644 index 0000000..8ab8dce --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/SystemFunctionCheckerTest.java @@ -0,0 +1,24 @@ +package com.keyware.sonar.java.rules.checkers;/* + *@title SystemFunctionCheckerTest + *@description + *@author Admin + *@version 1.0 + *@create 2024/1/11 9:35 + */ + +import com.keyware.sonar.java.utils.FilesUtils; +import org.junit.jupiter.api.Test; +import org.sonar.java.checks.verifier.CheckVerifier; + +public class SystemFunctionCheckerTest { + + + @Test + public void test(){ + CheckVerifier.newVerifier() + .onFile("src/test/files/SystemFunctionChecker.java") + .withCheck(new SystemFunctionChecker()) + .withClassPath(FilesUtils.getClassPath("target/test-jars")) + .verifyIssues(); + } +}