JavaWeb中的URL Redirect

  • A+

  一般服务端未对传入的跳转url变量进行检查和控制,可能导致可恶意构造任意一个恶意地址,诱导用户跳转到恶意网站。由于是从可信的站点跳转出去的,造成钓鱼风险;也可能引发的XSS漏洞(主要是跳转常常使用302跳转,即设置HTTP响应头,Location:url,如果url包含了CRLF,则可能隔断了HTTP响应头,从而导致xss漏洞)。

重定向原理

  具体的过程如下:

  客户端浏览器发送http请求->web服务器接受后发送302状态码响应及对应新的location给浏览器->浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址->服务器根据此请求寻找资源并发送给客户端,在这里location可以重定向到任意URL。

  重定向响应格式如下:

图片.png

常见功能点

  • 用户登录、统一身份认证处,认证完了会通过url=的形式跳转到类似操作的页面。
  • 用户分享、收藏内容后,跳转。
  • 跨域认证授权后会进行跳转。
  • ......

审计思路

  首先肯定是快速定位可能存在redirect业务的代码段,可以通过常见的参数,或者是常见实现方法的关键字进行定位。定位到业务代码后,如果跳转的url可控且缺少安全防护,那么就很可能存在缺陷了。

常见参数

redirect
redirect_do
redirect_url
url
jump
jump_to
target
to
link
domain

常见的Redirect方式

HttpServletResponse跳转

  HttpServletResponse中的sendRedirect()方法的作用是重定向,向浏览器发送一个特殊的Header,然后由浏览器来做重定向,转到指定的页面。

java
@RequestMapping("payforward/{contNo}")
public void payforward(@PathVariable("contNo") String contNo,String url,HttpServletRequest req, HttpServletResponse resp) throws Exception {
resp.sendRedirect(url+"?contNo="+contNo);
}

  当然也可以简单的使用如下方式进行跳转:

java
String target = request.getParameter("url");
response.setStatus(302);
response.setHeader("Location", target);

通过ModelAndView跳转

  在SpringMVC中,当controller中的方法返回ModelAndView的时候,默认是使用的转发。那么可以在指定的视图前添加redirect:来进行跳转。此时springmvc.xml配置文件中的视图解析器将会失效。例如下面的例子:

java
@RequestMapping("alipayforward")
public ModelAndView alipayforward(@PathVariable("contNo") String contNo,String url) throws Exception {
String url = "redirect:"+url+"?contNo="+contNo;
return new ModelAndView(url);
}

  当然了也可以返回String类型的重定向:

java
@RequestMapping("/redirectStr.do")
public String redirectStr(String url)throws Exception{
return "redirect:"+url;
}

Struts2中的Redirect

  Struts2配置中result参数的redirect类型同样也是是调用HttpServletResponse的sendRedirect(String)方法来重定向到指定的资源。例如如下struts2.xml的配置,设置redirect类型后,通过在<param name="location">中接受Action传递的地址,当Action中的execute()方法返回success时,即可进行重定向:

图片.png

  Action中的内容:

```java
public class DemoAction implements Action{

private String redirectURL;
public String getRedirectURL() {
    return redirectURL;
}
public void setRedirectURL(String redirectURL) {
    this.redirectURL = redirectURL;
}
@Override
public String execute() throws Exception {

    return SUCCESS;
}

}
```

  当然也可以使用注解的方式,进行定义:

@Result(name="",type="redirect",location="指定前往的地址。可以是一个view,也可以是一个action。")
  此外还需要注意st-017漏洞,其中并没有检查redirect的location值,只是直接将location直接添加到响应的HTTP 302跳转请求头中,所以导致了URL跳转漏洞,影响范围为Struts 2.3.15.1之前的所有版本。

<c:redirect>标签

  JSP标签库中的<c:redirect/>标签通过自动重写URL来将浏览器重定向至一个新的URL,它提供内容相关的URL,并且支持c:param标签。语法格式如下:

图片.png

  其中的url参数代表需要跳转的目标url,例如下面的例子会跳转到https://www.sec-in.com/

图片.png

利用JavaScript动态跳转

  jsp中常用到js来跳转页面,最常见的就是location.href,例如在当前页面重定向到新的URL页面:

self.location.href="url"
location.href="url"
windows.location.href="url"

  一般是在服务器端设置对应的url,然后封装在对应的域中(例如request),然后在jsp中通过EL表达式从对应的域中取值,设置对应的跳转url触发对应的方法后即可跳转,例如:

图片.png

相关案例

  系统设置了相关的重定向接口,从前端获取url参数,然后进行DES解密,然后封装在modelView中,然后跳转到view层:

java
@GetMapping("/redirectPage")
public String redirectPage(ModelMap model,String url,String storeName){
try{
storeName = URLEncoder.encode(storeName,"utf-8");
String key = "security";
EncryptUtil des = new EncryptUtil(key,"utf-8");
url=des.decode(url);
}catch(Exception e){
e.printStackTrace();
url="error";
}
model.addAttribute("url",url);
model.addAttribute("storeName",storeName);
return "/common/redirect"
}

  整个过程没有相应的安全防护,View层通过获取ModelMap封装在requset域的url参数和值,通过location.href进行相应的跳转,虽然url是加密传输的,可以尝试结合js,使用相应加密算法生成相关的恶意url,达到任意URL Redirect效果:

图片.png

修复建议

  • 对传入的URL做认证处理,保证该URL来自于信任域。例如如下方式:

 1.通过限制Referer保证将要跳转URL的有效性,避免攻击者生成自己的恶意跳转链接。

 2.加入有效性验证Token,保证所有生成的链接都来自于可信域,通过在生成的链接里加入用户不可控的Token对生成的链接进行校验。

  • 关键参数前端不可控
  • 对跳转的URL进行白名单检查

相关推荐: 从安全角度谈Java反射机制--序章

前言    众所周知,Java目前影响最大的是反序列化漏洞,换一句话说Java安全是从反序列化漏洞开始,但反序列化漏洞又可以基于反射,这次笔者带你走进Java安全的大门。    Java反序列化的payload大多与反射…