Merge remote-tracking branch 'origin/master'

wuhaoyang
wuhaoyang 10 months ago
commit 9d6f3c0c13
  1. 157
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/DLLVerifyChecker.java
  2. 151
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyChecker.java
  3. 14
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/SendMessageChecker.java
  4. 35
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/DLLVerifyCheckerTest.java
  5. 36
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyCheckerTest.java
  6. 57
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/DLLVerifyChecker.cc
  7. 14
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyChecker.cc

@ -0,0 +1,157 @@
/*
* 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.HashMap;
import java.util.List;
import java.util.Map;
/**
* TODO DLLVerifyChecker
*
* @author RenFengJiang
* @date 2024/1/19
*/
@Rule(key = "DLLVerifyChecker", name = "在动态加载库前对输入数据进行验证", description = "检测代码调用动态库时,判断为动态库传参的类型与动态库要求是否一致", priority = Priority.INFO, tags = {"28suo"})
@ActivatedByDefault
@SqaleConstantRemediation("5min")
public class DLLVerifyChecker extends SquidCheck<Grammar> {
private static String name = "在动态加载库前对输入数据进行验证";
@Override
public void init() {
// 指定当前访问器需要访问的节点类型,functionBody(函数)主体节点
this.subscribeTo(
CxxGrammarImpl.functionBody
);
}
/**
* 访问AST节点
*
* @param node 要处理的AST节点该节点类型为通过subscribeTo方法订阅的类型
*/
@Override
public void visitNode(@Nonnull AstNode node) {
Map<String, Integer> map = ifParam(node);
List<AstNode> simps = node.getDescendants(CxxGrammarImpl.simpleDeclaration);
for(AstNode simp :simps){
//判断动态加载库类型
if("HINSTANCE".equals(simp.getTokenValue())){
loadParam(map,simp);
}else if ("void".equals(simp.getTokenValue())){
openParam(map,simp);
}
}
}
//判断是否是dlopen格式的动态加载库
public void openParam(Map<String,Integer> map,AstNode simp){
//获取方法名
List<AstNode> descendants = simp.getDescendants(CxxGrammarImpl.postfixExpression);
if(descendants != null){
for(AstNode desc : descendants){
//判断是否式动态加载库
if("dlopen".equals(desc.getTokenValue())){
//获取其中的参数列表
AstNode firstDescendant = desc.getFirstDescendant(CxxGrammarImpl.additiveExpression);
if(firstDescendant != null){
List<AstNode> children = firstDescendant.getChildren();
for(AstNode dren : children){
//获取参数并进行判断是否是传入的参数
if("IDENTIFIER".equals(dren.getName())){
if(map.containsKey(dren.getTokenValue())){
//判断参数是否进行过校验
Integer integer = map.get(dren.getTokenValue());
//判断参数校验是否在使用之前
if(dren.getTokenLine() > integer){
getContext().createLineViolation(this,name,dren);
}
}else {
getContext().createLineViolation(this,name,dren);
}
}
}
}else {
getContext().createLineViolation(this,name,desc);
}
}
}
}
}
//对LoadLibrary格式的动态加载库进行校验
public void loadParam(Map<String,Integer> map,AstNode simp){
//获取方法名
AstNode firstDescendant = simp.getFirstDescendant(CxxGrammarImpl.postfixExpression);
if(firstDescendant != null){
if("LoadLibrary".equals(firstDescendant.getTokenValue())){
//获取其中的参数列表
List<AstNode> descendants = firstDescendant.getDescendants(CxxGrammarImpl.expressionList);
if(descendants != null){
for (AstNode desc : descendants){
//判断参数是否进行过校验
if (map.containsKey(desc.getTokenValue())){
//判断参数校验是否在使用之前
int tokenLine = map.get(desc.getTokenValue());
if(desc.getTokenLine() > tokenLine){
getContext().createLineViolation(this,name,desc);
break;
}
}else {
getContext().createLineViolation(this,name,desc);
break;
}
}
}else {
getContext().createLineViolation(this,name,firstDescendant);
}
}
}
}
//获取if判断中的参数
public static Map<String, Integer> ifParam(AstNode node){
Map<String, Integer> map = new HashMap<>();
//选择节点语句
List<AstNode> nodeDescendants = node.getDescendants(CxxGrammarImpl.selectionStatement);
for (AstNode astNode:nodeDescendants) {
//判断节点是不是if节点
if("if".equals(astNode.getToken().getValue())){
//获取其中的参数
List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expressionList);
astNodeList.addAll(astNode.getDescendants(CxxGrammarImpl.condition));
for (AstNode expr:astNodeList) {
map.put(expr.getTokenValue(),expr.getTokenLine());
}
//判断第二种情况获取到if里面的参数
if(astNodeList.size() == 0){
List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.relationalExpression);
for (AstNode as:astNodes) {
List<AstNode> children = as.getChildren();
for (AstNode chil:children) {
map.put(chil.getTokenValue(),chil.getTokenLine());
}
}
}
}
}
return map;
}
}

@ -0,0 +1,151 @@
/*
* 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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* TODO IntegerCountVerifyChecker
*
* @author RenFengJiang
* @date 2024/1/18
*/
@Rule(key = "IntegerCountVerifyChecker", name = "來自用戶的整型数据进行算术运算应进行验证", description = "对来自用户的整形数据作算术运算前进行验证,确保运算结果不会溢出", priority = Priority.INFO, tags = {"28suo"})
@ActivatedByDefault
@SqaleConstantRemediation("5min")
public class IntegerCountVerifyChecker extends SquidCheck<Grammar> {
@Override
public void init() {
// 指定当前访问器需要访问的节点类型,functionBody(函数)主体节点
this.subscribeTo(
CxxGrammarImpl.functionBody
);
}
/**
* 访问AST节点
*
* @param node 要处理的AST节点该节点类型为通过subscribeTo方法订阅的类型
*/
@Override
public void visitNode(@Nonnull AstNode node) {
//存放用户输入的整形变量
List<String> cinList = verdictUserParam(node);
//获取到if判断中的参数
Map<String, Integer> map = ifParam(node);
//获取到算术表达式
List<AstNode> descendants = node.getDescendants(CxxGrammarImpl.multiplicativeExpression);
descendants.addAll(node.getDescendants(CxxGrammarImpl.additiveExpression));
for (AstNode desc:descendants) {
//获取到算术表达式中的参数
List<AstNode> children = desc.getChildren();
for(AstNode dren:children){
//过滤掉无用的参数
if("IDENTIFIER".equals(dren.getName())){
//判断是否存在于用户传递的参数集合中
if(cinList.contains(dren.getTokenValue())){
//判断是否进行过校验
if(map.containsKey(dren.getTokenValue())){
Integer integer = map.get(dren.getTokenValue());
//判断校验是否在算术之前
if(integer > dren.getTokenLine()){
getContext().createLineViolation(this,"來自用戶的整型数据进行算术运算应进行验证",dren);
}
}else {
getContext().createLineViolation(this,"來自用戶的整型数据进行算术运算应进行验证",dren);
}
}
}
}
}
}
//获取用户输入的整形变量
public static List verdictUserParam(AstNode node){
//存放整型变量
List<String> lists = new ArrayList<>();
//存放用户输入的整形变量
List<String> cinList = new ArrayList<>();
//获取所有的语句
List<AstNode> statList = node.getDescendants(CxxGrammarImpl.statement);
for (AstNode stList : statList){
//判断是否是整形变量
if("int".equals(stList.getTokenValue())){
List<AstNode> listDescendants = stList.getDescendants(CxxGrammarImpl.initDeclarator);
for(AstNode desc : listDescendants){
lists.add(desc.getTokenValue());
}
//判断是否是std类型
}else if("std".equals(stList.getTokenValue())){
//获取到方法名称
AstNode firstDescendant = stList.getFirstDescendant(CxxGrammarImpl.qualifiedId);
List<AstNode> children = firstDescendant.getChildren();
for(AstNode desc : children){
//判断是否是用户输入方法
if("cin".equals(desc.getTokenValue())){
//获取用户输入中的参数变量
AstNode descendant = stList.getFirstDescendant(CxxGrammarImpl.shiftExpression);
List<AstNode> descendantChildren = descendant.getChildren();
for(AstNode dant:descendantChildren){
if("IDENTIFIER".equals(dant.getName())){
//判断输入的是否是整形变量
if(lists.contains(dant.getTokenValue())){
cinList.add(dant.getTokenValue());
}
}
}
}
}
}
}
return cinList;
}
public static Map<String, Integer> ifParam(AstNode node){
Map<String, Integer> map = new HashMap<>();
//选择节点语句
List<AstNode> nodeDescendants = node.getDescendants(CxxGrammarImpl.selectionStatement);
for (AstNode astNode:nodeDescendants) {
//判断节点是不是if节点
if("if".equals(astNode.getToken().getValue())){
//获取其中的参数
List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expressionList);
astNodeList.addAll(astNode.getDescendants(CxxGrammarImpl.condition));
for (AstNode expr:astNodeList) {
map.put(expr.getTokenValue(),expr.getTokenLine());
}
//判断第二种情况获取到if里面的参数
if(astNodeList.size() == 0){
List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.relationalExpression);
for (AstNode as:astNodes) {
List<AstNode> children = as.getChildren();
for (AstNode chil:children) {
map.put(chil.getTokenValue(),chil.getTokenLine());
}
}
}
}
}
return map;
}
}

@ -36,6 +36,12 @@ public class SendMessageChecker extends SquidCheck<Grammar> {
CxxGrammarImpl.functionBody
);
}
private static List<String> lists = new ArrayList(){{
add("weapon");
add("unit");
add("param");
}};
/**
* 访问AST节点
@ -45,10 +51,7 @@ public class SendMessageChecker extends SquidCheck<Grammar> {
@Override
public void visitNode(@Nonnull AstNode node) {
//创建集合存入违规敏感字段
List<String> lists = new ArrayList();
lists.add("weapon");
lists.add("unit");
lists.add("param");
//获取到所有的表达式
List<AstNode> descendants = node.getDescendants(CxxGrammarImpl.expression);
for (AstNode des:descendants) {
@ -62,7 +65,8 @@ public class SendMessageChecker extends SquidCheck<Grammar> {
if("STRING".equals(astNode.getName())){
}else {
if(lists.contains(astNode.getTokenValue())){
//判斷其中是否包含敏感字段
if(lists.contains(astNode.getTokenValue().toLowerCase())){
getContext().createLineViolation(this,"发送敏感信息前应对敏感信息进行加密",des);
}
}

@ -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 DLLVerifyCheckerTest
*
* @author RenFengJiang
* @date 2024/1/19
*/
public class DLLVerifyCheckerTest {
@Test
public void checkTest() throws IOException {
var checker = new DLLVerifyChecker();
var tester = CxxFileTesterHelper.create("DLLVerifyChecker.cc");
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(13).withMessage("在动态加载库前对输入数据进行验证")
.next().atLine(36).withMessage("在动态加载库前对输入数据进行验证")
.noMore();
}
}

@ -0,0 +1,36 @@
/*
* 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 IntegerCountVerifyCheckerTest
*
* @author RenFengJiang
* @date 2024/1/18
*/
public class IntegerCountVerifyCheckerTest {
@Test
public void checkTest() throws IOException {
var checker = new IntegerCountVerifyChecker();
var tester = CxxFileTesterHelper.create("IntegerCountVerifyChecker.cc");
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(10).withMessage("來自用戶的整型数据进行算术运算应进行验证")
.next().atLine(10).withMessage("來自用戶的整型数据进行算术运算应进行验证")
.noMore();
}
}

@ -0,0 +1,57 @@
#include <iostream>
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
int main()
{
std::String a = "your_dll.dll";
if(a != "a"){
}
HINSTANCE hInsts = LoadLibrary(a);//error
//加载dll
// HINSTANCE hInst = LoadLibrary("your_dll.dll");
if (hInst == NULL) {
std::cout << "无法加载库" << std::endl;
return -1;
}
//获取函数
typedef void (*FuncType)();
FuncType func = (FuncType)GetProcAddress(hInst, "函数名称");
if (func == NULL) {
std::cout << "无法获取函数" << std::endl;
return -1;
}
//调用函数
func();
//卸载dll
FreeLibrary(hInst);
std::String b = "c";
//加载so库
if(b != "a"){
}
void *handle = dlopen(b, RTLD_LAZY);//error
if (!handle) {
std::cerr << "无法打开库:" << dlerror() << '\n';
return 1;
}
//获取函数
typedef void (*FuncType)();
dlerror();
FuncType func = (FuncType)dlsym(handle, "函数名称");
const char *dlsym_error = dlerror();
if (dlsym_error) {
std::cerr << "无法加载符号 '函数名称':" << dlsym_error << '\n';
dlclose(handle);
return 1;
}
//调用函数
func();
//关闭库文件
dlclose(handle);
#endif
return 0;
}

@ -0,0 +1,14 @@
#include <iostream>
int main() {
int num1, num2;
// 输入两个整数
// std::cout << "请输入两个整数:";
std::cin >> num1 >> num2;
// 执行算术运算并打印结果
// if(num1 > 0){
// }
std::cout << "两数之和:" << num1 + num2 << std::endl;
// std::cout << "两数之差:" << num1 - num2 << std::endl;
// std::cout << "两数之积:" << num1 * num2 << std::endl;
return 0;
}
Loading…
Cancel
Save