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 javax.servlet.http.HttpServlet; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import javax.servlet.http.HttpSession; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import javax.servlet.http.*; |
||||
|
||||
public class ExampleServlet extends HttpServlet { |
||||
private static final long serialVersionUID = 1391640560504378168L; |
||||
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) { |
||||
// 直接从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
|
||||
Cookie[] cookies = request.getCookies(); |
||||
Cookie[] cookies = request.getCookies();// Noncompliant {{页面隐藏域字段、Cookie、URL等关键参数不能直接获取,应缓存到服务器端的会话中并通过会话获取}}
|
||||
// 将参数存储到session
|
||||
HttpSession session = request.getSession(); |
||||
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