commit
05ced611ef
@ -0,0 +1,109 @@ |
|||||||
|
/* |
||||||
|
* 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.java.model.DefaultModuleScannerContext; |
||||||
|
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor; |
||||||
|
import org.sonar.plugins.java.api.ModuleScannerContext; |
||||||
|
import org.sonar.plugins.java.api.internal.EndOfAnalysis; |
||||||
|
import org.sonar.plugins.java.api.tree.*; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* TODO 通过用户名口令、数据证书等其他手段对用户身份进行验证。 |
||||||
|
* AuthenticationChecker |
||||||
|
* |
||||||
|
* @author WuHaoYang |
||||||
|
* @date 2024/1/23 |
||||||
|
*/ |
||||||
|
@Rule(key = "AuthenticationChecker") |
||||||
|
public class AuthenticationChecker extends IssuableSubscriptionVisitor implements EndOfAnalysis { |
||||||
|
|
||||||
|
private static final Set<String> VALID_PATHS = new HashSet<>(Arrays.asList("/login", "/auto","signin")); |
||||||
|
private boolean isValidPathFound = false; |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<Tree.Kind> nodesToVisit() { |
||||||
|
return Collections.singletonList(Tree.Kind.METHOD); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void visitNode(Tree tree) { |
||||||
|
MethodTree methodTree = (MethodTree) tree; |
||||||
|
|
||||||
|
for (AnnotationTree annotation : methodTree.modifiers().annotations()) { |
||||||
|
if (isWebAnnotation(annotation)) { |
||||||
|
if (checkAnnotationArguments(annotation)) { |
||||||
|
isValidPathFound = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isWebAnnotation(AnnotationTree annotation) { |
||||||
|
TypeTree typeTree = annotation.annotationType(); |
||||||
|
return "PostMapping".equals(typeTree.toString()) || "RequestMapping".equals(typeTree.toString()); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean checkAnnotationArguments(AnnotationTree annotation) { |
||||||
|
for (ExpressionTree arg : annotation.arguments()) { |
||||||
|
if (arg.is(Tree.Kind.ASSIGNMENT)) { |
||||||
|
AssignmentExpressionTree aet = (AssignmentExpressionTree) arg; |
||||||
|
IdentifierTree it = (IdentifierTree) aet.variable(); |
||||||
|
if ("value".equals(it.name())) { |
||||||
|
if (aet.expression().is(Tree.Kind.NEW_ARRAY)) { |
||||||
|
NewArrayTree nat = (NewArrayTree) aet.expression(); |
||||||
|
for (ExpressionTree et : nat.initializers()) { |
||||||
|
LiteralTree lt = (LiteralTree) et; |
||||||
|
System.out.println(lt.value().toString()); |
||||||
|
if (checkUrl(lt.value().toString())) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (aet.expression().is(Tree.Kind.STRING_LITERAL)) { |
||||||
|
LiteralTree lt = (LiteralTree) aet.expression(); |
||||||
|
System.out.println(lt.value().toString()); |
||||||
|
if (checkUrl(lt.value().toString())) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (arg.is(Tree.Kind.STRING_LITERAL)) { |
||||||
|
LiteralTree lt = (LiteralTree) arg; |
||||||
|
System.out.println(lt.value().toString()); |
||||||
|
if (checkUrl(lt.value().toString())) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
private boolean checkUrl(String url) { |
||||||
|
for (String validPath : VALID_PATHS) { |
||||||
|
if (url.endsWith(validPath) || url.contains(validPath)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void endOfAnalysis(ModuleScannerContext context) { |
||||||
|
var defaultContext = (DefaultModuleScannerContext) context; |
||||||
|
if (!isValidPathFound) { |
||||||
|
System.out.println("应通过用户名口令、数据证书等其他手段对用户身份进行验证"); |
||||||
|
defaultContext.addIssueOnProject(this, "应通过用户名口令、数据证书等其他手段对用户身份进行验证"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. |
||||||
|
* 项目名称:信息安全性设计准则检查插件 |
||||||
|
* 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 |
||||||
|
* 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.keyware.sonar.java.rules.checkers; |
||||||
|
|
||||||
|
import org.sonar.api.batch.fs.InputFile; |
||||||
|
import org.sonar.api.batch.sensor.SensorContext; |
||||||
|
import org.sonar.api.rule.RuleKey; |
||||||
|
|
||||||
|
/** |
||||||
|
* TODO ConfigCheck |
||||||
|
* |
||||||
|
* @author RenFengJiang |
||||||
|
* @date 2024/1/23 |
||||||
|
*/ |
||||||
|
public interface ConfigCheck { |
||||||
|
default void execute(SensorContext context, InputFile inputFile, RuleKey ruleKey){} |
||||||
|
default void endOfCheck(SensorContext context, RuleKey ruleKey){} |
||||||
|
} |
@ -0,0 +1,96 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. |
||||||
|
* 项目名称:信息安全性设计准则检查插件 |
||||||
|
* 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 |
||||||
|
* 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.keyware.sonar.java.rules.checkers; |
||||||
|
|
||||||
|
import org.sonar.api.batch.fs.InputFile; |
||||||
|
import org.sonar.api.batch.sensor.SensorContext; |
||||||
|
import org.sonar.api.rule.RuleKey; |
||||||
|
import org.sonar.check.Rule; |
||||||
|
import org.yaml.snakeyaml.Yaml; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.FileInputStream; |
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Scanner; |
||||||
|
|
||||||
|
/** |
||||||
|
* TODO SessionDateChecker |
||||||
|
* |
||||||
|
* @author RenFengJiang |
||||||
|
* @date 2024/1/22 |
||||||
|
*/ |
||||||
|
@Rule(key = "SessionDateChecker") |
||||||
|
public class SessionDateChecker implements ConfigCheck { |
||||||
|
|
||||||
|
private boolean boo = true; |
||||||
|
public void execute(SensorContext context, InputFile inputFile, RuleKey ruleKey){ |
||||||
|
if(boo){ |
||||||
|
//文件名称
|
||||||
|
String filename = inputFile.filename(); |
||||||
|
//校验文件后缀
|
||||||
|
if (filename.endsWith(".properties")) { |
||||||
|
try { |
||||||
|
File file = new File(inputFile.absolutePath()); |
||||||
|
try (Scanner scanner = new Scanner(file)) { |
||||||
|
while (scanner.hasNextLine()) { |
||||||
|
String line = scanner.nextLine(); |
||||||
|
if (line.contains("server.servlet.session.timeout")) { |
||||||
|
boo = false; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (FileNotFoundException e) { |
||||||
|
System.out.println("文件未找到: " + e.getMessage()); |
||||||
|
return; // 文件未找到时立即返回
|
||||||
|
} |
||||||
|
} |
||||||
|
if (filename.endsWith(".yml")){ |
||||||
|
// 获取当前输入文件的绝对路径
|
||||||
|
File file1 = inputFile.file(); |
||||||
|
File absoluteFile = file1.getAbsoluteFile(); |
||||||
|
// 构建目录路径
|
||||||
|
Yaml yaml = new Yaml(); |
||||||
|
try (FileInputStream fis = new FileInputStream(file1)) { |
||||||
|
Map<String, Object> obj = yaml.load(fis); |
||||||
|
if (obj != null){ |
||||||
|
String sessionTimeout = searchForSessionTimeout(obj, "server", "servlet", "session", "timeout"); |
||||||
|
if (sessionTimeout != null) { |
||||||
|
boo = false; |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (IOException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String searchForSessionTimeout(Map<String, Object> map, String... keys) { |
||||||
|
Map<String, Object> currentLevel = map; |
||||||
|
for (int i = 0; i < keys.length - 1; ++i) { |
||||||
|
Object nextLevel = currentLevel.get(keys[i]); |
||||||
|
if (nextLevel instanceof Map) { |
||||||
|
currentLevel = (Map<String, Object>) nextLevel; |
||||||
|
} else { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
return currentLevel.get(keys[keys.length - 1]).toString(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void endOfCheck(SensorContext context, RuleKey ruleKey) { |
||||||
|
if(boo){ |
||||||
|
var issue = context.newIssue(); |
||||||
|
issue.at(issue.newLocation().on(context.project()).message("设置会话过期的日期")).forRule(ruleKey).save(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
<p>通过用户名口令、数据证书等其他手段对用户身份进行验证</p> |
||||||
|
<h2>通过用户名口令、数据证书等其他手段对用户身份进行验证</h2> |
||||||
|
<pre> |
||||||
|
|
||||||
|
</pre> |
||||||
|
<h2>合规解决方案</h2> |
||||||
|
<pre> |
||||||
|
|
||||||
|
</pre> |
@ -0,0 +1,13 @@ |
|||||||
|
{ |
||||||
|
"title": "通过用户名口令、数据证书等其他手段对用户身份进行验证", |
||||||
|
"type": "CODE_SMELL", |
||||||
|
"status": "ready", |
||||||
|
"remediation": { |
||||||
|
"func": "Constant\/Issue", |
||||||
|
"constantCost": "5min" |
||||||
|
}, |
||||||
|
"tags": [ |
||||||
|
"28suo" |
||||||
|
], |
||||||
|
"defaultSeverity": "Minor" |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
<!-- |
||||||
|
~ Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. |
||||||
|
~ 项目名称:信息安全性设计准则检查插件 |
||||||
|
~ 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 |
||||||
|
~ 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 |
||||||
|
--> |
||||||
|
|
||||||
|
<p>设置会话过期的日期</p> |
||||||
|
<h2>设置会话过期的日期</h2> |
||||||
|
<pre> |
||||||
|
|
||||||
|
</pre> |
||||||
|
<h2>合规解决方案</h2> |
||||||
|
<pre> |
||||||
|
|
||||||
|
</pre> |
@ -0,0 +1,13 @@ |
|||||||
|
{ |
||||||
|
"title": "设置会话过期的日期", |
||||||
|
"type": "CODE_SMELL", |
||||||
|
"status": "ready", |
||||||
|
"remediation": { |
||||||
|
"func": "Constant\/Issue", |
||||||
|
"constantCost": "5min" |
||||||
|
}, |
||||||
|
"tags": [ |
||||||
|
"28suo" |
||||||
|
], |
||||||
|
"defaultSeverity": "Minor" |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
|
||||||
|
|
||||||
|
@Controller |
||||||
|
public class AuthController { |
||||||
|
|
||||||
|
@PostMapping("/account/aa") |
||||||
|
public String login() { |
||||||
|
return "login"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@PostMapping(value ={"/path/bb", "/path/www", "/path/eee"}) |
||||||
|
public String signin() { |
||||||
|
return "login"; |
||||||
|
} |
||||||
|
|
||||||
|
@RequestMapping("/myapp/cc") |
||||||
|
public String auth() { |
||||||
|
return "login"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
# |
||||||
|
# Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. |
||||||
|
# 项目名称:信息安全性设计准则检查插件 |
||||||
|
# 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 |
||||||
|
# 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 |
||||||
|
# |
||||||
|
|
||||||
|
# 设置会话超时时间为30分钟 |
||||||
|
server.servlet.session.timeout=30m |
@ -0,0 +1,4 @@ |
|||||||
|
server: |
||||||
|
servlet: |
||||||
|
session: |
||||||
|
timeout: 30m |
@ -0,0 +1,32 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. |
||||||
|
* 项目名称:信息安全性设计准则检查插件 |
||||||
|
* 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 |
||||||
|
* 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 |
||||||
|
*/ |
||||||
|
package com.keyware.sonar.java.rules.checkers; |
||||||
|
|
||||||
|
import com.keyware.sonar.java.utils.FilesUtils; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.sonar.java.checks.verifier.CheckVerifier; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 通过用户名口令、数据证书等其他手段对用户身份进行验证。 单元测试类 |
||||||
|
* |
||||||
|
* @author WuHaoYang |
||||||
|
* @date 2024/1/23 |
||||||
|
*/ |
||||||
|
public class AuthenticationCheckerTest { |
||||||
|
|
||||||
|
|
||||||
|
@Test |
||||||
|
void detected() { |
||||||
|
|
||||||
|
CheckVerifier.newVerifier() |
||||||
|
.onFiles("src/test/files/AuthenticationChecker.java") |
||||||
|
.withCheck(new AuthenticationChecker()) |
||||||
|
.withClassPath(FilesUtils.getClassPath("target/test-jars")) |
||||||
|
.verifyIssueOnProject("应通过用户名口令、数据证书等其他手段对用户身份进行验证"); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue