目录遍历安全问题

时间:2011-06-01 18:05:47

标签: 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文件夹不应该公开访问,但在某种程度上它适用于这种情况。 我正在使用带有Java 1.4,Spring Security 2.0.5和Struts 1.3的Websphere 5.1。 从我读到的,它似乎与编码有关,%c0%ae是'。' (点)UTF-8。

我在另一个运行在不同环境(使用Java 7,Spring Security 3和Spring MVC的Tomcat 6)的webapp上尝试了同样的事情,但我无法重现这个问题。第二个webapp有一个过滤器强制编码UTF-8页面(org.springframework.web.filter.CharacterEncodingFilter),所以我在第一个webapp上尝试了相同的配置,但它没有做到这一点。 有什么想法吗?

感谢。

5 个答案:

答案 0 :(得分:2)

我将回答我自己的问题 因此,由于我的选择有限,我最终做的是在Spring Security配置文件中添加一个安全规则,例如

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

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

答案 1 :(得分:1)

您可以在通过其他网络服务器/应用服务器或Web application firewalls代理这些请求之前修复或拒绝这些请求。另一个Java应用服务器或类似NginxVarnish之类的东西可以做到这一点。

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

答案 2 :(得分:0)

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

要在tomcat中设置URL编码,您需要在&lt; Connector&gt;中添加属性。 server.xml的元素:

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

答案 3 :(得分:0)

如果你无法升级(古老的WebSphere + Java 1.4,哎哟!),一种可能的解决方法(更多的是hackaround,真的)是编写一个简单的过滤器,映射到每个请求,执行正确的字符集转换和拒绝无效请求。

我确信通过一些挖掘你可以找到一个实现来检查你可能没有想过的事情。

当然,这仍然会带来8年的其他安全性(更不用说生产力)问题。

糟糕

没有注意到没有注意到问题的年龄。

答案 4 :(得分:0)

这是我的实施

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;
    }

}

并将过滤器添加到我的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>