diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/HashSaltPassWordChecker.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/HashSaltPassWordChecker.java new file mode 100644 index 0000000..8d8eb7a --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/HashSaltPassWordChecker.java @@ -0,0 +1,93 @@ +/* + * 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.ast.visitors.SubscriptionVisitor; +import org.sonar.java.model.declaration.VariableTreeImpl; +import org.sonar.java.model.expression.IdentifierTreeImpl; +import org.sonar.java.model.expression.MemberSelectExpressionTreeImpl; +import org.sonar.java.model.expression.MethodInvocationTreeImpl; +import org.sonar.plugins.java.api.tree.*; + +import java.util.Collections; +import java.util.List; + +/** + * TODO HashSaltPassWordChecker + * + * @author RenFengJiang + * @date 2024/1/11 + */ +@Rule(key = "HashSaltPassWordChecker") +public class HashSaltPassWordChecker extends SubscriptionVisitor { + + @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 node = (MethodTree) tree; + var bodyVisitor = new MethodeBodyVisitor(this); + node.block().accept(bodyVisitor); + } + + + static class MethodeBodyVisitor extends BaseTreeVisitor { + // 存放盐值后的密码 + public String strPassWord = ""; + private final HashSaltPassWordChecker checker; + + MethodeBodyVisitor(HashSaltPassWordChecker checker) { + this.checker = checker; + } + + @Override + public void visitMethodInvocation(MethodInvocationTree tree) { +// 获取到方法调用 + ExpressionTree expressionTree = tree.methodSelect(); + if (expressionTree instanceof MemberSelectExpressionTreeImpl) { +// 获取到调用的方法 + MemberSelectExpressionTreeImpl memberSelectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree; + if ("setPassWord".equals(memberSelectExpressionTree.identifier().name())) { + Tree parent = tree.arguments(); + if (parent instanceof ArgumentListTreeImpl) { + for (ExpressionTree expressionTree1 : (ArgumentListTreeImpl) parent) { + if (expressionTree1 instanceof IdentifierTreeImpl) { + IdentifierTreeImpl identifierTree = (IdentifierTreeImpl) expressionTree1; +// 判断set中使用的参数 + if(!identifierTree.name().equals(strPassWord)){ + checker.context.reportIssue(checker, identifierTree, "应使用盐值计算口令"); + } + } + } + } +// 判断是否是生成的加盐后的密码 + }else if("BCrypt".equals(memberSelectExpressionTree.expression().toString()) && "hashpw".equals(memberSelectExpressionTree.identifier().name())){ + Tree parent = memberSelectExpressionTree.parent(); + if(parent instanceof MethodInvocationTreeImpl){ + MethodInvocationTreeImpl methodInvocationTree = (MethodInvocationTreeImpl) parent; + Tree parent1 = methodInvocationTree.parent(); + if(parent1 instanceof VariableTreeImpl){ + VariableTreeImpl variableTree = (VariableTreeImpl) parent1; +// 加盐后的参数名称 + strPassWord = variableTree.simpleName().name(); + } + } + } + } + } + } +} diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SecurityCookieChecker.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SecurityCookieChecker.java index eab05c5..0e1ee4e 100644 --- a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SecurityCookieChecker.java +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SecurityCookieChecker.java @@ -48,8 +48,6 @@ public class SecurityCookieChecker extends SubscriptionVisitor { if(!(bodyVisitor.booAge && bodyVisitor.booCure)){ context.reportIssue(this,node.simpleName(),"设置HTTPS会话中cookie的安全属性"); } - }else { - } } } @@ -70,7 +68,6 @@ public class SecurityCookieChecker extends SubscriptionVisitor { @Override public void visitMethodInvocation(MethodInvocationTree tree) { ExpressionTree expressionTree = tree.methodSelect(); - System.out.println(expressionTree); if(expressionTree instanceof MemberSelectExpressionTree){ MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree; switch (memberSelectExpressionTree.identifier().name()){ diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/HashSaltPassWordChecker.html b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/HashSaltPassWordChecker.html new file mode 100644 index 0000000..088bf9e --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/HashSaltPassWordChecker.html @@ -0,0 +1,9 @@ +

应使用盐值计算口令

+

使用盐值计算散列值,增加攻击者破解口令的难度

+
+
+
+

合规解决方案

+
+
+
diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/HashSaltPassWordChecker.json b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/HashSaltPassWordChecker.json new file mode 100644 index 0000000..5cf48f7 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/HashSaltPassWordChecker.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/HashSaltPassWordRule.java b/sonar-keyware-plugins-java/src/test/files/HashSaltPassWordRule.java new file mode 100644 index 0000000..e1cc25a --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/files/HashSaltPassWordRule.java @@ -0,0 +1,11 @@ +class HashSaltPassWordRule{ + public static void cs(Student studnet){ + // 结合盐值和口令进行散列计算 +// String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt()); + + studnet.setPassWord(hashedPassword);// Noncompliant {{应使用盐值计算口令}} + + } + + +} \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/HashSaltPassWordCheckerTest.java b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/HashSaltPassWordCheckerTest.java new file mode 100644 index 0000000..b9149ae --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/HashSaltPassWordCheckerTest.java @@ -0,0 +1,31 @@ +/* + * 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 HashSaltPassWordCheckerTest + * + * @author RenFengJiang + * @date 2024/1/11 + */ +public class HashSaltPassWordCheckerTest { + @Test + void detected() { + HashSaltPassWordChecker rule = new HashSaltPassWordChecker(); + + + CheckVerifier.newVerifier() + .onFile("src/test/files/HashSaltPassWordRule.java") + .withCheck(rule) + .withClassPath(FilesUtils.getClassPath("target/test-jars")) + .verifyIssues(); + } +}