Headline
CVE-2022-23553: Alpine/WhitelistUrlFilter.java at alpine-parent-1.10.2 · stevespringett/Alpine
Alpine is a scaffolding library in Java. Alpine prior to version 1.10.4 allows URL access filter bypass. This issue has been fixed in version 1.10.4. There are no known workarounds.
/* * This file is part of Alpine. * * Licensed under the Apache License, Version 2.0 (the “License”); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an “AS IS” BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 * Copyright © Steve Springett. All Rights Reserved. */ package alpine.filters; import org.apache.commons.lang3.StringUtils; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; /** * WhitelistUrlFilter is a configurable Servlet Filter that can prevent access to * specific URLs. The filter will ignore access to all URLs that are not specifically * whitelisted. Ignored URLs result in a HTTP 404 response. * * The filter may be used when specific files or directories should not be accessible. * In the case of executable WARs, use of this filter is highly recommended since * executable WARs must meet the requirements of both JAR and WAR files, thus placing * compiled classes and their package structure inside the document webroot. * * Sample usage: * <pre> * <filter> * <filter-name>WhitelistUrlFilter</filter-name> * <filter-class>alpine.filters.WhitelistUrlFilter</filter-class> * <init-param> * <param-name>allowUrls</param-name> * <param-value>/images,/css</param-value> * </init-param> * </filter> * * <filter-mapping> * <filter-name>WhitelistUrlFilter</filter-name> * <url-pattern>/*</url-pattern> * </filter-mapping> * * </pre> * * Optionally, the forwardTo parameter can be specified to instruct the * WhitelistUrlFilter to forward the request to a URL of another Servlet, * JSP, or HTML file should the originally requested URL not be whitelisted. * This may be necessary in some Single Page Applications (SPA). * * @author Steve Springett * @since 1.0.0 */ public final class WhitelistUrlFilter implements Filter { private String[] allowUrls = {}; private String[] forwardExcludes = {}; private String forwardTo = null; /** * Initialize “allowUrls” parameter from web.xml. * * @param filterConfig A filter configuration object used by a servlet container * to pass information to a filter during initialization. */ public void init(final FilterConfig filterConfig) { final String allowParam = filterConfig.getInitParameter(“allowUrls”); if (StringUtils.isNotBlank(allowParam)) { this.allowUrls = allowParam.split(“,”); } final String forwardExcludesParam = filterConfig.getInitParameter(“forwardExcludes”); if (StringUtils.isNotBlank(forwardExcludesParam)) { this.forwardExcludes = forwardExcludesParam.split(“,”); } final String forwardToParam = filterConfig.getInitParameter(“forwardTo”); if (StringUtils.isNotBlank(forwardToParam)) { this.forwardTo = forwardToParam; } } /** * Check for allowed URLs being requested. * * @param request The request object. * @param response The response object. * @param chain Refers to the {@code FilterChain} object to pass control to the next {@code Filter}. * @throws IOException a IOException * @throws ServletException a ServletException */ public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { final HttpServletRequest req = (HttpServletRequest) request; final HttpServletResponse res = (HttpServletResponse) response; final String requestUri = req.getRequestURI(); if (requestUri != null) { boolean allowed = false; final String requestUrlExcludingContext = requestUri.substring(req.getContextPath().length()); for (final String url: allowUrls) { if (requestUrlExcludingContext.equals(“/”)) { if (url.trim().equals(“/”) || (url.trim().equals(“/index.jsp”)) || (url.trim().equals(“/index.html”))) { allowed = true; } } else if (requestUrlExcludingContext.startsWith(url.trim())) { allowed = true; } } if (!allowed) { if (forwardTo != null) { for (final String url: allowUrls) { if (forwardExcludes != null && Arrays.stream(forwardExcludes).anyMatch(url::equals)) { break; } final int occurrence = requestUrlExcludingContext.indexOf(url); if (occurrence > -1) { final String queryString = (req.getQueryString() == null) ? “” : “?” + req.getQueryString(); final String resourceUrl = requestUrlExcludingContext.substring(occurrence) + queryString; req.getRequestDispatcher(resourceUrl).forward(request, response); return; } } req.getRequestDispatcher(forwardTo).forward(request, response); } else { res.setStatus(HttpServletResponse.SC_NOT_FOUND); } return; } } chain.doFilter(request, response); } private boolean isExcludedForwardPath(String url) { return Arrays.stream(forwardExcludes).anyMatch(url::equals); } /** * {@inheritDoc} */ public void destroy() { } }
Related news
Alpine is a scaffolding library in Java. Alpine prior to version 1.10.4 allows URL access filter bypass. This issue has been fixed in version 1.10.4. There are no known workarounds.