Java 目录遍历安全问题

Java 目录遍历安全问题,java,security,Java,Security,我有一个Java webapp,它容易受到通过URL编码的目录横向(也称为路径横向)攻击。认证后: 如果我打了http://localhost:8080/Web/WEB-INF/web.xml,我得到一个404(这很好) 如果我击中http://localhost:8080/Web/%c0%ae/WEB-INF/web.xml,我可以读取文件(这显然不好) 根据Servlet规范,WEB-INF文件夹不应该公开访问,但在这种情况下它可以工作。 我将WebSphere5.1与Java1.4、Spr

我有一个Java webapp,它容易受到通过URL编码的目录横向(也称为路径横向)攻击。认证后:

如果我打了http://localhost:8080/Web/WEB-INF/web.xml,我得到一个404(这很好)
  • 如果我击中http://localhost:8080/Web/%c0%ae/WEB-INF/web.xml,我可以读取文件(这显然不好)
  • 根据Servlet规范,WEB-INF文件夹不应该公开访问,但在这种情况下它可以工作。 我将WebSphere5.1与Java1.4、SpringSecurity2.0.5和Struts1.3一起使用。 从我所读到的,它似乎与UTF-8中的编码有关,%c0%ae是“.”(点)

    我在一个不同的webapp上尝试了同样的方法,这个webapp运行在不同的环境中(Tomcat6与Java7、SpringSecurity3和SpringMVC),但我无法重现这个问题。第二个webapp有一个过滤器,用于强制对UTF-8中的页面进行编码(
    org.springframework.web.filter.CharacterEncodingFilter
    ),因此我在第一个webapp上尝试了相同的配置,但没有成功。 有什么想法吗


    谢谢。

    过滤器更改请求正文的字符编码,而不是URL

    要在tomcat中设置URL编码,需要在server.xml元素中添加一个属性:

    <Connector port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               URIEncoding="UTF-8"
               redirectPort="8443" />
    

    您可以在这些请求到达Websphere之前通过另一个Web服务器/appserver或代理服务器修复或拒绝这些请求。要么是另一个Java应用服务器,要么可能是类似于或的东西,都可以做到这一点

    当然,真正的解决方案是升级。这只是一个可以被颠覆的创可贴。“修复”安全问题的方法确实是错误的。

    如果您无法升级(古老的WebSphere+Java 1.4,哎哟!),一个可能的解决方法(实际上更像是黑客解决方法)是编写一个简单的过滤器,映射到每个请求,进行适当的字符集转换并拒绝无效的请求

    我相信,通过一些挖掘,您可以找到一个检查您可能没有想到的事情的实现

    当然,这仍然会留下8年的其他安全问题(更不用说生产率了)

    哎呀
    没有注意到没有注意到这个问题有多老。

    我要回答我自己的问题。
    因此,在有限的选项下,我最终要做的是在Spring安全配置文件中添加一条安全规则,如

    <sec:intercept-url pattern="/**/WEB-INF/**" access="no-access"/>
    
    
    

    它将对WEB-INF的访问限制为“无访问”角色,而实际上该角色不是一个角色。这将阻止访问所有用户。这并不理想,但在升级之前,它会起作用。

    这是我的实现

    import java.io.IOException;
    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;
    
    /**
     *
     * @author davidandrade
     */
    public class RestrictURL implements Filter {
    
        private FilterConfig fcgConfFiltr_t;
    
        private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(RestrictURL.class.getName());
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            fcgConfFiltr_t = filterConfig;
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse res = (HttpServletResponse) response;
            String strUrlPetici_t = req.getRequestURL().toString();
            String strUrlBase___t = strUrlPetici_t.substring(0, strUrlPetici_t.indexOf(fcgConfFiltr_t.getServletContext().getContextPath()) + fcgConfFiltr_t.getServletContext().getContextPath().length());
    
            try {
    
                res.addHeader("X-Frame-Options", "SAMEORIGIN");
                log.info("URL Req: " + strUrlPetici_t);
    
                if (strUrlPetici_t.toLowerCase().contains("%co") || strUrlPetici_t.toLowerCase().contains("%ae")) {
                    sendErrorRedirect(req, res, "/404.jsf", new Exception("DirectoryTransversalRequired"));
                } else {
                    try {
                        fcgConfFiltr_t.getServletContext().getRequestDispatcher(strUrlPetici_t).forward(request, response);
                    } catch (IllegalArgumentException e) {
                        chain.doFilter(request, response);
                    }
                }
    
            } catch (Exception e) {
                log.error("", e);
                sendErrorRedirect(req, res, "/404.jsf", e);
    
            }
        }
    
        protected void sendErrorRedirect(HttpServletRequest request, HttpServletResponse response, String errorPageURL, Throwable e) throws ServletException, IOException {
            request.setAttribute("exception", e);
            fcgConfFiltr_t.getServletContext().getRequestDispatcher(errorPageURL).forward(request, response);
        }
    
        @Override
        public void destroy() {
            fcgConfFiltr_t = null;
        }
    
    }
    
    并将筛选器添加到my web.xml

    <filter>
            <filter-name>DirectoryTransversalFilter</filter-name>
            <filter-class>com.sec.RestrictURL</filter-class> <!-- mandatory -->
        </filter>
        <filter-mapping>
            <filter-name>DirectoryTransversalFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
    
    直接横向滤波器
    com.sec.RestrictURL
    直接横向滤波器
    /*
    
    您有没有办法在将要部署的系统上更新Spring和/或Java版本?听起来像CVE-2010-3700不幸的是不是,这不在我的控制之下。那么我建议限量发布。这是这个版本的一个已知问题,如果客户不升级到新版本,他将不得不忍受它给他带来的麻烦。我知道不是很有用。对不起,也许其他人会想出一些办法。我可以看出这确实是一个已知的问题。谢谢,Eduard。运行具有许多已发布漏洞的旧版本软件可能不是最好的主意。谢谢Maurice,但是Websphere中是否有类似的软件?不幸的是,我没有添加此类组件的选项。但是,如何确定请求无效?您是否需要手动更新此类请求的列表?您可能还应该为META-INF添加一个规则。您可以在META-INF中定义安全规则?这是如何工作的?不,我的意思是你应该使用相同类型的规则来阻止对META-INF的访问,而不仅仅是WEB-INF。