欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]J2EE漏洞与OWASP ESAPI修复方案之(URL_Redirection)

[原创]J2EE漏洞与OWASP ESAPI修复方案之(URL_Redirection)

一、  URL_Redirection漏洞介绍
这类漏洞,一般称之为url重定向或url跳转漏洞,利用这类漏洞可以用于网页钓鱼,设想下这种http://www.cmbchina.com/example.jsp?forward=http://40069911.jp/121.html发过来,保不准只关注到www.cmbchina.com,url重定向跳转类漏洞owasp官方定义为Unvalidated Redirects and Forwards,翻译成中文是“未经验证的重定向和转发”,漏洞介绍:https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet
    J2EE这类漏洞产生,引用owasp官方阐述,一般是由于采用了不安全的URL Redirects, 比如response.sendRedirect(url);或者采用了不安全的Forward,比如request.getRequestDispatcher(url).forward(request, response)。分别简单分析下:
ν  Dangerous URL Redirects
1)、Dangerous URL Redirect Example 1
response.sendRedirect(request.getParameter("url"));
2)、Dangerous URL Redirect Example 2:
某些MVC框架,可能直接封装了跳转方法:
[HttpPost]
 public ActionResult LogOn(LogOnModel model, string returnUrl)
 {
   if (ModelState.IsValid)
   {
     if (MembershipService.ValidateUser(model.UserName, model.Password))
     {
       FormsService.SignIn(model.UserName, model.RememberMe);
       if (!String.IsNullOrEmpty(returnUrl))
       {
         return Redirect(returnUrl);
       }
       else
       {
         return RedirectToAction("Index", "Home");
       }
     }
     else
     {
       ModelState.AddModelError("", "The user name or password provided is incorrect.");
     }
   }
   return View(model);
 }
ν  Dangerous Forward Example
public class ForwardServlet extends HttpServlet 
{
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String query = request.getQueryString();
    if (query.contains("url")) 
    {
      String url= request.getParameter("url");
      try 
      {
        request.getRequestDispatcher(url).forward(request, response);
      } 
      catch (ServletException e) 
      {
        e.printStackTrace();
      }
    }
  }
}
讨论下:request.getRequestDispatcher(url).forward(request, response)与response.sendRedirect(url)都可以跳转,是否都存在url重定向漏洞,需要对比分析一下,
OWASP官网介绍危险的forward样例时,提到了下面这段话,不知道大家有没有注意:

Dangerous Forward Example
When applications allow user input to forward requests between different parts of the site, the application must check that the user is authorized to access the url,
意思简单说就是forward一般用于应用中网站不同资源间转发请求,例如url=English.html表示英文页面,url=Chinese.html表示中文页面,admin.jsp表示后台页面,通过forward可以有效网站资源间跳转,
http://www.example.com/function.jsp?url=english.html
http://www.example.com/function.jsp?url=chinese.html http://www.example.com/function.jsp?url=admin.jsp 
说的很清楚forward()方法只能重定向到同一个Web应用程序中的某个资源,在资源跳转间需要考虑授权,防止非授权访问,forward()方法只能重定向到同一个Web应用程序中的某个资源,sendRedirect()方法可以让你重定向到任何URL。
二、安全修复方案
Preventing Unvalidated Redirects and Forwards
Safe use of redirects and forwards can be done in a number of ways: 
?  Simply avoid using redirects and forwards(1、尽量避免使用这两类)
?  If used, do not allow the url as user input for the destination. This can usually be done. In this case, you should have a method to validate URL(2、万一要用也可以,需要有个方法验证客户端传入的url参数有效性). 
?  If user input can’t be avoided, ensure that the supplied value is valid, appropriate for the application, and is authorized for the user. 
?  It is recommended that any such destination input be mapped to a value, rather than the actual URL or portion of the URL, and that server side code translate this value to the target URL. (3、需要考虑授权、映射表,不在讨论范畴)
?  Sanitize input by creating a list of trusted URL's (lists of hosts or a regex)(4、创建信任url白名单,主机列表、正则表达式). 
?  Force all redirects to first go through a page notifying users that they are going off of your site, and have them click a link to confirm(4、强制所有重定向先弹出通知,他们将关闭您的网站的用户页面,并让他们点击一个链接,确认、简单而言就是跳转前有个notice,告诉你前往xx站点,你点不点?). 
不知道是因为这类漏洞没代表性,还是没查到,查了下OWASP ESAPI的确没有针对类似漏洞的修复esapi介绍,一般有的话,都有类似这种参考修复:

自己动手吧,修复考虑两类情况:
1、  跳转只发生在同一网站内
修复方案1、直接建议使用request.getRequestDispatcher(url).forward(request, response)
这样接受进来的参数,也没法构造跳转到不可信网站链接(本网站某页面被挂马除外)
     String url= request.getParameter("url");
          try {
        request.getRequestDispatcher(url).forward(request, response);
      } catch (Exception e) {
        e.printStackTrace();
      }  
修复方案2-把传入的http|https过滤掉,没了http、https头跳转会404 error
String url=request.getParameter("url").toLowerCase();
    try {
      String safe=url.replaceAll("(http|https)", "");//没了http、https头跳转不了
      response.sendRedirect(safe);
    } catch (Exception e) {
      e.printStackTrace();
    }
2、  业务需要,需在不同网站间跳转,设置可信域名白名单,超出不让跳转
HashMap<String, String> extMap = new HashMap<String, String>();
    extMap.put("white_url", "www.sohu.com,www.baidu.com,sina.com,59.123.11.80:8080");//信任域名列表
    String url=request.getParameter("url")+"/".toLowerCase();
    int start = url.lastIndexOf("://");
    String input = url.substring(start+3).substring(0, url.substring(start+3).indexOf("/"));
    try {
      if (!Arrays.<String> asList(extMap.get("white_url").split(",")).contains(input)){
        response.getWriter().println("Invalid url_redirection...");
      }
      else{    
        response.sendRedirect(url);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

上传的附件 esapi.jpg

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功