Compare commits

..

No commits in common. 'master' and 'wuhaoyang' have entirely different histories.

  1. 2
      sonar-keyware-plugins-ConfigurationDetection/src/main/java/com/keyware/sonar/Configuration/ConfigurationFileLanguage.java
  2. 108
      sonar-keyware-plugins-ConfigurationDetection/src/main/java/com/keyware/sonar/Configuration/rules/checkers/ConfigurationFileChecker.java
  3. 44
      sonar-keyware-plugins-ConfigurationDetection/src/main/java/com/keyware/sonar/Configuration/rules/checkers/SessionDateChecker.java
  4. 7
      sonar-keyware-plugins-cxx/pom.xml
  5. 49
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/CxxSquidSensor.java
  6. 7
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/FlagLineSensor.java
  7. 15
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/SecurityDesignRuleRepository.java
  8. 7
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/SecurityDesignWayProfile.java
  9. 16
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/BufferDataChecker.java
  10. 10
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/CmdDataVerifyChecker.java
  11. 92
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/DLLVerifyChecker.java
  12. 15
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/EncryptionAlgorithmChecker.java
  13. 21
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/ErrorMessageChecker.java
  14. 2
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/FVNRPassWordChecker.java
  15. 9
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/FVNRShaChecker.java
  16. 120
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/FileAccessChecker.java
  17. 8
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/HighEncryptDesChecker.java
  18. 16
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyChecker.java
  19. 6
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/LogFileWriteChecker.java
  20. 19
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/NumericalCopyChecker.java
  21. 12
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/PRNGVerifyChecker.java
  22. 64
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/PassWordCountChecker.java
  23. 103
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/PathVerifyChecker.java
  24. 2
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/ReallocMainChecker.java
  25. 38
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/SQLVerifyChecker.java
  26. 40
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/SendMessageChecker.java
  27. 24
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/SqlVarNameChecker.java
  28. 35
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/UserInputPasswordChecker.java
  29. 43
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/ValidatePasswordCheck.java
  30. 124
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/VerificationPathChecker.java
  31. 20
      sonar-keyware-plugins-cxx/src/main/java/com/keyware/sonar/cxx/rules/checkers/VirtualLockUsageChecker.java
  32. 259
      sonar-keyware-plugins-cxx/src/main/java/org/sonar/cxx/squidbridge/AstScanner.java
  33. 2
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/BufferDataCheckerTest.java
  34. 1
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/DLLVerifyCheckerTest.java
  35. 1
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/EncryptionAlgorithmCheckerTest.java
  36. 3
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/FileAccessCheckerTest.java
  37. 1
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyCheckerTest.java
  38. 2
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/NumericalCopyTest.java
  39. 1
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/PRNGVerifyCheckerTest.java
  40. 2
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/PassWordCountCheckerTest.java
  41. 2
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/PathVerifyCheckerTest.java
  42. 2
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/ReallocMainCheckerTest.java
  43. 3
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/SQLVerifyCheckerTest.java
  44. 1
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/SendMessageCheckerTest.java
  45. 1
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/UserInputPasswordCheckerTest.java
  46. 1
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/VerificationPathCheckerTest.java
  47. 3
      sonar-keyware-plugins-cxx/src/test/java/com/keyware/sonar/cxx/rules/checkers/VirtualLockUsageCheckerTest.java
  48. 12
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/BufferDataChecker.cc
  49. 6
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/DLLVerifyChecker.cc
  50. 2
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/EncryptionAlgorithmChecker.cc
  51. 7
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/FVNRPassWordChecker.cc
  52. 5
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/FileAccessChecker.cc
  53. 9
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/IntegerCountVerifyChecker.cc
  54. 18
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/NumericalCopyChecker.cc
  55. 4
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/PRNGVerifyChecker.cc
  56. 24
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/PassWordCountChecker.cc
  57. 24
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/PathVerifyChecker.cc
  58. 58
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/SQLVerifyChecker.cc
  59. 2
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/SendMessageChecker.cc
  60. 14
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/UserInputPasswordChecker.cc
  61. 7
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/VerificationPathChecker.cc
  62. 7
      sonar-keyware-plugins-cxx/src/test/resources/com/keyware/sonar/cxx/rules/checkers/VirtualLockUsageChecker.cc
  63. 62
      sonar-keyware-plugins-java/pom.xml
  64. 66
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/Java.java
  65. 200
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/KeyJavaSensor.java
  66. 1
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/JavaFileCheckRegistrar.java
  67. 1
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/JavaSecurityDesignRulesRepository.java
  68. 4
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/RulesList.java
  69. 4
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/AuthenticationChecker.java
  70. 16
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/CookieSensitiveParameterCheck.java
  71. 10
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicCodeChecker.java
  72. 2
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadChecker.java
  73. 18
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/FileCheck.java
  74. 58
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/HashSaltPassWordChecker.java
  75. 80
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/HostIdentityChecker.java
  76. 40
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/HttpInputDataChecker.java
  77. 23
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/InputSQLVerifyChecker.java
  78. 62
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/Md5PassWordVerifyChecker.java
  79. 104
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/OptionsVerifyChecker.java
  80. 85
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/PasswordInputTagJavaChecker.java
  81. 86
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/PasswordRegexCheck.java
  82. 82
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/RSAEncryptionChecker.java
  83. 63
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/RedirectUrlChecker.java
  84. 38
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SecurityCookieChecker.java
  85. 10
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SendMessageVerifyChecker.java
  86. 40
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SessionCacheParamsChecker.java
  87. 4
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/SessionDateChecker.java
  88. 59
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/UploadFileVerifyChecker.java
  89. 32
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/UpperCycleLimitRuleChecker.java
  90. 47
      sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/UserStatusVerifyChecker.java
  91. 4
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/AuthenticationChecker.html
  92. 2
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/AuthenticationChecker.json
  93. 16
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/HostIdentityChecker.html
  94. 13
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/HostIdentityChecker.json
  95. 16
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/PasswordInputTagJavaChecker.html
  96. 13
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/PasswordInputTagJavaChecker.json
  97. 33
      sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/Sonar_way_profile.json
  98. 26
      sonar-keyware-plugins-java/src/test/files/FileCheck.java
  99. 20
      sonar-keyware-plugins-java/src/test/files/HashSaltPassWordRule.java
  100. 26
      sonar-keyware-plugins-java/src/test/files/HostIdentityChecker.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -21,7 +21,7 @@ public class ConfigurationFileLanguage extends AbstractLanguage {
public static final String NAME = "Configuration"; public static final String NAME = "Configuration";
public static final String KEY = "cfg"; public static final String KEY = "cfg";
public static final String FILE_SUFFIXES_KEY = "sonar.disposition.file.suffixes"; public static final String FILE_SUFFIXES_KEY = "sonar.disposition.file.suffixes";
public static final String FILE_SUFFIXES_DEFAULT_VALUE = ".properties,.ini,.conf,.yml,.json"; public static final String FILE_SUFFIXES_DEFAULT_VALUE = ".properties,.ini,.conf,.xml,.yml,.json";
private final Configuration config; private final Configuration config;

@ -15,8 +15,15 @@ import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.issue.NewIssue; import org.sonar.api.batch.sensor.issue.NewIssue;
import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleKey;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.yaml.snakeyaml.Yaml;
import javax.xml.parsers.*;
import java.io.*; import java.io.*;
import java.util.Map;
import java.util.Scanner; import java.util.Scanner;
@ -124,35 +131,15 @@ public class ConfigurationFileChecker implements ConfigCheck{
} }
} }
if (filename.endsWith(".xml") && !filename.equals("pom.xml")) { if (filename.endsWith(".xml") && !filename.equals("pom.xml")){
// 获取当前输入文件的绝对路径 // 获取当前输入文件的绝对路径
File file1 = inputFile.file(); File file1 = inputFile.file();
File absoluteFile = file1.getAbsoluteFile(); File absoluteFile = file1.getAbsoluteFile();
BufferedReader reader = null; File xmlFile = absoluteFile;
int lineNumber = 0;
try { processXML(xmlFile);
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file1), "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
lineNumber++;
if (line.contains("<password>")) {
// 创建和保存issue
NewIssue newIssue = context.newIssue();
newIssue
.forRule(ruleKey)
.at(newIssue.newLocation().on(inputFile)
.at(inputFile.selectLine(lineNumber)))
.save();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try { reader.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
} }
if (filename.endsWith(".json")) { if (filename.endsWith(".json")) {
@ -194,29 +181,70 @@ public class ConfigurationFileChecker implements ConfigCheck{
} }
} }
if (filename.endsWith(".yml")) { if (filename.endsWith(".yml")){
File file = inputFile.file();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
int lineNumber = 0;
while ((line = reader.readLine()) != null) { // 获取当前输入文件的绝对路径
lineNumber++; File file1 = inputFile.file();
if (line.trim().startsWith("password:")) { Yaml yaml = new Yaml();
// 创建并保存issue try (FileInputStream fis = new FileInputStream(file1)) {
NewIssue newIssue = context.newIssue(); Map<String, Object> obj = yaml.load(fis);
newIssue if (obj != null) {
.forRule(ruleKey) String password = searchPassword(obj, 1);
.at(newIssue.newLocation().on(inputFile) if (password != null) {
.at(inputFile.selectLine(lineNumber)))
.save();
} }
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
}
private static String searchPassword(Map<String, Object> map, int lineNum) {
for (String key : map.keySet()) {
if ("password".equals(key) && map.get(key) instanceof String) {
return (String) map.get(key);
} else if (map.get(key) instanceof Map) {
lineNum++;
String password = searchPassword((Map<String, Object>) map.get(key), lineNum);
if (password != null) {
return password;
}
}
}
return null;
} }
public static int getLineNumber(Node node) {
Document document = node.getOwnerDocument();
document.getDocumentElement().normalize();
String xmlContent = document.getDocumentElement().getTextContent();
String[] lines = xmlContent.split("\n");
for(int i = 0; i < lines.length; i++) {
if(lines[i].contains(node.getTextContent())) {
return i+2;
}
}
return -1;
}
public static void processXML(File xmlFile) {
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("password");
for (int i = 0; i < nList.getLength(); i++) {
Node nNode = nList.item(i);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
int lineNumber = getLineNumber(nNode);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} }

@ -13,7 +13,10 @@ import org.sonar.api.rule.RuleKey;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import java.io.*; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.Scanner; import java.util.Scanner;
@ -26,36 +29,11 @@ import java.util.Scanner;
@Rule(key = "SessionDateChecker") @Rule(key = "SessionDateChecker")
public class SessionDateChecker implements ConfigCheck { public class SessionDateChecker implements ConfigCheck {
private boolean boo = false; private boolean boo = true;
public void execute(SensorContext context, InputFile inputFile, RuleKey ruleKey){ public void execute(SensorContext context, InputFile inputFile, RuleKey ruleKey){
if(!boo){ if(boo){
//文件名称 //文件名称
String filename = inputFile.filename(); String filename = inputFile.filename();
if (filename.endsWith(".xml")) {
// 获取当前输入文件的绝对路径
File file1 = inputFile.file();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file1), "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("<session-timeout>-1</session-timeout>")) {
boo = true;
break;
}
}
} catch (Exception e) {
System.out.println("文件未找到: " + e.getMessage());
return; // 文件未找到时立即返回
} finally {
if (reader != null) {
try { reader.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
}
//校验文件后缀 //校验文件后缀
if (filename.endsWith(".properties")) { if (filename.endsWith(".properties")) {
try { try {
@ -63,8 +41,8 @@ public class SessionDateChecker implements ConfigCheck {
try (Scanner scanner = new Scanner(file)) { try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine(); String line = scanner.nextLine();
if (!line.contains("server.servlet.session.timeout")) { if (line.contains("server.servlet.session.timeout")) {
boo = true; boo = false;
break; break;
} }
} }
@ -84,8 +62,8 @@ public class SessionDateChecker implements ConfigCheck {
Map<String, Object> obj = yaml.load(fis); Map<String, Object> obj = yaml.load(fis);
if (obj != null){ if (obj != null){
String sessionTimeout = searchForSessionTimeout(obj, "server", "servlet", "session", "timeout"); String sessionTimeout = searchForSessionTimeout(obj, "server", "servlet", "session", "timeout");
if (sessionTimeout == null) { if (sessionTimeout != null) {
boo = true; boo = false;
} }
} }
} catch (IOException e) { } catch (IOException e) {
@ -99,7 +77,7 @@ public class SessionDateChecker implements ConfigCheck {
Map<String, Object> currentLevel = map; Map<String, Object> currentLevel = map;
for (int i = 0; i < keys.length - 1; ++i) { for (int i = 0; i < keys.length - 1; ++i) {
Object nextLevel = currentLevel.get(keys[i]); Object nextLevel = currentLevel.get(keys[i]);
if (nextLevel != null && nextLevel instanceof Map) { if (nextLevel instanceof Map) {
currentLevel = (Map<String, Object>) nextLevel; currentLevel = (Map<String, Object>) nextLevel;
} else { } else {
return null; return null;

@ -124,13 +124,6 @@
<artifactId>junit-jupiter-api</artifactId> <artifactId>junit-jupiter-api</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.13</version>
</dependency>
</dependencies> </dependencies>

@ -308,17 +308,17 @@ public class CxxSquidSensor implements ProjectSensor {
visitors.add(check); visitors.add(check);
} }
} }
}
var squidConfig = createConfiguration(); var squidConfig = createConfiguration();
var scanner = CxxAstScanner.create(squidConfig, visitors.toArray(new SquidAstVisitor[visitors.size()])); var scanner = CxxAstScanner.create(squidConfig, visitors.toArray(new SquidAstVisitor[visitors.size()]));
Iterable<InputFile> inputFiles = getInputFiles(context, squidConfig); Iterable<InputFile> inputFiles = getInputFiles(context, squidConfig);
scanner.scanInputFiles(inputFiles); scanner.scanInputFiles(inputFiles);
Collection<SourceCode> squidSourceFiles = scanner.getIndex().search(); Collection<SourceCode> squidSourceFiles = scanner.getIndex().search();
save(squidSourceFiles); save(squidSourceFiles);
} }
}
@Override @Override
public String toString() { public String toString() {
@ -428,10 +428,10 @@ public class CxxSquidSensor implements ProjectSensor {
private void saveMeasures(InputFile inputFile, SourceCode sourceCode) { private void saveMeasures(InputFile inputFile, SourceCode sourceCode) {
InputComponent input = inputFile; InputComponent input = inputFile;
if (sourceCode instanceof SourceFile) { if(sourceCode instanceof SourceFile){
// NOSONAR // NOSONAR
noSonarFilter.noSonarInFile(inputFile, ((SourceFile) sourceCode).getNoSonarTagLines()); noSonarFilter.noSonarInFile(inputFile, ((SourceFile)sourceCode).getNoSonarTagLines());
} else { }else{
input = context.project(); input = context.project();
} }
@ -501,27 +501,23 @@ public class CxxSquidSensor implements ProjectSensor {
RuleKey ruleKey = checks.ruleKey(checker); RuleKey ruleKey = checks.ruleKey(checker);
if (ruleKey != null) { if (ruleKey != null) {
try {
var newIssue = context.newIssue().forRule(RuleKey.of(repositoryKey, ruleKey.rule())); var newIssue = context.newIssue().forRule(RuleKey.of(repositoryKey, ruleKey.rule()));
var location = newIssue.newLocation(); var location = newIssue.newLocation();
if (sourceCode instanceof SourceFile) { if(sourceCode instanceof SourceFile){
location.on(inputFile).at(inputFile.selectLine(line)); location.on(inputFile).at(inputFile.selectLine(line));
} else { }else{
location.on(context.project()); location.on(context.project());
} }
location.message(message.getText(Locale.CHINA)); location.message(message.getText(Locale.CHINA));
newIssue.at(location); newIssue.at(location);
newIssue.save(); newIssue.save();
} catch (Exception e) {
LOG.error("save issue error, rule key: {}", message);
}
} else { } else {
LOG.debug("Unknown rule key: %s", message); LOG.debug("Unknown rule key: %s", message);
} }
} }
} }
if (sourceCode instanceof SourceFile) { if(sourceCode instanceof SourceFile) {
var sourceFile = (SourceFile) sourceCode; var sourceFile = (SourceFile) sourceCode;
if (MultiLocatitionSquidCheck.hasMultiLocationCheckMessages(sourceFile)) { if (MultiLocatitionSquidCheck.hasMultiLocationCheckMessages(sourceFile)) {
for (var issue : MultiLocatitionSquidCheck.getMultiLocationCheckMessages(sourceFile)) { for (var issue : MultiLocatitionSquidCheck.getMultiLocationCheckMessages(sourceFile)) {
@ -546,13 +542,12 @@ public class CxxSquidSensor implements ProjectSensor {
} }
private void saveFileLinesContext(InputFile inputFile, SourceCode sourceCode) { private void saveFileLinesContext(InputFile inputFile, SourceCode sourceCode) {
if (sourceCode instanceof SourceProject || inputFile == null) { if(sourceCode instanceof SourceProject || inputFile == null){
return; return;
} }
// measures for the lines of file // measures for the lines of file
var fileLinesContext = fileLinesContextFactory.createFor(inputFile); var fileLinesContext = fileLinesContextFactory.createFor(inputFile);
List<Integer> linesOfCode = (List<Integer>) sourceCode.getData(CxxMetric.NCLOC_DATA); List<Integer> linesOfCode = (List<Integer>) sourceCode.getData(CxxMetric.NCLOC_DATA);
if (linesOfCode != null && !linesOfCode.isEmpty()) {
linesOfCode.stream().sequential().distinct().forEach((line) -> { linesOfCode.stream().sequential().distinct().forEach((line) -> {
try { try {
fileLinesContext.setIntValue(CoreMetrics.NCLOC_DATA_KEY, line, 1); fileLinesContext.setIntValue(CoreMetrics.NCLOC_DATA_KEY, line, 1);
@ -561,10 +556,7 @@ public class CxxSquidSensor implements ProjectSensor {
LOG.debug("NCLOC error in file '{}' at line:{}", inputFile.filename(), line); LOG.debug("NCLOC error in file '{}' at line:{}", inputFile.filename(), line);
} }
}); });
}
List<Integer> executableLines = (List<Integer>) sourceCode.getData(CxxMetric.EXECUTABLE_LINES_DATA); List<Integer> executableLines = (List<Integer>) sourceCode.getData(CxxMetric.EXECUTABLE_LINES_DATA);
if (executableLines != null && !executableLines.isEmpty()) {
executableLines.stream().sequential().distinct().forEach((line) -> { executableLines.stream().sequential().distinct().forEach((line) -> {
try { try {
fileLinesContext.setIntValue(CoreMetrics.EXECUTABLE_LINES_DATA_KEY, line, 1); fileLinesContext.setIntValue(CoreMetrics.EXECUTABLE_LINES_DATA_KEY, line, 1);
@ -573,23 +565,16 @@ public class CxxSquidSensor implements ProjectSensor {
LOG.debug("EXECUTABLE LINES error in file '{}' at line:{}", inputFile.filename(), line); LOG.debug("EXECUTABLE LINES error in file '{}' at line:{}", inputFile.filename(), line);
} }
}); });
}
try {
fileLinesContext.save(); fileLinesContext.save();
}catch (Exception e){
LOG.error(e.getMessage());
}
} }
private void saveCpdTokens(InputFile inputFile, SourceCode sourceCode) { private void saveCpdTokens(InputFile inputFile, SourceCode sourceCode) {
if (sourceCode instanceof SourceProject || inputFile == null) { if(sourceCode instanceof SourceProject || inputFile == null){
return; return;
} }
NewCpdTokens cpdTokens = context.newCpdTokens().onFile(inputFile); NewCpdTokens cpdTokens = context.newCpdTokens().onFile(inputFile);
List<CxxCpdVisitor.CpdToken> data = (List<CxxCpdVisitor.CpdToken>) sourceCode.getData(CxxMetric.CPD_TOKENS_DATA); List<CxxCpdVisitor.CpdToken> data = (List<CxxCpdVisitor.CpdToken>) sourceCode.getData(CxxMetric.CPD_TOKENS_DATA);
if (data != null && !data.isEmpty()) {
data.forEach((item) -> { data.forEach((item) -> {
try { try {
TextRange range = inputFile.newRange(item.startLine, item.startCol, item.endLine, item.endCol); TextRange range = inputFile.newRange(item.startLine, item.startCol, item.endLine, item.endCol);
@ -599,21 +584,18 @@ public class CxxSquidSensor implements ProjectSensor {
LOG.debug("CPD error in file '{}' at line:{}, column:{}", inputFile.filename(), item.startLine, item.startCol); LOG.debug("CPD error in file '{}' at line:{}, column:{}", inputFile.filename(), item.startLine, item.startCol);
} }
}); });
}
cpdTokens.save(); cpdTokens.save();
} }
private void saveHighlighting(InputFile inputFile, SourceCode sourceCode) { private void saveHighlighting(InputFile inputFile, SourceCode sourceCode) {
if (sourceCode instanceof SourceProject || inputFile == null) { if(sourceCode instanceof SourceProject || inputFile == null){
return; return;
} }
NewHighlighting newHighlighting = context.newHighlighting().onFile(inputFile); NewHighlighting newHighlighting = context.newHighlighting().onFile(inputFile);
List<CxxHighlighterVisitor.Highlight> data = (List<CxxHighlighterVisitor.Highlight>) sourceCode.getData( List<CxxHighlighterVisitor.Highlight> data = (List<CxxHighlighterVisitor.Highlight>) sourceCode.getData(
CxxMetric.HIGHLIGTHING_DATA); CxxMetric.HIGHLIGTHING_DATA);
if(data != null && !data.isEmpty()){
data.forEach((item) -> { data.forEach((item) -> {
try { try {
newHighlighting.highlight(item.startLine, item.startLineOffset, item.endLine, item.endLineOffset, newHighlighting.highlight(item.startLine, item.startLineOffset, item.endLine, item.endLineOffset,
@ -624,24 +606,15 @@ public class CxxSquidSensor implements ProjectSensor {
item.startLine, item.startLineOffset, item.endLine, item.endLineOffset); item.startLine, item.startLineOffset, item.endLine, item.endLineOffset);
} }
}); });
}
try {
newHighlighting.save(); newHighlighting.save();
}catch (Exception e){
LOG.error(e.getMessage());
}
} }
private <T extends Serializable> void saveMetric(InputComponent file, Metric<T> metric, T value) { private <T extends Serializable> void saveMetric(InputComponent file, Metric<T> metric, T value) {
try {
context.<T>newMeasure() context.<T>newMeasure()
.withValue(value) .withValue(value)
.forMetric(metric) .forMetric(metric)
.on(file) .on(file)
.save(); .save();
}catch (Exception e){
LOG.error(e.getMessage());
}
} }
} }

@ -6,7 +6,6 @@
*/ */
package com.keyware.sonar.cxx; package com.keyware.sonar.cxx;
import com.keyware.sonar.cxx.rules.SecurityDesignRuleRepository;
import com.keyware.sonar.cxx.rules.checkers.FlagLineRule; import com.keyware.sonar.cxx.rules.checkers.FlagLineRule;
import com.keyware.sonar.cxx.rules.checkers.SqlVarNameChecker; import com.keyware.sonar.cxx.rules.checkers.SqlVarNameChecker;
import org.sonar.api.batch.fs.FilePredicates; import org.sonar.api.batch.fs.FilePredicates;
@ -22,18 +21,18 @@ public class FlagLineSensor implements Sensor {
public FlagLineSensor(CheckFactory checkFactory) { public FlagLineSensor(CheckFactory checkFactory) {
checks = checkFactory.create(SecurityDesignRuleRepository.REPOSITORY_SQL_KEY); checks = checkFactory.create("cxx-security-design-rules");
checks.addAnnotatedChecks(SqlVarNameChecker.class); checks.addAnnotatedChecks(SqlVarNameChecker.class);
} }
@Override @Override
public void describe(SensorDescriptor descriptor) { public void describe(SensorDescriptor descriptor) {
//传感器名称 //传感器名称
descriptor.name("FlagLine1RuleSensor"); descriptor.name("FlagLine1Rule" + "sensor");
//传感器识别的语言 //传感器识别的语言
descriptor.onlyOnLanguages(CxxLanguage.KEY); descriptor.onlyOnLanguages(CxxLanguage.KEY);
//传感器扫描的规则库 //传感器扫描的规则库
descriptor.createIssuesForRuleRepository(SecurityDesignRuleRepository.REPOSITORY_SQL_KEY); descriptor.createIssuesForRuleRepository("cxx-security-design-rules");
} }
@Override @Override

@ -23,19 +23,17 @@ import java.util.List;
*/ */
public class SecurityDesignRuleRepository implements RulesDefinition { public class SecurityDesignRuleRepository implements RulesDefinition {
public final static String REPOSITORY_KEY = "cxx-security-design-rules"; public final static String REPOSITORY_KEY = "cxx-security-design-rules";
public final static String REPOSITORY_LOG_KEY = "log-security-design-rules"; public final static String REPOSITORY_log_key = "log-security-design-rules";
public final static String REPOSITORY_SQL_KEY = "sql-security-design-rules";
public final static String REPOSITORY_NAME = "C++信息安全性设计准则"; public final static String REPOSITORY_NAME = "C++信息安全性设计准则";
// 规则检查器的集合,当有新的规则开发完毕后,需要添加到下面的集合中 // 规则检查器的集合,当有新的规则开发完毕后,需要添加到下面的集合中
public final static List<Class> RULE_CHECKERS = Arrays.asList(ABCVarNameChecker.class,BufferDataChecker.class, CmdDataVerifyChecker.class, public final static List<Class> RULE_CHECKERS = Arrays.asList(ABCVarNameChecker.class,BufferDataChecker.class, CmdDataVerifyChecker.class,
DLLVerifyChecker.class,EncryptionAlgorithmChecker.class,ErrorMessageChecker.class, DLLVerifyChecker.class,EncryptionAlgorithmChecker.class,ErrorMessageChecker.class,
FileAccessChecker.class,FormatFunctionCheck.class,FVNRPassWordChecker.class,FVNRShaChecker.class,HighEncryptDesChecker.class, FileAccessChecker.class,FormatFunctionCheck.class,FVNRPassWordChecker.class,FVNRShaChecker.class,HighEncryptDesChecker.class,
HostIdentityVerifyChecker.class,IntegerCountVerifyChecker.class,LogFileWriteChecker.class,NumericalCopyChecker.class, HostIdentityVerifyChecker.class,IntegerCountVerifyChecker.class,LogChecker.class,LogFileWriteChecker.class,NumericalCopyChecker.class,
PassWordCountChecker.class,PathVerifyChecker.class,PRNGVerifyChecker.class,ReallocMainChecker.class,SendMessageChecker.class, PassWordCountChecker.class,PathVerifyChecker.class,PRNGVerifyChecker.class,ReallocMainChecker.class,SendMessageChecker.class,
SQLVerifyChecker.class,UserInputPasswordChecker.class,ValidatePasswordCheck.class,VerificationPathChecker.class,VirtualLockUsageChecker.class); SQLVerifyChecker.class,UserInputPasswordChecker.class,ValidatePasswordCheck.class,VerificationPathChecker.class,VirtualLockUsageChecker.class);
@Override @Override
public void define(Context context) { public void define(Context context) {
var repository = context.createRepository(REPOSITORY_KEY, CxxLanguage.KEY). var repository = context.createRepository(REPOSITORY_KEY, CxxLanguage.KEY).
@ -43,14 +41,9 @@ public class SecurityDesignRuleRepository implements RulesDefinition {
new AnnotationBasedRulesDefinition(repository, CxxLanguage.KEY).addRuleClasses(false, RULE_CHECKERS); new AnnotationBasedRulesDefinition(repository, CxxLanguage.KEY).addRuleClasses(false, RULE_CHECKERS);
repository.done(); repository.done();
var repository1 = context.createRepository(REPOSITORY_LOG_KEY, LogLanguage.KEY). var repository1 = context.createRepository(REPOSITORY_log_key, LogLanguage.KEY).
setName(REPOSITORY_NAME); setName(REPOSITORY_NAME);
new AnnotationBasedRulesDefinition(repository1, LogLanguage.KEY).addRuleClasses(false, List.of(LogChecker.class)); new AnnotationBasedRulesDefinition(repository1, LogLanguage.KEY).addRuleClasses(false, RULE_CHECKERS);
repository1.done(); repository1.done();
var repository2 = context.createRepository(REPOSITORY_SQL_KEY, CxxLanguage.KEY).
setName(REPOSITORY_NAME);
new AnnotationBasedRulesDefinition(repository2, CxxLanguage.KEY).addRuleClasses(false, List.of(SqlVarNameChecker.class));
repository2.done();
} }
} }

@ -22,7 +22,7 @@ public class SecurityDesignWayProfile implements BuiltInQualityProfilesDefinitio
@Override @Override
public void define(Context context) { public void define(Context context) {
var way = context.createBuiltInQualityProfile("C++信息安全性设计准则", CxxLanguage.KEY); var way = context.createBuiltInQualityProfile("C++信息安全性设计准则", CxxLanguage.KEY);
//way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "ABCVarNameChecker"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "ABCVarNameChecker");
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "BufferDataChecker"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "BufferDataChecker");
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "CmdDataVerifyChecker"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "CmdDataVerifyChecker");
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "DLLVerifyChecker"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "DLLVerifyChecker");
@ -42,6 +42,7 @@ public class SecurityDesignWayProfile implements BuiltInQualityProfilesDefinitio
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "PRNGVerifyChecker"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "PRNGVerifyChecker");
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "ReallocMainChecker"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "ReallocMainChecker");
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "SendMessageChecker"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "SendMessageChecker");
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "FlagLine1Rule");
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "SQLVerifyChecker"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "SQLVerifyChecker");
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "UserInputPasswordChecker"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "UserInputPasswordChecker");
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "ValidatePasswordCheck"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "ValidatePasswordCheck");
@ -49,8 +50,8 @@ public class SecurityDesignWayProfile implements BuiltInQualityProfilesDefinitio
way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "VirtualLockUsageChecker"); way.activateRule(SecurityDesignRuleRepository.REPOSITORY_KEY, "VirtualLockUsageChecker");
way.done(); way.done();
var way1 = context.createBuiltInQualityProfile("log信息安全性设计准则", LogLanguage.KEY); var way1 = context.createBuiltInQualityProfile("LogLanguage信息安全性设计准则", LogLanguage.KEY);
way1.activateRule(SecurityDesignRuleRepository.REPOSITORY_LOG_KEY, "LogChecker"); way1.activateRule(SecurityDesignRuleRepository.REPOSITORY_log_key, "LogChecker");
way1.done(); way1.done();
} }
} }

@ -92,7 +92,7 @@ public class BufferDataChecker extends SquidCheck<Grammar> {
for (AstNode ast:descendants) { for (AstNode ast:descendants) {
String name = ast.getParent().getToken().getValue(); String name = ast.getParent().getToken().getValue();
//判断是否时使用sanitizeString方法 //判断是否时使用sanitizeString方法
if("memcpy".equals(name) || "strncpy".equals(name) || "memset".equals(name) || "strcpy".equals(name)){ if("memcpy".equals(name) || "strncpy".equals(name) || "memset".equals(name)){
//判断方法参数是否进行校验 //判断方法参数是否进行校验
List<AstNode> astNodeList = ast.getDescendants(CxxGrammarImpl.initializerList); List<AstNode> astNodeList = ast.getDescendants(CxxGrammarImpl.initializerList);
AstNode astNode = astNodeList.get(astNodeList.size() - 1); AstNode astNode = astNodeList.get(astNodeList.size() - 1);
@ -101,20 +101,6 @@ public class BufferDataChecker extends SquidCheck<Grammar> {
if(!lists.contains(tokenValue)){ if(!lists.contains(tokenValue)){
reportIssue(ast, "应对读写缓冲区的数据长度进行检查"); reportIssue(ast, "应对读写缓冲区的数据长度进行检查");
} }
}else if("scanf".equals(name)){
List<AstNode> astNodeList = ast.getDescendants(CxxGrammarImpl.initializerList);
if(astNodeList != null){
AstNode astNode = astNodeList.get(astNodeList.size() - 1);
List<AstNode> childrens = astNode.getChildren();
if(childrens.size() != 0){
String tokenValue = childrens.get(0).getTokenValue();
boolean boo = tokenValue.chars().anyMatch(Character::isDigit);
if(!boo){
reportIssue(ast, "应对读写缓冲区的数据长度进行检查");
}
}
}
} }
} }
} }

@ -72,13 +72,12 @@ public class CmdDataVerifyChecker extends SquidCheck<Grammar> {
//判断节点是不是if节点 //判断节点是不是if节点
if("if".equals(astNode.getToken().getValue())){ if("if".equals(astNode.getToken().getValue())){
//获取其中的参数 //获取其中的参数
List<AstNode> descendants = astNode.getDescendants(CxxGrammarImpl.condition); List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expressionList);
// List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expressionList); astNodeList.addAll(astNode.getDescendants(CxxGrammarImpl.condition));
// astNodeList.addAll(astNode.getDescendants(CxxGrammarImpl.condition)); for (AstNode expr:astNodeList) {
for (AstNode expr:descendants) {
lists.add(expr.getToken().getValue()); lists.add(expr.getToken().getValue());
} }
if(descendants.size() == 0){ if(astNodeList.size() == 0){
List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.relationalExpression); List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.relationalExpression);
for (AstNode as:astNodes) { for (AstNode as:astNodes) {
List<AstNode> children = as.getChildren(); List<AstNode> children = as.getChildren();
@ -95,7 +94,6 @@ public class CmdDataVerifyChecker extends SquidCheck<Grammar> {
String name = ast.getParent().getToken().getValue(); String name = ast.getParent().getToken().getValue();
//判断是否时使用sanitizeString方法 //判断是否时使用sanitizeString方法
if("system".equals(name)){ if("system".equals(name)){
String valueName = ast.getToken().getValue();
//判断方法参数是否进行校验 //判断方法参数是否进行校验
if(!lists.contains(ast.getToken().getValue())){ if(!lists.contains(ast.getToken().getValue())){
reportIssue(ast, "在构建命令前对输入数据进行验证"); reportIssue(ast, "在构建命令前对输入数据进行验证");

@ -32,7 +32,6 @@ import java.util.Map;
public class DLLVerifyChecker extends SquidCheck<Grammar> { public class DLLVerifyChecker extends SquidCheck<Grammar> {
private static String name = "在动态加载库前对输入数据进行验证"; private static String name = "在动态加载库前对输入数据进行验证";
@Override @Override
public void init() { public void init() {
// 指定当前访问器需要访问的节点类型,functionBody(函数)主体节点 // 指定当前访问器需要访问的节点类型,functionBody(函数)主体节点
@ -49,86 +48,101 @@ public class DLLVerifyChecker extends SquidCheck<Grammar> {
@Override @Override
public void visitNode(@Nonnull AstNode node) { public void visitNode(@Nonnull AstNode node) {
Map<String, Integer> map = ifParam(node); Map<String, Integer> map = ifParam(node);
List<AstNode> descendants = node.getDescendants(CxxGrammarImpl.postfixExpression); List<AstNode> simps = node.getDescendants(CxxGrammarImpl.simpleDeclaration);
for (AstNode desc :descendants){ for(AstNode simp :simps){
if("dlopen".equals(desc.getTokenValue())){ //判断动态加载库类型
loadParam(map,desc); if("HINSTANCE".equals(simp.getTokenValue())){
}else if ("LoadLibrary".equals(desc.getTokenValue())){ loadParam(map,simp);
openParam(map,desc); }else if ("void".equals(simp.getTokenValue())){
openParam(map,simp);
} }
} }
} }
//判断是否是dlopen格式的动态加载库 //判断是否是dlopen格式的动态加载库
public void openParam(Map<String, Integer> map, AstNode simp) { 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 = simp.getFirstDescendant(CxxGrammarImpl.expressionList); AstNode firstDescendant = desc.getFirstDescendant(CxxGrammarImpl.expressionList);
if (firstDescendant != null) { if(firstDescendant != null){
List<AstNode> children = firstDescendant.getChildren(); List<AstNode> children = firstDescendant.getChildren();
for (AstNode dren : children) { for(AstNode dren : children){
//获取参数并进行判断是否是传入的参数 //获取参数并进行判断是否是传入的参数
if ("IDENTIFIER".equals(dren.getName()) || "initializerList".equals(dren.getName())) { if("IDENTIFIER".equals(dren.getName()) || "initializerList".equals(dren.getName())){
if (map.containsKey(dren.getTokenValue())) { if(map.containsKey(dren.getTokenValue())){
//判断参数是否进行过校验 //判断参数是否进行过校验
Integer integer = map.get(dren.getTokenValue()); Integer integer = map.get(dren.getTokenValue());
//判断参数校验是否在使用之前 //判断参数校验是否在使用之前
if (dren.getTokenLine() < integer) { if(dren.getTokenLine() < integer){
getContext().createLineViolation(this, name, dren); getContext().createLineViolation(this,name,dren);
}
}else {
getContext().createLineViolation(this,name,dren);
}
}
} }
} else {
getContext().createLineViolation(this, name, dren);
} }
} }
} }
} }
} }
//对LoadLibrary格式的动态加载库进行校验 //对LoadLibrary格式的动态加载库进行校验
public void loadParam(Map<String, Integer> map, AstNode simp) { public void loadParam(Map<String,Integer> map,AstNode simp){
List<AstNode> descendants = simp.getDescendants(CxxGrammarImpl.expressionList); //获取方法名
if (descendants != null) { AstNode firstDescendant = simp.getFirstDescendant(CxxGrammarImpl.postfixExpression);
for (AstNode desc : descendants) { 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())) { if (map.containsKey(desc.getTokenValue())){
//判断参数校验是否在使用之前 //判断参数校验是否在使用之前
int tokenLine = map.get(desc.getTokenValue()); int tokenLine = map.get(desc.getTokenValue());
if (desc.getTokenLine() < tokenLine) { if(desc.getTokenLine() < tokenLine){
getContext().createLineViolation(this, name, desc); getContext().createLineViolation(this,name,desc);
break; break;
} }
} else { }else {
getContext().createLineViolation(this, name, desc); getContext().createLineViolation(this,name,desc);
break; break;
} }
} }
} else { }else {
getContext().createLineViolation(this, name, simp); getContext().createLineViolation(this,name,firstDescendant);
}
}
} }
} }
//获取if判断中的参数 //获取if判断中的参数
public static Map<String, Integer> ifParam(AstNode node) { public static Map<String, Integer> ifParam(AstNode node){
Map<String, Integer> map = new HashMap<>(); Map<String, Integer> map = new HashMap<>();
//选择节点语句 //选择节点语句
List<AstNode> nodeDescendants = node.getDescendants(CxxGrammarImpl.selectionStatement); List<AstNode> nodeDescendants = node.getDescendants(CxxGrammarImpl.selectionStatement);
for (AstNode astNode : nodeDescendants) { for (AstNode astNode:nodeDescendants) {
//判断节点是不是if节点 //判断节点是不是if节点
if ("if".equals(astNode.getToken().getValue())) { if("if".equals(astNode.getToken().getValue())){
//获取其中的参数 //获取其中的参数
List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expressionList); List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expressionList);
astNodeList.addAll(astNode.getDescendants(CxxGrammarImpl.condition)); astNodeList.addAll(astNode.getDescendants(CxxGrammarImpl.condition));
for (AstNode expr : astNodeList) { for (AstNode expr:astNodeList) {
map.put(expr.getTokenValue(), expr.getTokenLine()); map.put(expr.getTokenValue(),expr.getTokenLine());
} }
//判断第二种情况获取到if里面的参数 //判断第二种情况获取到if里面的参数
if (astNodeList.size() == 0) { if(astNodeList.size() == 0){
List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.relationalExpression); List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.relationalExpression);
for (AstNode as : astNodes) { for (AstNode as:astNodes) {
List<AstNode> children = as.getChildren(); List<AstNode> children = as.getChildren();
for (AstNode chil : children) { for (AstNode chil:children) {
map.put(chil.getTokenValue(), chil.getTokenLine()); map.put(chil.getTokenValue(),chil.getTokenLine());
} }
} }
} }

@ -43,9 +43,7 @@ public class EncryptionAlgorithmChecker extends SquidCheck<Grammar> {
@Override @Override
public void visitNode(AstNode astNode) { public void visitNode(AstNode astNode) {
AstNode descendant = astNode.getFirstDescendant(CxxGrammarImpl.declaratorId); var varName = astNode.getFirstDescendant(CxxGrammarImpl.declaratorId).getTokenOriginalValue();
if(descendant != null){
var varName =descendant.getTokenValue();
if(varName.contains("password") && !cache.containsKey(varName)){ if(varName.contains("password") && !cache.containsKey(varName)){
cache.put(varName, astNode); cache.put(varName, astNode);
var next = astNode.getNextAstNode(); var next = astNode.getNextAstNode();
@ -53,11 +51,11 @@ public class EncryptionAlgorithmChecker extends SquidCheck<Grammar> {
var callNode = next.getFirstDescendant(CxxGrammarImpl.postfixExpression); var callNode = next.getFirstDescendant(CxxGrammarImpl.postfixExpression);
if(callNode != null){ if(callNode != null){
var callList = callNode.getDescendants(CxxGrammarImpl.className); var callList = callNode.getDescendants(CxxGrammarImpl.className);
if(callList != null && !callList.isEmpty()) { if(!callList.isEmpty()) {
var funName = callList.get(callList.size() - 1).getTokenValue(); var funName = callList.get(callList.size() - 1).getTokenOriginalValue();
var paramList = callNode.getDescendants(CxxGrammarImpl.expressionList); var paramList = callNode.getDescendants(CxxGrammarImpl.expressionList);
if("hashpw".equalsIgnoreCase(funName) && paramList.stream().anyMatch(item-> { if("hashpw".equalsIgnoreCase(funName) && paramList.stream().anyMatch(item-> {
var name = item.getTokenValue(); var name = item.getTokenOriginalValue();
return name != null && ("password".equals(name) || "salt".equals(name)); return name != null && ("password".equals(name) || "salt".equals(name));
})){ })){
cache.remove(varName); cache.remove(varName);
@ -69,11 +67,6 @@ public class EncryptionAlgorithmChecker extends SquidCheck<Grammar> {
cache.values().forEach(item->{ cache.values().forEach(item->{
getContext().createLineViolation(this, "特定字段未使用单向加密算法对口令进行加密并存储", item); getContext().createLineViolation(this, "特定字段未使用单向加密算法对口令进行加密并存储", item);
}); });
}else if(astNode.getTokenValue().contains("AESEncryption") ){
getContext().createLineViolation(this, "特定字段未使用单向加密算法对口令进行加密并存储", astNode);
}
} }
String tokenValue = astNode.getTokenValue();
} }
} }

@ -53,24 +53,19 @@ public class ErrorMessageChecker extends SquidCheck<Grammar> {
*/ */
@Override @Override
public void visitNode(@Nonnull AstNode node) { public void visitNode(@Nonnull AstNode node) {
//声明集合
List<AstNode> children;
//获取第一种情况参数列表 //获取第一种情况参数列表
AstNode firstDescendant = node.getFirstDescendant(CxxGrammarImpl.additiveExpression); AstNode firstDescendant = node.getFirstDescendant(CxxGrammarImpl.additiveExpression);
if(firstDescendant != null){ if(firstDescendant != null){
//第一种情况获取参数列表 //第一种情况获取参数列表
List<AstNode> children = firstDescendant.getChildren(); children = firstDescendant.getChildren();
//判断参数列表是否包含违规参数
for(AstNode chil : children){
if("IDENTIFIER".equals(chil.getName())){
if(lists.contains(chil.getTokenValue().toLowerCase())){
getContext().createLineViolation(this,"抛出异常消息不得包含敏感信息",chil);
}
}
}
}else { }else {
//获取第二种情况获取参数列表 //获取第二种情况获取参数列表
AstNode descendant = node.getFirstDescendant(CxxGrammarImpl.initializerList); AstNode descendant = node.getFirstDescendant(CxxGrammarImpl.initializerList);
if(descendant != null){ children = descendant.getChildren();
List<AstNode> children = descendant.getChildren(); }
//判断参数列表是否包含违规参数
for(AstNode chil : children){ for(AstNode chil : children){
if("IDENTIFIER".equals(chil.getName())){ if("IDENTIFIER".equals(chil.getName())){
if(lists.contains(chil.getTokenValue().toLowerCase())){ if(lists.contains(chil.getTokenValue().toLowerCase())){
@ -78,10 +73,6 @@ public class ErrorMessageChecker extends SquidCheck<Grammar> {
} }
} }
} }
}
}
} }
} }

@ -43,7 +43,7 @@ public class FVNRPassWordChecker extends SquidCheck<Grammar> {
List<String> inputFileLines = getContext().getInputFileLines(); List<String> inputFileLines = getContext().getInputFileLines();
for (String str:inputFileLines) { for (String str:inputFileLines) {
if(str.startsWith("#include")){ if(str.startsWith("#include")){
if(str.contains("openssl/aes.h") || str.contains("openssl/des.h") || str.contains("\"aes.h\"")){ if(str.contains("openssl/aes.h") || str.contains("openssl/des.h")){
getContext().createFileViolation(this, "应使用单向不可逆算法对密码进行加密"); getContext().createFileViolation(this, "应使用单向不可逆算法对密码进行加密");
break; break;
} }

@ -41,13 +41,14 @@ public class FVNRShaChecker extends SquidCheck<Grammar> {
public void visitFile(@Nullable AstNode astNode) { public void visitFile(@Nullable AstNode astNode) {
//逐行获取内容 //逐行获取内容
List<String> inputFileLines = getContext().getInputFileLines(); List<String> inputFileLines = getContext().getInputFileLines();
for (String str : inputFileLines) { for (String str:inputFileLines) {
if (str.startsWith("#include")) { if(str.startsWith("#include")){
if (!str.contains("sha.h") && !str.contains("blake2.h") && !str.contains("md5.h")) { if(str.contains("openssl/") || str.contains("cryptopp/") ){
if(!str.contains("sha.h") && !str.contains("blake2.h") && !str.contains("md5.h")){
getContext().createFileViolation(this, "应使用不可逆标准散列算法"); getContext().createFileViolation(this, "应使用不可逆标准散列算法");
break; break;
} }
}
} }
} }
} }

@ -6,9 +6,7 @@
*/ */
package com.keyware.sonar.cxx.rules.checkers; package com.keyware.sonar.cxx.rules.checkers;
import com.sonar.cxx.sslr.api.AstNode; import com.sonar.cxx.sslr.api.AstNode;
import com.sonar.cxx.sslr.api.GenericTokenType;
import com.sonar.cxx.sslr.api.Grammar; import com.sonar.cxx.sslr.api.Grammar;
import org.sonar.check.Priority; import org.sonar.check.Priority;
import org.sonar.check.Rule; import org.sonar.check.Rule;
@ -17,10 +15,6 @@ import org.sonar.cxx.squidbridge.annotations.ActivatedByDefault;
import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation; import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation;
import org.sonar.cxx.squidbridge.checks.SquidCheck; import org.sonar.cxx.squidbridge.checks.SquidCheck;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** /**
* 在访问文件或目录前对路径名进行验证 * 在访问文件或目录前对路径名进行验证
@ -33,106 +27,68 @@ import java.util.Set;
@ActivatedByDefault @ActivatedByDefault
@SqaleConstantRemediation("5min") @SqaleConstantRemediation("5min")
public class FileAccessChecker extends SquidCheck<Grammar> { public class FileAccessChecker extends SquidCheck<Grammar> {
private boolean filePathChecked = false;
private Set<String> conditionVariables; private boolean filePathUsedInIf = false;
@Override @Override
public void init() { public void init() {
subscribeTo(CxxGrammarImpl.selectionStatement); subscribeTo(CxxGrammarImpl.selectionStatement, CxxGrammarImpl.declaration, CxxGrammarImpl.statement);
subscribeTo(CxxGrammarImpl.declaration);
subscribeTo(CxxGrammarImpl.postfixExpression);
conditionVariables = new HashSet<>();
} }
@Override @Override
public void visitNode(AstNode node) { public void visitNode(AstNode astNode) {
if (node.is(CxxGrammarImpl.selectionStatement)) { if (astNode.is(CxxGrammarImpl.selectionStatement)) {
handleIfStatement(node); checkIfStatement(astNode);
} else if (node.is(CxxGrammarImpl.declaration)) { } else if (astNode.is(CxxGrammarImpl.declaration)) {
addAllIdentifiers(node); checkDeclaration(astNode);
handleDeclaration(node); } else if (astNode.is(CxxGrammarImpl.statement)) {
} else if (node.is(CxxGrammarImpl.postfixExpression)) { checkStatement(astNode);
verdictExpression(node);
} }
} }
private void verdictExpression(AstNode node) { private void checkIfStatement(AstNode ifStatement) {
String methodName = node.getTokenValue(); AstNode condition = ifStatement.getFirstChild(CxxGrammarImpl.condition);
if (methodName != null) { filePathUsedInIf = containsFilePathCheck(condition);
if ("fopen".equals(methodName)) { if (!filePathUsedInIf) {
List<AstNode> descendants = node.getDescendants(CxxGrammarImpl.expressionList); createViolation(ifStatement, "在访问文件或目录前需要对路径名进行验证");
if(descendants != null){
for(AstNode desc : descendants){
String name = desc.getTokenValue();
if (!conditionVariables.contains(name)) {
getContext().createLineViolation(this, "在访问文件或目录前需要对路径名进行验证", node);
}
}
}
}
} }
filePathUsedInIf = false;
} }
private void handleDeclaration(AstNode node) { private void checkDeclaration(AstNode declaration) {
AstNode ifstreamNode = findIfstreamNode(node); AstNode declaratorNode = declaration.getFirstDescendant(CxxGrammarImpl.declarator);
if (ifstreamNode != null) { filePathChecked = containsFilePathCheck(declaratorNode);
handleIfstreamDeclaration(ifstreamNode); if (declaratorNode != null && !filePathChecked) {
String variableName = declaratorNode.getTokenOriginalValue();
if (variableName != null && variableName.equals("filePath")) {
System.out.println(variableName);
getContext().createLineViolation(this, "在访问文件或目录前需要对路径名进行验证", declaratorNode);
} }
} }
private AstNode findIfstreamNode(AstNode node) {
if (node.getToken() != null && "ifstream".equals(node.getTokenValue())) {
return node;
}
for (AstNode child : node.getChildren()) {
AstNode result = findIfstreamNode(child);
if (result != null) {
return result;
} }
}
return null;
}
private void handleIfStatement(AstNode node) { private void checkStatement(AstNode statement) {
AstNode conditionNode = node.getFirstDescendant(CxxGrammarImpl.condition); AstNode condition = statement.getFirstChild(CxxGrammarImpl.condition);
if (conditionNode != null) { filePathChecked = containsFilePathCheck(condition);
addAllIdentifiers(conditionNode);
}
} }
private void addAllIdentifiers(AstNode node) { private boolean containsFilePathCheck(AstNode node) {
for (AstNode child : node.getChildren()) { if (node != null && node.getTokenOriginalValue().equals("filePath")) {
if (child.getType().equals(CxxGrammarImpl.selectionStatement)) { return true;
// 找到 if 语句节点
AstNode conditionNode = child.getFirstDescendant(CxxGrammarImpl.condition);
if(conditionNode != null){
// 找到条件部分的节点
AstNode identifierNode = conditionNode.getFirstDescendant(GenericTokenType.IDENTIFIER);
// 找到代表标识符的节点
if (identifierNode != null) {
String codeInsideIf = identifierNode.getTokenValue();
// 获取标识符节点的值
conditionVariables.add(codeInsideIf);
} }
if (node != null) {
for (AstNode child : node.getChildren()) {
// 如果 if 中使用了 filePath,则停止递归并跳过 ifstream file(filePath) 检查
if (containsFilePathCheck(child)) {
return true;
} }
} else {
addAllIdentifiers(child);
} }
} }
return false; // 节点或其任何子节点中找不到“filePath”
} }
private void handleIfstreamDeclaration(AstNode ifstreamNode) { private void createViolation(AstNode node, String message) {
AstNode parameterDeclarationNode = ifstreamNode.getFirstDescendant(CxxGrammarImpl.parameterDeclaration); getContext().createLineViolation(this, message, node);
if (parameterDeclarationNode != null) {
AstNode identifierNode = parameterDeclarationNode.getFirstDescendant(GenericTokenType.IDENTIFIER);
if (identifierNode != null) {
String ifstreamParam = identifierNode.getTokenValue();
if (!conditionVariables.contains(ifstreamParam)) {
getContext().createLineViolation(this, "在访问文件或目录前需要对路径名进行验证", ifstreamNode);
}
}
}
} }
} }

@ -41,13 +41,15 @@ public class HighEncryptDesChecker extends SquidCheck<Grammar> {
public void visitFile(@Nullable AstNode astNode) { public void visitFile(@Nullable AstNode astNode) {
//逐行获取内容 //逐行获取内容
List<String> inputFileLines = getContext().getInputFileLines(); List<String> inputFileLines = getContext().getInputFileLines();
for (String str : inputFileLines) { for (String str:inputFileLines) {
if (str.startsWith("#include")) { if(str.startsWith("#include")){
if (str.contains("des.h") || str.contains("blake2.h")) { if(str.contains("openssl/") || str.contains("cryptopp/") ){
if(!str.contains("aes.h") && !str.contains("des.h") ){
getContext().createFileViolation(this, "应采用加密强度较高的标准加密算法"); getContext().createFileViolation(this, "应采用加密强度较高的标准加密算法");
break; break;
} }
} }
} }
} }
}
} }

@ -96,14 +96,12 @@ public class IntegerCountVerifyChecker extends SquidCheck<Grammar> {
}else if("std".equals(stList.getTokenValue())){ }else if("std".equals(stList.getTokenValue())){
//获取到方法名称 //获取到方法名称
AstNode firstDescendant = stList.getFirstDescendant(CxxGrammarImpl.qualifiedId); AstNode firstDescendant = stList.getFirstDescendant(CxxGrammarImpl.qualifiedId);
if (firstDescendant!=null){
List<AstNode> children = firstDescendant.getChildren(); List<AstNode> children = firstDescendant.getChildren();
for(AstNode desc : children){ for(AstNode desc : children){
//判断是否是用户输入方法 //判断是否是用户输入方法
if("cin".equals(desc.getTokenValue())){ if("cin".equals(desc.getTokenValue())){
//获取用户输入中的参数变量 //获取用户输入中的参数变量
AstNode descendant = stList.getFirstDescendant(CxxGrammarImpl.shiftExpression); AstNode descendant = stList.getFirstDescendant(CxxGrammarImpl.shiftExpression);
if (descendant!=null){
List<AstNode> descendantChildren = descendant.getChildren(); List<AstNode> descendantChildren = descendant.getChildren();
for(AstNode dant:descendantChildren){ for(AstNode dant:descendantChildren){
if("IDENTIFIER".equals(dant.getName())){ if("IDENTIFIER".equals(dant.getName())){
@ -117,20 +115,6 @@ public class IntegerCountVerifyChecker extends SquidCheck<Grammar> {
} }
} }
} }
}else {
List<AstNode> descendants = stList.getDescendants(CxxGrammarImpl.declSpecifier);
AstNode descendant = stList.getFirstDescendant(CxxGrammarImpl.postfixExpression);
AstNode declName = stList.getFirstDescendant(CxxGrammarImpl.declarator);
if(descendants != null && descendant != null && declName != null){
for(AstNode desc : descendants){
if(desc.getTokenValue().contains("int") ){
cinList.add(declName.getTokenValue());
break;
}
}
}
}
}
return cinList; return cinList;
} }

@ -90,7 +90,6 @@ public class LogFileWriteChecker extends SquidCheck<Grammar> {
tokenValue = descendant.getTokenValue(); tokenValue = descendant.getTokenValue();
} else { } else {
AstNode firstDescendant = dec.getFirstDescendant(CxxGrammarImpl.andExpression); AstNode firstDescendant = dec.getFirstDescendant(CxxGrammarImpl.andExpression);
if(firstDescendant != null){
List<AstNode> astNodeList = firstDescendant.getChildren(); List<AstNode> astNodeList = firstDescendant.getChildren();
for (AstNode ast : astNodeList) { for (AstNode ast : astNodeList) {
if ("IDENTIFIER".equals(ast.getName())) { if ("IDENTIFIER".equals(ast.getName())) {
@ -99,18 +98,15 @@ public class LogFileWriteChecker extends SquidCheck<Grammar> {
} }
} }
}
List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expression); List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expression);
for (AstNode ast : astNodeList) { for (AstNode ast : astNodeList) {
if (tokenValue.equals(ast.getTokenValue())) { if (tokenValue.equals(ast.getTokenValue())) {
AstNode descendant1 = ast.getFirstDescendant(CxxGrammarImpl.postfixExpression); AstNode descendant1 = ast.getFirstDescendant(CxxGrammarImpl.postfixExpression);
if(descendant1 != null){
List<AstNode> childrens = descendant1.getChildren(); List<AstNode> childrens = descendant1.getChildren();
for (AstNode fir : childrens) { for (AstNode fir : childrens) {
//判断是否是debug、info、warn、error //判断是否是debug、info、warn、error
if (lists.contains(fir.getTokenValue())) { if (lists.contains(fir.getTokenValue())) {
AstNode inits = ast.getFirstDescendant(CxxGrammarImpl.initializerList); AstNode inits = ast.getFirstDescendant(CxxGrammarImpl.initializerList);
if(inits != null){
List<AstNode> descendantChildren = inits.getChildren(); List<AstNode> descendantChildren = inits.getChildren();
for (AstNode chil : descendantChildren) { for (AstNode chil : descendantChildren) {
if ("IDENTIFIER".equals(chil.getName())) { if ("IDENTIFIER".equals(chil.getName())) {
@ -133,8 +129,6 @@ public class LogFileWriteChecker extends SquidCheck<Grammar> {
} }
} }
} }
}
}
} }
} }

@ -26,25 +26,22 @@ public class NumericalCopyChecker extends SquidCheck<Grammar> {//当私有数组
public void init() { public void init() {
// 订阅要检查AST节点类型,用于在visitNode方法中检查该类型节点 // 订阅要检查AST节点类型,用于在visitNode方法中检查该类型节点
this.subscribeTo( this.subscribeTo(
CxxGrammarImpl.translationUnit CxxGrammarImpl.functionDefinition
); );
} }
public void visitNode(AstNode astNode) { public void visitNode(AstNode astNode) {
List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.declarator); List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.declarator);
for (AstNode as : astNodeList) {
if (as.getTokenValue().contains("&") || as.getTokenValue().contains("*")) {
List<String> lists = new ArrayList(); List<String> lists = new ArrayList();
for (AstNode desc : astNodeList) { List<AstNode> descendant = astNode.getDescendants(CxxGrammarImpl.expression);
if (desc.getTokenValue().contains("private")) { for (AstNode desc : descendant) {
lists.add(desc.getTokenValue()); lists.add(desc.getTokenValue());
} }
}
for (AstNode as : astNodeList) {
if (as.getTokenValue().contains("&") || as.getTokenValue().contains("*")) {
List<AstNode> descendan = astNode.getDescendants(CxxGrammarImpl.statement); List<AstNode> descendan = astNode.getDescendants(CxxGrammarImpl.statement);
for (AstNode ast : descendan) { for (AstNode ast : descendan) {
List<AstNode> descendants = ast.getDescendants(CxxGrammarImpl.expression); List<AstNode> descendants = ast.getDescendants(CxxGrammarImpl.expression);
for (AstNode des : descendants) { for (AstNode des : descendants) {
if ("return".equals(des.getParent().getTokenValue())) {
if (lists.contains(des.getTokenValue())) { if (lists.contains(des.getTokenValue())) {
getContext().createLineViolation(this, "应返回该私有数值的副本", des); getContext().createLineViolation(this, "应返回该私有数值的副本", des);
} }
@ -52,6 +49,10 @@ public class NumericalCopyChecker extends SquidCheck<Grammar> {//当私有数组
} }
} }
} }
} }
}
} }

@ -33,12 +33,9 @@ public class PRNGVerifyChecker extends SquidCheck<Grammar> {
@Override @Override
public void init() { public void init() {
// 指定当前访问器需要访问的节点类型,functionBody(函数)主体节点 // 指定当前访问器需要访问的节点类型,functionBody(函数)主体节点
subscribeTo( this.subscribeTo(
CxxGrammarImpl.declarationStatement CxxGrammarImpl.declarationStatement
); );
subscribeTo(
CxxGrammarImpl.postfixExpression
);
} }
/** /**
@ -48,11 +45,6 @@ public class PRNGVerifyChecker extends SquidCheck<Grammar> {
*/ */
@Override @Override
public void visitNode(@Nonnull AstNode node) { public void visitNode(@Nonnull AstNode node) {
if(node.is(CxxGrammarImpl.postfixExpression)){
if(node.getTokenValue().contains("rand")){
getContext().createLineViolation(this, "应使用目前被业界专家认为较强的经过良好审核的加密PRNG算法", node);
}
}else if(node.is(CxxGrammarImpl.declarationStatement)){
List<AstNode> descendants = node.getDescendants(CxxGrammarImpl.typeName); List<AstNode> descendants = node.getDescendants(CxxGrammarImpl.typeName);
for (AstNode desc:descendants) { for (AstNode desc:descendants) {
if(lists.contains(desc.getTokenValue())){ if(lists.contains(desc.getTokenValue())){
@ -60,8 +52,6 @@ public class PRNGVerifyChecker extends SquidCheck<Grammar> {
break; break;
} }
} }
}
} }
} }

@ -17,7 +17,6 @@ import org.sonar.cxx.squidbridge.annotations.ActivatedByDefault;
import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation; import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation;
import org.sonar.cxx.squidbridge.checks.SquidCheck; import org.sonar.cxx.squidbridge.checks.SquidCheck;
import javax.annotation.Nonnull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -47,12 +46,12 @@ public class PassWordCountChecker extends SquidCheck<Grammar> {
* @param astNode 要处理的AST节点该节点类型为通过subscribeTo方法订阅的类型 * @param astNode 要处理的AST节点该节点类型为通过subscribeTo方法订阅的类型
*/ */
@Override @Override
public void visitNode(@Nonnull AstNode astNode) { public void visitNode(AstNode astNode) {
BodyWay bodyWay = new BodyWay(this); BodyWay bodyWay = new BodyWay(this);
bodyWay.accept(astNode); bodyWay.accept(astNode);
} }
class BodyWay extends SubscriptionAstVisitor { class BodyWay extends SubscriptionAstVisitor{
/** /**
* 构造函数需要传入初代访问器 * 构造函数需要传入初代访问器
@ -73,78 +72,45 @@ public class PassWordCountChecker extends SquidCheck<Grammar> {
//获取方法参数列表 //获取方法参数列表
List<AstNode> nodeDescendants = astNode.getDescendants(CxxGrammarImpl.expressionList); List<AstNode> nodeDescendants = astNode.getDescendants(CxxGrammarImpl.expressionList);
List<String> seqLists = new ArrayList<>(); List<String> seqLists = new ArrayList<>();
for (AstNode desc : nodeDescendants) { for(AstNode desc :nodeDescendants){
seqLists.add(desc.getTokenValue()); seqLists.add(desc.getTokenValue());
} }
//判读入参有没有进行赋值操作 //判读入参有没有进行赋值操作
List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.assignmentExpression); List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.assignmentExpression);
List<String> aslists = new ArrayList<>(); List<String> aslists = new ArrayList<>();
for (AstNode ast : astNodes) { for(AstNode ast : astNodes){
if (seqLists.contains(ast.getTokenValue())) { if(seqLists.contains(ast.getTokenValue())){
aslists.add(ast.getTokenValue()); aslists.add(ast.getTokenValue());
} }
} }
//获取到声明hash变量名 //获取到声明hash变量名
List<String> lists = new ArrayList<>(); List<String> lists = new ArrayList<>();
List<AstNode> astNodeDescendants = astNode.getDescendants(CxxGrammarImpl.simpleDeclaration); List<AstNode> astNodeDescendants = astNode.getDescendants(CxxGrammarImpl.simpleDeclaration);
for (AstNode des : astNodeDescendants) { for(AstNode des :astNodeDescendants){
if("std".equals(des.getTokenValue())){
List<AstNode> descendants = des.getDescendants(CxxGrammarImpl.typeName); List<AstNode> descendants = des.getDescendants(CxxGrammarImpl.typeName);
for (AstNode dan : descendants) { for (AstNode dan : descendants){
if ("hash".equals(dan.getTokenValue())) { if("hash".equals(dan.getTokenValue())){
List<AstNode> nodeList = des.getDescendants(CxxGrammarImpl.initDeclarator); List<AstNode> nodeList = des.getDescendants(CxxGrammarImpl.initDeclarator);
for (AstNode lis : nodeList) { for (AstNode lis:nodeList) {
lists.add(lis.getTokenValue()); lists.add(lis.getTokenValue());
} }
} }
} }
}
} }
//判断生成的散列值参数是否是进行赋后的入参 //判断生成的散列值参数是否是进行赋后的入参
List<AstNode> descendants = astNode.getDescendants(CxxGrammarImpl.postfixExpression); List<AstNode> descendants = astNode.getDescendants(CxxGrammarImpl.postfixExpression);
for (AstNode desc : descendants) { for (AstNode desc:descendants) {
if (lists.contains(desc.getTokenValue())) { if(lists.contains(desc.getTokenValue())){
List<AstNode> descDescendants = desc.getDescendants(CxxGrammarImpl.expressionList); List<AstNode> descDescendants = desc.getDescendants(CxxGrammarImpl.expressionList);
for (AstNode dd : descDescendants) { for(AstNode dd : descDescendants){
if (!aslists.contains(dd.getTokenValue())) { if(!aslists.contains(dd.getTokenValue())){
reportIssue(dd, "使用盐值计算散列值"); reportIssue(dd, "使用盐值计算散列值");
} }
} }
} }
} }
List arrLists = new ArrayList();
//获取数组
List<AstNode> nodeList = astNode.getDescendants(CxxGrammarImpl.initDeclaratorList);
for(AstNode node : nodeList){
AstNode firstDescendant = node.getFirstDescendant(CxxGrammarImpl.constantExpression);
if(firstDescendant != null){
if(firstDescendant.getTokenValue().contains("SHA256_DIGEST_LENGTH")){
aslists.add(node.getTokenValue());
}
}
}
List<AstNode> nodes = astNode.getDescendants(CxxGrammarImpl.postfixExpression);
for(AstNode node : nodes){
String methodName = node.getTokenValue();
if (methodName.contains("hash") || methodName.contains("encryptor")) {
AstNode init = node.getFirstDescendant(CxxGrammarImpl.initializerList);
boolean booPassword = false;
boolean booHash = true;
if(init != null){
List<AstNode> children = init.getChildren();
for(AstNode child : children){
if(child.getTokenValue().toLowerCase().contains("password")){
booPassword = true;
}else if(arrLists.contains(child.getTokenValue())){
booHash = false;
}
}
}
if(booHash && booPassword){
reportIssue(init, "使用盐值计算散列值");
}
}
}
} }
} }
} }

@ -6,9 +6,7 @@
*/ */
package com.keyware.sonar.cxx.rules.checkers; package com.keyware.sonar.cxx.rules.checkers;
import com.keyware.sonar.cxx.SubscriptionAstVisitor;
import com.sonar.cxx.sslr.api.AstNode; import com.sonar.cxx.sslr.api.AstNode;
import com.sonar.cxx.sslr.api.AstNodeType;
import com.sonar.cxx.sslr.api.Grammar; import com.sonar.cxx.sslr.api.Grammar;
import org.sonar.check.Priority; import org.sonar.check.Priority;
import org.sonar.check.Rule; import org.sonar.check.Rule;
@ -18,7 +16,6 @@ import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation;
import org.sonar.cxx.squidbridge.checks.SquidCheck; import org.sonar.cxx.squidbridge.checks.SquidCheck;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -40,7 +37,7 @@ public class PathVerifyChecker extends SquidCheck<Grammar> {
public void init() { public void init() {
// 指定当前访问器需要访问的节点类型,functionBody(函数)主体节点 // 指定当前访问器需要访问的节点类型,functionBody(函数)主体节点
this.subscribeTo( this.subscribeTo(
CxxGrammarImpl.functionBody CxxGrammarImpl.declarationStatement
); );
} }
@ -51,9 +48,21 @@ public class PathVerifyChecker extends SquidCheck<Grammar> {
*/ */
@Override @Override
public void visitNode(@Nonnull AstNode node) { public void visitNode(@Nonnull AstNode node) {
IfBuffer ifBuffer = new IfBuffer(this); //获取参数
ifBuffer.accept(node); AstNode firstDescendant = node.getFirstDescendant(CxxGrammarImpl.initializer);
List<AstNode> 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);
}
}
}
}
} }
//判断是不是路径 //判断是不是路径
@ -80,84 +89,4 @@ public class PathVerifyChecker extends SquidCheck<Grammar> {
return matcher.find(); // 使用find()而不是matches(),因为matches()要求整个字符串都符合模式 return matcher.find(); // 使用find()而不是matches(),因为matches()要求整个字符串都符合模式
} }
class IfBuffer extends SubscriptionAstVisitor {
List lists = new ArrayList<String>();
public IfBuffer(SquidCheck<Grammar> checker) {
super(checker);
}
@Override
public List<AstNodeType> visitNodeTypes() {
// 指定当前访问器需要访问的节点类型,这里指定了simpleDeclaration(简单声明)节点类型
return List.of(CxxGrammarImpl.functionBody);
}
@Override
public void visitNode(@Nonnull AstNode node) {
//选择节点语句
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);
for (AstNode expr : astNodeList) {
lists.add(expr.getToken().getValue());
}
if (astNodeList.size() == 0) {
List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.relationalExpression);
for (AstNode as : astNodes) {
List<AstNode> children = as.getChildren();
for (AstNode chil : children) {
lists.add(chil.getTokenValue());
}
}
}
}
}
List<AstNode> astNodes = node.getDescendants(CxxGrammarImpl.declarationStatement);
if (astNodes !=null && !astNodes.isEmpty()) {
for (AstNode astNode : astNodes) {
//获取参数
AstNode firstDescendant = astNode.getFirstDescendant(CxxGrammarImpl.initializer);
if (firstDescendant != null) {
List<AstNode> 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)) {
reportIssue(chil, "使用关键资源时指定资源所在的路径");
}
}
}
}
}
}
}
List<AstNode> descendants = node.getDescendants(CxxGrammarImpl.expression);
for (AstNode ast : descendants) {
AstNode descendant = ast.getFirstDescendant(CxxGrammarImpl.postfixExpression);
if (descendant != null) {
String methodName = descendant.getTokenValue();
if ("system".equals(methodName) || "fopen".equals(methodName)) {
List<AstNode> childrens = descendant.getChildren();
if (childrens != null && !childrens.isEmpty()) {
String tokenValue = childrens.get(0).getTokenValue();
if (tokenValue != null && !lists.equals(tokenValue)) {
reportIssue(descendant, "使用关键资源时指定资源所在的路径");
}
}
}
}
}
}
}
} }

@ -92,7 +92,7 @@ public class ReallocMainChecker extends SquidCheck<Grammar> {
String name = as.getToken().getValue(); String name = as.getToken().getValue();
//判断参数是否存在在集合中 //判断参数是否存在在集合中
if(!lists.contains(name)){ if(!lists.contains(name)){
reportIssue(as, "使用realloc函数前应先清敏感信息"); reportIssue(as, "使用realloc函数前应先清敏感信息");
} }
} }
} }

@ -54,7 +54,6 @@ public class SQLVerifyChecker extends SquidCheck<Grammar> {
class IfSQL extends SubscriptionAstVisitor{ class IfSQL extends SubscriptionAstVisitor{
List lists = new ArrayList<String>(); List lists = new ArrayList<String>();
List names = new ArrayList<String>();
public IfSQL(SquidCheck<Grammar> checker){ public IfSQL(SquidCheck<Grammar> checker){
super(checker); super(checker);
} }
@ -100,43 +99,6 @@ public class SQLVerifyChecker extends SquidCheck<Grammar> {
} }
} }
} }
List<AstNode> astNodes = node.getDescendants(CxxGrammarImpl.declarationStatement);
for(AstNode astNode : astNodes){
String tokenValue = astNode.getTokenValue();
if(tokenValue != null && tokenValue.equals("char")){
AstNode descendant = astNode.getFirstDescendant(CxxGrammarImpl.initDeclaratorList);
if(descendant != null && descendant.getTokenValue().contains("sql")){
names.add(descendant.getTokenValue());
} }
} }
}
List<AstNode> expressions = node.getDescendants(CxxGrammarImpl.expression);
for (AstNode ast : expressions) {
AstNode descendant = ast.getFirstDescendant(CxxGrammarImpl.postfixExpression);
if (descendant != null) {
String methodName = descendant.getTokenValue();
if ("strcat".equals(methodName) ) {
List<AstNode> astNodeList = descendant.getDescendants(CxxGrammarImpl.initializerList);
boolean booValue = false;
for(AstNode astNode : astNodeList){
List<AstNode> childrens = astNode.getChildren();
if (childrens != null && !childrens.isEmpty()) {
for(AstNode chil : childrens){
if(names.contains(chil.getTokenValue()) ){
booValue = true;
}else if(booValue && chil.getName() == "IDENTIFIER"&& !lists.contains(chil.getTokenValue())){
reportIssue(chil, "在使用SQL语句前对输入数据进行验证");
break;
}
}
}
}
}
}
}
}
}
} }

@ -36,16 +36,10 @@ public class SendMessageChecker extends SquidCheck<Grammar> {
CxxGrammarImpl.functionBody CxxGrammarImpl.functionBody
); );
} }
private static List<String> lists = new ArrayList(){{
private static List<String> lists = new ArrayList() {{
add("weapon"); add("weapon");
add("unit"); add("unit");
add("param"); add("param");
add("address");
add("name");
add("password");
add("orgname");
add("armsname");
}}; }};
@ -60,40 +54,20 @@ public class SendMessageChecker extends SquidCheck<Grammar> {
//获取到所有的表达式 //获取到所有的表达式
List<AstNode> descendants = node.getDescendants(CxxGrammarImpl.expression); List<AstNode> descendants = node.getDescendants(CxxGrammarImpl.expression);
for (AstNode des : descendants) { for (AstNode des:descendants) {
//判断表达式是否是send发送信息 //判断表达式是否是send发送信息
if ("send".equals(des.getTokenValue())) { if("send".equals(des.getTokenValue())){
//获取其中的参数 //获取其中的参数
AstNode firstDescendant = des.getFirstDescendant(CxxGrammarImpl.initializerList); AstNode firstDescendant = des.getFirstDescendant(CxxGrammarImpl.initializerList);
List<AstNode> children = firstDescendant.getChildren(); List<AstNode> children = firstDescendant.getChildren();
if (children != null) {
AstNode astNode = children.get(2); AstNode astNode = children.get(2);
//判断其中的参数类型 //判断其中的参数类型
if ("STRING".equals(astNode.getName())) { if("STRING".equals(astNode.getName())){
} else {
//判斷其中是否包含敏感字段
if (lists.contains(astNode.getTokenValue().toLowerCase())) {
getContext().createLineViolation(this, "发送敏感信息前应对敏感信息进行加密", des);
}
}
}
} else if (des.getTokenValue().startsWith("send")) {
//获取其中的参数
AstNode firstDescendant = des.getFirstDescendant(CxxGrammarImpl.initializerList);
if(firstDescendant != null){
List<AstNode> children = firstDescendant.getChildren();
if (children != null) {
AstNode astNode = children.get(0);
//判断其中的参数类型
if ("STRING".equals(astNode.getName())) {
} else { }else {
//判斷其中是否包含敏感字段 //判斷其中是否包含敏感字段
if (lists.contains(astNode.getTokenValue().toLowerCase())) { if(lists.contains(astNode.getTokenValue().toLowerCase())){
getContext().createLineViolation(this, "发送敏感信息前应对敏感信息进行加密", des); getContext().createLineViolation(this,"发送敏感信息前应对敏感信息进行加密",des);
}
}
} }
} }
} }

@ -25,7 +25,7 @@ import java.util.Scanner;
* @author GuoXin * @author GuoXin
* @date 2024/1/6 * @date 2024/1/6
*/ */
@Rule(key = "SqlVarNameChecker", name = "sql注入", description = "sql注入有一定风险", priority = Priority.INFO, tags = {"28suo"}) @Rule(key = "FlagLine1Rule", name = "sql注入", description = "sql注入有一定风险", priority = Priority.INFO, tags = {"28suo"})
@ActivatedByDefault @ActivatedByDefault
@SqaleConstantRemediation("5min") @SqaleConstantRemediation("5min")
public class SqlVarNameChecker implements FlagLineRule { public class SqlVarNameChecker implements FlagLineRule {
@ -54,5 +54,25 @@ public class SqlVarNameChecker implements FlagLineRule {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
/*
@Override
public void visitNode(AstNode node) {
File file = getContext().getFile();
System.out.println("文件路径: " + file.getAbsolutePath());
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
int lineNumber = 0;
while ((line = reader.readLine()) != null) {
lineNumber++;
if (line.contains("= '") || line.contains("OR 1=1") || line.contains("='")
|| line.contains("DROP TABLE") || line.contains("' OR 'a'='a") || line.contains("'; DROP TABLE users; --")
|| line.contains("'; EXEC xp_cmdshell 'dir'") || line.contains("' OR username LIKE '%") || line.contains("' AND SLEEP(5)")
|| line.contains("= \\'' +") || line.contains("= ?")) {
getContext().createLineViolation(ABCVarNameChecker.this, "sql 注入有一定风险", lineNumber);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}*/
} }

@ -17,7 +17,6 @@ import org.sonar.cxx.squidbridge.checks.SquidCheck;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -37,15 +36,11 @@ public class UserInputPasswordChecker extends SquidCheck<Grammar> {
@Override @Override
public void init() { public void init() {
subscribeTo(CxxGrammarImpl.functionBody);
subscribeTo(CxxGrammarImpl.simpleDeclaration); subscribeTo(CxxGrammarImpl.simpleDeclaration);
} }
@Override @Override
public void visitNode(@Nullable AstNode astNode) { public void visitNode(AstNode astNode) {
if(astNode.is(CxxGrammarImpl.simpleDeclaration)){
var declNode = astNode.getFirstDescendant(CxxGrammarImpl.declSpecifier); var declNode = astNode.getFirstDescendant(CxxGrammarImpl.declSpecifier);
if (declNode == null) { if (declNode == null) {
return; return;
@ -82,38 +77,10 @@ public class UserInputPasswordChecker extends SquidCheck<Grammar> {
} }
}); });
}else if(astNode.is(CxxGrammarImpl.functionBody)){
List<AstNode> expressions = astNode.getDescendants(CxxGrammarImpl.expression);
boolean booPut = true;
for (AstNode ast : expressions) {
AstNode descendant = ast.getFirstDescendant(CxxGrammarImpl.postfixExpression);
if (descendant != null) {
String methodName = descendant.getTokenValue();
if ("scanf".equals(methodName) && booPut) {
getContext().createLineViolation(this, "用户输入口令时对口令域进行掩饰,通常,用户输入的每一个字符都应该以“*”形式回显", descendant);
}else if("putchar".equals(methodName)){
List<AstNode> children = descendant.getChildren();
for(AstNode chil : children){
if("\'*\'".contains(chil.getTokenValue())){
booPut = false;
}
}
}
}
}
}
} }
@Override @Override
public void leaveFile(@Nullable AstNode astNode) { public void leaveFile(@Nullable AstNode astNode) {
fieldsMap.values().forEach(node -> getContext().createLineViolation(this, "用户输入口令时对口令域进行掩饰,通常,用户输入的每一个字符都应该以“*”形式回显", node)); fieldsMap.values().forEach(node -> getContext().createLineViolation(this, "用户输入口令时对口令域进行掩饰,通常,用户输入的每一个字符都应该以“*”形式回显", node));
fieldsMap.clear();
} }
} }

@ -15,7 +15,6 @@ import org.sonar.cxx.squidbridge.annotations.ActivatedByDefault;
import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation; import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation;
import org.sonar.cxx.squidbridge.checks.SquidCheck; import org.sonar.cxx.squidbridge.checks.SquidCheck;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -29,7 +28,7 @@ import java.util.List;
@SqaleConstantRemediation("5min") @SqaleConstantRemediation("5min")
public class ValidatePasswordCheck extends SquidCheck<Grammar> { public class ValidatePasswordCheck extends SquidCheck<Grammar> {
private List lists = new ArrayList();
private static final String passwordRegex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@#$%^&+=!]).{10,}$"; private static final String passwordRegex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@#$%^&+=!]).{10,}$";
@Override @Override
@ -39,32 +38,13 @@ public class ValidatePasswordCheck extends SquidCheck<Grammar> {
@Override @Override
public void visitNode(AstNode astNode) { public void visitNode(AstNode astNode) {
VerdictPassword(astNode);
checkPasswordValidationInMain(astNode);
} AstNode functionNameNode = astNode.getFirstDescendant(CxxGrammarImpl.declaratorId);
String functionName = functionNameNode.getTokenOriginalValue();
private void VerdictPassword(AstNode node) { //检查函数是否为main
List<AstNode> nodeDescendants = node.getDescendants(CxxGrammarImpl.selectionStatement); if ("main".equals(functionName)) {
for (AstNode astNode : nodeDescendants) { checkPasswordValidationInMain(astNode);
//判断节点是不是if节点
if ("if".equals(astNode.getToken().getValue())) {
//获取其中的参数
List<AstNode> astNodeList = astNode.getDescendants(CxxGrammarImpl.expressionList);
for (AstNode expr : astNodeList) {
lists.add(expr.getToken().getValue());
}
if (astNodeList.size() == 0) {
List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.relationalExpression);
for (AstNode as : astNodes) {
List<AstNode> children = as.getChildren();
for (AstNode chil : children) {
lists.add(chil.getTokenValue());
}
}
}
}
} }
} }
@ -78,10 +58,10 @@ public class ValidatePasswordCheck extends SquidCheck<Grammar> {
AstNode declaratorId = initDeclarator.getFirstDescendant(CxxGrammarImpl.declaratorId); AstNode declaratorId = initDeclarator.getFirstDescendant(CxxGrammarImpl.declaratorId);
if (declaratorId != null) { if (declaratorId != null) {
String variableName = declaratorId.getTokenValue(); String variableName = declaratorId.getTokenOriginalValue();
// 检查变量是否命名为password // 检查变量是否命名为password
if (variableName.toLowerCase().contains("password")) { if ("password".equalsIgnoreCase(variableName)) {
checkPasswordInitialization(initDeclarator); checkPasswordInitialization(initDeclarator);
} }
} }
@ -99,16 +79,13 @@ public class ValidatePasswordCheck extends SquidCheck<Grammar> {
if (initializationValue != null) { if (initializationValue != null) {
String passwordValue = initializationValue.getTokenValue(); String passwordValue = initializationValue.getTokenOriginalValue();
if (!passwordValue.matches(passwordRegex)) { if (!passwordValue.matches(passwordRegex)) {
System.out.println("未通过正则校验的口令:"+passwordValue);
getContext().createLineViolation(this, "口令不匹配足够复杂度", initializationValue); getContext().createLineViolation(this, "口令不匹配足够复杂度", initializationValue);
} }
} }
} else {
if (!lists.contains(declaration.getTokenValue())) {
getContext().createLineViolation(this, "口令不匹配足够复杂度", declaration);
}
} }
} }

@ -16,15 +16,10 @@ import org.sonar.cxx.squidbridge.annotations.ActivatedByDefault;
import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation; import org.sonar.cxx.squidbridge.annotations.SqaleConstantRemediation;
import org.sonar.cxx.squidbridge.checks.SquidCheck; import org.sonar.cxx.squidbridge.checks.SquidCheck;
import java.io.BufferedReader; import java.util.ArrayList;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.List; import java.util.List;
/** import static com.sonar.cxx.sslr.api.GenericTokenType.IDENTIFIER;
* 在构建路径名前对输入数据进行验证确保外部输入仅包含允许的构成路径名的字符
*/
@Rule(key = "VerificationPathChecker", name = "在构建路径名前对数据进行校验", description = "对输入数据进行校验", priority = Priority.INFO, tags = {"28suo"}) @Rule(key = "VerificationPathChecker", name = "在构建路径名前对数据进行校验", description = "对输入数据进行校验", priority = Priority.INFO, tags = {"28suo"})
@ActivatedByDefault @ActivatedByDefault
@ -33,122 +28,45 @@ public class VerificationPathChecker extends SquidCheck<Grammar> {
@Override @Override
public void init() { public void init() {
this.subscribeTo(CxxGrammarImpl.functionBody); // 订阅要检查AST节点类型,用于在visitNode方法中检查该类型节点
this.subscribeTo(
CxxGrammarImpl.functionBody
);
} }
public void visitNode(AstNode astNode) { public void visitNode(AstNode astNode) {
List<AstNode> descendants = astNode.getDescendants(CxxGrammarImpl.statement); List<AstNode> descendants = astNode.getDescendants(CxxGrammarImpl.statement);
for (AstNode ast : descendants) { for (AstNode ast:descendants) {
if (processAst(ast)) { List<AstNode> descendants1 = ast.getDescendants(CxxGrammarImpl.shiftExpression);
break; for (AstNode desc :descendants1) {
} if("cin".equals(desc.getTokenValue())){
}
MethodJudge(astNode);
}
//方法拼接判断
private void MethodJudge(AstNode node){
boolean boo = true;
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);
for (AstNode expr : astNodeList) {
if(expr.getTokenValue().toLowerCase().equals("filename")){
boo = false;
break;
}
}
if (astNodeList.size() == 0) {
List<AstNode> astNodes = astNode.getDescendants(CxxGrammarImpl.relationalExpression);
for (AstNode as : astNodes) {
List<AstNode> children = as.getChildren();
for (AstNode chil : children) {
if(chil.getTokenValue().toLowerCase().equals("filename")){
boo = false;
break;
}
}
}
}
}
}
List<AstNode> expressions = node.getDescendants(CxxGrammarImpl.expression);
for (AstNode ast : expressions) {
AstNode descendant = ast.getFirstDescendant(CxxGrammarImpl.postfixExpression);
if (descendant != null) {
String methodName = descendant.getTokenValue();
if ("strcat".equals(methodName) ) {
List<AstNode> astNodeList = descendant.getDescendants(CxxGrammarImpl.initializerList);
for(AstNode astNode : astNodeList){
List<AstNode> childrens = astNode.getChildren();
if (childrens != null && !childrens.isEmpty()) {
for(AstNode chil : childrens){
if(chil.getTokenValue().toLowerCase().equals("filename") ){
getContext().createLineViolation(this, "在构建路径名前对数据进行校验", chil);
break;
}
}
}
}
}
}
}
}
private boolean processAst(AstNode ast) {
List<AstNode> innerDescendants = ast.getDescendants(CxxGrammarImpl.shiftExpression);
for (AstNode desc : innerDescendants) {
if ("cin".equals(desc.getTokenValue())) {
List<AstNode> children = desc.getChildren(); List<AstNode> children = desc.getChildren();
for (AstNode chil : children) { for (AstNode chil:children) {
if ("IDENTIFIER".equals(chil.getName())) { if("IDENTIFIER".equals(chil.getName())){
if (chil.getTokenValue().toLowerCase().contains("path")) { if(chil.getTokenValue().toLowerCase().contains("path")){
boolean boo = true; boolean boo = true;
List<AstNode> exprs = ast.getDescendants(CxxGrammarImpl.postfixExpression); List<AstNode> exprs = astNode.getDescendants(CxxGrammarImpl.postfixExpression);
for (AstNode expr : exprs) { for (AstNode expr:exprs) {
if (expr.getTokenValue().contains("check") || expr.getTokenValue().contains("verify") || expr.getTokenValue().contains("valid")) { if(expr.getTokenValue().contains("check") || expr.getTokenValue().contains("verify") || expr.getTokenValue().contains("valid")){
List<AstNode> astNodeList = expr.getDescendants(CxxGrammarImpl.expressionList); List<AstNode> astNodeList = expr.getDescendants(CxxGrammarImpl.expressionList);
for (AstNode asrList : astNodeList) { for (AstNode asrList:astNodeList) {
if (chil.getTokenValue().equals(asrList.getTokenValue())) { if(chil.getTokenValue().equals(asrList.getTokenValue())){
boo = false; boo = false;
} }
} }
} }
} }
int lineNumber = chil.getTokenLine(); if(boo){
if (boo && isLineInFile(lineNumber)) {
getContext().createLineViolation(this, "在构建路径名前对数据进行校验", chil); getContext().createLineViolation(this, "在构建路径名前对数据进行校验", chil);
return true;
} }
} }
} }
} }
}
}
return false;
} }
private boolean isLineInFile(int lineNumber) {
try {
int totalLines = countLines(getContext().getFile());
return lineNumber <= totalLines;
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
public int countLines(File file) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
int lines = 0;
while (reader.readLine() != null) lines++;
return lines;
} }
} }
} }

@ -33,7 +33,7 @@ import java.util.Map;
@SqaleConstantRemediation("5min") @SqaleConstantRemediation("5min")
public class VirtualLockUsageChecker extends SquidCheck<Grammar> { public class VirtualLockUsageChecker extends SquidCheck<Grammar> {
private List<String> keywords = Arrays.asList("add", "keyword2", "keyword3","password","name","type","token","username"); private List<String> keywords = Arrays.asList("add", "keyword2", "keyword3");
private Map<String, Map<String, AstNode>> caches = new HashMap<>(); private Map<String, Map<String, AstNode>> caches = new HashMap<>();
@Override @Override
@ -43,12 +43,10 @@ public class VirtualLockUsageChecker extends SquidCheck<Grammar> {
@Override @Override
public void visitNode(AstNode astNode) { public void visitNode(AstNode astNode) {
AstNode descendant = astNode.getFirstDescendant(CxxGrammarImpl.declaratorId); String varName = astNode.getFirstDescendant(CxxGrammarImpl.declaratorId).getTokenOriginalValue();
if(descendant != null){
String varName = descendant.getTokenValue();
for (String keyword : keywords) { for (String keyword : keywords) {
if (varName.equals(keyword) && (!caches.equals(keyword) || !caches.get(keyword).equals(varName))) { if (varName.contains(keyword) && (!caches.containsKey(keyword) || !caches.get(keyword).containsKey(varName))) {
caches.putIfAbsent(keyword, new HashMap<>()); caches.putIfAbsent(keyword, new HashMap<>());
caches.get(keyword).put(varName, astNode); caches.get(keyword).put(varName, astNode);
processNode(astNode, keyword); processNode(astNode, keyword);
@ -56,19 +54,15 @@ public class VirtualLockUsageChecker extends SquidCheck<Grammar> {
} }
} }
}
private void processNode(AstNode astNode, String keyword) { private void processNode(AstNode astNode, String keyword) {
AstNode descendant = astNode.getFirstDescendant(CxxGrammarImpl.declaratorId); String varName = astNode.getFirstDescendant(CxxGrammarImpl.declaratorId).getTokenOriginalValue();
if (descendant != null){
String varName = descendant.getTokenValue();
AstNode currentNode = astNode.getNextAstNode(); AstNode currentNode = astNode.getNextAstNode();
while (currentNode != null) { while (currentNode != null) {
AstNode callNode = currentNode.getFirstDescendant(CxxGrammarImpl.postfixExpression); AstNode callNode = currentNode.getFirstDescendant(CxxGrammarImpl.postfixExpression);
if (callNode != null && callNode.getTokenValue().equalsIgnoreCase("VirtualLock")) { if (callNode != null && callNode.getTokenOriginalValue().equalsIgnoreCase("VirtualLock")) {
List<AstNode> paramList = callNode.getDescendants(CxxGrammarImpl.expressionList); List<AstNode> paramList = callNode.getDescendants(CxxGrammarImpl.expressionList);
if (paramList.stream().anyMatch(item -> item.getTokenValue().contains(keyword))) { if (paramList.stream().anyMatch(item -> item.getTokenOriginalValue().contains(keyword))) {
caches.get(keyword).remove(varName); caches.get(keyword).remove(varName);
break; break;
} }
@ -76,7 +70,6 @@ public class VirtualLockUsageChecker extends SquidCheck<Grammar> {
currentNode = currentNode.getNextSibling(); currentNode = currentNode.getNextSibling();
} }
} }
}
@Override @Override
public void leaveFile(AstNode astNode) { public void leaveFile(AstNode astNode) {
@ -86,6 +79,7 @@ public class VirtualLockUsageChecker extends SquidCheck<Grammar> {
private void reportViolations() { private void reportViolations() {
caches.values().forEach(cache -> caches.values().forEach(cache ->
cache.values().forEach(item -> { cache.values().forEach(item -> {
System.out.println("特定字段"+item.getFirstDescendant(CxxGrammarImpl.declaratorId).getTokenOriginalValue()+"未使用VirtualLock()函数锁定存放敏感信息的内存");
getContext().createLineViolation(this, "特定字段未使用VirtualLock()函数锁定存放敏感信息的内存", item); getContext().createLineViolation(this, "特定字段未使用VirtualLock()函数锁定存放敏感信息的内存", item);
}) })
); );

@ -1,259 +0,0 @@
/*
* Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved.
* 项目名称28所 C++ 信息安全性设计准则
* 项目描述用于检查C++源代码的安全性设计准则的Sonarqube插件
* 版权说明本软件属北京关键科技股份有限公司所有在未获得北京关键科技股份有限公司正式授权情况下任何企业和个人不能获取阅读安装传播本软件涉及的任何受知识产权保护的内容
*/
package org.sonar.cxx.squidbridge; // cxx: in use
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.sonar.cxx.sslr.api.AstNode;
import com.sonar.cxx.sslr.api.Grammar;
import com.sonar.cxx.sslr.api.RecognitionException;
import com.sonar.cxx.sslr.impl.Parser;
import com.sonar.cxx.sslr.impl.ast.AstWalker;
import java.io.File;
import java.io.InterruptedIOException;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nullable;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.cxx.squidbridge.api.AnalysisException;
import org.sonar.cxx.squidbridge.api.SourceCodeSearchEngine;
import org.sonar.cxx.squidbridge.api.SourceCodeTreeDecorator;
import org.sonar.cxx.squidbridge.api.SourceProject;
import org.sonar.cxx.squidbridge.indexer.SquidIndex;
import org.sonar.cxx.squidbridge.measures.MetricDef;
public class AstScanner<G extends Grammar> {
private static final Logger LOG = Loggers.get(AstScanner.class);
private final List<SquidAstVisitor<G>> visitors;
private final Parser<G> parser;
private final SquidAstVisitorContextImpl<G> context;
private final SquidIndex indexer = new SquidIndex();
private final MetricDef[] metrics;
private final MetricDef filesMetric;
protected AstScanner(Builder<G> builder) {
this.visitors = Lists.newArrayList(builder.visitors);
this.parser = builder.baseParser;
this.context = builder.context;
this.context.setGrammar(parser.getGrammar());
this.context.getProject().setSourceCodeIndexer(indexer);
this.context.setCommentAnalyser(builder.commentAnalyser);
this.metrics = builder.metrics;
this.filesMetric = builder.filesMetric;
indexer.index(context.getProject());
}
public SourceCodeSearchEngine getIndex() {
return indexer;
}
public void scanFile(File file) {
scanFiles(java.util.List.of(file));
}
public void scanInputFile(InputFile inputFile) {
scanInputFiles(java.util.List.of(inputFile));
}
public void scanFiles(Collection<File> files) {
initVisitors();
var astWalker = new AstWalker(visitors);
for (var file : files) {
checkCancel();
context.setFile(file, filesMetric);
Exception parseException = null;
AstNode ast = null;
try {
try {
ast = parser.parse(file);
} catch (Exception e) {
parseException = handleParseException(file, e);
}
walkAndVisit(astWalker, ast, parseException);
} catch (Throwable e) {
throw new AnalysisException("Unable to parse file: " + file.getAbsolutePath(), e);
}
}
destroyVisitors();
decorateSquidTree();
}
public void scanInputFiles(Iterable<InputFile> inputFiles) {
initVisitors();
var astWalker = new AstWalker(visitors);
for (var inputFile : inputFiles) {
var file = new File(inputFile.uri().getPath());
checkCancel();
context.setInputFile(inputFile, filesMetric);
Exception parseException = null;
AstNode ast = null;
try {
try {
ast = parser.parse(inputFile.contents());
} catch (Exception e) {
parseException = handleParseException(file, e);
}
walkAndVisit(astWalker, ast, parseException);
} catch (Throwable e) {
LOG.error("Unable to parse file: " + file.getAbsolutePath(), e);
}
}
destroyVisitors();
decorateSquidTree();
}
private static Exception handleParseException(File file, Exception e) {
checkInterrupted(e);
if (e instanceof RecognitionException) {
LOG.error("Unable to parse file: " + file.getAbsolutePath());
LOG.error(e.getMessage());
} else {
LOG.error("Unable to parse file: " + file.getAbsolutePath(), e);
}
return e;
}
private void walkAndVisit(AstWalker astWalker, AstNode ast, @Nullable Exception parseException) throws Throwable {
if (parseException == null) {
astWalker.walkAndVisit(ast);
} else {
// process parse error
for (var visitor : visitors) {
visitor.visitFile(ast);
}
for (var visitor : visitors) {
if (visitor instanceof AstScannerExceptionHandler) {
if (parseException instanceof RecognitionException) {
((AstScannerExceptionHandler) visitor)
.processRecognitionException((RecognitionException) parseException);
} else {
((AstScannerExceptionHandler) visitor).processException(parseException);
}
}
}
for (var visitor : visitors) {
visitor.leaveFile(ast);
}
}
context.popTillSourceProject();
}
private void initVisitors() {
for (var visitor : visitors) {
visitor.init();
}
}
private void destroyVisitors() {
for (var visitor : visitors) {
visitor.destroy();
}
}
/**
* Checks if the root cause of the thread is related to an interrupt.
* Note that when such an exception is thrown, the interrupt flag is reset.
*/
private static void checkInterrupted(Exception e) {
Throwable cause = Throwables.getRootCause(e);
if (cause instanceof InterruptedException || cause instanceof InterruptedIOException) {
throw new AnalysisException("Analysis cancelled", e);
}
}
private static void checkCancel() {
if (Thread.interrupted()) {
throw new AnalysisException("Analysis cancelled");
}
}
protected void decorateSquidTree() {
if (metrics != null && metrics.length > 0) {
SourceProject project = context.getProject();
var decorator = new SourceCodeTreeDecorator(project);
decorator.decorateWith(metrics);
}
}
public static <G extends Grammar> Builder<G> builder(SquidAstVisitorContextImpl<G> context) {
return new Builder<>(context);
}
public static class Builder<G extends Grammar> {
private Parser<G> baseParser;
private final List<SquidAstVisitor<G>> visitors = Lists.newArrayList();
private final SquidAstVisitorContextImpl<G> context;
private CommentAnalyser commentAnalyser;
private MetricDef[] metrics;
private MetricDef filesMetric;
public Builder(SquidAstVisitorContextImpl<G> context) {
checkNotNull(context, "context cannot be null");
this.context = context;
}
public Builder<G> setBaseParser(Parser<G> baseParser) {
checkNotNull(baseParser, "baseParser cannot be null");
this.baseParser = baseParser;
return this;
}
public Builder<G> setCommentAnalyser(CommentAnalyser commentAnalyser) {
checkNotNull(commentAnalyser, "commentAnalyser cannot be null");
this.commentAnalyser = commentAnalyser;
return this;
}
public Builder<G> withSquidAstVisitor(SquidAstVisitor<G> visitor) {
checkNotNull(visitor, "visitor cannot be null");
if(visitor.getContext() == null){
visitor.setContext(context);
visitors.add(visitor);
}
return this;
}
public Builder<G> withMetrics(MetricDef... metrics) {
for (var metric : metrics) {
checkNotNull(metric, "metrics cannot be null");
}
this.metrics = metrics.clone();
return this;
}
public Builder<G> setFilesMetric(MetricDef filesMetric) {
checkNotNull(filesMetric, "filesMetric cannot be null");
this.filesMetric = filesMetric;
return this;
}
public AstScanner<G> build() {
checkState(baseParser != null, "baseParser must be set");
checkState(commentAnalyser != null, "commentAnalyser must be set");
checkState(filesMetric != null, "filesMetric must be set");
return new AstScanner<>(this);
}
}
}

@ -30,8 +30,6 @@ public class BufferDataCheckerTest {
.next().atLine(17).withMessage("应对读写缓冲区的数据长度进行检查") .next().atLine(17).withMessage("应对读写缓冲区的数据长度进行检查")
.next().atLine(30).withMessage("应对读写缓冲区的数据长度进行检查") .next().atLine(30).withMessage("应对读写缓冲区的数据长度进行检查")
.next().atLine(43).withMessage("应对读写缓冲区的数据长度进行检查") .next().atLine(43).withMessage("应对读写缓冲区的数据长度进行检查")
.next().atLine(67).withMessage("应对读写缓冲区的数据长度进行检查")
.next().atLine(73).withMessage("应对读写缓冲区的数据长度进行检查")
.noMore(); .noMore();
} }
} }

@ -29,7 +29,6 @@ public class DLLVerifyCheckerTest {
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(17).withMessage("在动态加载库前对输入数据进行验证") .next().atLine(17).withMessage("在动态加载库前对输入数据进行验证")
.next().atLine(43).withMessage("在动态加载库前对输入数据进行验证") .next().atLine(43).withMessage("在动态加载库前对输入数据进行验证")
.next().atLine(83).withMessage("在动态加载库前对输入数据进行验证")
.noMore(); .noMore();
} }
} }

@ -30,7 +30,6 @@ public class EncryptionAlgorithmCheckerTest {
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(9).withMessage("特定字段未使用单向加密算法对口令进行加密并存储") .next().atLine(9).withMessage("特定字段未使用单向加密算法对口令进行加密并存储")
.next().atLine(10).withMessage("特定字段未使用单向加密算法对口令进行加密并存储")
.noMore(); .noMore();
} }

@ -27,8 +27,7 @@ public class FileAccessCheckerTest {
var tester = CxxFileTesterHelper.create("FileAccessChecker.cc"); var tester = CxxFileTesterHelper.create("FileAccessChecker.cc");
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(14).withMessage("在访问文件或目录前需要对路径名进行验证") .next().atLine(13).withMessage("在访问文件或目录前需要对路径名进行验证")
.next().atLine(17).withMessage("在访问文件或目录前需要对路径名进行验证")
.noMore(); .noMore();
} }
} }

@ -30,7 +30,6 @@ public class IntegerCountVerifyCheckerTest {
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(10).withMessage("來自用戶的整型数据进行算术运算应进行验证") .next().atLine(10).withMessage("來自用戶的整型数据进行算术运算应进行验证")
.next().atLine(10).withMessage("來自用戶的整型数据进行算术运算应进行验证") .next().atLine(10).withMessage("來自用戶的整型数据进行算术运算应进行验证")
.next().atLine(18).withMessage("來自用戶的整型数据进行算术运算应进行验证")
.noMore(); .noMore();
} }
} }

@ -23,7 +23,7 @@ public class NumericalCopyTest {
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(15).withMessage("应返回该私有数值的副本") .next().atLine(15).withMessage("应返回该私有数值的副本")
// .next().atLine(20).withMessage("应返回该私有数值的副本") .next().atLine(25).withMessage("应返回该私有数值的副本")
.noMore(); .noMore();
} }

@ -31,7 +31,6 @@ public class PRNGVerifyCheckerTest {
.next().atLine(8).withMessage("应使用目前被业界专家认为较强的经过良好审核的加密PRNG算法") .next().atLine(8).withMessage("应使用目前被业界专家认为较强的经过良好审核的加密PRNG算法")
.next().atLine(11).withMessage("应使用目前被业界专家认为较强的经过良好审核的加密PRNG算法") .next().atLine(11).withMessage("应使用目前被业界专家认为较强的经过良好审核的加密PRNG算法")
.next().atLine(14).withMessage("应使用目前被业界专家认为较强的经过良好审核的加密PRNG算法") .next().atLine(14).withMessage("应使用目前被业界专家认为较强的经过良好审核的加密PRNG算法")
.next().atLine(18).withMessage("应使用目前被业界专家认为较强的经过良好审核的加密PRNG算法")
.noMore(); .noMore();
} }
} }

@ -29,8 +29,6 @@ public class PassWordCountCheckerTest {
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(10).withMessage("使用盐值计算散列值") .next().atLine(10).withMessage("使用盐值计算散列值")
.next().atLine(31).withMessage("使用盐值计算散列值")
.next().atLine(43).withMessage("使用盐值计算散列值")
.noMore(); .noMore();
} }
} }

@ -29,8 +29,6 @@ public class PathVerifyCheckerTest {
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(4).withMessage("使用关键资源时指定资源所在的路径") .next().atLine(4).withMessage("使用关键资源时指定资源所在的路径")
.next().atLine(5).withMessage("使用关键资源时指定资源所在的路径") .next().atLine(5).withMessage("使用关键资源时指定资源所在的路径")
.next().atLine(18).withMessage("使用关键资源时指定资源所在的路径")
.next().atLine(31).withMessage("使用关键资源时指定资源所在的路径")
.noMore(); .noMore();
} }
} }

@ -27,7 +27,7 @@ public class ReallocMainCheckerTest {
var tester = CxxFileTesterHelper.create("ReallocMainChecker.cc"); var tester = CxxFileTesterHelper.create("ReallocMainChecker.cc");
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(27).withMessage("使用realloc函数前应先清敏感信息") .next().atLine(27).withMessage("使用realloc函数前应先清敏感信息")
.noMore(); .noMore();
} }

@ -28,8 +28,7 @@ public class SQLVerifyCheckerTest {
var tester = CxxFileTesterHelper.create("SQLVerifyChecker.cc"); var tester = CxxFileTesterHelper.create("SQLVerifyChecker.cc");
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
// .next().atLine(26).withMessage("在使用SQL语句前对输入数据进行验证") .next().atLine(26).withMessage("在使用SQL语句前对输入数据进行验证")
.next().atLine(5).withMessage("在使用SQL语句前对输入数据进行验证")
.noMore(); .noMore();
} }
} }

@ -28,7 +28,6 @@ public class SendMessageCheckerTest {
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(13).withMessage("发送敏感信息前应对敏感信息进行加密") .next().atLine(13).withMessage("发送敏感信息前应对敏感信息进行加密")
.next().atLine(14).withMessage("发送敏感信息前应对敏感信息进行加密")
.noMore(); .noMore();
} }
} }

@ -29,7 +29,6 @@ public class UserInputPasswordCheckerTest {
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(18).withMessage("用户输入口令时对口令域进行掩饰,通常,用户输入的每一个字符都应该以“*”形式回显") .next().atLine(18).withMessage("用户输入口令时对口令域进行掩饰,通常,用户输入的每一个字符都应该以“*”形式回显")
.next().atLine(22).withMessage("用户输入口令时对口令域进行掩饰,通常,用户输入的每一个字符都应该以“*”形式回显") .next().atLine(22).withMessage("用户输入口令时对口令域进行掩饰,通常,用户输入的每一个字符都应该以“*”形式回显")
.next().atLine(59).withMessage("用户输入口令时对口令域进行掩饰,通常,用户输入的每一个字符都应该以“*”形式回显")
.noMore(); .noMore();
} }
} }

@ -21,7 +21,6 @@ public class VerificationPathCheckerTest {
var tester = CxxFileTesterHelper.create("VerificationPathChecker.cc"); var tester = CxxFileTesterHelper.create("VerificationPathChecker.cc");
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(11).withMessage("在构建路径名前对数据进行校验")
.next().atLine(12).withMessage("在构建路径名前对数据进行校验") .next().atLine(12).withMessage("在构建路径名前对数据进行校验")
.noMore(); .noMore();
} }

@ -30,9 +30,6 @@ public class VirtualLockUsageCheckerTest {
SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker); SourceFile file = CxxAstScanner.scanSingleInputFile(tester.asInputFile(), checker);
CheckMessagesVerifier.verify(file.getCheckMessages()) CheckMessagesVerifier.verify(file.getCheckMessages())
.next().atLine(8).withMessage("特定字段未使用VirtualLock()函数锁定存放敏感信息的内存") .next().atLine(8).withMessage("特定字段未使用VirtualLock()函数锁定存放敏感信息的内存")
.next().atLine(10).withMessage("特定字段未使用VirtualLock()函数锁定存放敏感信息的内存")
.next().atLine(12).withMessage("特定字段未使用VirtualLock()函数锁定存放敏感信息的内存")
.next().atLine(14).withMessage("特定字段未使用VirtualLock()函数锁定存放敏感信息的内存")
.noMore(); .noMore();
} }
} }

@ -61,15 +61,3 @@ int main() {
return 0; return 0;
} }
void vulnerable_function(char *input) {
char buffer[10];
strcpy(buffer, input); // 没有检查输入长度,可能导致缓冲区溢出
}
void example(){
char value[11];
printf("Enter The Value");
scanf("%s",values);// 没有检查输入长度,可能导致缓冲区溢出
}

@ -76,9 +76,3 @@ int main()
return 0; return 0;
} }
void load(char * libaryName){
char path[32] = "C:\\";
strcat(path,libaryName);
HANDLE hlib = LoadLibrary(path);
}

@ -7,7 +7,7 @@ using namespace bcrypt;
int main() { int main() {
// 用户输入的原始密码 // 用户输入的原始密码
string password = "userPassword123"; string password = "userPassword123";
AESEncryption aesEncryptor;
// 使用cpp-bcrypt生成盐和哈希 // 使用cpp-bcrypt生成盐和哈希
// bcrypt::generate_salt(); // 生成一个随机盐 // bcrypt::generate_salt(); // 生成一个随机盐
// string salt = bcrypt::get_salt(); // string salt = bcrypt::get_salt();

@ -1,6 +1,5 @@
#include <openssl/aes.h>// error #include <openssl/aes.h>// error
#include <openssl/des.h>// error #include <openssl/des.h>// error
#include "aes.h"// error
#include <string.h> #include <string.h>
void encryptWithAES(const unsigned char* plaintext, size_t plaintext_len, void encryptWithAES(const unsigned char* plaintext, size_t plaintext_len,
@ -33,9 +32,3 @@ int main() {
return 0; return 0;
} }
int encryptor(char* input,char* output)//加密函数,输出参数返回加密后的字符串
{
AESEncryption aesEncryptor;
int r= aesEncryptor.enc(input,output);//使用双向可逆的 AES加密算法
}

@ -10,12 +10,9 @@ int main() {
int a = 5; int a = 5;
if (a<4) { if (a<5) {
ifstream file(filePath); ifstream file(filePath);
File * file;
file = fopen(filePath,"r");
cout << "File opened successfully." << endl; cout << "File opened successfully." << endl;
file.close(); file.close();

@ -12,12 +12,3 @@ int main() {
// std::cout << "两数之积:" << num1 * num2 << std::endl; // std::cout << "两数之积:" << num1 * num2 << std::endl;
return 0; return 0;
} }
unsigned int num;
void exfun(){
unsigned int mrsp = pacjget_get_int();
char * response = malloc((mrsp + num) * sizeof(char *));
unsigned int i;
for(i =0;i<mrsp;i++){
response[i] = packet_get_string();
}
}

@ -4,8 +4,8 @@ class MyClass {
private: private:
std::array<int, 10> privateArray; std::array<int, 10> privateArray;
public: public:
// 假设初始化已经在构造函数或其他地方完成 // 假设初始化已经在构造函数或其他地方完成
// 返回的是私有数组的副本 // 返回的是私有数组的副本
// const std::array<int, 10> getPrivateArrayRef() const { // const std::array<int, 10> getPrivateArrayRef() const {
// return privateArray; // return privateArray;
// } // }
@ -15,8 +15,14 @@ public:
return privateArray; // error return privateArray; // error
} }
// 返回的是私有数组的指针 // 返回的是私有数组的副本
// int* getPrivateArrayPtr() { // int getPrivateArrayPtr() {
// return privateArray.data(); // error // return privateArray.data();
// } // }
}
// 返回的是私有数组的指针
int* getPrivateArrayPtr() {
return privateArray.data(); // error
}
};

@ -14,9 +14,5 @@ int main(){
std::knuth_b knuthGenerator(rd()); // 使用更好的随机种子初始化knuth_b std::knuth_b knuthGenerator(rd()); // 使用更好的随机种子初始化knuth_b
std::cout << knuthGenerator() << std::endl; std::cout << knuthGenerator() << std::endl;
for(i=0;i<8;i++){
num = 10*rand()/(RAND_MAX+1);
iv[i] = num + '0';
}
return 0; return 0;
} }

@ -18,27 +18,3 @@ int main() {
test(input); test(input);
return 0; return 0;
} }
void calculate_hash(const char *password, unsigned char *hash) {
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, password, strlen(password));
SHA256_Final(hash, &ctx);
}
int main() {
const char *password = "mysecretpassword";
unsigned char hash[SHA256_DIGEST_LENGTH];
calculate_hash(password, hash);
printf("Password: %s\n", password);
printf("SHA256 Hash: ");
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
printf("%02x", hash[i]);
}
printf("\n");
return 0;
}
void ef(cahr* password){
char psw[1024] = {0};
inr r= encryptor(password,psw);
}

@ -6,27 +6,3 @@ int main() {
//std::String testString1 = "C:\\Users\\User\\Documents"; //std::String testString1 = "C:\\Users\\User\\Documents";
return 0; return 0;
} }
void load_resource(const char *filename) {
char buffer[100];
FILE *fp;
// 假设程序加载资源的路径是固定的 "/path/to/resources/"
const char *resource_path = "/path/to/resources/";
// 构建资源文件的完整路径
snprintf(buffer, sizeof(buffer), "%s%s", resource_path, filename);
// 打开资源文件
fp = fopen(buffer, "r");
if (fp == NULL) {
printf("无法打开文件 %s\n", buffer);
return;
}
// 读取文件内容并处理
// 假设这里是处理文件内容的代码...
// 关闭文件
fclose(fp);
}
void example_fun(void){
//攻击者可在搜索优先级更高的文件夹中放入和dir同名的恶意程序导致 command的内容无法正确执行
system(command);//本例中 command=“dir.exe E:\\data”
}

@ -1,7 +1,53 @@
#include<stdio.h> #include <iostream>
#include<string.h> #include <mysql_driver.h> // MySQL Connector/C++库头文件
void sqlQuery(char * name){ #include <mysql_connection.h>
char sqlQuery[64] = "select * from cus where userid=";
strcat(sqlQuery,name); // 假设你已经有了一个sanitizeString函数,用于清理SQL注入风险
strcat(sqlQuery,"'"); std::string sanitizeString(const std::string& input) {
// 在这里实现SQL字符串清理逻辑
return cleanedInput;
}
int main() {
try {
sql::mysql::MySQL_Driver *driver;
sql::Connection *con;
// 初始化数据库连接
driver = sql::mysql::get_mysql_driver_instance();
con = driver->connect("tcp://127.0.0.1:3306", "username", "password");
con->setSchema("your_database");
std::string inputQuery = "";
std::cout << "请输入SQL查询语句: ";
std::getline(std::cin, inputQuery);
// 对输入的SQL语句进行验证和处理
std::string sqlQuery = sanitizeString(inputQuery);
// 创建并执行SQL语句
sql::Statement *stmt = con->createStatement();
sql::ResultSet *res = stmt->executeQuery(sqlQuery);
// 处理查询结果
while (res->next()) {
// 从结果集中获取数据并进行处理
// 这里假设你知道第一列的名字,如果不是,请替换为实际列名
std::string resultData = res->getString("your_column_name");
std::cout << "查询结果: " << resultData << std::endl;
}
delete stmt;
delete res;
delete con;
}
catch (sql::SQLException &e) {
std::cerr << "# ERR: SQLException in " << __FILE__;
std::cerr << "(" << __FUNCTION__ << ") on line " << __LINE__ << std::endl;
std::cerr << "# ERR: " << e.what();
std::cerr << " (MySQL error code: " << e.getErrorCode();
std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl;
}
return 0;
} }

@ -11,7 +11,7 @@ int main() {
std::string param = "Hello, Server!"; std::string param = "Hello, Server!";
send(socket_fd,param.c_str(), param.size()); // 发送信息 send(socket_fd,param.c_str(), param.size()); // 发送信息
send_message(address);
// ...其他处理,如关闭连接等 // ...其他处理,如关闭连接等
close(socket_fd); close(socket_fd);

@ -47,17 +47,3 @@ int main(int argc, char *argv[])
dialog.show(); dialog.show();
return app.exec(); return app.exec();
} }
void exaa(){
char password[MAX_STR_LEN];
int i =0;
char c ='0';
printf("Please password:");
while(i<MAX_STR_LEN && c != '\n')
{
// putchar('*');
scanf("%c",&c);
password[i] =c;
i++;
}
}

@ -3,13 +3,14 @@
using namespace std; using namespace std;
// 假设以下两个函数用于检查和验证路径 // 假设以下两个函数用于检查和验证路径
void checkPath(const string& path); void checkPath(const std::string& path);
void verifyPath(const string& path); void verifyPath(const std::string& path);
int main(){ int main(){
string userPath; string userPath;
cout << "Enter a path: ";
cin >> userPath; cin >> userPath;
strcat(path,filename);
// 在获取用户输入之后立即对其进行验证 // 在获取用户输入之后立即对其进行验证
// checkPath(userPath); // checkPath(userPath);
// verifyPath(userPath); // verifyPath(userPath);

@ -7,11 +7,10 @@ int main() {
string add = "北京市"; //error string add = "北京市"; //error
string keyword2 = "北京市"; //error // string keyword2 = "北京市"; //error
//
string keyword3 = "北京市"; //error // string keyword3 = "北京市"; //error
char * password = "";
// 利用vector<char>管理内存 // 利用vector<char>管理内存
// vector<char> addressBuffer(add.begin(), add.end()); // vector<char> addressBuffer(add.begin(), add.end());
// //

@ -110,13 +110,6 @@
<version>1.28</version> <version>1.28</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -148,61 +141,6 @@
<goals> <goals>
<goal>shade</goal> <goal>shade</goal>
</goals> </goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createDependencyReducedPom>false</createDependencyReducedPom>
<minimizeJar>true</minimizeJar>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/LICENSE*</exclude>
<exclude>META-INF/NOTICE*</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>META-INF/*.SF</exclude>
<exclude>LICENSE*</exclude>
<exclude>NOTICE*</exclude>
</excludes>
</filter>
<filter>
<artifact>cglib:cglib-nodep</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>org.sonarsource.java:java-frontend</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>xerces:xercesImpl</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>xml-apis:xml-apis</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>org.apache.tomcat.embed:tomcat-embed-jasper</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<!-- this is needed because org.apache.el.ExpressionFactoryImpl is instantiated with reflection -->
<filter>
<artifact>org.apache.tomcat.embed:tomcat-embed-el</artifact>
<includes>
<include>**</include>
</includes>
</filter>
</filters>
</configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>

@ -1,66 +0,0 @@
/*
* Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved.
* 项目名称信息安全性设计准则检查插件
* 项目描述用于检查源代码的安全性设计准则的Sonarqube插件
* 版权说明本软件属北京关键科技股份有限公司所有在未获得北京关键科技股份有限公司正式授权情况下任何企业和个人不能获取阅读安装传播本软件涉及的任何受知识产权保护的内容
*/
package com.keyware.sonar.java;
import java.util.Arrays;
import org.sonar.api.config.Configuration;
import org.sonar.api.resources.AbstractLanguage;
/**
* Java language implementation
*
* @since 1.3
*/
public class Java extends AbstractLanguage {
/**
* Java key
*/
public static final String KEY = "java";
/**
* Java name
*/
public static final String NAME = "Java";
/**
* Key of the file suffix parameter
*/
public static final String FILE_SUFFIXES_KEY = "sonar.java.file.suffixes";
/**
* Default Java fil
* es knows suffixes
*/
public static final String DEFAULT_FILE_SUFFIXES = ".java,.jav";
/**
* Settings of the plugin.
*/
private final Configuration settings;
/**
* Default constructor
*/
public Java(Configuration settings) {
super(KEY, NAME);
this.settings = settings;
}
/**
* {@inheritDoc}
*
* @see org.sonar.api.resources.AbstractLanguage#getFileSuffixes()
*/
@Override
public String[] getFileSuffixes() {
String[] suffixes = Arrays.stream(settings.getStringArray(Java.FILE_SUFFIXES_KEY)).filter(s -> s != null && !s.trim().isEmpty()).toArray(String[]::new);
return suffixes.length > 0 ? suffixes : DEFAULT_FILE_SUFFIXES.split(",");
}
}

@ -1,200 +0,0 @@
/*
* Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved.
* 项目名称信息安全性设计准则检查插件
* 项目描述用于检查源代码的安全性设计准则的Sonarqube插件
* 版权说明本软件属北京关键科技股份有限公司所有在未获得北京关键科技股份有限公司正式授权情况下任何企业和个人不能获取阅读安装传播本软件涉及的任何受知识产权保护的内容
*/
package com.keyware.sonar.java;
import java.io.File;
import java.util.*;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.Phase;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
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.config.Configuration;
import org.sonar.api.issue.NoSonarFilter;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.scan.issue.filter.FilterableIssue;
import org.sonar.api.scan.issue.filter.IssueFilterChain;
import org.sonar.java.JavaFrontend;
import org.sonar.java.Measurer;
import org.sonar.java.SonarComponents;
import org.sonar.java.annotations.VisibleForTesting;
import org.sonar.java.checks.CheckList;
import org.sonar.java.filters.PostAnalysisIssueFilter;
import org.sonar.java.jsp.Jasper;
import org.sonar.java.model.GeneratedFile;
import org.sonar.java.model.JavaVersionImpl;
import org.sonar.java.se.SymbolicExecutionVisitor;
import org.sonar.java.se.checks.SECheck;
import org.sonar.plugins.java.api.JavaCheck;
import org.sonar.plugins.java.api.JavaResourceLocator;
import org.sonar.plugins.java.api.JavaVersion;
import org.sonarsource.analyzer.commons.BuiltInQualityProfileJsonLoader;
import org.sonarsource.performance.measure.PerformanceMeasure;
import static org.sonar.api.rules.RuleAnnotationUtils.getRuleKey;
@Phase(name = Phase.Name.PRE)
public class KeyJavaSensor implements Sensor{
private static final Logger LOG = LoggerFactory.getLogger(KeyJavaSensor.class);
private static final String PERFORMANCE_MEASURE_ACTIVATION_PROPERTY = "sonar.java.performance.measure";
private static final String PERFORMANCE_MEASURE_FILE_PATH_PROPERTY = "sonar.java.performance.measure.path";
private static final String PERFORMANCE_MEASURE_DESTINATION_FILE = "sonar.java.performance.measure.json";
static final String SONAR_WAY_PATH = "/org/sonar/l10n/java/rules/java/Sonar_way_profile.json";
private final SonarComponents sonarComponents;
private final FileSystem fs;
private final JavaResourceLocator javaResourceLocator;
private final Configuration settings;
private final NoSonarFilter noSonarFilter;
@Nullable
private final Jasper jasper;
private final PostAnalysisIssueFilter postAnalysisIssueFilter;
public KeyJavaSensor(SonarComponents sonarComponents, FileSystem fs,
JavaResourceLocator javaResourceLocator, Configuration settings,
NoSonarFilter noSonarFilter,
PostAnalysisIssueFilter postAnalysisIssueFilter, @Nullable Jasper jasper) {
this.noSonarFilter = noSonarFilter;
this.sonarComponents = sonarComponents;
this.fs = fs;
this.javaResourceLocator = javaResourceLocator;
this.settings = settings;
this.postAnalysisIssueFilter = postAnalysisIssueFilter;
this.jasper = jasper;
this.sonarComponents.registerMainCheckClasses(CheckList.REPOSITORY_KEY, CheckList.getJavaChecks());
}
@Override
public void describe(SensorDescriptor descriptor) {
descriptor.onlyOnLanguage(Java.KEY).name("KeyJavaSensor");
}
@Override
public void execute(SensorContext context) {
PerformanceMeasure.Duration sensorDuration = createPerformanceMeasureReport(context);
sonarComponents.setSensorContext(context);
sonarComponents.setCheckFilter(createCheckFilter(sonarComponents.isAutoScanCheckFiltering()));
Measurer measurer = new Measurer(context, noSonarFilter);
JavaFrontend frontend = new JavaFrontend(getJavaVersion(), sonarComponents, measurer, javaResourceLocator, postAnalysisIssueFilter,
insertSymbolicExecutionVisitor(sonarComponents.mainChecks()));
frontend.scan(getSourceFiles(), getTestFiles(), runJasper(context));
sensorDuration.stop();
}
private UnaryOperator<List<JavaCheck>> createCheckFilter(boolean isAutoScanCheckFiltering) {
if (isAutoScanCheckFiltering) {
Set<RuleKey> autoScanCompatibleRules = new HashSet<>(KeyJavaSensor.sonarJavaSonarWayRuleKeys());
CheckList.getJavaChecksNotWorkingForAutoScan().stream()
.map(checkClass -> RuleKey.of(CheckList.REPOSITORY_KEY, getRuleKey(checkClass)))
.forEach(autoScanCompatibleRules::remove);
return checks -> checks.stream()
.filter(check -> sonarComponents.getRuleKey(check).map(autoScanCompatibleRules::contains).orElse(false))
.collect(Collectors.toList());
} else {
return UnaryOperator.identity();
}
}
static Set<RuleKey> sonarJavaSonarWayRuleKeys() {
return BuiltInQualityProfileJsonLoader.loadActiveKeysFromJsonProfile(SONAR_WAY_PATH).stream()
.map(rule -> RuleKey.of(CheckList.REPOSITORY_KEY, rule))
.collect(Collectors.toSet());
}
private static PerformanceMeasure.Duration createPerformanceMeasureReport(SensorContext context) {
return PerformanceMeasure.reportBuilder()
.activate(context.config().get(PERFORMANCE_MEASURE_ACTIVATION_PROPERTY).filter("true"::equals).isPresent())
.toFile(context.config().get(PERFORMANCE_MEASURE_FILE_PATH_PROPERTY)
.filter(path -> !path.isEmpty())
.orElseGet(() -> Optional.ofNullable(context.fileSystem().workDir())
.filter(File::exists)
.map(file -> file.toPath().resolve(PERFORMANCE_MEASURE_DESTINATION_FILE).toString())
.orElse(null)))
.appendMeasurementCost()
.start("KeyJavaSensor");
}
@VisibleForTesting
static JavaCheck[] insertSymbolicExecutionVisitor(List<JavaCheck> checks) {
List<SECheck> seChecks = checks.stream()
.filter(SECheck.class::isInstance)
.map(SECheck.class::cast)
.collect(Collectors.toList());
if (seChecks.isEmpty()) {
LOG.info("No rules with 'symbolic-execution' tag were enabled,"
+ " the Symbolic Execution Engine will not run during the analysis.");
return checks.toArray(new JavaCheck[0]);
}
List<JavaCheck> newList = new ArrayList<>(checks);
// insert an instance of SymbolicExecutionVisitor before the first SECheck
newList.add(newList.indexOf(seChecks.get(0)), new SymbolicExecutionVisitor(seChecks));
return newList.toArray(new JavaCheck[0]);
}
private Collection<GeneratedFile> runJasper(SensorContext context) {
if (sonarComponents.isAutoScan()) {
// for security reasons, do not run jasper to generate code in autoscan mode
return Collections.emptyList();
}
return jasper != null ? jasper.generateFiles(context, sonarComponents.getJavaClasspath()) : Collections.emptyList();
}
private Iterable<InputFile> getSourceFiles() {
return javaFiles(InputFile.Type.MAIN);
}
private Iterable<InputFile> getTestFiles() {
return javaFiles(InputFile.Type.TEST);
}
private Iterable<InputFile> javaFiles(InputFile.Type type) {
return fs.inputFiles(fs.predicates().and(fs.predicates().hasLanguage(Java.KEY), fs.predicates().hasType(type)));
}
private JavaVersion getJavaVersion() {
Optional<String> javaVersionAsString = settings.get(JavaVersion.SOURCE_VERSION);
if (!javaVersionAsString.isPresent()) {
return new JavaVersionImpl();
}
String enablePreviewAsString = settings.get(JavaVersion.ENABLE_PREVIEW).orElse("false");
JavaVersion javaVersion = JavaVersionImpl.fromStrings(javaVersionAsString.get(), enablePreviewAsString);
if (javaVersion.arePreviewFeaturesEnabled() && javaVersion.asInt() < JavaVersionImpl.MAX_SUPPORTED) {
LOG.warn("sonar.java.enablePreview is set but will be discarded as the Java version is less than the max" +
" supported version ({} < {})", javaVersion.asInt(), JavaVersionImpl.MAX_SUPPORTED);
javaVersion = new JavaVersionImpl(javaVersion.asInt(), false);
}
LOG.info("Configured Java source version ({}): {}, preview features enabled ({}): {}",
JavaVersion.SOURCE_VERSION, javaVersion.asInt(), JavaVersion.ENABLE_PREVIEW, javaVersion.arePreviewFeaturesEnabled());
return javaVersion;
}
@Override
public String toString() {
return getClass().getSimpleName();
}
}

@ -27,6 +27,7 @@ public class JavaFileCheckRegistrar implements CheckRegistrar {
public void register(RegistrarContext registrarContext) { public void register(RegistrarContext registrarContext) {
// 调用 registerClassesForRepository 以将类与正确的存储库密钥相关联 // 调用 registerClassesForRepository 以将类与正确的存储库密钥相关联
registrarContext.registerClassesForRepository(JavaSecurityDesignRulesRepository.REPOSITORY_KEY, RulesList.getJavaRules(), Collections.emptyList()); registrarContext.registerClassesForRepository(JavaSecurityDesignRulesRepository.REPOSITORY_KEY, RulesList.getJavaRules(), Collections.emptyList());
registrarContext.registerClassesForRepository(JavaSecurityDesignRulesRepository.REPOSITORY_KEY + "-" + HtmlConstants.LANGUAGE_KEY, RulesList.getHtmlRules(), Collections.emptyList());
} }
} }

@ -6,6 +6,7 @@
*/ */
package com.keyware.sonar.java.rules; package com.keyware.sonar.java.rules;
import com.keyware.sonar.java.rules.checkers.SessionDateChecker;
import org.sonar.api.SonarEdition; import org.sonar.api.SonarEdition;
import org.sonar.api.SonarProduct; import org.sonar.api.SonarProduct;
import org.sonar.api.SonarQubeSide; import org.sonar.api.SonarQubeSide;

@ -42,9 +42,7 @@ public final class RulesList {
SystemFunctionChecker.class, SystemFunctionChecker.class,
UploadFileVerifyChecker.class, UploadFileVerifyChecker.class,
UpperCycleLimitRuleChecker.class, UpperCycleLimitRuleChecker.class,
UserStatusVerifyChecker.class, UserStatusVerifyChecker.class
HostIdentityChecker.class,
PasswordInputTagJavaChecker.class
); );
} }
public static List<Class<? extends JavaCheck>> getHtmlRules() { public static List<Class<? extends JavaCheck>> getHtmlRules() {

@ -8,6 +8,7 @@ package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.sonar.java.model.DefaultModuleScannerContext;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.ModuleScannerContext; import org.sonar.plugins.java.api.ModuleScannerContext;
import org.sonar.plugins.java.api.internal.EndOfAnalysis; import org.sonar.plugins.java.api.internal.EndOfAnalysis;
@ -98,9 +99,10 @@ public class AuthenticationChecker extends IssuableSubscriptionVisitor implement
@Override @Override
public void endOfAnalysis(ModuleScannerContext context) { public void endOfAnalysis(ModuleScannerContext context) {
var defaultContext = (DefaultModuleScannerContext) context;
if (!isValidPathFound) { if (!isValidPathFound) {
System.out.println("应通过用户名口令、数据证书等其他手段对用户身份进行验证"); System.out.println("应通过用户名口令、数据证书等其他手段对用户身份进行验证");
context.addIssueOnProject(this, "应通过用户名口令、数据证书等其他手段对用户身份进行验证"); defaultContext.addIssueOnProject(this, "应通过用户名口令、数据证书等其他手段对用户身份进行验证");
} }
} }
} }

@ -30,7 +30,7 @@ public class CookieSensitiveParameterCheck extends IssuableSubscriptionVisitor {
@Override @Override
public List<Tree.Kind> nodesToVisit() { public List<Tree.Kind> nodesToVisit() {
return Arrays.asList(Tree.Kind.METHOD_INVOCATION, Tree.Kind.VARIABLE); return Arrays.asList(Tree.Kind.METHOD_INVOCATION, Tree.Kind.VARIABLE, Tree.Kind.STRING_LITERAL);
} }
@Override @Override
@ -39,6 +39,8 @@ public class CookieSensitiveParameterCheck extends IssuableSubscriptionVisitor {
visitMethodInvocation((MethodInvocationTree) tree); visitMethodInvocation((MethodInvocationTree) tree);
} else if (tree.is(Tree.Kind.VARIABLE)) { } else if (tree.is(Tree.Kind.VARIABLE)) {
visitVariable((VariableTree) tree); visitVariable((VariableTree) tree);
} else if (tree.is(Tree.Kind.STRING_LITERAL)) {
visitStringLiteral((LiteralTree) tree);
} }
} }
@ -92,13 +94,15 @@ public class CookieSensitiveParameterCheck extends IssuableSubscriptionVisitor {
System.out.println("Cookie参数设置中的value属性与局部变量一致: " + variableName); System.out.println("Cookie参数设置中的value属性与局部变量一致: " + variableName);
reportIssue(expression, "Cookie参数设置中包含敏感字段"); reportIssue(expression, "Cookie参数设置中包含敏感字段");
} }
} else if (expression.is(Tree.Kind.STRING_LITERAL)) {
String literalValue = LiteralTree.class.cast(expression).value();
if (containsSensitiveParam(literalValue)) {
System.out.println("Cookie参数设置中的name属性包含敏感字符串: " + literalValue);
reportIssue(expression, "Cookie参数设置中包含敏感字段");
} }
} }
private void visitStringLiteral(LiteralTree literalTree) {
String literalValue = literalTree.value();
if (containsSensitiveParam(literalValue)) {
System.out.println("Cookie参数设置中包含敏感字段: " + literalValue);
reportIssue(literalTree, "Cookie参数设置中包含敏感字段");
}
} }
private boolean containsSensitiveParam(String value) { private boolean containsSensitiveParam(String value) {

@ -37,18 +37,16 @@ public class DynamicCodeChecker extends IssuableSubscriptionVisitor {
MethodInvocationTree node = (MethodInvocationTree) tree; MethodInvocationTree node = (MethodInvocationTree) tree;
var expressionTree = node.methodSelect(); var expressionTree = node.methodSelect();
if (expressionTree != null && expressionTree instanceof MemberSelectExpressionTree) { if (expressionTree instanceof MemberSelectExpressionTree) {
var exprTree = (MemberSelectExpressionTree) expressionTree; var exprTree = (MemberSelectExpressionTree) expressionTree;
var name = exprTree.identifier(); var name = exprTree.identifier();
if ("eval".equals(name.toString())) { if ("eval".equals(name.toString())) {
var varNameNode = exprTree.expression(); var varNameNode = exprTree.expression();
if (varNameNode != null && varNameNode instanceof IdentifierTree) { if (varNameNode instanceof IdentifierTree) {
var varName = (IdentifierTree) varNameNode; var varName = (IdentifierTree) varNameNode;
if (varName != null) {
var symbol = varName.symbol(); var symbol = varName.symbol();
if (symbol != null) {
var varDecler = symbol.declaration(); var varDecler = symbol.declaration();
if (varDecler != null && varDecler instanceof VariableTree) { if (varDecler != null) {
var variableTree = (VariableTree) varDecler; var variableTree = (VariableTree) varDecler;
var typeName = variableTree.type().toString(); var typeName = variableTree.type().toString();
if ("ScriptEngine".equals(typeName)) { if ("ScriptEngine".equals(typeName)) {
@ -59,7 +57,5 @@ public class DynamicCodeChecker extends IssuableSubscriptionVisitor {
} }
} }
} }
}
}
} }

@ -72,7 +72,7 @@ public class DynamicLibraryLoadChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitMethodInvocation(MethodInvocationTree tree) { public void visitMethodInvocation(MethodInvocationTree tree) {
var methodSelect = tree.methodSelect(); var methodSelect = tree.methodSelect();
if (methodSelect != null && methodSelect instanceof MemberSelectExpressionTree) { if (methodSelect instanceof MemberSelectExpressionTree) {
var mset = (MemberSelectExpressionTree) methodSelect; var mset = (MemberSelectExpressionTree) methodSelect;
// 判断是否调用了System.loadLibrary() // 判断是否调用了System.loadLibrary()
if (mset.firstToken() != null && "System".equals(mset.firstToken().text()) && "loadLibrary".equals(mset.identifier().name())) { if (mset.firstToken() != null && "System".equals(mset.firstToken().text()) && "loadLibrary".equals(mset.identifier().name())) {

@ -23,7 +23,7 @@ import java.util.List;
*/ */
@Rule(key = "FileCheck") @Rule(key = "FileCheck")
public class FileCheck extends IssuableSubscriptionVisitor { public class FileCheck extends IssuableSubscriptionVisitor {
private static final List<String> FILE_NAME_VARS = Arrays.asList("fileName", "fileExt", "fileSuffix", "fileEnd"); private static final List<String> FILE_NAME_VARS = Arrays.asList("fileName", "fileExt", "fileSuffix");
@Override @Override
public List<Tree.Kind> nodesToVisit() { public List<Tree.Kind> nodesToVisit() {
@ -37,22 +37,20 @@ public class FileCheck extends IssuableSubscriptionVisitor {
ExpressionTree condition = ifStatement.condition(); ExpressionTree condition = ifStatement.condition();
// 在条件中检查文件名、文件扩展名或文件后缀的使用 // 在条件中检查文件名、文件扩展名或文件后缀的使用
IdenVisitor idenVisitor = new IdenVisitor(); checkVariableUsage(condition);
condition.accept(idenVisitor);
if(idenVisitor.boo){
reportIssue(tree, "在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为");
}
} }
} }
class IdenVisitor extends BaseTreeVisitor { private void checkVariableUsage(ExpressionTree condition) {
boolean boo = false; condition.accept(new BaseTreeVisitor() {
@Override @Override
public void visitIdentifier(IdentifierTree tree) { public void visitIdentifier(IdentifierTree tree) {
if (FILE_NAME_VARS.contains(tree.name())) { if (FILE_NAME_VARS.contains(tree.name())) {
// 如果在条件中发现了文件名、文件扩展名或文件后缀的使用 // 如果在条件中发现了文件名、文件扩展名或文件后缀的使用,报告问题
boo = true; System.out.println("依赖文件的名称或者扩展后缀:"+tree.name());
reportIssue(tree, "在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为");
} }
} }
});
} }
} }

@ -7,10 +7,14 @@
package com.keyware.sonar.java.rules.checkers; package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.sonar.java.ast.parser.ArgumentListTreeImpl;
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.IssuableSubscriptionVisitor; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.*;
import javax.annotation.Nonnull;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -34,13 +38,10 @@ public class HashSaltPassWordChecker extends IssuableSubscriptionVisitor {
} }
@Override @Override
public void visitNode(@Nonnull Tree tree) { public void visitNode(Tree tree) {
MethodTree node = (MethodTree) tree; MethodTree node = (MethodTree) tree;
var bodyVisitor = new MethodeBodyVisitor(this); var bodyVisitor = new MethodeBodyVisitor(this);
BlockTree block = node.block(); node.block().accept(bodyVisitor);
if(block != null){
block.accept(bodyVisitor);
}
} }
@ -55,31 +56,34 @@ public class HashSaltPassWordChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitMethodInvocation(MethodInvocationTree tree) { public void visitMethodInvocation(MethodInvocationTree tree) {
//获取到方法调用 // 获取到方法调用
ExpressionTree expressionTree = tree.methodSelect(); ExpressionTree expressionTree = tree.methodSelect();
if (expressionTree.is(Tree.Kind.MEMBER_SELECT)) { if (expressionTree instanceof MemberSelectExpressionTreeImpl) {
// 获取到调用的方法 // 获取到调用的方法
MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree; MemberSelectExpressionTreeImpl memberSelectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree;
if ("setPassWord".equals(memberSelectExpressionTree.identifier().name())) { if ("setPassWord".equals(memberSelectExpressionTree.identifier().name())) {
Arguments arguments = tree.arguments(); Tree parent = tree.arguments();
for (ExpressionTree expressionTree1 : arguments) { if (parent instanceof ArgumentListTreeImpl) {
if (expressionTree1.is(Tree.Kind.IDENTIFIER)) { for (ExpressionTree expressionTree1 : (ArgumentListTreeImpl) parent) {
IdentifierTree identifierTree = (IdentifierTree) expressionTree1; if (expressionTree1 instanceof IdentifierTreeImpl) {
// 判断set中使用的参数 IdentifierTreeImpl identifierTree = (IdentifierTreeImpl) expressionTree1;
// 判断set中使用的参数
if(!identifierTree.name().equals(strPassWord)){ if(!identifierTree.name().equals(strPassWord)){
checker.context.reportIssue(checker, identifierTree, "应使用盐值计算口令"); checker.context.reportIssue(checker, identifierTree, "应使用盐值计算口令");
} }
} else { }else {
checker.context.reportIssue(checker, expressionTree1, "应使用盐值计算口令"); checker.context.reportIssue(checker, expressionTree1, "应使用盐值计算口令");
} }
} }
} else if("BCrypt".equals(memberSelectExpressionTree.expression().toString()) && "hashpw".equals(memberSelectExpressionTree.identifier().name())){ }
// 判断是否是生成的加盐后的密码
}else if("BCrypt".equals(memberSelectExpressionTree.expression().toString()) && "hashpw".equals(memberSelectExpressionTree.identifier().name())){
Tree parent = memberSelectExpressionTree.parent(); Tree parent = memberSelectExpressionTree.parent();
if(parent != null && parent instanceof MethodInvocationTree){ if(parent instanceof MethodInvocationTreeImpl){
MethodInvocationTree methodInvocationTree = (MethodInvocationTree) parent; MethodInvocationTreeImpl methodInvocationTree = (MethodInvocationTreeImpl) parent;
Tree parent1 = methodInvocationTree.parent(); Tree parent1 = methodInvocationTree.parent();
if(parent1 != null && parent1 instanceof VariableTree){ if(parent1 instanceof VariableTreeImpl){
VariableTree variableTree = (VariableTree) parent1; VariableTreeImpl variableTree = (VariableTreeImpl) parent1;
// 加盐后的参数名称 // 加盐后的参数名称
strPassWord = variableTree.simpleName().name(); strPassWord = variableTree.simpleName().name();
} }
@ -87,17 +91,5 @@ public class HashSaltPassWordChecker extends IssuableSubscriptionVisitor {
} }
} }
} }
@Override
public void visitNewClass(NewClassTree classTree) {
// 判断是否为RedirectView,如果是,则判断是否有参数,如果有参数,则判断参数的类型是否由方法传递进来的
String name = classTree.identifier().toString();
if ("PBEKeySpec".equals(name)) {
if (classTree.arguments().size() < 2) {
// 获取第一个参数语法树节点
checker.context.reportIssue(checker, classTree, "应使用盐值计算口令");
}
}
}
} }
} }

@ -1,80 +0,0 @@
/*
* 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.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*;
import java.util.Collections;
import java.util.List;
/**
* 通过用户名口令数据证书等其他手段对主机身份进行鉴别
*
* @author RenFengJiang
* @date 2024/7/3
*/
@Rule(key = "HostIdentityChecker")
public class HostIdentityChecker extends IssuableSubscriptionVisitor {
@Override
public List<Tree.Kind> nodesToVisit() {
return Collections.singletonList(Tree.Kind.METHOD);
}
@Override
public void visitNode(Tree tree) {
MethodTree methodTree = (MethodTree) tree;
List<VariableTree> parameters = methodTree.parameters();
// 盘带是否是文件上传类
boolean boo = parameters.stream().anyMatch(type -> "HttpServletRequest".equals(type.type().toString()));
if(boo){
NodeIf nodeIf = new NodeIf();
methodTree.block().accept(nodeIf);
if(nodeIf.getNameBoolean() || nodeIf.getPasswordBoolean()){
context.reportIssue(this,methodTree.simpleName(),"通过用户名口令、数据证书等其他手段对主机身份进行鉴别");
}
}
}
public class NodeIf extends BaseTreeVisitor {
public boolean nameBoolean = true;
private boolean passwordBoolean = true;
boolean getNameBoolean(){
return nameBoolean;
}
boolean getPasswordBoolean(){
return passwordBoolean;
}
@Override
public void visitIfStatement(IfStatementTree tree) {
//获取到if表达式
ExpressionTree condition = tree.condition();
if (condition != null && condition instanceof BinaryExpressionTree) {
BinaryExpressionTree binaryExpressionTree = (BinaryExpressionTree) condition;
//判断是否进行if判断
if ("username".equals(binaryExpressionTree.leftOperand().toString())) {
nameBoolean = false;
} else if ("password".equals(binaryExpressionTree.rightOperand().toString())) {
passwordBoolean = false;
}
}
if (condition != null && condition instanceof IdentifierTree) {
IdentifierTree identifierTree = (IdentifierTree) condition;
//判断是否进行if判断
if ("username".equals(identifierTree.name())) {
nameBoolean = false;
} else if ("password".equals(identifierTree.name())) {
passwordBoolean = false;
}
}
}
}
}

@ -7,11 +7,15 @@
package com.keyware.sonar.java.rules.checkers; package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.sonar.java.ast.parser.ArgumentListTreeImpl;
import org.sonar.java.model.expression.BinaryExpressionTreeImpl;
import org.sonar.java.model.expression.IdentifierTreeImpl;
import org.sonar.java.model.expression.LiteralTreeImpl;
import org.sonar.java.model.expression.MemberSelectExpressionTreeImpl;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -50,12 +54,12 @@ public class HttpInputDataChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitIfStatement(IfStatementTree tree) { public void visitIfStatement(IfStatementTree tree) {
ExpressionTree condition = tree.condition(); ExpressionTree condition = tree.condition();
if (condition.is(Tree.Kind.EQUAL_TO, Tree.Kind.NOT_EQUAL_TO)) { if (condition instanceof BinaryExpressionTreeImpl) {
BinaryExpressionTree binaryExpressionTree = (BinaryExpressionTree) condition; BinaryExpressionTreeImpl binaryExpressionTree = (BinaryExpressionTreeImpl) condition;
List<Tree> children = binaryExpressionTree.children();
for (Tree operand : Arrays.asList(binaryExpressionTree.leftOperand(), binaryExpressionTree.rightOperand())) { for (Tree child:children) {
if (operand.is(Tree.Kind.IDENTIFIER)) { if(child instanceof IdentifierTreeImpl){
IdentifierTree identifierTree = (IdentifierTree) operand; IdentifierTreeImpl identifierTree = (IdentifierTreeImpl) child;
list.add(identifierTree.name()); list.add(identifierTree.name());
} }
} }
@ -65,17 +69,20 @@ public class HttpInputDataChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitMethodInvocation(MethodInvocationTree tree) { public void visitMethodInvocation(MethodInvocationTree tree) {
ExpressionTree expressionTree = tree.methodSelect(); ExpressionTree expressionTree = tree.methodSelect();
if (expressionTree.is(Tree.Kind.MEMBER_SELECT)) { if(expressionTree instanceof MemberSelectExpressionTreeImpl){
MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree; MemberSelectExpressionTreeImpl memberSelectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree;
if ("setHeader".equals(memberSelectExpressionTree.identifier().name()) if("setHeader".equals(memberSelectExpressionTree.identifier().name()) || "addHeader".equals(memberSelectExpressionTree.identifier().name())){
|| "addHeader".equals(memberSelectExpressionTree.identifier().name())) {
Arguments arguments = tree.arguments(); Arguments arguments = tree.arguments();
for (ExpressionTree argument : arguments) { if(arguments instanceof ArgumentListTreeImpl){
if(argument.is(Tree.Kind.STRING_LITERAL)){ for (ExpressionTree argument : (ArgumentListTreeImpl) arguments) {
checker.context.reportIssue(checker, argument, "HTTP输入数据验证"); if(argument instanceof LiteralTreeImpl){
LiteralTreeImpl literalTree = (LiteralTreeImpl) argument;
if("STRING_LITERAL".equals(literalTree.kind().name())){
checker.context.reportIssue(checker, literalTree, "HTTP输入数据验证");
break; break;
} else if(argument.is(Tree.Kind.IDENTIFIER)){ }
IdentifierTree identifierTree = (IdentifierTree) argument; }else if(argument instanceof IdentifierTreeImpl){
IdentifierTreeImpl identifierTree = (IdentifierTreeImpl) argument;
if(!list.contains(identifierTree.name())){ if(!list.contains(identifierTree.name())){
checker.context.reportIssue(checker, identifierTree, "HTTP输入数据验证"); checker.context.reportIssue(checker, identifierTree, "HTTP输入数据验证");
break; break;
@ -86,4 +93,5 @@ public class HttpInputDataChecker extends IssuableSubscriptionVisitor {
} }
} }
} }
}
} }

@ -7,6 +7,9 @@
package com.keyware.sonar.java.rules.checkers; package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.sonar.java.ast.parser.ArgumentListTreeImpl;
import org.sonar.java.model.expression.IdentifierTreeImpl;
import org.sonar.java.model.expression.MemberSelectExpressionTreeImpl;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.*;
@ -61,17 +64,19 @@ public class InputSQLVerifyChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitMethodInvocation(MethodInvocationTree tree) { public void visitMethodInvocation(MethodInvocationTree tree) {
ExpressionTree expressionTree = tree.methodSelect(); ExpressionTree expressionTree = tree.methodSelect();
if (expressionTree.is(Tree.Kind.MEMBER_SELECT)) { if(expressionTree instanceof MemberSelectExpressionTreeImpl){
MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree; MemberSelectExpressionTreeImpl memberSelectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree;
if ("prepareStatement".equals(memberSelectExpressionTree.identifier().name()) || "executeQuery".equals(memberSelectExpressionTree.identifier().name())) { if("prepareStatement".equals(memberSelectExpressionTree.identifier().name())){
Arguments arguments = tree.arguments(); Arguments arguments = tree.arguments();
for (ExpressionTree argument : arguments) { if(arguments instanceof ArgumentListTreeImpl){
if (argument.is(Tree.Kind.IDENTIFIER)) { for (ExpressionTree argument : (ArgumentListTreeImpl) arguments) {
IdentifierTree identifierTree = (IdentifierTree) argument; if (argument instanceof IdentifierTreeImpl){
IdentifierTreeImpl identifierTree = (IdentifierTreeImpl) argument;
String name = identifierTree.name(); String name = identifierTree.name();
// 判断使用的sql是否存在集合中 //判断使用的sql是否存在集合中
if (!lists.contains(name)) { if(!lists.contains(name)){
checker.context.reportIssue(checker, argument, "使用sql语句前应对其进行验证"); checker.context.reportIssue(checker,argument,"使用sql语句前应对其进行验证");
}
} }
} }
} }

@ -7,6 +7,11 @@
package com.keyware.sonar.java.rules.checkers; package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.sonar.java.ast.parser.ArgumentListTreeImpl;
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.IssuableSubscriptionVisitor; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.*;
@ -36,10 +41,7 @@ public class Md5PassWordVerifyChecker extends IssuableSubscriptionVisitor {
public void visitNode(Tree tree) { public void visitNode(Tree tree) {
MethodTree node = (MethodTree) tree; MethodTree node = (MethodTree) tree;
var bodyVisitor = new MethodeBodyVisitor(this); var bodyVisitor = new MethodeBodyVisitor(this);
BlockTree block = node.block(); node.block().accept(bodyVisitor);
if(block != null){
block.accept(bodyVisitor);
}
} }
@ -56,48 +58,36 @@ public class Md5PassWordVerifyChecker extends IssuableSubscriptionVisitor {
public void visitMethodInvocation(MethodInvocationTree tree) { public void visitMethodInvocation(MethodInvocationTree tree) {
//获取到方法调用 //获取到方法调用
ExpressionTree expressionTree = tree.methodSelect(); ExpressionTree expressionTree = tree.methodSelect();
if (expressionTree.is(Tree.Kind.MEMBER_SELECT)) { if (expressionTree instanceof MemberSelectExpressionTreeImpl) {
MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree; //获取到调用的方法
MemberSelectExpressionTreeImpl memberSelectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree;
if ("setPassWord".equals(memberSelectExpressionTree.identifier().name())) { if ("setPassWord".equals(memberSelectExpressionTree.identifier().name())) {
Arguments arguments = tree.arguments(); Tree parent = tree.arguments();
//改用arguments,这里没必要再用 instanceof 检查接口了 if (parent instanceof ArgumentListTreeImpl) {
for (ExpressionTree argument : arguments) { for (ExpressionTree expressionTree1 : (ArgumentListTreeImpl) parent) {
if (argument.is(Tree.Kind.IDENTIFIER)) { if (expressionTree1 instanceof IdentifierTreeImpl) {
IdentifierTree identifierTree = (IdentifierTree) argument; IdentifierTreeImpl identifierTree = (IdentifierTreeImpl) expressionTree1;
String name = identifierTree.name(); //判断set中使用的参数
if (!name.equals(strPassWord)) { if(!identifierTree.name().equals(strPassWord)){
checker.context.reportIssue(checker, identifierTree, "应使用单向不可逆的加密算法"); checker.context.reportIssue(checker, identifierTree, "应使用单向不可逆的加密算法");
} }
} else { }else {
checker.context.reportIssue(checker, argument, "应使用单向不可逆的加密算法"); checker.context.reportIssue(checker, expressionTree1, "应使用单向不可逆的加密算法");
}
} }
} }
} else if (memberSelectExpressionTree.identifier().name().toLowerCase(Locale.ROOT).contains("md5hex") //判断是否使用单向不可逆加密方式
|| memberSelectExpressionTree.identifier().name().toLowerCase(Locale.ROOT).contains("encrypt")) { }else if(memberSelectExpressionTree.identifier().name().toLowerCase(Locale.ROOT).contains("md5hex") || memberSelectExpressionTree.identifier().name().toLowerCase(Locale.ROOT).contains("encrypt")){
Tree parent = memberSelectExpressionTree.parent(); Tree parent = memberSelectExpressionTree.parent();
//对parent进行了instanceof检查,这是不正确的,应该使用is(Tree.Kind.SOMETHING) if(parent instanceof MethodInvocationTreeImpl){
if (parent.is(Tree.Kind.METHOD_INVOCATION)) { MethodInvocationTreeImpl methodInvocationTree = (MethodInvocationTreeImpl) parent;
MethodInvocationTree methodInvocationTree = (MethodInvocationTree) parent;
Tree parent1 = methodInvocationTree.parent(); Tree parent1 = methodInvocationTree.parent();
//这同样是对parent1进行了instanceof检查,这是不正确的,应该使用is(Tree.Kind.SOMETHING) if(parent1 instanceof VariableTreeImpl){
if (parent1.is(Tree.Kind.VARIABLE)) { VariableTreeImpl variableTree = (VariableTreeImpl) parent1;
VariableTree variableTree = (VariableTree) parent1; //获取加密后的名称
strPassWord = variableTree.simpleName().name(); strPassWord = variableTree.simpleName().name();
} }
} }
}else if ("Cipher".equals(memberSelectExpressionTree.expression().toString()) && "getInstance".equals(memberSelectExpressionTree.identifier().name())) {
// 获取参数列表
List<ExpressionTree> arguments = tree.arguments();
for (ExpressionTree argument : arguments) {
if (argument.is(Tree.Kind.STRING_LITERAL)) {
LiteralTree literalTree = (LiteralTree) argument;
String c = ((LiteralTree) argument).token().text();
// 对参数进行判断判断是否符合要求
if (literalTree.token().text().startsWith("\"AES")) {
checker.context.reportIssue(checker, argument, "应使用单向不可逆的加密算法");
}
}
}
} }
} }
} }

@ -8,8 +8,17 @@
package com.keyware.sonar.java.rules.checkers; package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; 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.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; 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.Collections;
import java.util.List; import java.util.List;
@ -23,90 +32,59 @@ import java.util.List;
* @date 2024/1/22 * @date 2024/1/22
*/ */
@Rule(key = "OptionsVerifyChecker") @Rule(key = "OptionsVerifyChecker")
public class OptionsVerifyChecker extends IssuableSubscriptionVisitor { public class OptionsVerifyChecker extends IssuableSubscriptionVisitor implements EndOfAnalysis {
private boolean boo = true;
@Override @Override
public List<Tree.Kind> nodesToVisit() { public List<Tree.Kind> nodesToVisit() {
return Collections.singletonList(Tree.Kind.METHOD); /**
* Tree.Kind.METHOD方法节点
* Tree.Kind.BLOCK方法的代码块节点
* Tree.Kind.METHOD_INVOCATION 方法的调用节点
*/
return Collections.singletonList(Tree.Kind.METHOD_INVOCATION);
} }
@Override @Override
public void visitNode(Tree tree) { public void visitNode(Tree tree) {
MethodTree node = (MethodTree) tree; //判断项目是否配置
List<VariableTree> parameters = node.parameters(); if(boo){
//盘带是否是文件上传类 MethodInvocationTreeImpl methodInvocationTree = (MethodInvocationTreeImpl) tree;
boolean booleanRestorn = parameters.stream().anyMatch(type -> "HttpServletResponse".equals(type.type().toString())); ExpressionTree expressionTree = methodInvocationTree.methodSelect();
if (booleanRestorn) { if(expressionTree instanceof MemberSelectExpressionTreeImpl){
MethodCall methodCall = new MethodCall(); MemberSelectExpressionTreeImpl selectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree;
node.block().accept(methodCall); //获取到调用方法判断是否是设置配置方法
if (methodCall.getBooleanInner()) { if("addHeader".equals(selectExpressionTree.identifier().name()) || "setHeader".equals(selectExpressionTree.identifier().name())){
context.reportIssue(this, node.simpleName(), "应设置X-Frame-Options的值为deny"); //获取方法参数
} Arguments arguments = methodInvocationTree.arguments();
} if(arguments instanceof ArgumentListTreeImpl){
DeclarationVerdict declarationVerdict = new DeclarationVerdict(node,this);
node.block().accept(declarationVerdict);
}
private class MethodCall extends BaseTreeVisitor {
private boolean booleanInner = true;
public boolean getBooleanInner() {
return booleanInner;
}
public void visitMethodInvocation(MethodInvocationTree tree) {
if (booleanInner) {
ExpressionTree expressionTree = tree.methodSelect();
if (expressionTree.is(Tree.Kind.MEMBER_SELECT)) {
MemberSelectExpressionTree selectExpressionTree = (MemberSelectExpressionTree) expressionTree;
if ("addHeader".equals(selectExpressionTree.identifier().name()) || "setHeader".equals(selectExpressionTree.identifier().name())) {
Arguments arguments = tree.arguments();
boolean one = false; boolean one = false;
boolean two = false; boolean two = false;
for (ExpressionTree argument : arguments) { for (ExpressionTree argument : (ArgumentListTreeImpl) arguments) {
if (argument.is(Tree.Kind.STRING_LITERAL)) { if(argument instanceof LiteralTreeImpl){
String literalValue = ((LiteralTree) argument).value(); LiteralTreeImpl literalTree = (LiteralTreeImpl) argument;
if ("\"X-Frame-Options\"".equals(literalValue)) { //判断参数
if("\"X-Frame-Options\"".equals(literalTree.token().text())){
one = true; one = true;
} else if ("\"DENY\"".equals(literalValue) ||"\"deny\"".equals(literalValue)) { }else if("\"DENY\"".equals(literalTree.token().text())){
two = true; two = true;
} }
} }
} }
if (one && two) { if(one && two){
booleanInner = false; boo = false;
}
} }
} }
} }
} }
} }
public class DeclarationVerdict extends BaseTreeVisitor {
private MethodTree node;
private OptionsVerifyChecker checker;
public DeclarationVerdict( MethodTree node,OptionsVerifyChecker checker){
this.node = node;
this.checker = checker;
} }
@Override @Override
public void visitVariable(VariableTree tree) { public void endOfAnalysis(ModuleScannerContext context) {
IdentifierTree identifierTree = tree.simpleName(); var defaultContext = (DefaultModuleScannerContext) context;
TypeTree type = tree.type(); if(boo){
if(type != null && type instanceof IdentifierTree){ defaultContext.addIssueOnProject(this, "应设置X-Frame-Options的值为deny");
IdentifierTree fierTree = (IdentifierTree) type;
if("HttpServletResponse".equals(fierTree.name())){
MethodCall methodCall = new MethodCall();
node.block().accept(methodCall);
if (methodCall.getBooleanInner()) {
context.reportIssue(checker, identifierTree, "应设置X-Frame-Options的值为deny");
}
}
}
} }
} }
} }

@ -1,85 +0,0 @@
/*
* 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.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*;
import java.util.Collections;
import java.util.List;
/**
* 用户输入口令时应对口令域进行掩饰用户输入的每一个字符都应该以星号形式回显
*
* @author RenFengJiang
* @date 2024/7/3
*/
@Rule(key = "PasswordInputTagJavaChecker")
public class PasswordInputTagJavaChecker extends IssuableSubscriptionVisitor {
@Override
public List<Tree.Kind> nodesToVisit() {
/**
* Tree.Kind.METHOD方法节点
* Tree.Kind.BLOCK方法的代码块节点
* Tree.Kind.METHOD_INVOCATION 方法的调用节点
*/
return Collections.singletonList(Tree.Kind.BLOCK);
}
@Override
public void visitNode(Tree tree) {
BlockTree node = (BlockTree) tree;
MethodeBodyVisitor methodeBodyVisitor = new MethodeBodyVisitor(this, node);
node.accept(methodeBodyVisitor);
}
static class MethodeBodyVisitor extends BaseTreeVisitor {
private BlockTree blockTree;
private PasswordInputTagJavaChecker checker;
public MethodeBodyVisitor(PasswordInputTagJavaChecker checker, BlockTree blockTree){
this.checker = checker;
this.blockTree = blockTree;
}
@Override
public void visitNewClass(NewClassTree tree) {
String name = tree.identifier().toString();
if("JTextField".equals(name)){
MethodeCall methodeCall = new MethodeCall();
blockTree.accept(methodeCall);
if(methodeCall.getEchoBoolean()){
checker.context.reportIssue(checker, tree, "Java用户输入口令时应对口令域进行掩饰,用户输入的每一个字符都应该以星号形式回显");
}
}
}
}
static class MethodeCall extends BaseTreeVisitor {
//是否存在JTextField输入
private boolean echoBoolean = true;
public boolean getEchoBoolean() {
return echoBoolean;
}
@Override
public void visitMethodInvocation(MethodInvocationTree tree) {
//获取到方法调用
ExpressionTree expressionTree = tree.methodSelect();
if (expressionTree.is(Tree.Kind.MEMBER_SELECT)) {
MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree;
if ("setEchoChar".equals(memberSelectExpressionTree.identifier().name())) {
echoBoolean = false;
}
}
}
}
}

@ -18,82 +18,66 @@ import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.*;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
@Rule(key = "PasswordRegexCheck") @Rule(key = "PasswordRegexCheck")
public class PasswordRegexCheck extends IssuableSubscriptionVisitor { public class PasswordRegexCheck extends IssuableSubscriptionVisitor {
private static final String MATCHER_METHOD = "matcher";
private static final String PASSWORD_PARAMETER = "password";
@Override @Override
public List<Tree.Kind> nodesToVisit() { public List<Tree.Kind> nodesToVisit() {
// 在这里,我们只考虑方法
return Collections.singletonList(Tree.Kind.METHOD); return Collections.singletonList(Tree.Kind.METHOD);
} }
@Override @Override
public void visitNode(Tree tree) { public void visitNode(Tree tree) {
MethodTree method = (MethodTree) tree; if (tree.is(Tree.Kind.METHOD)) {
// 检查是否存在名为 “password”的参数 MethodTree methodTree = (MethodTree) tree;
List<VariableTree> passwordParameters = method.parameters().stream() checkPasswordValidation(methodTree);
.filter(param -> "password".equals(param.simpleName().name()))
.collect(Collectors.toList());
if (!passwordParameters.isEmpty()) {
// 确认参数 "password" 是否在正确的正则表达式之下被检查
boolean passwordIsCheckedWithRegex = passwordParameters.stream()
.anyMatch(param -> isPasswordValidatedWithRegex(method, param));
if (!passwordIsCheckedWithRegex) {
reportIssue(method.simpleName(), "未对口令进行复杂度验证");
}
} }
} }
private void checkPasswordValidation(MethodTree methodTree) {
private boolean isPasswordValidatedWithRegex(Tree tree, VariableTree passwordParameter) { boolean hasPasswordValidation = false;
PasswordValidationVisitor visitor = new PasswordValidationVisitor(passwordParameter);
tree.accept(visitor); for (StatementTree statement : methodTree.block().body()) {
return visitor.isPasswordValidated(); if (statement.is(Tree.Kind.VARIABLE)) {
VariableTree variableTree = (VariableTree) statement;
if (variableTree.initializer() != null && variableTree.initializer().is(Tree.Kind.METHOD_INVOCATION)) {
MethodInvocationTree methodInvocationTree = (MethodInvocationTree) variableTree.initializer();
String methodName = methodInvocationTree.methodSymbol().name();
if (MATCHER_METHOD.equals(methodName)) {
hasPasswordValidation = hasPasswordValidation || hasPasswordParameter(methodInvocationTree.arguments());
} }
private static class PasswordValidationVisitor extends BaseTreeVisitor {
private final VariableTree passwordParameter;
private boolean passwordValidated = false;
PasswordValidationVisitor(VariableTree passwordParameter) {
this.passwordParameter = passwordParameter;
} }
@Override
public void visitMethodInvocation(MethodInvocationTree tree) {
// 改变行为,查找是否存在匹配指定方法调用模式的表达式
if (isCorrectPasswordValidationMethod(tree)) {
passwordValidated = true;
} }
super.visitMethodInvocation(tree);
} }
public boolean isPasswordValidated() { if (!hasPasswordValidation) {
return passwordValidated; //如果没有发现密码验证,报告问题
System.out.println("未对口令进行复杂度验证"+methodTree.simpleName());
reportIssue(methodTree.simpleName(), "未对口令进行复杂度验证");
}
} }
private boolean isCorrectPasswordValidationMethod(MethodInvocationTree mit) { private boolean hasPasswordParameter(List<ExpressionTree> arguments) {
if ("matches".equals(mit.methodSymbol().name()) for (ExpressionTree argument : arguments) {
&& mit.methodSelect().is(Tree.Kind.MEMBER_SELECT) if (argument.is(Tree.Kind.IDENTIFIER)) {
&& ((MemberSelectExpressionTree) mit.methodSelect()).identifier().name().equals("matcher") IdentifierTree identifier = (IdentifierTree) argument;
&& ((MemberSelectExpressionTree) mit.methodSelect()).expression().is(Tree.Kind.METHOD_INVOCATION)) { if (PASSWORD_PARAMETER.equalsIgnoreCase(identifier.name())) {
//检查标识符是否有密码验证
MethodInvocationTree innerMit = (MethodInvocationTree) ((MemberSelectExpressionTree) mit.methodSelect()).expression(); return hasPasswordValidationInMethod(identifier.name());
if ("compile".equals(innerMit.methodSymbol().name())
&& innerMit.methodSelect().is(Tree.Kind.MEMBER_SELECT)
&& "Pattern".equals( ((MemberSelectExpressionTree)innerMit.methodSelect()).expression().toString())) {
// 需要确定参数中包含名为 'password' 的参数
List<VariableTree> arguments = mit.methodSymbol().declaration().parameters().stream().filter(param -> param.symbol().name().equals("password")).collect(Collectors.toList());
return (!arguments.isEmpty());
} }
} }
}
return false; return false;
} }
private boolean hasPasswordValidationInMethod(String paramName) {
//参数名是'password',已经存在
return PASSWORD_PARAMETER.equalsIgnoreCase(paramName);
} }
} }

@ -7,11 +7,13 @@
package com.keyware.sonar.java.rules.checkers; package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.sonar.java.ast.parser.ArgumentListTreeImpl;
import org.sonar.java.model.InternalSyntaxToken;
import org.sonar.java.model.expression.LiteralTreeImpl;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.*;
import java.util.ArrayList; import java.util.Collections;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
@ -23,8 +25,6 @@ import java.util.List;
@Rule(key = "RSAEncryptionChecker") @Rule(key = "RSAEncryptionChecker")
public class RSAEncryptionChecker extends IssuableSubscriptionVisitor { public class RSAEncryptionChecker extends IssuableSubscriptionVisitor {
private List nameLists = new ArrayList();
@Override @Override
public List<Tree.Kind> nodesToVisit() { public List<Tree.Kind> nodesToVisit() {
/** /**
@ -32,73 +32,39 @@ public class RSAEncryptionChecker extends IssuableSubscriptionVisitor {
* Tree.Kind.BLOCK方法的代码块节点 * Tree.Kind.BLOCK方法的代码块节点
* Tree.Kind.METHOD_INVOCATION 方法的调用节点 * Tree.Kind.METHOD_INVOCATION 方法的调用节点
*/ */
return Arrays.asList(Tree.Kind.METHOD_INVOCATION, Tree.Kind.CLASS); return Collections.singletonList(Tree.Kind.METHOD_INVOCATION);
} }
@Override @Override
public void visitNode(Tree tree) { public void visitNode(Tree tree) {
if (tree.is(Tree.Kind.CLASS)) {
MethodBOdyVisitor methodBOdyVisitor = new MethodBOdyVisitor();
tree.accept(methodBOdyVisitor);
nameLists = methodBOdyVisitor.getNameLists();
} else if (tree.is(Tree.Kind.METHOD_INVOCATION)) {
MethodInvocationTree methodInvocationTree = (MethodInvocationTree) tree; MethodInvocationTree methodInvocationTree = (MethodInvocationTree) tree;
ExpressionTree expressionTree = methodInvocationTree.methodSelect(); ExpressionTree expressionTree = methodInvocationTree.methodSelect();
if (expressionTree != null) { // 获取到方法调用
// 获取到方法调用 if(expressionTree instanceof MemberSelectExpressionTree){
if (expressionTree instanceof MemberSelectExpressionTree) {
MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree; MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree;
// 判断是否符合标准 // 判断是否符合标准
String a = memberSelectExpressionTree.expression().toString(); if("Cipher".equals(memberSelectExpressionTree.expression().toString()) && "getInstance".equals(memberSelectExpressionTree.identifier().name())){
String b = memberSelectExpressionTree.identifier().name(); // 获取参数列表
if ("Cipher".equals(memberSelectExpressionTree.expression().toString()) && "getInstance".equals(memberSelectExpressionTree.identifier().name())) { Arguments arguments = methodInvocationTree.arguments();
// 获取参数列表 if(arguments instanceof ArgumentListTreeImpl){
List<ExpressionTree> arguments = methodInvocationTree.arguments(); // 获取到参数列表
for (ExpressionTree argument : arguments) { ArgumentListTreeImpl argumentListTree = (ArgumentListTreeImpl) arguments;
if (argument.is(Tree.Kind.STRING_LITERAL)) { for (ExpressionTree argument : argumentListTree) {
LiteralTree literalTree = (LiteralTree) argument; if(argument instanceof LiteralTreeImpl){
String c = ((LiteralTree) argument).token().text(); LiteralTreeImpl literalTree = (LiteralTreeImpl) argument;
// 对参数进行判断判断是否符合要求 // 获取到其中的参数
if (!literalTree.token().text().startsWith("\"RSA")) { SyntaxToken syntaxToken = literalTree.token();
context.reportIssue(this, argument, "使用RSA最优加密填充"); if(syntaxToken instanceof InternalSyntaxToken){
} InternalSyntaxToken internalSyntaxToken = (InternalSyntaxToken) syntaxToken;
} else if (!nameLists.equals(argument.toString())) { // 对参数进行判断判断是否符合要求
context.reportIssue(this, argument, "使用RSA最优加密填充"); if(!(internalSyntaxToken.text().startsWith("\"RSA") && internalSyntaxToken.text().contains("OAEPWithSHA-256AndMGF1Padding"))){
} context.reportIssue(this,tree,"使用RSA最优加密填充");
} }
} }
} }
} }
} }
} }
static class MethodBOdyVisitor extends BaseTreeVisitor {
private List nameLists = new ArrayList();
public MethodBOdyVisitor() {
}
public List getNameLists() {
return nameLists;
}
@Override
public void visitVariable(VariableTree tree) {
IdentifierTree identifierTree = tree.simpleName();
ExpressionTree initializer = tree.initializer();
if (identifierTree != null && initializer != null && initializer instanceof LiteralTree) {
LiteralTree literalTree = (LiteralTree) initializer;
if (literalTree.value().startsWith("\"RSA")) {
nameLists.add(identifierTree.name());
}
}
} }
} }
} }

@ -11,7 +11,6 @@ import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.*;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -44,15 +43,6 @@ public class RedirectUrlChecker extends IssuableSubscriptionVisitor {
checkByStringType(block, parameters); checkByStringType(block, parameters);
} }
} }
if(!parameters.isEmpty()){
for (VariableTree parameter : parameters) {
if("HttpServletResponse".equals(parameter.type().toString())){
String name = parameter.simpleName().name();
MethodeBodyVisitor methodeBodyVisitor = new MethodeBodyVisitor(this, name);
methodTree.block().accept(methodeBodyVisitor);
}
}
}
} }
private void checkByStringType(BlockTree block, List<? extends VariableTree> methodParameters) { private void checkByStringType(BlockTree block, List<? extends VariableTree> methodParameters) {
@ -61,7 +51,7 @@ public class RedirectUrlChecker extends IssuableSubscriptionVisitor {
ReturnStatementTree rs = (ReturnStatementTree) statementTree; ReturnStatementTree rs = (ReturnStatementTree) statementTree;
ExpressionTree exprTree = rs.expression(); ExpressionTree exprTree = rs.expression();
if (exprTree != null && !exprTree.is(Tree.Kind.STRING_LITERAL)) { if (exprTree != null && !exprTree.is(Tree.Kind.STRING_LITERAL)) {
if (exprTree != null && exprTree instanceof BinaryExpressionTree) { if (exprTree instanceof BinaryExpressionTree) {
BinaryExpressionTree bExprTree = (BinaryExpressionTree) exprTree; BinaryExpressionTree bExprTree = (BinaryExpressionTree) exprTree;
if (bExprTree.is(Tree.Kind.PLUS) && bExprTree.leftOperand().is(Tree.Kind.STRING_LITERAL) && bExprTree.rightOperand().is(Tree.Kind.IDENTIFIER)) { if (bExprTree.is(Tree.Kind.PLUS) && bExprTree.leftOperand().is(Tree.Kind.STRING_LITERAL) && bExprTree.rightOperand().is(Tree.Kind.IDENTIFIER)) {
var identifierTree = (IdentifierTree) bExprTree.rightOperand(); var identifierTree = (IdentifierTree) bExprTree.rightOperand();
@ -85,49 +75,6 @@ public class RedirectUrlChecker extends IssuableSubscriptionVisitor {
} }
//判断HttpServletResponse类型重定向
static class MethodeBodyVisitor extends BaseTreeVisitor {
private final RedirectUrlChecker checker;
private String name ;
private List lists = new ArrayList<String>();
MethodeBodyVisitor(RedirectUrlChecker checker,String name){
this.checker = checker;
this.name = name;
}
@Override
public void visitIfStatement(IfStatementTree tree) {
ExpressionTree condition = tree.condition();
condition.accept(new BaseTreeVisitor(){
@Override
public void visitIdentifier(IdentifierTree tree) {
lists.add(tree.name());
}
});
}
@Override
public void visitMethodInvocation(MethodInvocationTree tree) {
ExpressionTree expressionTree = tree.methodSelect();
if (expressionTree.is(Tree.Kind.MEMBER_SELECT)) {
MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree;
if ("sendRedirect".equals(memberSelectExpressionTree.identifier().name()) && name.equals(memberSelectExpressionTree.expression().toString())) {
Arguments arguments = tree.arguments();
for (ExpressionTree argument : arguments) {
if (argument.is(Tree.Kind.IDENTIFIER)) {
IdentifierTree identifierTree = (IdentifierTree) argument;
String paramName = identifierTree.name();
// 判断使用的sql是否存在集合中
if (!lists.contains(paramName)) {
checker.context.reportIssue(checker, argument, "在重定向前对输入数据进行验证");
}
}
}
}
}
}
}
/** /**
* 判断方法是否为public方法 * 判断方法是否为public方法
* *
@ -139,13 +86,13 @@ public class RedirectUrlChecker extends IssuableSubscriptionVisitor {
var hasMappingAnnotation = false; var hasMappingAnnotation = false;
for (ModifierTree modifier : methodTree.modifiers()) { for (ModifierTree modifier : methodTree.modifiers()) {
// 判断是否为公共方法 // 判断是否为公共方法
if (!isPublic && modifier != null && modifier instanceof ModifierKeywordTree) { if (!isPublic && modifier instanceof ModifierKeywordTree) {
if (((ModifierKeywordTree) modifier).modifier() == Modifier.PUBLIC) { if (((ModifierKeywordTree) modifier).modifier() == Modifier.PUBLIC) {
isPublic = true; isPublic = true;
} }
} }
// 判断是否包含Mapping注解 // 判断是否包含Mapping注解
if (!hasMappingAnnotation && modifier != null && modifier instanceof AnnotationTree) { if (!hasMappingAnnotation && modifier instanceof AnnotationTree) {
AnnotationTree annotationTree = (AnnotationTree) modifier; AnnotationTree annotationTree = (AnnotationTree) modifier;
if (annotationTree.annotationType() instanceof IdentifierTree) { if (annotationTree.annotationType() instanceof IdentifierTree) {
IdentifierTree identifierTree = (IdentifierTree) annotationTree.annotationType(); IdentifierTree identifierTree = (IdentifierTree) annotationTree.annotationType();
@ -189,7 +136,7 @@ public class RedirectUrlChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitMethodInvocation(MethodInvocationTree invocationTree) { public void visitMethodInvocation(MethodInvocationTree invocationTree) {
ExpressionTree expressionTree = invocationTree.methodSelect(); ExpressionTree expressionTree = invocationTree.methodSelect();
if (expressionTree != null && expressionTree instanceof MemberSelectExpressionTree) { if (expressionTree instanceof MemberSelectExpressionTree) {
MemberSelectExpressionTree member = (MemberSelectExpressionTree) expressionTree; MemberSelectExpressionTree member = (MemberSelectExpressionTree) expressionTree;
if (member.expression().symbolType().is("org.springframework.web.servlet.view.RedirectView") if (member.expression().symbolType().is("org.springframework.web.servlet.view.RedirectView")
&& "setUrl".equals(member.identifier().name())) { && "setUrl".equals(member.identifier().name())) {
@ -201,7 +148,7 @@ public class RedirectUrlChecker extends IssuableSubscriptionVisitor {
private void checkArgs(ExpressionTree argNode, Tree tree) { private void checkArgs(ExpressionTree argNode, Tree tree) {
// 判断该语法树节点是否为IdentifierTree,如果是,则说明语法树节点为变量,然后判断该变量是否是包含在方法的参数列表中 // 判断该语法树节点是否为IdentifierTree,如果是,则说明语法树节点为变量,然后判断该变量是否是包含在方法的参数列表中
if (argNode != null && argNode instanceof IdentifierTree) { if (argNode instanceof IdentifierTree) {
IdentifierTree identifierTree = (IdentifierTree) argNode; IdentifierTree identifierTree = (IdentifierTree) argNode;
String argName = identifierTree.name(); String argName = identifierTree.name();
if (methodParameters.stream().anyMatch(parameter -> parameter.simpleName().name().equals(argName))) { if (methodParameters.stream().anyMatch(parameter -> parameter.simpleName().name().equals(argName))) {

@ -42,46 +42,44 @@ public class SecurityCookieChecker extends IssuableSubscriptionVisitor {
// 盘带是否是文件上传类 // 盘带是否是文件上传类
boolean boo = parameters.stream().anyMatch(type -> "HttpServletResponse".equals(type.type().toString())); boolean boo = parameters.stream().anyMatch(type -> "HttpServletResponse".equals(type.type().toString()));
if(boo){ if(boo){
var bodyVisitor = new MethodBOdyVisitor(); var bodyVisitor = new MethodBOdyVisitor(this);
node.block().accept(bodyVisitor); node.block().accept(bodyVisitor);
if(bodyVisitor.booCure){ if(bodyVisitor.booHttp){
if(!(bodyVisitor.booAge && bodyVisitor.booCure)){
context.reportIssue(this,node.simpleName(),"设置HTTPS会话中cookie的安全属性"); context.reportIssue(this,node.simpleName(),"设置HTTPS会话中cookie的安全属性");
} }
// if(bodyVisitor.booHttp){ }
// if(!(bodyVisitor.booAge && bodyVisitor.booCure)){
// context.reportIssue(this,node.simpleName(),"设置HTTPS会话中cookie的安全属性");
// }
// }
} }
} }
static class MethodBOdyVisitor extends BaseTreeVisitor{ static class MethodBOdyVisitor extends BaseTreeVisitor{
private final SecurityCookieChecker checker;
// 判断是否是https请求 // 判断是否是https请求
private boolean booCure = true; private boolean booCure = false;
// 设置cooker时长 // 设置cooker时长
// private boolean booAge = false; private boolean booAge = false;
// 设置访问 // 设置访问
// private boolean booHttp = false; private boolean booHttp = false;
public MethodBOdyVisitor( ){ public MethodBOdyVisitor(SecurityCookieChecker checker ){
this.checker = checker;
} }
@Override @Override
public void visitMethodInvocation(MethodInvocationTree tree) { public void visitMethodInvocation(MethodInvocationTree tree) {
ExpressionTree expressionTree = tree.methodSelect(); ExpressionTree expressionTree = tree.methodSelect();
if(expressionTree != null && expressionTree instanceof MemberSelectExpressionTree){ if(expressionTree instanceof MemberSelectExpressionTree){
MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree; MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree;
switch (memberSelectExpressionTree.identifier().name()){ switch (memberSelectExpressionTree.identifier().name()){
// case "setHttpOnly": case "setHttpOnly":
// booHttp = true; booHttp = true;
// break; break;
case "setSecure": case "setSecure":
booCure = false; booCure = true;
break;
case "setMaxAge":
booAge = true;
break; break;
// case "setMaxAge":
// booAge = true;
// break;
} }
} }
} }

@ -8,6 +8,9 @@
package com.keyware.sonar.java.rules.checkers; package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; import org.sonar.check.Rule;
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.IssuableSubscriptionVisitor; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.*;
@ -45,10 +48,10 @@ public class SendMessageVerifyChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitNode(Tree tree) { public void visitNode(Tree tree) {
MethodInvocationTree methodInvocationTree = (MethodInvocationTree) tree; MethodInvocationTreeImpl methodInvocationTree = (MethodInvocationTreeImpl) tree;
ExpressionTree expressionTree = methodInvocationTree.methodSelect(); ExpressionTree expressionTree = methodInvocationTree.methodSelect();
if(expressionTree.is(Tree.Kind.IDENTIFIER)){ if(expressionTree instanceof IdentifierTreeImpl){
IdentifierTree identifierTree = (IdentifierTree) expressionTree; IdentifierTreeImpl identifierTree = (IdentifierTreeImpl) expressionTree;
//判断方法是否是方法调用的节点 //判断方法是否是方法调用的节点
if(identifierTree.name().toLowerCase().contains("send")){ if(identifierTree.name().toLowerCase().contains("send")){
IdenVisitor idenVisitor = new IdenVisitor(this); IdenVisitor idenVisitor = new IdenVisitor(this);
@ -70,6 +73,7 @@ public class SendMessageVerifyChecker extends IssuableSubscriptionVisitor {
checker.context.reportIssue(checker, tree, "发送信息规则检查"); checker.context.reportIssue(checker, tree, "发送信息规则检查");
} }
} }
} }
} }

@ -7,9 +7,16 @@
package com.keyware.sonar.java.rules.checkers; package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.sonar.java.ast.parser.ArgumentListTreeImpl;
import org.sonar.java.model.expression.LiteralTreeImpl;
import org.sonar.java.model.expression.MemberSelectExpressionTreeImpl;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.semantic.Type; import org.sonar.plugins.java.api.semantic.Type;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.Arguments;
import org.sonar.plugins.java.api.tree.ExpressionTree;
import org.sonar.plugins.java.api.tree.MethodInvocationTree;
import org.sonar.plugins.java.api.tree.Tree;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List; import java.util.List;
@ -29,10 +36,9 @@ public class SessionCacheParamsChecker extends IssuableSubscriptionVisitor {
"userid", "userid",
"token", "token",
"url", "url",
"userpassword", "userpassword"
"price"
); );
private static final String requestType = "HttpServletRequest"; private static final String requestType = "javax.servlet.http.HttpServletRequest";
@Override @Override
public List<Tree.Kind> nodesToVisit() { public List<Tree.Kind> nodesToVisit() {
@ -41,28 +47,32 @@ public class SessionCacheParamsChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitNode(@Nonnull Tree tree) { public void visitNode(@Nonnull Tree tree) {
// ((MemberSelectExpressionTree)methodInvocationTree.methodSelect()).expression().symbolType()
MethodInvocationTree methodInvocationTree = (MethodInvocationTree) tree; MethodInvocationTree methodInvocationTree = (MethodInvocationTree) tree;
Symbol.MethodSymbol methodSymbol = methodInvocationTree.methodSymbol();
if(methodSymbol.isMethodSymbol()) {
//获取参数 //获取参数
ExpressionTree expressionTree = methodInvocationTree.methodSelect(); ExpressionTree expressionTree = methodInvocationTree.methodSelect();
if(expressionTree.is(Tree.Kind.MEMBER_SELECT)){ if(expressionTree instanceof MemberSelectExpressionTreeImpl){
MemberSelectExpressionTree selectExpressionTree = (MemberSelectExpressionTree) expressionTree; MemberSelectExpressionTreeImpl selectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree;
//获取参数类型 //获取参数类型
Type type = selectExpressionTree.expression().symbolType(); Type type = selectExpressionTree.expression().symbolType();
String fierName = selectExpressionTree.identifier().name();
if(type != null){ if(type != null){
//判断参数类型和调用方法符不符合要求 //判断参数类型和调用方法符不符合要求
if(type.fullyQualifiedName().contains(requestType) if(requestType.equals(type.fullyQualifiedName())
&& ("getParameter".equals(fierName) || "getCookies".equals(fierName))) { && ("getParameter".equals(methodSymbol.name()) || "getCookies".equals(methodSymbol.name()))) {
//如果是getCookies方法直接抛错 //如果是getCookies方法直接抛错
if("getCookies".equals(fierName)){ if("getCookies".equals(methodSymbol.name())){
reportIssue(methodInvocationTree, "页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取"); reportIssue(methodInvocationTree, "页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取");
}else { }else {
//获取参数 //获取参数
Arguments arguments = methodInvocationTree.arguments(); Arguments arguments = methodInvocationTree.arguments();
for (ExpressionTree argument : arguments) { if(arguments instanceof ArgumentListTreeImpl){
if(argument.is(Tree.Kind.STRING_LITERAL)){ for (ExpressionTree argument : (ArgumentListTreeImpl) arguments) {
String name = ((LiteralTree) argument).value() if(argument instanceof LiteralTreeImpl){
.replace("\"", "").toLowerCase(); LiteralTreeImpl literalTree = (LiteralTreeImpl) argument;
//获取参数值
String name = literalTree.token().text().replace("\"", "").toLowerCase();
//判断是否是违规项 //判断是否是违规项
if(HIDED_PARAMS.contains(name)){ if(HIDED_PARAMS.contains(name)){
reportIssue(methodInvocationTree, "页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取"); reportIssue(methodInvocationTree, "页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取");
@ -75,4 +85,6 @@ public class SessionCacheParamsChecker extends IssuableSubscriptionVisitor {
} }
} }
} }
}
}
} }

@ -27,7 +27,7 @@ import java.util.Scanner;
* @date 2024/1/22 * @date 2024/1/22
*/ */
@Rule(key = "SessionDateChecker") @Rule(key = "SessionDateChecker")
public class SessionDateCheckera implements ConfigCheck { public class SessionDateChecker implements ConfigCheck {
private boolean boo = true; private boolean boo = true;
public void execute(SensorContext context, InputFile inputFile, RuleKey ruleKey){ public void execute(SensorContext context, InputFile inputFile, RuleKey ruleKey){
@ -77,7 +77,7 @@ public class SessionDateCheckera implements ConfigCheck {
Map<String, Object> currentLevel = map; Map<String, Object> currentLevel = map;
for (int i = 0; i < keys.length - 1; ++i) { for (int i = 0; i < keys.length - 1; ++i) {
Object nextLevel = currentLevel.get(keys[i]); Object nextLevel = currentLevel.get(keys[i]);
if (nextLevel != null && nextLevel instanceof Map) { if (nextLevel instanceof Map) {
currentLevel = (Map<String, Object>) nextLevel; currentLevel = (Map<String, Object>) nextLevel;
} else { } else {
return null; return null;

@ -37,9 +37,6 @@ public class UploadFileVerifyChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitNode(Tree tree) { public void visitNode(Tree tree) {
MethodTree node = (MethodTree) tree; MethodTree node = (MethodTree) tree;
DeclarationVerdict declarationVerdict = new DeclarationVerdict(node,this);
((MethodTree) tree).block().accept(declarationVerdict);
List<VariableTree> parameters = node.parameters(); List<VariableTree> parameters = node.parameters();
//盘带是否是文件上传类 //盘带是否是文件上传类
boolean boo = parameters.stream().anyMatch(type -> "MultipartFile".equals(type.type().toString())); boolean boo = parameters.stream().anyMatch(type -> "MultipartFile".equals(type.type().toString()));
@ -99,35 +96,35 @@ public class UploadFileVerifyChecker extends IssuableSubscriptionVisitor {
public void visitMethodInvocation(MethodInvocationTree tree) { public void visitMethodInvocation(MethodInvocationTree tree) {
//获取到方法调用的参数 //获取到方法调用的参数
ExpressionTree expressionTree = tree.methodSelect(); ExpressionTree expressionTree = tree.methodSelect();
if (expressionTree != null && expressionTree instanceof MemberSelectExpressionTree) { if (expressionTree instanceof MemberSelectExpressionTree) {
MemberSelectExpressionTree expressionTree1 = (MemberSelectExpressionTree) expressionTree; MemberSelectExpressionTree expressionTree1 = (MemberSelectExpressionTree) expressionTree;
//对调用方法进行判断 //对调用方法进行判断
if ("getOriginalFilename".equals(expressionTree1.identifier().toString())) { if ("getOriginalFilename".equals(expressionTree1.identifier().toString())) {
Tree parent = expressionTree1.parent(); Tree parent = expressionTree1.parent();
if (parent != null && parent instanceof MethodInvocationTree) { if (parent instanceof MethodInvocationTree) {
MethodInvocationTree memberSelectExpressionTree = (MethodInvocationTree) parent; MethodInvocationTree memberSelectExpressionTree = (MethodInvocationTree) parent;
Tree parent1 = memberSelectExpressionTree.parent(); Tree parent1 = memberSelectExpressionTree.parent();
if (parent1 != null && parent1 instanceof VariableTree) { if (parent1 instanceof VariableTree) {
VariableTree variableTree = (VariableTree) parent1; VariableTree variableTree = (VariableTree) parent1;
fileName = variableTree.simpleName().toString(); fileName = variableTree.simpleName().toString();
} }
} }
} else if ("extName".equals(expressionTree1.identifier().toString())) { } else if ("extName".equals(expressionTree1.identifier().toString())) {
Tree parent = expressionTree1.parent(); Tree parent = expressionTree1.parent();
if (parent != null && parent instanceof MethodInvocationTree) { if (parent instanceof MethodInvocationTree) {
MethodInvocationTree memberSelectExpressionTree = (MethodInvocationTree) parent; MethodInvocationTree memberSelectExpressionTree = (MethodInvocationTree) parent;
Tree parent1 = memberSelectExpressionTree.parent(); Tree parent1 = memberSelectExpressionTree.parent();
if (parent1 != null && parent1 instanceof VariableTree) { if (parent1 instanceof VariableTree) {
VariableTree variableTree = (VariableTree) parent1; VariableTree variableTree = (VariableTree) parent1;
fileType = variableTree.simpleName().toString(); fileType = variableTree.simpleName().toString();
} }
} }
} else if ("getSize".equals(expressionTree1.identifier().toString())) { } else if ("getSize".equals(expressionTree1.identifier().toString())) {
Tree parent = expressionTree1.parent(); Tree parent = expressionTree1.parent();
if (parent != null && parent instanceof MethodInvocationTree) { if (parent instanceof MethodInvocationTree) {
MethodInvocationTree memberSelectExpressionTree = (MethodInvocationTree) parent; MethodInvocationTree memberSelectExpressionTree = (MethodInvocationTree) parent;
Tree parent1 = memberSelectExpressionTree.parent(); Tree parent1 = memberSelectExpressionTree.parent();
if (parent1 != null && parent1 instanceof VariableTree) { if (parent1 instanceof VariableTree) {
VariableTree variableTree = (VariableTree) parent1; VariableTree variableTree = (VariableTree) parent1;
sizeName = variableTree.simpleName().toString(); sizeName = variableTree.simpleName().toString();
} }
@ -142,10 +139,10 @@ public class UploadFileVerifyChecker extends IssuableSubscriptionVisitor {
public class NodeIf extends BaseTreeVisitor { public class NodeIf extends BaseTreeVisitor {
private Object name; private String name;
public boolean boo = true; public boolean boo = true;
public NodeIf(Object name) { public NodeIf(String name) {
this.name = name; this.name = name;
} }
@ -153,7 +150,7 @@ public class UploadFileVerifyChecker extends IssuableSubscriptionVisitor {
public void visitIfStatement(IfStatementTree tree) { public void visitIfStatement(IfStatementTree tree) {
//获取到if表达式 //获取到if表达式
ExpressionTree condition = tree.condition(); ExpressionTree condition = tree.condition();
if (condition != null && condition instanceof BinaryExpressionTree) { if (condition instanceof BinaryExpressionTree) {
BinaryExpressionTree binaryExpressionTree = (BinaryExpressionTree) condition; BinaryExpressionTree binaryExpressionTree = (BinaryExpressionTree) condition;
//判断是否进行if判断 //判断是否进行if判断
if (name.equals(binaryExpressionTree.leftOperand().toString())) { if (name.equals(binaryExpressionTree.leftOperand().toString())) {
@ -162,42 +159,6 @@ public class UploadFileVerifyChecker extends IssuableSubscriptionVisitor {
boo = false; boo = false;
} }
} }
if (condition != null && condition instanceof IdentifierTree) {
IdentifierTree identifierTree = (IdentifierTree) condition;
//判断是否进行if判断
if (name.equals(identifierTree.name())) {
boo = false;
} else if (name.equals(identifierTree.name())) {
boo = false;
}
}
}
}
public class DeclarationVerdict extends BaseTreeVisitor {
private MethodTree node;
private UploadFileVerifyChecker checker;
public DeclarationVerdict( MethodTree node,UploadFileVerifyChecker checker){
this.node = node;
this.checker = checker;
}
@Override
public void visitVariable(VariableTree tree) {
IdentifierTree identifierTree = tree.simpleName();
TypeTree type = tree.type();
if(type != null && type instanceof IdentifierTree){
IdentifierTree fierTree = (IdentifierTree) type;
if("Fileltem".equals(fierTree.name())){
NodeIf nodeIf = new NodeIf(identifierTree.name());
node.block().accept(nodeIf);
if (nodeIf.boo) {
context.reportIssue(checker, identifierTree, value);
}
}
}
} }
} }
} }

@ -7,6 +7,7 @@
package com.keyware.sonar.java.rules.checkers; package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.sonar.java.model.expression.BinaryExpressionTreeImpl;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.*;
@ -31,10 +32,8 @@ public class UpperCycleLimitRuleChecker extends IssuableSubscriptionVisitor {
MethodTree methodTree = (MethodTree) tree; MethodTree methodTree = (MethodTree) tree;
List<VariableTree> args = methodTree.parameters(); List<VariableTree> args = methodTree.parameters();
BlockTree blockTree = methodTree.block(); BlockTree blockTree = methodTree.block();
if(blockTree != null){
blockTree.accept(new MethodBlockVisitor(this, args)); blockTree.accept(new MethodBlockVisitor(this, args));
} }
}
class MethodBlockVisitor extends BaseTreeVisitor { class MethodBlockVisitor extends BaseTreeVisitor {
@ -48,39 +47,32 @@ public class UpperCycleLimitRuleChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitForStatement(ForStatementTree fnode) { public void visitForStatement(ForStatementTree fnode) {
ExpressionTree ffnode = fnode.condition(); var ffnode = fnode.condition();
if (ffnode.is(Tree.Kind.EQUAL_TO, Tree.Kind.NOT_EQUAL_TO, Tree.Kind.LESS_THAN, Tree.Kind.LESS_THAN_OR_EQUAL_TO, Tree.Kind.GREATER_THAN, Tree.Kind.GREATER_THAN_OR_EQUAL_TO)) { if (ffnode instanceof BinaryExpressionTreeImpl) {
BinaryExpressionTree binaryExpressionTree = (BinaryExpressionTree) ffnode; ExpressionTree leftOperand = ((BinaryExpressionTreeImpl) ffnode).leftOperand();
ExpressionTree leftOperand = binaryExpressionTree.leftOperand();
checkVar(leftOperand); checkVar(leftOperand);
ExpressionTree rightOperand = binaryExpressionTree.rightOperand(); ExpressionTree rightOperand = ((BinaryExpressionTreeImpl) ffnode).rightOperand();
checkVar(rightOperand); checkVar(rightOperand);
} }
} }
@Override @Override
public void visitWhileStatement(WhileStatementTree wnode) { public void visitWhileStatement(WhileStatementTree wnode) {
ExpressionTree wwnode = wnode.condition(); var wwnode = wnode.condition();
if (wwnode.is(Tree.Kind.EQUAL_TO, Tree.Kind.NOT_EQUAL_TO, Tree.Kind.LESS_THAN, Tree.Kind.LESS_THAN_OR_EQUAL_TO, Tree.Kind.GREATER_THAN, Tree.Kind.GREATER_THAN_OR_EQUAL_TO)) { ExpressionTree teea = ((BinaryExpressionTreeImpl) wwnode).leftOperand();
BinaryExpressionTree binaryExpressionTree = (BinaryExpressionTree) wwnode; checkVar(teea);
ExpressionTree leftOperand = binaryExpressionTree.leftOperand();
checkVar(leftOperand);
}
} }
@Override @Override
public void visitDoWhileStatement(DoWhileStatementTree dnode) { public void visitDoWhileStatement(DoWhileStatementTree dnode) {
ExpressionTree ddnode = dnode.condition(); var ddnode = dnode.condition();
if (ddnode.is(Tree.Kind.EQUAL_TO, Tree.Kind.NOT_EQUAL_TO, Tree.Kind.LESS_THAN, Tree.Kind.LESS_THAN_OR_EQUAL_TO, Tree.Kind.GREATER_THAN, Tree.Kind.GREATER_THAN_OR_EQUAL_TO)) { ExpressionTree teeas = ((BinaryExpressionTreeImpl) ddnode).leftOperand();
BinaryExpressionTree binaryExpressionTree = (BinaryExpressionTree) ddnode; checkVar(teeas);
ExpressionTree leftOperand = binaryExpressionTree.leftOperand();
checkVar(leftOperand);
}
} }
private void checkVar(ExpressionTree operand) { private void checkVar(ExpressionTree operand) {
if (operand != null && operand instanceof IdentifierTree) { if (operand instanceof IdentifierTree) {
IdentifierTree identifierTree = (IdentifierTree) operand; IdentifierTree identifierTree = (IdentifierTree) operand;
var name = identifierTree.name(); var name = identifierTree.name();
for (VariableTree varTree : args) { for (VariableTree varTree : args) {

@ -8,6 +8,10 @@
package com.keyware.sonar.java.rules.checkers; package com.keyware.sonar.java.rules.checkers;
import org.sonar.check.Rule; import org.sonar.check.Rule;
import org.sonar.java.ast.parser.ArgumentListTreeImpl;
import org.sonar.java.model.declaration.VariableTreeImpl;
import org.sonar.java.model.expression.LiteralTreeImpl;
import org.sonar.java.model.expression.MemberSelectExpressionTreeImpl;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.tree.*; import org.sonar.plugins.java.api.tree.*;
@ -32,16 +36,15 @@ public class UserStatusVerifyChecker extends IssuableSubscriptionVisitor {
MethodTree methodTree = (MethodTree) tree; MethodTree methodTree = (MethodTree) tree;
//判断是否是doFilter或doFilter方法 //判断是否是doFilter或doFilter方法
boolean boo = verifyMethod(methodTree); boolean boo = verifyMethod(methodTree);
if (boo) { if(boo){
//内部实现类 //内部实现类
VisitMethod visitMethod = new VisitMethod(this); VisitMethod visitMethod = new VisitMethod(this);
//调用内部实现类 //调用内部实现类
methodTree.block().accept(visitMethod); methodTree.block().accept(visitMethod);
//判断是否满足4个条件 //判断是否满足4个条件
if (visitMethod.booOne && visitMethod.booTwo && visitMethod.booThree && visitMethod.booFour) { if(visitMethod.booOne && visitMethod.booTwo && visitMethod.booThree && visitMethod.booFour){
} else { }else{
System.out.println(methodTree.simpleName());
context.reportIssue(this, methodTree.simpleName(), "对用户进行身份鉴别并建立一个新的会话时让原来的会话失效"); context.reportIssue(this, methodTree.simpleName(), "对用户进行身份鉴别并建立一个新的会话时让原来的会话失效");
} }
@ -50,15 +53,19 @@ public class UserStatusVerifyChecker extends IssuableSubscriptionVisitor {
public static boolean verifyMethod(MethodTree methodTree) { public static boolean verifyMethod(MethodTree methodTree) {
//preHandle //preHandle
// if ("doFilter".equals(methodTree.simpleName().name()) || "preHandle".equals(methodTree.simpleName().name())) { if ("doFilter".equals(methodTree.simpleName().name()) || "preHandle".equals(methodTree.simpleName().name())) {
//获取参数 //获取参数
List<VariableTree> parameters = methodTree.parameters(); List<VariableTree> parameters = methodTree.parameters();
for (VariableTree variable : parameters) { for (VariableTree variable : parameters) {
if (variable.type().symbolType().name().endsWith("ServletRequest")) { if (variable instanceof VariableTreeImpl) {
//判断参数是否有ServletRequest
VariableTreeImpl variableTree = (VariableTreeImpl) variable;
if (variableTree.type().toString().endsWith("ServletRequest")) {
return true; return true;
} }
} }
//} }
}
return false; return false;
} }
@ -79,34 +86,36 @@ public class UserStatusVerifyChecker extends IssuableSubscriptionVisitor {
@Override @Override
public void visitMethodInvocation(MethodInvocationTree tree) { public void visitMethodInvocation(MethodInvocationTree tree) {
ExpressionTree expressionTree = tree.methodSelect(); ExpressionTree expressionTree = tree.methodSelect();
if (expressionTree.is(Tree.Kind.MEMBER_SELECT)) { if(expressionTree instanceof MemberSelectExpressionTreeImpl){
//判断是否调用指定的方法 //判断是否调用指定的方法
MemberSelectExpressionTree selectExpressionTree = (MemberSelectExpressionTree) expressionTree; MemberSelectExpressionTreeImpl selectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree;
if ("getParameter".equals(selectExpressionTree.identifier().name()) || "getSession".equals(selectExpressionTree.identifier().name())) { if("getParameter".equals(selectExpressionTree.identifier().name()) || "getSession".equals(selectExpressionTree.identifier().name())){
//获取到调用方法的参数 //获取到调用方法的参数
Arguments arguments = tree.arguments(); Arguments arguments = tree.arguments();
//调用判断参数的方法 //调用判断参数的方法
verifyParam(arguments); verifyParam(arguments);
} else if ("invalidate".equals(selectExpressionTree.identifier().name())) { }else if ("invalidate".equals(selectExpressionTree.identifier().name())){
booFour = true; booFour = true;
} }
} }
} }
public void verifyParam(Arguments arguments) { public void verifyParam(Arguments arguments){
for (ExpressionTree argument : arguments) { if(arguments instanceof ArgumentListTreeImpl){
if (argument.is(Tree.Kind.STRING_LITERAL)) { for (ExpressionTree argument : (ArgumentListTreeImpl) arguments) {
LiteralTree literalTree = (LiteralTree) argument; if(argument instanceof LiteralTreeImpl){
String strName = literalTree.value().replace("\"", "").toLowerCase(); LiteralTreeImpl literalTree = (LiteralTreeImpl) argument;
if ("username".equals(strName)) { String strName = literalTree.token().text().replace("\"", "").toLowerCase();
if("username".equals(strName)){
booOne = true; booOne = true;
} else if ("password".equals(strName)) { }else if("password".equals(strName)){
booTwo = true; booTwo = true;
} else if ("false".equals(strName)) { }else if("false".equals(strName)){
booThree = true; booThree = true;
} }
} }
} }
} }
} }
}
} }

@ -1,5 +1,5 @@
<p>通过用户名口令、数据证书等其他手段对用户身份进行验证</p> <p>通过用户名口令、数据证书等其他手段对用户身份进行验证</p>
<h2>通过用户名口令、数据证书等其他手段对用户身份进行验证</h2> <h2>通过用户名口令、数据证书等其他手段对用户身份进行验证</h2>
<pre> <pre>
</pre> </pre>

@ -1,5 +1,5 @@
{ {
"title": "通过用户名口令、数据证书等其他手段对用户身份进行验证", "title": "通过用户名口令、数据证书等其他手段对用户身份进行验证",
"type": "CODE_SMELL", "type": "CODE_SMELL",
"status": "ready", "status": "ready",
"remediation": { "remediation": {

@ -1,16 +0,0 @@
<!--
~ Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved.
~ 项目名称:信息安全性设计准则检查插件
~ 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件
~ 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
-->
<p>通过用户名口令、数据证书等其他手段对主机身份进行鉴别</p>
<h2>通过用户名口令、数据证书等其他手段对主机身份进行鉴别</h2>
<pre>
</pre>
<h2>合规解决方案</h2>
<pre>
</pre>

@ -1,13 +0,0 @@
{
"title": "通过用户名口令、数据证书等其他手段对主机身份进行鉴别",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"28suo"
],
"defaultSeverity": "Minor"
}

@ -1,16 +0,0 @@
<!--
~ Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved.
~ 项目名称:信息安全性设计准则检查插件
~ 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件
~ 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
-->
<h2>Java用户输入口令时应对口令域进行掩饰,用户输入的每一个字符都应该以星号形式回显</h2>
<p>Java用户输入口令时应对口令域进行掩饰,用户输入的每一个字符都应该以星号形式回显</p>
<pre>
</pre>
<h2>合规解决方案</h2>
<pre>
</pre>

@ -1,13 +0,0 @@
{
"title": "Java用户输入口令时应对口令域进行掩饰,用户输入的每一个字符都应该以星号形式回显",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "15min"
},
"tags": [
"28suo"
],
"defaultSeverity": "Major"
}

@ -1,33 +0,0 @@
{
"name": "Sonar way",
"ruleKeys": [
"ABCVarNameChecker",
"AbsolutePathDetectorChecker",
"AuthenticationChecker",
"AvoidSensitiveInfoInLogsCheck",
"ConfigurationFileChecker",
"CookieSensitiveParameterCheck",
"DynamicCodeChecker",
"DynamicLibraryLoadChecker",
"ErrorMessageChecker",
"FileCheck",
"HashSaltPassWordChecker",
"HttpInputDataChecker",
"InputSQLVerifyChecker",
"Md5PassWordVerifyChecker",
"OptionsVerifyChecker",
"PasswordInputTagChecker",
"PasswordRegexCheck",
"PathAndKeywordCheck",
"RedirectUrlChecker",
"RSAEncryptionChecker",
"SecurityCookieChecker",
"SendMessageVerifyChecker",
"SessionCacheParamsChecker",
"SessionDateChecker",
"SystemFunctionChecker",
"UploadFileVerifyChecker",
"UpperCycleLimitRuleChecker",
"UserStatusVerifyChecker"
]
}

@ -1,38 +1,22 @@
public class FileCheck { public class FileCheck{
public String FileName() { public String FileName(){
String fileName = ""; String fileName = "";
String fileExt = ""; String fileExt = "";
String fileSuffix = ""; String fileSuffix = "";
if (fileName.endsWith("png")) {// Noncompliant {{在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为}} if(fileName.endsWith("png") ){// Noncompliant {{在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为}}
} }
if (fileExt.equals("jpg")) {// Noncompliant {{在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为}} if(fileExt.equals("jpg") ){// Noncompliant {{在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为}}
} }
if (fileSuffix.equals("jpg")) {// Noncompliant {{在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为}} if(fileSuffix.equals("jpg")){// Noncompliant {{在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为}}
} }
return null; return null;
} }
public void imageBeauty(HttpServletRequest request) { //处理图像文件
DiskFileltemFactory factory = new DiskFileltemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = upload.parseRequest(request);
Iterator<Fileltem> iter = items.iterator();
while (iter.hasNext()) {
FileItem item = iter.next();
String fileName = item.getName();
String fileEnd = fileName.substring(fileName.lastlndexOf(".") + 1).toLowerCase();
//依赖文件扩展名进行验证
if (fileEnd != null && fileEnd.matches(regex)) {// Noncompliant {{在服务器端不允许仅仅依赖文件的名称或者扩展后缀决定软件的行为,应依赖文件的内容决定软件的行为}}
//对文件的相关操作
}
}
}
} }

@ -1,7 +1,7 @@
public class HashSaltPassWordRule { public class HashSaltPassWordRule {
public static void cs(Student student) { public static void cs(Student student){
// 结合盐值和口令进行散列计算 // 结合盐值和口令进行散列计算
// String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt()); // String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());
@ -29,22 +29,4 @@ public class HashSaltPassWordRule {
} }
} }
public class Example {
private String encrypt(String password, KeySpec key) { //加密函数,返回加密后的字符串
MessageDigest md = MessageDigest.getInstance("SHA-256");
}
public void storePassword(String password) {
byte[] salt = new byte[length];
Random random = new SecureRandom();
random.nextBytes(salt);//随机生成盐值
// 使用盐值生成密钥KeySpec key = new PBEKeySpec(password.toCharArray(),salt,iterationCount);
// KeySpec keyspec = new PBEKeySpec(ssword.toCharArray(),salt,iterationCount);//生成密钥
KeySpec keyspec = new PBEKeySpec(ssword.toCharArray());// Noncompliant {{应使用盐值计算口令}}
//仅使用单向加密,还是容易被攻击者用彩虹表等方式破解口令
String encryptedPassword = encrypt(password, key);
//将 encryptedPassword 存放到数据库
}
}
} }

@ -1,26 +0,0 @@
/*
* Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved.
* 项目名称信息安全性设计准则检查插件
* 项目描述用于检查源代码的安全性设计准则的Sonarqube插件
* 版权说明本软件属北京关键科技股份有限公司所有在未获得北京关键科技股份有限公司正式授权情况下任何企业和个人不能获取阅读安装传播本软件涉及的任何受知识产权保护的内容
*/
import java.net.*;
public class Example {
private boolean trusted;
public void getTrust(HttpServletRequest request) {// Noncompliant {{通过用户名口令、数据证书等其他手段对主机身份进行鉴别}}
String ip = request.getRemoteAddr();
InetAddress address = InetAddress.getByName(ip);
//攻击者可通过DNS欺骗绕过依赖域名的主机身份鉴别
if (address.getCanonicalHostName().endsWith("trustme.com")) {
trusted = true;
}
// String username = request.getParameter("username");
// String password = request.getParameter("password");
// if (username != null &.&.password != null){
// }
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save