前言
工作中渗透测试检测出,越权漏洞进行修复的记录。一、越权漏洞是什么?
越权操作类型包含:横向越权操作和纵向越权操作。本次测试中验证出存在纵向越权,指的是一个低级别攻击者非法访问高级别用户的资源,如图所示的情况。
二、给出的修复建议
遍历检查各功能接口(如查询、新增、注册账号、密码重置等功能接口)的授权和鉴权情况,完善session认证机制,做到举一反三。应严格执行session认证机制,使用session对用户的身份进行判断和控制,对用户操作进行权限校验,防止通过修改参数进入未授权页面及进行非法操作。
严格对用户操作进行权限校验,防止通过修改参数进入未授权页面及进行非法操作,建议在服务端对请求的数据和当前用户身份做校验检查。流程描述:在服务器接收到用户发送的页面访问请求时,根据预设的识别策略,从用户的页面访问请求中提取该用户对应的用户唯一标识信息,同时提取所述页面访问请求对应的应答页面中的表单及该表单中不可修改参数,将所述表单及不可修改参数与所述用户唯一标识信息绑定后记录到参数列表中;检测到用户提交请求页面的表单时,将所述请求页面的表单及不可修改参数与该用户对应的所述参数列表中记录的表单及不可修改参数进行比对,控制该用户的访问。
三、修复过程
1、准备过滤器
public class UserServiceValidateFilter implements Filter {
private final Logger logger = LogManager.getLogger(UserServiceValidateFilter.class);
private OrRequestMatcher orRequestMatcher;
/**
* 不需要被过滤器拦截的页面 ,主要用于静态资源的放行
* 在web.xml中配置filter的init-param
*/
private String excludedPaths;
private String [] excludedPathArray;
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
//自定义过滤器处理逻辑
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化时读取web.xml中配置的init-param
excludedPaths = filterConfig.getInitParameter("excludedPaths");
if(!StringUtils.isEmpty(excludedPaths)){
excludedPathArray = excludedPaths.split(",");
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 判断是否是直接放行的请求
if (!isFilterExcludeRequest(request)) {
//System.out.println("进行鉴权过滤器处理逻辑,url:"+request.getRequestURL());
// 这里写你的过滤器处理逻辑
doFilterInternal(request, response, chain);
} else {
//放行
//System.out.println("鉴权过滤器放行连接,url:"+request.getRequestURL());
chain.doFilter(servletRequest,servletResponse);
}
}
@Override
public void destroy() {
}
public OrRequestMatcher getOrRequestMatcher() {
return orRequestMatcher;
}
public void setOrRequestMatcher(OrRequestMatcher orRequestMatcher) {
this.orRequestMatcher = orRequestMatcher;
}
/**
* 判断是否是 过滤器直接放行的请求
* 主要用于静态资源的放行
* @return
*/
private boolean isFilterExcludeRequest(HttpServletRequest request) {
if(null != excludedPathArray && excludedPathArray.length > 0) {
String url = request.getRequestURI();
for (String ecludedUrl : excludedPathArray) {
if (ecludedUrl.startsWith("*.")) {
// 如果配置的是后缀匹配, 则把前面的*号干掉,然后用endWith来判断
if(url.endsWith(ecludedUrl.substring(1))){
return true;
}
} else if (ecludedUrl.endsWith("/*")) {
if(!ecludedUrl.startsWith("/")) {
// 前缀匹配,必须要是/开头
ecludedUrl = "/" + ecludedUrl;
}
// 如果配置是前缀匹配, 则把最后的*号干掉,然后startWith来判断
String prffixStr = request.getContextPath() + ecludedUrl.substring(0, ecludedUrl.length() - 1);
if(url.startsWith(prffixStr)) {
return true;
}
} else {
// 如果不是前缀匹配也不是后缀匹配,那就是全路径匹配
if(!ecludedUrl.startsWith("/")) {
// 全路径匹配,也必须要是/开头
ecludedUrl = "/" + ecludedUrl;
}
String targetUrl = request.getContextPath() + ecludedUrl;
if(url.equals(targetUrl)) {
return true;
}
}
}
}
return false;
}
}
2、配置不需要被过滤器拦截的链接
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--用户请求权限过滤-->
<filter>
<filter-name>userServiceValidateFilter</filter-name>
<filter-class>xxx.xxx.xxx.xxx.UserServiceValidateFilter</filter-class>
<init-param>
<!-- 配置不需要被过滤器拦截的链接,只支持配后缀、前缀 及全路径,多个配置用逗号分隔 -->
<param-name>excludedPaths</param-name>
<param-value>*.css,*.html,*.js,*.ico,*.png,*.jsp,*.woff,*.woff2,*.ttf</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>userServiceValidateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3、注册过滤器
@Bean
public FilterRegistrationBean<UserServiceValidateFilter> userServiceValidateFilterFilterRegistrationBean() {
FilterRegistrationBean<UserServiceValidateFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new UserServiceValidateFilter());
registrationBean.addUrlPatterns("/*"); // 这里配置需要过滤的URL
registrationBean.setName("userServiceValidateFilter");
registrationBean.setOrder(2); // 设置过滤器的执行顺序,数字越小越优先
return registrationBean;
}