commit
ab4ae0f844
@ -0,0 +1,124 @@ |
|||||||
|
/* |
||||||
|
* 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.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.tree.*; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 对用户进行身份鉴别并建立一个新的会话时让原来的会话失效 |
||||||
|
* |
||||||
|
* @author RenFengJiang |
||||||
|
* @date 2024/1/24 |
||||||
|
*/ |
||||||
|
@Rule(key = "UserStatusVerifyChecker") |
||||||
|
public class UserStatusVerifyChecker extends IssuableSubscriptionVisitor { |
||||||
|
@Override |
||||||
|
public List<Tree.Kind> nodesToVisit() { |
||||||
|
return List.of(Tree.Kind.METHOD); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void visitNode(Tree tree) { |
||||||
|
//将Tree强转成MethodTree
|
||||||
|
MethodTree methodTree = (MethodTree) tree; |
||||||
|
//判断是否是doFilter或doFilter方法
|
||||||
|
boolean boo = verifyMethod(methodTree); |
||||||
|
if(boo){ |
||||||
|
//内部实现类
|
||||||
|
VisitMethod visitMethod = new VisitMethod(this); |
||||||
|
//调用内部实现类
|
||||||
|
methodTree.block().accept(visitMethod); |
||||||
|
//判断是否满足4个条件
|
||||||
|
if(visitMethod.booOne && visitMethod.booTwo && visitMethod.booThree && visitMethod.booFour){ |
||||||
|
|
||||||
|
}else{ |
||||||
|
context.reportIssue(this, methodTree.simpleName(), "对用户进行身份鉴别并建立一个新的会话时让原来的会话失效"); |
||||||
|
} |
||||||
|
|
||||||
|
}else { |
||||||
|
context.reportIssue(this, methodTree.simpleName(), "对用户进行身份鉴别并建立一个新的会话时让原来的会话失效"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean verifyMethod(MethodTree methodTree) { |
||||||
|
//判断是否是doFilter或doFilter方法
|
||||||
|
if ("doFilter".equals(methodTree.simpleName().name()) || "doFilter".equals(methodTree.simpleName().name())) { |
||||||
|
//获取参数
|
||||||
|
List<VariableTree> parameters = methodTree.parameters(); |
||||||
|
for (VariableTree variable : parameters) { |
||||||
|
if (variable instanceof VariableTreeImpl) { |
||||||
|
//判断参数是否有ServletRequest
|
||||||
|
VariableTreeImpl variableTree = (VariableTreeImpl) variable; |
||||||
|
if (variableTree.type().toString().endsWith("ServletRequest")) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
static class VisitMethod extends BaseTreeVisitor { |
||||||
|
private final UserStatusVerifyChecker checker; |
||||||
|
|
||||||
|
private boolean booOne = false; |
||||||
|
private boolean booTwo = false; |
||||||
|
private boolean booThree = false; |
||||||
|
private boolean booFour = false; |
||||||
|
|
||||||
|
|
||||||
|
public VisitMethod(UserStatusVerifyChecker checker) { |
||||||
|
this.checker = checker; |
||||||
|
} |
||||||
|
|
||||||
|
//方法调用节点
|
||||||
|
@Override |
||||||
|
public void visitMethodInvocation(MethodInvocationTree tree) { |
||||||
|
ExpressionTree expressionTree = tree.methodSelect(); |
||||||
|
if(expressionTree instanceof MemberSelectExpressionTreeImpl){ |
||||||
|
//判断是否调用指定的方法
|
||||||
|
MemberSelectExpressionTreeImpl selectExpressionTree = (MemberSelectExpressionTreeImpl) expressionTree; |
||||||
|
if("getParameter".equals(selectExpressionTree.identifier().name()) || "getSession".equals(selectExpressionTree.identifier().name())){ |
||||||
|
//获取到调用方法的参数
|
||||||
|
Arguments arguments = tree.arguments(); |
||||||
|
//调用判断参数的方法
|
||||||
|
verifyParam(arguments); |
||||||
|
}else if ("invalidate".equals(selectExpressionTree.identifier().name())){ |
||||||
|
booFour = true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void verifyParam(Arguments arguments){ |
||||||
|
if(arguments instanceof ArgumentListTreeImpl){ |
||||||
|
for (ExpressionTree argument : (ArgumentListTreeImpl) arguments) { |
||||||
|
if(argument instanceof LiteralTreeImpl){ |
||||||
|
LiteralTreeImpl literalTree = (LiteralTreeImpl) argument; |
||||||
|
String strName = literalTree.token().text().replace("\"", "").toLowerCase(); |
||||||
|
if("username".equals(strName)){ |
||||||
|
booOne = true; |
||||||
|
}else if("password".equals(strName)){ |
||||||
|
booTwo = true; |
||||||
|
}else if("false".equals(strName)){ |
||||||
|
booThree = true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
<!-- |
||||||
|
~ Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. |
||||||
|
~ 项目名称:信息安全性设计准则检查插件 |
||||||
|
~ 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 |
||||||
|
~ 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 |
||||||
|
--> |
||||||
|
|
||||||
|
<p>页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取</p> |
||||||
|
<h2>页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取</h2> |
||||||
|
<pre> |
||||||
|
|
||||||
|
</pre> |
||||||
|
<h2>合规解决方案</h2> |
||||||
|
<pre> |
||||||
|
|
||||||
|
</pre> |
@ -0,0 +1,13 @@ |
|||||||
|
{ |
||||||
|
"title": "页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取", |
||||||
|
"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插件 |
||||||
|
~ 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 |
||||||
|
--> |
||||||
|
|
||||||
|
<h2>对用户进行身份鉴别并建立一个新的会话时让原来的会话失效</h2> |
||||||
|
<p>对用户进行身份鉴别并建立一个新的会话时让原来的会话失效</p> |
||||||
|
<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" |
||||||
|
} |
@ -1,22 +1,31 @@ |
|||||||
package com.example; |
import org.springframework.web.bind.annotation.GetMapping; |
||||||
import javax.servlet.http.HttpServlet; |
import org.springframework.web.bind.annotation.RestController; |
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
import javax.servlet.http.HttpServletResponse; |
import javax.servlet.http.*; |
||||||
import javax.servlet.http.HttpSession; |
|
||||||
public class ExampleServlet extends HttpServlet { |
public class ExampleServlet extends HttpServlet { |
||||||
|
private static final long serialVersionUID = 1391640560504378168L; |
||||||
|
|
||||||
public void doGet(HttpServletRequest request, HttpServletResponse response) { |
public void doGet(HttpServletRequest request, HttpServletResponse response) { |
||||||
// 直接从request获取参数
|
// 直接从request获取参数
|
||||||
String param = request.getParameter("userId"); // Noncompliant {{建议将页面隐藏域字段、Cookie、URL等关键参数缓存到服务器端的会话中,并通过会话获取}}
|
String param = request.getParameter("userId"); // Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
|
||||||
|
request.getParameter("userpassword");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
|
||||||
|
request.getParameter("token");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
|
||||||
|
request.getParameter("url");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
|
||||||
// 直接从request获取Cookies
|
// 直接从request获取Cookies
|
||||||
Cookie[] cookies = request.getCookies(); |
Cookie[] cookies = request.getCookies();// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
|
||||||
// 将参数存储到session
|
// 将参数存储到session
|
||||||
HttpSession session = request.getSession(); |
HttpSession session = request.getSession(); |
||||||
session.setAttribute("sessionParam", param); |
session.setAttribute("sessionParam", param); |
||||||
// 其他代码...
|
// 其他代码...
|
||||||
} |
} |
||||||
|
|
||||||
private void get(HttpServletRequest request, HttpServletResponse response){ |
@RestController |
||||||
|
class TestController{ |
||||||
|
|
||||||
|
@GetMapping("/get") |
||||||
|
public void get(HttpServletRequest request){ |
||||||
|
String userId = request.getParameter("userId");// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
|
||||||
|
} |
||||||
} |
} |
||||||
} |
} |
@ -0,0 +1,64 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. |
||||||
|
* 项目名称:信息安全性设计准则检查插件 |
||||||
|
* 项目描述:用于检查源代码的安全性设计准则的Sonarqube插件 |
||||||
|
* 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 |
||||||
|
*/ |
||||||
|
|
||||||
|
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; |
||||||
|
|
||||||
|
import javax.servlet.*; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
import javax.servlet.http.HttpSession; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public class ExampleServlet { |
||||||
|
private static final long serialVersionUID = 1391640560504378168L; |
||||||
|
|
||||||
|
public class AuthenticationFilter implements Filter { |
||||||
|
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {// Noncompliant {{对用户进行身份鉴别并建立一个新的会话时让原来的会话失效}}
|
||||||
|
// HttpServletRequest request = (HttpServletRequest) req;
|
||||||
|
// boolean isValidUser = false;
|
||||||
|
// String username = request.getParameter("username");
|
||||||
|
// String password = request.getParameter("password");
|
||||||
|
// // 这里应通过相关业务逻辑来验证用户名和密码的准确性
|
||||||
|
isValidUser = UserService.validate(username, password); |
||||||
|
if (isValidUser) { |
||||||
|
HttpSession oldSession = request.getSession(false); |
||||||
|
if (oldSession != null) { |
||||||
|
oldSession.invalidate(); |
||||||
|
} |
||||||
|
HttpSession newSession = request.getSession(true); |
||||||
|
newSession.setMaxInactiveInterval(30 * 60); |
||||||
|
newSession.setAttribute("username", username); |
||||||
|
chain.doFilter(req, resp); // 继续执行下一个过滤器或请求
|
||||||
|
} else { |
||||||
|
request.getRequestDispatcher("/login.jsp").forward(request, resp); // 跳转到登录页面
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class AuthenticationInterceptor extends HandlerInterceptorAdapter { |
||||||
|
@Override |
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// Noncompliant {{对用户进行身份鉴别并建立一个新的会话时让原来的会话失效}}
|
||||||
|
boolean isValidUser = false; |
||||||
|
String username = request.getParameter("username"); |
||||||
|
String password = request.getParameter("password"); |
||||||
|
isValidUser = UserService.validate(username, password); |
||||||
|
if (isValidUser) { |
||||||
|
HttpSession oldSession = request.getSession(false); |
||||||
|
if (oldSession != null) { |
||||||
|
// oldSession.invalidate();
|
||||||
|
} |
||||||
|
HttpSession newSession = request.getSession(true); |
||||||
|
newSession.setMaxInactiveInterval(30 * 60); |
||||||
|
newSession.setAttribute("username", username); |
||||||
|
return true; // 继续下一个拦截器或请求处理器
|
||||||
|
} else { |
||||||
|
response.sendRedirect("/login.jsp"); // 跳转到登录页面
|
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
/* |
||||||
|
* 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; |
||||||
|
|
||||||
|
/** |
||||||
|
* TODO SessionCacheParamsCheckerTest |
||||||
|
* |
||||||
|
* @author RenFengJiang |
||||||
|
* @date 2024/1/24 |
||||||
|
*/ |
||||||
|
public class SessionCacheParamsCheckerTest { |
||||||
|
@Test |
||||||
|
public void test() { |
||||||
|
CheckVerifier.newVerifier() |
||||||
|
.onFile("src/test/files/SessionCacheParamsChecker.java") |
||||||
|
.withCheck(new SessionCacheParamsChecker()) |
||||||
|
.withClassPath(FilesUtils.getClassPath("target/test-jars")) |
||||||
|
.verifyIssues(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* |
||||||
|
* 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 RenFengJiang |
||||||
|
* @date 2024/1/24 |
||||||
|
*/ |
||||||
|
public class UserStatusVerifyCheckerTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
void detected() { |
||||||
|
|
||||||
|
CheckVerifier.newVerifier() |
||||||
|
.onFile("src/test/files/UserStatusVerifyChecker.java") |
||||||
|
.withCheck(new UserStatusVerifyChecker()) |
||||||
|
.withClassPath(FilesUtils.getClassPath("target/test-jars")) |
||||||
|
.verifyIssues(); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue