java之url任意跳转漏洞

1 漏洞介绍

URLRedirect url重定向漏洞也称url任意跳转漏洞,网站信任了用户的输入导致恶意攻击,url重定向主要用来钓鱼,比如url跳转中最常见的跳转在登陆口,支付口,也就是一旦登陆将会跳转任意自己构造的网站,如果设置成自己的url则会造成钓鱼。url跳转常见的地方包括:

  1. 登陆跳转我认为是最常见的跳转类型,认证完后会跳转,所以在登陆的时候建议多观察url参数

  2. 用户分享、收藏内容过后,会跳转

  3. 跨站点认证、授权后,会跳转

  4. 站内点击其它网址链接时,会跳转

  5. 在一些用户交互页面也会出现跳转,如请填写对客服评价,评价成功跳转主页,填写问卷,等等业务,注意观察url。

  6. 业务完成后跳转这可以归结为一类跳转,比如修改密码,修改完成后跳转登陆页面,绑定银行卡,绑定成功后返回银行卡充值等页面,或者说给定一个链接办理VIP,但是你需要认证身份才能访问这个业务,这个时候通常会给定一个链接,认证之后跳转到刚刚要办理VIP的页面。

    2 审计方法

    结合业务场景,通过关键字在web层(Controller、Servlet类文件)中搜索一下关键字,确定漏洞的依据就是看是否直接转发、直接跳转、直接重定向的目的URL是源于前端且没有处理。常见关键字如下:

    • redirect

    • url

    • redirectUrl

    • callback

    • return_url

    • toUrl

    • ReturnUrl

    • fromUrl

    • redUrl

    • request

    • redirect_to

    • redirect_url

    • jump

    • jump_to

    • target

    • to

    • goto

    • linklinkto

    • domain

    • oauth_callback

    3 审计案例

    3.1 案例1-302 redirect

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/urlRedirection/setHeader" method="get" enctype="multipart/form-data">
            <input type="text" name="url" >
            <input type="submit">
        </form>
    </body>
    </html>
    复制代码
    @Controller
    @RequestMapping("/urlRedirection")
    public class URLRedirectionController {
    ​
        //去重定向前端页面
        @GetMapping("/toRedirectPage")
        public String toRedirectPage(){
            System.out.println("重定向漏洞页面");
            return "Demo13";
        }
    //302跳转
    @GetMapping("/urlRedirection")
        public void urlRedirection(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String url = request.getParameter("url");
        response.sendRedirect(url);
        }
    }

    通过上述代码,能够得出,urlRedirection方法接收了源于form表单的参数后直接通过

    response.sendRedirect(url)重定向,也就是说直接访问了来自前端url参数的url。

    当提交之后会直接跳转到百度页面,因此具有一定的风险性

    需要注意的是外部网址必须加http.www,只写域名仍然在改服务器上

    3.2 案例2-301 redirect

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/urlRedirection/setHeader" method="get" enctype="multipart/form-data">
            <input type="text" name="url" >
            <input type="submit">
        </form>
    </body>
    </html>
    复制代码
        //去重定向前端页面
        @GetMapping("/toRedirectPage")
        public String toRedirectPage(){
            System.out.println("重定向漏洞页面");
            return "Demo13";
        }
        @RequestMapping("/setHeader")
        @ResponseBody
        public static void setHeader(HttpServletRequest request, HttpServletResponse response) {
            String url = request.getParameter("url");
            response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // 301 redirect
            response.setHeader("Location", url);
        }

    同案例1的失效效果一样,只不过是后端发生跳转的类型不一致而已。

    3.3 案例3-urlRedirection重定向

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/urlRedirection/setHeader" method="get" enctype="multipart/form-data">
            <input type="text" name="url" >
            <input type="submit">
        </form>
    </body>
    </html>
    复制代码
    @GetMapping("/redirect")
    public String redirect(@RequestParam("url") String url) {
    return "redirect:" + url;
    }

    同案例1、2的效果一样,只不过是后端发生跳转的类型不一致而已。初次外获取参数的形式不一样,通过注解获取的。

    四、修复意见(二选一)

    1、将重定向改成转发

    转发(前往),服务器内部的重定向,在Servlet中通过RequestDispatcher转发给另一个程序处理请

    求,请求的数据依然在。所以forward相当于客户端向服务器发送一次请求,服务器处理两次,请求数

    据不会消失且URL地址只变化一次。因为转发只能在服务器内部进行(内部跳转),不会跳转到外

    部。参考代码如下:

    复制代码
    <%@ page contentType="text/html; charset=UTF-8" %>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/urlRedirection/forward" method="get" enctype="multipart/form-data">
            <input type="text" name="url" >
            <input type="submit">
        </form>
    </body>
    </html>
    复制代码
        @RequestMapping("/forward")
        @ResponseBody
        public static void forward(HttpServletRequest request, HttpServletResponse response) {
            String url = request.getParameter("url");
            RequestDispatcher rd = request.getRequestDispatcher(url);
            try {
                rd.forward(request, response);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    此时在提交百度一下,你就知道,发现无法跳转成功

    2、白名单与黑名单相结合的限制

    就是将需要重定向的目的URL整理成白名单,在进行重定向前匹配,如果不在白名单中禁止重定向。

    相关白名单校验参考代码如下:

    复制代码
        /**
         * 同时支持一级域名和多级域名,相关配置在resources目录下url_safe_domain.xml文件。
         * 优先判断黑名单,如果满足黑名单return null。
         *
         * @param url the url need to check
         * @return Safe url returns original url; Illegal url returns null;
         */
        public String checkURL(String url) throws IOException {
            if (null == url){
                return null;
            }
            try {
                URL url1 = new URL(url);
                String host = url1.getHost();
                // 必须http/https
                if (!url1.getProtocol().equals("https") && !url1.getProtocol().equals("http")) {
                    return null;
                }
    ​
                // 如果满足黑名单返回null
                if (blackDomains.contains(host)){
                    return null;
                }
                for(String blockDomain: blackDomains) {
                    if(host.endsWith("." + blockDomain)) {
                        return null;
                    }
                }
    ​
                // 支持多级域名
                if (safeDomains.contains(host)){
                    return url;
                }
    ​
                // 支持一级域名
                for(String safedomain: safeDomains) {
                    if(host.endsWith("." + safedomain)) {
                        return url;
                    }
                }
                return null;
            } catch (NullPointerException | MalformedURLException e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    ​

    例如黑名单和白名单的配置如下

    复制代码
    safeDomains=127.0.0.1,127.0.0.2
    blackDomains=baidu.com,qq.com

    当输入baidu.com时,将无法跳转。

    当将baidu.com添加到白名单,同时从黑名单中剔除出去,将成功跳转

相关推荐
l1x1n017 分钟前
No.2 笔记 | 网络安全攻防:PC、CS工具与移动应用分析
安全·web安全
guanyue.space5 小时前
网站可疑问题
web安全
小小工匠6 小时前
Web安全 - 路径穿越(Path Traversal)
安全·web安全·路径穿越
鲨鱼辣椒丶D8 小时前
「漏洞复现」用友U8 CRM config/fillbacksettingedit.php SQL注入漏洞
web安全
火红的小辣椒20 小时前
XSS基础
android·web安全
Z3r4y21 小时前
【Web】portswigger 服务端原型污染 labs 全解
javascript·web安全·nodejs·原型链污染·wp·portswigger
小镇航海家1 天前
红日靶场1学习笔记
网络·笔记·学习·web安全·渗透测试
你怎么睡得着的!1 天前
【web安全】——XSS漏洞
安全·web安全·xss