新增“慎重考虑写入日志文件信息的隐私性”准则

wuhaoyang
renfengshan 8 months ago
parent 2ada807f82
commit bcd123a05d
  1. 140
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.java
  2. 35
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteCheckerTest.java
  3. 64
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.cc

@ -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<Grammar> {
public void init() {
// 订阅要检查AST节点类型,用于在visitNode方法中检查该类型节点
this.subscribeTo(
CxxGrammarImpl.translationUnit
);
}
public void visitNode(AstNode astNode) {
//四种级别
List<String> lists = new ArrayList<>();
lists.add("debug");
lists.add("info");
lists.add("warn");
lists.add("error");
//敏感信息
List<String> listss = new ArrayList<>();
listss.add("username");
listss.add("orgname");
listss.add("armsname");
List<AstNode> 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<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expression);
for (AstNode as : astNodeList) {
//判断rotating_logger
if (firstDescendant.getTokenValue().equals(as.getTokenValue())) {
AstNode descendant1 = as.getFirstDescendant(CxxGrammarImpl.postfixExpression);
List<AstNode> children = descendant1.getChildren();
for (AstNode fir : children) {
//判断是否是debug、info、warn、error
if (lists.contains(fir.getTokenValue())) {
AstNode descendant = as.getFirstDescendant(CxxGrammarImpl.initializerList);
List<AstNode> 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<AstNode> 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<AstNode> astNodeList = firstDescendant.getChildren();
for (AstNode ast : astNodeList) {
if ("IDENTIFIER".equals(ast.getName())) {
tokenValue = ast.getTokenValue();
}
}
}
List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expression);
for (AstNode ast : astNodeList) {
if (tokenValue.equals(ast.getTokenValue())) {
AstNode descendant1 = ast.getFirstDescendant(CxxGrammarImpl.postfixExpression);
List<AstNode> childrens = descendant1.getChildren();
for (AstNode fir : childrens) {
//判断是否是debug、info、warn、error
if (lists.contains(fir.getTokenValue())) {
AstNode inits = ast.getFirstDescendant(CxxGrammarImpl.initializerList);
List<AstNode> 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<AstNode> chilChildren = chil.getChildren();
for (AstNode dren : chilChildren) {
if (listss.contains(dren.getTokenValue().toLowerCase())) {
getContext().createLineViolation(this, "慎重考虑写入日志文件信息的隐私性", dren);
break;
}
}
}
}
}
}
}
}
}
}
}
}
}

@ -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();
}
}

@ -1,28 +1,28 @@
#include "spdlog/spdlog.h" #include <spdlog/spdlog.h>
#include <log4cpp/Category.hh> #include <log4cpp/Category.h>
#include <log4cpp/Appender.hh> #include <log4cpp/Appender.h>
#include <log4cpp/FileAppender.hh> #include <log4cpp/FileAppender.h>
#include <log4cpp/Layout.hh> #include <log4cpp/Layout.h>
#include <log4cpp/PatternLayout.hh> #include <log4cpp/PatternLayout.h>
std::string username = "user1"; //std::string username = "user1";
std::string orgName = "org1"; //std::string orgName = "org1";
std::string armsName = "arms1"; //std::string armsName = "arms1";
// 创建一个rotating file sink,日志文件大小达到1MB时滚动并创建新的日志文件,最多保存3个历史文件
//创建一个rotating file sink,日志文件大小达到1MB时滚动并创建新的日志文件,最多保存3个历史文件
auto rotating_logger = spdlog::rotating_logger_mt("my_logger", "logs/mylogfile.log", 1048576, 3); auto rotating_logger = spdlog::rotating_logger_mt("my_logger", "logs/mylogfile.log", 1048576, 3);
// 设置日志级别为info及以上 // 设置日志级别为info及以上
rotating_logger->set_level(spdlog::level::info); rotating_logger->set_level(spdlog::level::info);
int writeLogFile1() { int writeLogFile1() {
// 写入不同级别的日志信息 // // 写入不同级别的日志信息
rotating_logger->debug("This is an debug message"); // rotating_logger->debug("This is an debug message");
rotating_logger->info("This is an info message"); // rotating_logger->info("This is an info message");
rotating_logger->warn("This is a warning"); // rotating_logger->warn("This is a warning");
rotating_logger->error("This is an error"); // rotating_logger->error("This is an error");
rotating_logger->debug( username); // error
rotating_logger->debug("This is an debug message %s, %s", username, orgName); // error
rotating_logger->info("This is an info message" + armsName); // error rotating_logger->info("This is an info message" + armsName); // error
rotating_logger->warn("This is a warning, {}", armsName); // error rotating_logger->warn("This is a warning, {}", armsName); // error
rotating_logger->error("This is an error" + armsName); // error rotating_logger->error("This is an error" + armsName); // error
@ -30,21 +30,23 @@ int writeLogFile1() {
return 0; return 0;
} }
int writeLogFile2() { //log4cpp::Category &myCat = log4cpp::Category::getInstance(std::string("MyCategory"));
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添加给它 int writeLogFile2() {
log4cpp::Category& root = log4cpp::Category::getRoot(); // log4cpp::PatternLayout* layout = new log4cpp::PatternLayout();
root.addAppender(fileAppender); // layout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S} [%p] %c: %m%n");
root.setPriority(log4cpp::Priority::INFO); // 设置最低记录的日志级别 //
// // 创建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.debug("This is an debug message %s, %s", username, orgName); // error
myCat.info("This is an info message" + armsName); // error myCat.info("This is an info message" + armsName); // error
myCat.warn("This is a warning, {}", armsName); // error myCat.warn("This is a warning, {}", armsName); // error

Loading…
Cancel
Save