Compare commits
No commits in common. 'master' and 'wuhaoyang' have entirely different histories.
@ -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); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -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; |
||||||
} |
} |
@ -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(); |
|
||||||
} |
|
||||||
} |
|
@ -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; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -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; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -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,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…
Reference in new issue