From bcd123a05d5af94f9114287690ae5843cf4f5588 Mon Sep 17 00:00:00 2001 From: renfengshan <1535889807@qq.com> Date: Sat, 20 Jan 2024 19:28:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E2=80=9C=E6=85=8E=E9=87=8D?= =?UTF-8?q?=E8=80=83=E8=99=91=E5=86=99=E5=85=A5=E6=97=A5=E5=BF=97=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E4=BF=A1=E6=81=AF=E7=9A=84=E9=9A=90=E7=A7=81=E6=80=A7?= =?UTF-8?q?=E2=80=9D=E5=87=86=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rules/checkers/LogFileWriteChecker.java | 140 ++++++++++++++++++ .../checkers/LogFileWriteCheckerTest.java | 35 +++++ .../cxx/rules/checkers/LogFileWriteChecker.cc | 64 ++++---- 3 files changed, 208 insertions(+), 31 deletions(-) create mode 100644 sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.java create mode 100644 sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteCheckerTest.java diff --git a/sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.java b/sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.java new file mode 100644 index 0000000..fce5f0c --- /dev/null +++ b/sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:C++ 信息安全性设计准则 + * 项目描述:用于检查C++源代码的安全性设计准则的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 java.util.ArrayList; +import java.util.List; + +@Rule(key = "LogFileWriteChecker", name = "慎重考虑写入日志文件信息的隐私性", description = "避免把敏感信息写入日志文件,日志文件只需记录必要的信息,包括日志类型、产生时间、错误信息等,不能在日志文件中记录武器参数、用户单位名称、重要控制命令等信息。", priority = Priority.INFO, tags = {"28suo"}) +@ActivatedByDefault +@SqaleConstantRemediation("5min") +public class LogFileWriteChecker extends SquidCheck { + public void init() { + // 订阅要检查AST节点类型,用于在visitNode方法中检查该类型节点 + this.subscribeTo( + CxxGrammarImpl.translationUnit + ); + } + + public void visitNode(AstNode astNode) { + + //四种级别 + List lists = new ArrayList<>(); + lists.add("debug"); + lists.add("info"); + lists.add("warn"); + lists.add("error"); + + //敏感信息 + List listss = new ArrayList<>(); + listss.add("username"); + listss.add("orgname"); + listss.add("armsname"); + + List descendants = astNode.getDescendants(CxxGrammarImpl.declaration); + descendants.addAll(astNode.getDescendants(CxxGrammarImpl.assignmentExpression)); + + for (AstNode dec : descendants) { + AstNode firstDescendantst = dec.getFirstDescendant(CxxGrammarImpl.postfixExpression); + if (firstDescendantst != null) { + if ("spdlog".equals(firstDescendantst.getTokenValue())) { + AstNode firstDescendant = dec.getFirstDescendant(CxxGrammarImpl.declarator); + List astNodeList = astNode.getDescendants(CxxGrammarImpl.expression); + for (AstNode as : astNodeList) { + //判断rotating_logger + if (firstDescendant.getTokenValue().equals(as.getTokenValue())) { + AstNode descendant1 = as.getFirstDescendant(CxxGrammarImpl.postfixExpression); + List children = descendant1.getChildren(); + for (AstNode fir : children) { + //判断是否是debug、info、warn、error + if (lists.contains(fir.getTokenValue())) { + AstNode descendant = as.getFirstDescendant(CxxGrammarImpl.initializerList); + List descendantChildren = descendant.getChildren(); + for (AstNode chil : descendantChildren) { + if ("IDENTIFIER".equals(chil.getName())) { + if (listss.contains(chil.getTokenValue().toLowerCase())) { + getContext().createLineViolation(this, "慎重考虑写入日志文件信息的隐私性", chil); + break; + } + } else if ("additiveExpression".equals(chil.getName())) { + List chilChildren = chil.getChildren(); + for (AstNode dren : chilChildren) { + if (listss.contains(dren.getTokenValue().toLowerCase())) { + getContext().createLineViolation(this, "慎重考虑写入日志文件信息的隐私性", dren); + break; + } + } + } + } + } + } + } + } + } else if ("log4cpp".equals(dec.getTokenValue())) { + AstNode descendant = dec.getFirstDescendant(CxxGrammarImpl.declaratorId); + String tokenValue = null; + if (descendant != null) { + tokenValue = descendant.getTokenValue(); + } else { + AstNode firstDescendant = dec.getFirstDescendant(CxxGrammarImpl.andExpression); + List astNodeList = firstDescendant.getChildren(); + for (AstNode ast : astNodeList) { + if ("IDENTIFIER".equals(ast.getName())) { + tokenValue = ast.getTokenValue(); + } + + } + } + List astNodeList = astNode.getDescendants(CxxGrammarImpl.expression); + for (AstNode ast : astNodeList) { + if (tokenValue.equals(ast.getTokenValue())) { + AstNode descendant1 = ast.getFirstDescendant(CxxGrammarImpl.postfixExpression); + List childrens = descendant1.getChildren(); + for (AstNode fir : childrens) { + //判断是否是debug、info、warn、error + if (lists.contains(fir.getTokenValue())) { + AstNode inits = ast.getFirstDescendant(CxxGrammarImpl.initializerList); + List descendantChildren = inits.getChildren(); + for (AstNode chil : descendantChildren) { + if ("IDENTIFIER".equals(chil.getName())) { + if (listss.contains(chil.getTokenValue().toLowerCase())) { + getContext().createLineViolation(this, "慎重考虑写入日志文件信息的隐私性", chil); + break; + } + } else if ("additiveExpression".equals(chil.getName())) { + List chilChildren = chil.getChildren(); + for (AstNode dren : chilChildren) { + if (listss.contains(dren.getTokenValue().toLowerCase())) { + getContext().createLineViolation(this, "慎重考虑写入日志文件信息的隐私性", dren); + break; + } + } + } + } + } + } + } + } + } + + } + } + } +} + + + + diff --git a/sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteCheckerTest.java b/sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteCheckerTest.java new file mode 100644 index 0000000..c865a31 --- /dev/null +++ b/sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteCheckerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:C++ 信息安全性设计准则 + * 项目描述:用于检查C++源代码的安全性设计准则的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; + +public class LogFileWriteCheckerTest { + @Test + public void checkTest() throws IOException { + var checker = new LogFileWriteChecker(); + var tester = CxxFileTesterHelper.create("LogFileWriteChecker.cc"); + SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); + CheckMessagesVerifier.verify(file.getCheckMessages()) + .next().atLine(25).withMessage("慎重考虑写入日志文件信息的隐私性") + .next().atLine(26).withMessage("慎重考虑写入日志文件信息的隐私性") + .next().atLine(27).withMessage("慎重考虑写入日志文件信息的隐私性") + .next().atLine(28).withMessage("慎重考虑写入日志文件信息的隐私性") + .next().atLine(50).withMessage("慎重考虑写入日志文件信息的隐私性") + .next().atLine(51).withMessage("慎重考虑写入日志文件信息的隐私性") + .next().atLine(52).withMessage("慎重考虑写入日志文件信息的隐私性") + .next().atLine(53).withMessage("慎重考虑写入日志文件信息的隐私性") + .noMore(); + } + +} diff --git a/sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.cc b/sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.cc index c889a40..4403db9 100644 --- a/sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.cc +++ b/sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.cc @@ -1,28 +1,28 @@ -#include "spdlog/spdlog.h" -#include -#include -#include -#include -#include - -std::string username = "user1"; -std::string orgName = "org1"; -std::string armsName = "arms1"; - -// 创建一个rotating file sink,日志文件大小达到1MB时滚动并创建新的日志文件,最多保存3个历史文件 +#include +#include +#include +#include +#include +#include + +//std::string username = "user1"; +//std::string orgName = "org1"; +//std::string armsName = "arms1"; + + +//创建一个rotating file sink,日志文件大小达到1MB时滚动并创建新的日志文件,最多保存3个历史文件 auto rotating_logger = spdlog::rotating_logger_mt("my_logger", "logs/mylogfile.log", 1048576, 3); // 设置日志级别为info及以上 rotating_logger->set_level(spdlog::level::info); int writeLogFile1() { - // 写入不同级别的日志信息 - rotating_logger->debug("This is an debug message"); - rotating_logger->info("This is an info message"); - rotating_logger->warn("This is a warning"); - rotating_logger->error("This is an error"); - - rotating_logger->debug("This is an debug message %s, %s", username, orgName); // error +// // 写入不同级别的日志信息 +// rotating_logger->debug("This is an debug message"); +// rotating_logger->info("This is an info message"); +// rotating_logger->warn("This is a warning"); +// rotating_logger->error("This is an error"); + rotating_logger->debug( username); // error rotating_logger->info("This is an info message" + armsName); // error rotating_logger->warn("This is a warning, {}", armsName); // error rotating_logger->error("This is an error" + armsName); // error @@ -30,21 +30,23 @@ int writeLogFile1() { return 0; } -int writeLogFile2() { - log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); - layout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] %c: %m%n"); - - // 创建FileAppender,并关联布局 - log4cpp::FileAppender *fileAppender = new log4cpp::FileAppender("fileAppender", "logs/mylogfile.log"); - fileAppender->setLayout(layout); +//log4cpp::Category &myCat = log4cpp::Category::getInstance(std::string("MyCategory")); - // 获取或创建一个category,并将appender添加给它 - log4cpp::Category& root = log4cpp::Category::getRoot(); - root.addAppender(fileAppender); - root.setPriority(log4cpp::Priority::INFO); // 设置最低记录的日志级别 +int writeLogFile2() { +// log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); +// layout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] %c: %m%n"); +// +// // 创建FileAppender,并关联布局 +// log4cpp::FileAppender *fileAppender = new log4cpp::FileAppender("fileAppender", "logs/mylogfile.log"); +// fileAppender->setLayout(layout); +// +// // 获取或创建一个category,并将appender添加给它 +// log4cpp::Category& root = log4cpp::Category::getRoot(); +// root.addAppender(fileAppender); +// root.setPriority(log4cpp::Priority::INFO); // 设置最低记录的日志级别 // 写入不同级别的日志信息 - log4cpp::Category& myCat = log4cpp::Category::getInstance(std::string("MyCategory")); + log4cpp::Category &myCat = log4cpp::Category::getInstance(std::string("MyCategory")); myCat.debug("This is an debug message %s, %s", username, orgName); // error myCat.info("This is an info message" + armsName); // error myCat.warn("This is a warning, {}", armsName); // error