From 0087499a7e0115cfdaff912234f1e08d316a30c4 Mon Sep 17 00:00:00 2001 From: RenFengJiang <1111> Date: Sun, 14 Jan 2024 15:08:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9Ajava=E4=BD=BF?= =?UTF-8?q?=E7=94=A8sql=E8=AF=AD=E5=8F=A5=E5=89=8D=E5=BA=94=E5=AF=B9?= =?UTF-8?q?=E5=85=B6=E8=BF=9B=E8=A1=8C=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rules/checkers/InputSQLVerifyChecker.java | 90 +++++++++++++++++++ .../rules/java/InputSQLVerifyChecker.html | 9 ++ .../rules/java/InputSQLVerifyChecker.json | 13 +++ .../src/test/files/InputSQLVerifyRule.java | 37 ++++++++ .../checkers/InputSQLVerifyCheckerTest.java | 32 +++++++ 5 files changed, 181 insertions(+) create mode 100644 sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/InputSQLVerifyChecker.java create mode 100644 sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/InputSQLVerifyChecker.html create mode 100644 sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/InputSQLVerifyChecker.json create mode 100644 sonar-keyware-plugins-java/src/test/files/InputSQLVerifyRule.java create mode 100644 sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/InputSQLVerifyCheckerTest.java diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/InputSQLVerifyChecker.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/InputSQLVerifyChecker.java new file mode 100644 index 0000000..79f301e --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/InputSQLVerifyChecker.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:Java 信息安全性设计准则 + * 项目描述:用于检查Java源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ +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.IdentifierTreeImpl; +import org.sonar.java.model.expression.MemberSelectExpressionTreeImpl; +import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.tree.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * TODO InputSQLVerifyChecker + * + * @author RenFengJiang + * @date 2024/1/14 + */ +@Rule(key = "InputSQLVerifyChecker") +public class InputSQLVerifyChecker extends IssuableSubscriptionVisitor { + + @Override + public List nodesToVisit() { + /** + * Tree.Kind.METHOD:方法节点 + * Tree.Kind.BLOCK:方法的代码块节点 + * Tree.Kind.METHOD_INVOCATION: 方法的调用节点 + */ + return Collections.singletonList(Tree.Kind.METHOD); + } + + @Override + public void visitNode(Tree tree) { + MethodTree blockTree = (MethodTree) tree; + MethodeBodyVisitor bodyVisitor = new MethodeBodyVisitor(this); + blockTree.accept(bodyVisitor); + } + + static class MethodeBodyVisitor extends BaseTreeVisitor { + private final InputSQLVerifyChecker checker; + private List lists = new ArrayList(); + MethodeBodyVisitor(InputSQLVerifyChecker checker){ + this.checker = checker; + } + + @Override + public void visitIfStatement(IfStatementTree tree) { + ExpressionTree condition = tree.condition(); + if(condition instanceof MethodInvocationTree){ + MethodInvocationTree methodInvocationTree = (MethodInvocationTree) condition; + ExpressionTree expressionTree = methodInvocationTree.methodSelect(); + if(expressionTree instanceof MemberSelectExpressionTreeImpl){ + MemberSelectExpressionTreeImpl memberSelectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree; + //将if判断中的参数存入集合中 + lists.add(memberSelectExpressionTree.expression().toString()); + } + } + } + + @Override + public void visitMethodInvocation(MethodInvocationTree tree) { + ExpressionTree expressionTree = tree.methodSelect(); + if(expressionTree instanceof MemberSelectExpressionTreeImpl){ + MemberSelectExpressionTreeImpl memberSelectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree; + if("prepareStatement".equals(memberSelectExpressionTree.identifier().name())){ + Arguments arguments = tree.arguments(); + if(arguments instanceof ArgumentListTreeImpl){ + for (ExpressionTree argument : (ArgumentListTreeImpl) arguments) { + if (argument instanceof IdentifierTreeImpl){ + IdentifierTreeImpl identifierTree = (IdentifierTreeImpl) argument; + String name = identifierTree.name(); + //判断使用的sql是否存在集合中 + if(!lists.contains(name)){ + checker.context.reportIssue(checker,argument,"使用sql语句前应对其进行验证"); + } + } + } + } + } + } + } + } +} diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/InputSQLVerifyChecker.html b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/InputSQLVerifyChecker.html new file mode 100644 index 0000000..5f63a49 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/InputSQLVerifyChecker.html @@ -0,0 +1,9 @@ +

使用sql语句前应对其进行验证

+

在程序中输入SQL语句,应在拼接SQL语句前对输入字符串数据进行验证,确保输入字符串数据不包含SQL语句的关键字符或仅包含允许的关键字符;在B/S系统中,在前端执行SQL命令检查校验

+
+
+
+

合规解决方案

+
+
+
diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/InputSQLVerifyChecker.json b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/InputSQLVerifyChecker.json new file mode 100644 index 0000000..688eeb1 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/InputSQLVerifyChecker.json @@ -0,0 +1,13 @@ +{ + "title": "使用sql语句前应对其进行验证", + "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/InputSQLVerifyRule.java b/sonar-keyware-plugins-java/src/test/files/InputSQLVerifyRule.java new file mode 100644 index 0000000..851be85 --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/files/InputSQLVerifyRule.java @@ -0,0 +1,37 @@ +public class InputSQLVerifyRile { + private static final String DB_URL = "jdbc:mysql://localhost:3306/mydatabase"; + private static final String USER = "username"; + private static final String PASS = "password"; + + public void executeQuery(String userInput) { + try { + // 获取数据库连接 + Connection conn = DriverManager.getConnection(DB_URL, USER, PASS); + + // 假设我们有一个用户ID字段,我们需要根据用户输入查找记录 + String sql = "SELECT * FROM users WHERE user_id = ?"; +// if(sql.indexOf("a")){ +// +// } + + // 创建预编译的Statement(PreparedStatement),用问号作为占位符代替实际值 + PreparedStatement pstmt = conn.prepareStatement(sql);// Noncompliant {{使用sql语句前应对其进行验证}} + + // 验证用户输入是否符合整数格式(这里仅作简单示例) + if (userInput.matches("\\d+")) { + int userId = Integer.parseInt(userInput); + pstmt.setInt(1, userId); + + // 执行查询 + ResultSet rs = pstmt.executeQuery(); + + // 处理结果集... + } else { + System.out.println("Invalid input. User ID must be a number."); + } + + } catch (SQLException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/InputSQLVerifyCheckerTest.java b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/InputSQLVerifyCheckerTest.java new file mode 100644 index 0000000..a748b3a --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/InputSQLVerifyCheckerTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:Java 信息安全性设计准则 + * 项目描述:用于检查Java源代码的安全性设计准则的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 InputSQLVerifyCheckerTest + * + * @author RenFengJiang + * @date 2024/1/14 + */ +public class InputSQLVerifyCheckerTest { + + @Test + void detected() { + InputSQLVerifyChecker rule = new InputSQLVerifyChecker(); + + + CheckVerifier.newVerifier() + .onFile("src/test/files/InputSQLVerifyRule.java") + .withCheck(rule) + .withClassPath(FilesUtils.getClassPath("target/test-jars")) + .verifyIssues(); + } +}