新增准则:在构建命令前对输入数据进行验证,确保输入数据仅能用于构成允许的命令行或干预命令

wuhaoyang
wuhaoyang 10 months ago
parent be630738d5
commit eba7619786
  1. 8
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/RulesList.java
  2. 93
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SystemFunctionChecker.java
  3. 9
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SystemFunctionChecker.html
  4. 13
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/SystemFunctionChecker.json
  5. 13
      sonar-keyware-plugins-java/src/test/files/SystemFunctionChecker.java
  6. 24
      sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/SystemFunctionCheckerTest.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,

@ -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<String> SYSTEM_FUNCTION_NAMES = new HashSet<>(Arrays.asList(
"exec",
"getRuntime().exec",
"ProcessBuilder.command"
));
@Override
public List<Tree.Kind> 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<ExpressionTree> 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<VariableTree> 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;
}
}

@ -0,0 +1,9 @@
<p>在构建命令前对输入数据进行验证</p>
<h2>在构建命令前对输入数据进行验证</h2>
<pre>
</pre>
<h2>合规解决方案</h2>
<pre>
</pre>

@ -0,0 +1,13 @@
{
"title": "在构建命令前对输入数据进行验证",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"28suo"
],
"defaultSeverity": "Minor"
}

@ -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 {{在构建命令前对输入数据进行验证}}
}
}

@ -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();
}
}
Loading…
Cancel
Save