diff --git a/sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/PathVerifyChecker.java b/sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/PathVerifyChecker.java new file mode 100644 index 0000000..56dd168 --- /dev/null +++ b/sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/PathVerifyChecker.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ + +package com.keyware.sonar.cxx.rules.checkers; + +import com.sonar.cxx.sslr.api.AstNode; +import com.sonar.cxx.sslr.api.Grammar; +import org.sonar.check.Priority; +import org.sonar.check.Rule; +import org.sonar.cxx.parser.CxxGrammarImpl; +import org.sonar.cxx.squidbridge.annotations.ActivatedByDefault; +import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation; +import org.sonar.cxx.squidbridge.checks.SquidCheck; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 使用关键资源时指定资源所在的路径 + * 1.获取到声明预计 + * 2.判断是不是路径 + * 3.判断是不是绝对路径 + * + * @author RenFengJiang + * @date 2024/1/22 + */ +@Rule(key = "PathVerifyChecker", name = "使用关键资源时指定资源所在的路径", description = "使用关键资源时指定资源所在的路径", priority = Priority.INFO, tags = {"28suo"}) +@ActivatedByDefault +@SqaleConstantRemediation("5min") +public class PathVerifyChecker extends SquidCheck { + @Override + public void init() { + // 指定当前访问器需要访问的节点类型,functionBody(函数)主体节点 + this.subscribeTo( + CxxGrammarImpl.declarationStatement + ); + } + + /** + * 访问AST节点 + * + * @param node 要处理的AST节点,该节点类型为通过subscribeTo方法订阅的类型 + */ + @Override + public void visitNode(@Nonnull AstNode node) { + //获取参数 + AstNode firstDescendant = node.getFirstDescendant(CxxGrammarImpl.initializer); + List children = firstDescendant.getChildren(); + for(AstNode chil : children){ + //判断参数类型 + if("STRING".equals(chil.getName())){ + String result = chil.getTokenValue().replace("\"", ""); + if(isPath(result)){ + //判断是不是windows或linux的绝对路径 + if(!isWindowsAbsolutePath(result) && !isLinuxAbsolutePath(result)){ + getContext().createLineViolation(this, "使用关键资源时指定资源所在的路径", chil); + } + } + } + } + } + + //判断是不是路径 + public static boolean isPath(String str) { + // 检查字符串是否至少包含一个有效的路径分隔符 + return (str.contains("/") || str.contains("\\")); // 注意:Java中需要双反斜杠来表示单个反斜杠字符 + } + + //windows下判断是否是绝对路径 + public static boolean isWindowsAbsolutePath(String path) { + // 正则表达式匹配以驱动器号(如C:)开始的路径 + String regex = "^([A-Za-z]):\\\\.*"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(path); + return matcher.matches(); + } + + //判断linux下判断是否是绝对路径 + public static boolean isLinuxAbsolutePath(String path) { + // 正则表达式匹配以根目录(/)开始的路径 + String regex = "^/"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(path); + + return matcher.find(); // 使用find()而不是matches(),因为matches()要求整个字符串都符合模式 + } +} diff --git a/sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/PathVerifyCheckerTest.java b/sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/PathVerifyCheckerTest.java new file mode 100644 index 0000000..9ae8478 --- /dev/null +++ b/sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/PathVerifyCheckerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ + +package com.keyware.sonar.cxx.rules.checkers; + +import com.keyware.sonar.cxx.CxxFileTesterHelper; +import org.junit.jupiter.api.Test; +import org.sonar.cxx.CxxAstScanner; +import org.sonar.cxx.squidbridge.api.SourceFile; +import org.sonar.cxx.squidbridge.checks.CheckMessagesVerifier; + +import java.io.IOException; + +/** + * TODO PathVerifyCheckerTest + * + * @author RenFengJiang + * @date 2024/1/22 + */ +public class PathVerifyCheckerTest { + @Test + public void checkTest() throws IOException { + var checker = new PathVerifyChecker(); + var tester = CxxFileTesterHelper.create("PathVerifyChecker.cc"); + SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); + CheckMessagesVerifier.verify(file.getCheckMessages()) + .next().atLine(3).withMessage("使用关键资源时指定资源所在的路径") + .next().atLine(4).withMessage("使用关键资源时指定资源所在的路径") + .noMore(); + } +} diff --git a/sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/PathVerifyChecker.cc b/sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/PathVerifyChecker.cc new file mode 100644 index 0000000..2e1abc8 --- /dev/null +++ b/sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/PathVerifyChecker.cc @@ -0,0 +1,7 @@ +int main() { + //std::String a = "/path/to/your/file.txt"; + std::String a = "path/to/your/file.txt"; + std::String testString1 = "User\\Documents"; + //std::String testString1 = "C:\\Users\\User\\Documents"; + return 0; +} \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/ConfigFileSquidSensor.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/ConfigFileSquidSensor.java new file mode 100644 index 0000000..7ce3247 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/ConfigFileSquidSensor.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ +package com.keyware.sonar.java; + +import com.keyware.sonar.java.rules.checkers.ConfigurationFileChecker; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.rule.CheckFactory; +import org.sonar.api.batch.rule.Checks; +import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.SensorDescriptor; +import org.sonar.api.measures.CoreMetrics; + +import java.io.IOException; + +public class ConfigFileSquidSensor implements Sensor { + private final Checks checks; + + private SensorContext context; + + public ConfigFileSquidSensor(CheckFactory checkFactory){ + checks = checkFactory.create("config"); + checks.addAnnotatedChecks(ConfigurationFileChecker.class); + } + @Override + public void describe(SensorDescriptor descriptor) { + descriptor + .name("ConfigSquidSensor") + .onlyOnLanguages(ConfigurationFileLanguage.KEY) + .createIssuesForRuleRepository("config"); + } + + @Override + public void execute(SensorContext context) { + FilePredicates p = context.fileSystem().predicates(); + for (InputFile inputFile : context.fileSystem().inputFiles(p.hasLanguages(ConfigurationFileLanguage.KEY))) { + checks.all().forEach(check -> { + check.execute(context, inputFile, checks.ruleKey(check)); + }); + } + } + + private String readFileContents(InputFile javaFile) { + String content; + try { + content = javaFile.contents(); + } catch (IOException e) { + System.err.println("Failed to read " + javaFile + " due to " + e.getMessage()); + content = ""; + } + return content; + } + + private void measureLines(SensorContext context, InputFile javaFile, String content) { + int lines = content.split("[\n\r]").length; + context.newMeasure() + .forMetric(CoreMetrics.NCLOC) + .on(javaFile) + .withValue(lines) + .save(); + } + + +} diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/ConfigurationFileLanguage.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/ConfigurationFileLanguage.java new file mode 100644 index 0000000..f2a6028 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/ConfigurationFileLanguage.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ +package com.keyware.sonar.java; + +import org.sonar.api.config.Configuration; +import org.sonar.api.config.PropertyDefinition; +import org.sonar.api.resources.AbstractLanguage; +import org.sonar.api.resources.Qualifiers; + +import java.util.Arrays; +import java.util.List; + +import static java.util.Arrays.asList; + +public class ConfigurationFileLanguage extends AbstractLanguage { + + public static final String NAME = "Configuration"; + public static final String KEY = "cfg"; + public static final String FILE_SUFFIXES_KEY = "sonar.disposition.file.suffixes"; + public static final String FILE_SUFFIXES_DEFAULT_VALUE = ".properties,.ini,.conf"; + + private final Configuration config; + + public ConfigurationFileLanguage(Configuration config) { + super(KEY, NAME); + this.config = config; + } + + @Override + public String[] getFileSuffixes() { + String[] suffixes = config.getStringArray(FILE_SUFFIXES_KEY); + + if (suffixes == null || suffixes.length == 0) { + return FILE_SUFFIXES_DEFAULT_VALUE.split(","); + } + + // 修剪空格和小写后缀 + return Arrays.stream(suffixes) + .map(String::trim) + .map(String::toLowerCase) + .toArray(String[]::new); + } + + public static List getProperties() { + return asList( + PropertyDefinition.builder(FILE_SUFFIXES_KEY) + .multiValues(true) + .defaultValue(FILE_SUFFIXES_DEFAULT_VALUE) + .category("FileType") + .name("File Suffixes") + .description("List of suffixes for files to analyze.") + .onQualifiers(Qualifiers.PROJECT) + .build() + ); + } +} diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/JavaSecurityDesignRulesPlugin.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/JavaSecurityDesignRulesPlugin.java index 6fc1f83..d271efc 100644 --- a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/JavaSecurityDesignRulesPlugin.java +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/JavaSecurityDesignRulesPlugin.java @@ -28,5 +28,14 @@ public class JavaSecurityDesignRulesPlugin implements Plugin { // 批处理扩展 - >对象在代码分析期间实例化 context.addExtension(JavaFileCheckRegistrar.class); + + context.addExtension(ConfigurationFileLanguage.class); + + + context.addExtension(ConfigFileSquidSensor.class); + + + context.addExtensions(ConfigurationFileLanguage.getProperties()); + } } diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/JavaSecurityDesignWayProfile.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/JavaSecurityDesignWayProfile.java index 8aa513c..e3aeef6 100644 --- a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/JavaSecurityDesignWayProfile.java +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/JavaSecurityDesignWayProfile.java @@ -30,5 +30,9 @@ public class JavaSecurityDesignWayProfile implements BuiltInQualityProfilesDefin var webWay = context.createBuiltInQualityProfile("Web信息安全性设计准则", HtmlConstants.LANGUAGE_KEY); RulesList.getHtmlRules().forEach(check -> webWay.activateRule(JavaSecurityDesignRulesRepository.REPOSITORY_KEY + "-" + HtmlConstants.LANGUAGE_KEY, check.getSimpleName())); webWay.done(); + + var cfgWay = context.createBuiltInQualityProfile("配置信息安全性设计规则", ConfigurationFileLanguage.KEY); + cfgWay.activateRule("config", "ConfigurationFileChecker"); + cfgWay.done(); } } diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/JavaSecurityDesignRulesRepository.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/JavaSecurityDesignRulesRepository.java index 679a4cc..e0ad7a1 100644 --- a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/JavaSecurityDesignRulesRepository.java +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/JavaSecurityDesignRulesRepository.java @@ -6,6 +6,7 @@ */ package com.keyware.sonar.java.rules; +import com.keyware.sonar.java.rules.checkers.ConfigurationFileChecker; import org.sonar.api.SonarEdition; import org.sonar.api.SonarProduct; import org.sonar.api.SonarQubeSide; @@ -15,10 +16,7 @@ import org.sonar.api.utils.Version; import org.sonar.plugins.html.api.HtmlConstants; import org.sonarsource.analyzer.commons.RuleMetadataLoader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Objects; -import java.util.Set; +import java.util.*; /** * 用于定义出现在规则页面中规则的元数据 @@ -50,10 +48,15 @@ public class JavaSecurityDesignRulesRepository implements RulesDefinition { setTemplates(javaRepo); javaRepo.done(); - RulesDefinition.NewRepository htmlRepo = context.createRepository(REPOSITORY_KEY + "-" + HtmlConstants.LANGUAGE_KEY, HtmlConstants.LANGUAGE_KEY).setName(REPOSITORY_NAME); + RulesDefinition.NewRepository htmlRepo = context.createRepository(REPOSITORY_KEY + "-" + HtmlConstants.LANGUAGE_KEY, HtmlConstants.LANGUAGE_KEY).setName("web"); ruleMetadataLoader.addRulesByAnnotatedClass(htmlRepo, new ArrayList<>(RulesList.getHtmlRules())); setTemplates(htmlRepo); htmlRepo.done(); + + RulesDefinition.NewRepository configRepo = context.createRepository("config", "cfg").setName("config"); + ruleMetadataLoader.addRulesByAnnotatedClass(configRepo, List.of(ConfigurationFileChecker.class)); + setTemplates(configRepo); + configRepo.done(); } private static void setTemplates(RulesDefinition.NewRepository repository) { diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/ConfigurationFileChecker.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/ConfigurationFileChecker.java new file mode 100644 index 0000000..ff710a2 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/ConfigurationFileChecker.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ +package com.keyware.sonar.java.rules.checkers; + +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.issue.NewIssue; +import org.sonar.api.rule.RuleKey; +import org.sonar.check.Rule; + +import java.io.*; +import java.util.Properties; +import java.util.Scanner; + + +/** + * TODO ConfigurationFileChecker + * + * @author WuHaoYang + * @date 2024/1/22 + */ +@Rule(key = "ConfigurationFileChecker") +public class ConfigurationFileChecker { + + + public void execute(SensorContext context, InputFile inputFile, RuleKey ruleKey){ + //文件名称 + String filename = inputFile.filename(); + System.out.println("[ConfigurationFileChecker]>>>>>" + filename); + + //校验文件后缀 + if (filename.endsWith(".properties")) { + try { + File file = new File(inputFile.absolutePath()); + try (Scanner scanner = new Scanner(file)) { + int lineNum = 1; + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.contains("password")) { + System.out.println(line); + NewIssue newIssue = context.newIssue(); + newIssue + .forRule(ruleKey) + .at(newIssue.newLocation() + .on(inputFile) + .at(inputFile.selectLine(lineNum))) + .save(); + break; + } + lineNum ++; + } + } + } catch (FileNotFoundException e) { + System.out.println("文件未找到: " + e.getMessage()); + } + } + + + if (filename.endsWith(".ini")){ + // 获取当前输入文件的绝对路径 + File file1 = inputFile.file(); + File absoluteFile = file1.getAbsoluteFile(); + + // 构建目录路径 + File folder = new File(String.valueOf(absoluteFile)).getParentFile(); + System.out.println("---------------ini文件路径----------------"+folder); + File[] listOfFiles = folder.listFiles(); + + int lineNum = 1; + for (File file : listOfFiles) { + if (file.isFile() && file.getName().endsWith(".ini")) { + Properties properties = new Properties(); + + try (FileInputStream fileInput = new FileInputStream(file)) { + properties.load(fileInput); + String password = properties.getProperty("password"); + System.out.println("password=" + password); + NewIssue newIssue = context.newIssue(); + newIssue + .forRule(ruleKey) + .at(newIssue.newLocation() + .on(inputFile) + .at(inputFile.selectLine(lineNum))) + .save(); + } catch (IOException e) { + e.printStackTrace(); + } + } + lineNum++; + } + } + + + + if (filename.endsWith(".conf")){ + // 获取当前输入文件的绝对路径 + File file1 = inputFile.file(); + File absoluteFile = file1.getAbsoluteFile(); + + // 构建目录路径 + File folder = new File(String.valueOf(absoluteFile)).getParentFile(); + + System.out.println("---------------conf文件路径----------------"+folder); + + File[] listOfFiles = folder.listFiles((dir, name) -> name.endsWith(".conf")); + + int lineNum = 1; + for (File file : listOfFiles) { + if (file.isFile()) { + Properties prop = new Properties(); + InputStream input = null; + + try { + input = new FileInputStream(file); + prop.load(input); + + if (prop.containsKey("password")) { + System.out.println("password="+ prop.getProperty("password")); + NewIssue newIssue = context.newIssue(); + newIssue + .forRule(ruleKey) + .at(newIssue.newLocation() + .on(inputFile) + .at(inputFile.selectLine(lineNum))) + .save(); + } + + } catch (IOException ex) { + ex.printStackTrace(); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + lineNum++; + } + } + } + +} diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/OptionsVerifyChecker.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/OptionsVerifyChecker.java new file mode 100644 index 0000000..dc854c1 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/OptionsVerifyChecker.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的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.DefaultModuleScannerContext; +import org.sonar.java.model.expression.LiteralTreeImpl; +import org.sonar.java.model.expression.MemberSelectExpressionTreeImpl; +import org.sonar.java.model.expression.MethodInvocationTreeImpl; +import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; +import org.sonar.plugins.java.api.ModuleScannerContext; +import org.sonar.plugins.java.api.internal.EndOfAnalysis; +import org.sonar.plugins.java.api.tree.Arguments; +import org.sonar.plugins.java.api.tree.ExpressionTree; +import org.sonar.plugins.java.api.tree.Tree; + +import java.util.Collections; +import java.util.List; + +/** + * 应设置X-Frame-Options的值为deny + * 1.获取所有方法调用节点 + * 2.判断方法中的参数是否否和要求 + * + * @author RenFengJiang + * @date 2024/1/22 + */ +@Rule(key = "OptionsVerifyChecker") +public class OptionsVerifyChecker extends IssuableSubscriptionVisitor implements EndOfAnalysis { + + private boolean boo = true; + @Override + public List nodesToVisit() { + /** + * Tree.Kind.METHOD:方法节点 + * Tree.Kind.BLOCK:方法的代码块节点 + * Tree.Kind.METHOD_INVOCATION: 方法的调用节点 + */ + return Collections.singletonList(Tree.Kind.METHOD_INVOCATION); + } + + @Override + public void visitNode(Tree tree) { + //判断项目是否配置 + if(boo){ + MethodInvocationTreeImpl methodInvocationTree = (MethodInvocationTreeImpl) tree; + ExpressionTree expressionTree = methodInvocationTree.methodSelect(); + if(expressionTree instanceof MemberSelectExpressionTreeImpl){ + MemberSelectExpressionTreeImpl selectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree; + //获取到调用方法判断是否是设置配置方法 + if("addHeader".equals(selectExpressionTree.identifier().name()) || "setHeader".equals(selectExpressionTree.identifier().name())){ + //获取方法参数 + Arguments arguments = methodInvocationTree.arguments(); + if(arguments instanceof ArgumentListTreeImpl){ + boolean one = false; + boolean two = false; + for (ExpressionTree argument : (ArgumentListTreeImpl) arguments) { + if(argument instanceof LiteralTreeImpl){ + LiteralTreeImpl literalTree = (LiteralTreeImpl) argument; + //判断参数 + if("\"X-Frame-Options\"".equals(literalTree.token().text())){ + one = true; + }else if("\"DENY\"".equals(literalTree.token().text())){ + two = true; + } + } + } + if(one && two){ + boo = false; + } + } + } + } + } + } + + @Override + public void endOfAnalysis(ModuleScannerContext context) { + var defaultContext = (DefaultModuleScannerContext) context; + if(boo){ + defaultContext.addIssueOnProject(this, "应设置X-Frame-Options的值为deny"); + } + } +} diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/ConfigurationFileChecker.html b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/ConfigurationFileChecker.html new file mode 100644 index 0000000..7f14d75 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/ConfigurationFileChecker.html @@ -0,0 +1,9 @@ +

禁止在容易受攻击的地方明文存储口令密码

+

禁止在容易受攻击的地方明文存储口令密码,如果需要,考虑存储口令的单向加密散列,以替代明文口令存储。

+
+
+
+

合规解决方案

+
+
+
diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/ConfigurationFileChecker.json b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/ConfigurationFileChecker.json new file mode 100644 index 0000000..cf2fffc --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/ConfigurationFileChecker.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/main/resources/org/sonar/l10n/java/rules/java/OptionsVerifyChecker.html b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/OptionsVerifyChecker.html new file mode 100644 index 0000000..7cb1467 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/OptionsVerifyChecker.html @@ -0,0 +1,16 @@ + + +

应设置X-Frame-Options的值为deny(表示页面不允许在frame中展示)或SAMEORIGIN(表示页面可以在相同域名页面的frame中展示),禁止网页被未信任源加载。

+

应设置X-Frame-Options的值为deny

+
+
+
+

合规解决方案

+
+
+
diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/OptionsVerifyChecker.json b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/OptionsVerifyChecker.json new file mode 100644 index 0000000..f0f29b4 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/OptionsVerifyChecker.json @@ -0,0 +1,13 @@ +{ + "title": "应设置X-Frame-Options的值为deny", + "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/OptionsVerifyRule.java b/sonar-keyware-plugins-java/src/test/files/OptionsVerifyRule.java new file mode 100644 index 0000000..f0addf4 --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/files/OptionsVerifyRule.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ + +import javax.servlet.*; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class OptionsVerifyChecker implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException {} + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletResponse res = (HttpServletResponse) response; + res.addHeader("X-Frame-Options", "DENY"); + chain.doFilter(request, response); + } + + @Override + public void destroy() {} + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + response.setHeader("X-Frame-Options", "DENY"); // 或者使用SAMEORIGIN,ALLOW-FROM等其他策略 + filterChain.doFilter(request, response); + } +} \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/files/configFile/ConfigurationFileChecker.conf b/sonar-keyware-plugins-java/src/test/files/configFile/ConfigurationFileChecker.conf new file mode 100644 index 0000000..662d821 --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/files/configFile/ConfigurationFileChecker.conf @@ -0,0 +1,2 @@ +# 这是一个conf配置文件 +password = yourpassword \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/files/configFile/ConfigurationFileChecker.ini b/sonar-keyware-plugins-java/src/test/files/configFile/ConfigurationFileChecker.ini new file mode 100644 index 0000000..c57ef7f --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/files/configFile/ConfigurationFileChecker.ini @@ -0,0 +1,3 @@ +[UserCredentials] +username = exampleUser +password = examplePassword \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/files/configFile/ConfigurationFileChecker.properties b/sonar-keyware-plugins-java/src/test/files/configFile/ConfigurationFileChecker.properties new file mode 100644 index 0000000..ed2cc37 --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/files/configFile/ConfigurationFileChecker.properties @@ -0,0 +1,2 @@ +# ConfigurationFileChecker.properties +password=abc123 \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/files/options/OptionsVerifyOneRule.java b/sonar-keyware-plugins-java/src/test/files/options/OptionsVerifyOneRule.java new file mode 100644 index 0000000..0ce0cf2 --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/files/options/OptionsVerifyOneRule.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ + +import org.springframework.web.filter.OncePerRequestFilter; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class XFrameOptionsFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { +// response.setHeader("X-Frame-Options", "DENY"); // 或者使用SAMEORIGIN,ALLOW-FROM等其他策略 + filterChain.doFilter(request, response); + } +} + +// 注册过滤器 +public class WebConfig implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + // ...其他配置... + Dynamic registration = servletContext.addFilter("xFrameOptionsFilter", new XFrameOptionsFilter()); + registration.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*"); + } +} \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/files/options/OptionsVerifyTwoRule.java b/sonar-keyware-plugins-java/src/test/files/options/OptionsVerifyTwoRule.java new file mode 100644 index 0000000..f1aced2 --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/files/options/OptionsVerifyTwoRule.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:信息安全性设计准则检查插件 + * 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ + +import javax.servlet.*; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class XFrameOptionsFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException {} + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletResponse res = (HttpServletResponse) response; +// res.addHeader("X-Frame-Options", "DENY"); + chain.doFilter(request, response); + } + + @Override + public void destroy() {} +} \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/JavaSecurityDesignRulesPluginTest.java b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/JavaSecurityDesignRulesPluginTest.java index ff7eb95..3410494 100644 --- a/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/JavaSecurityDesignRulesPluginTest.java +++ b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/JavaSecurityDesignRulesPluginTest.java @@ -8,6 +8,7 @@ package com.keyware.sonar.java; import org.junit.jupiter.api.Test; import org.sonar.api.*; +import org.sonar.api.config.PropertyDefinition; import org.sonar.api.utils.Version; import static org.assertj.core.api.Assertions.assertThat; @@ -26,11 +27,22 @@ public class JavaSecurityDesignRulesPluginTest { new JavaSecurityDesignRulesPlugin().define(context); assertThat(context.getExtensions()) - .extracting(ext -> ((Class) ext).getSimpleName()) + .extracting((ext) -> { + var type = ext.getClass().getSimpleName(); + if("Class".equals(type)){ + return ((Class) ext).getSimpleName(); + }else if("PropertyDefinition".equals(type)){ + return ((PropertyDefinition) ext).name(); + } + return ext.getClass().getSimpleName(); + }) .containsExactlyInAnyOrder( "JavaSecurityDesignRulesRepository", "JavaSecurityDesignWayProfile", - "JavaFileCheckRegistrar"); + "JavaFileCheckRegistrar", + "ConfigurationFileLanguage", + "ConfigFileSquidSensor", + "File Suffixes"); } public static class MockedSonarRuntime implements SonarRuntime { diff --git a/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/OptionsVerifyCheckerTest.java b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/OptionsVerifyCheckerTest.java new file mode 100644 index 0000000..60a3d64 --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/OptionsVerifyCheckerTest.java @@ -0,0 +1,39 @@ +/* + * 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; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * TODO OptionsVerifyCheckerTest + * + * @author RenFengJiang + * @date 2024/1/22 + */ +public class OptionsVerifyCheckerTest { + Collection lists = new ArrayList(){ + { + add("src/test/files/options/OptionsVerifyOneRule.java"); + add("src/test/files/options/OptionsVerifyTwoRule.java"); + } + }; + @Test + void detected() { + + CheckVerifier.newVerifier() + .onFiles(lists) + .withCheck(new OptionsVerifyChecker()) + .withClassPath(FilesUtils.getClassPath("target/test-jars")) + .verifyIssueOnProject("应设置X-Frame-Options的值为deny"); + } +}