SSRF
漏洞案例
漏洞描述
安全编码
SSRF(Server-Side Request Forgery) 服务器端请求伪造,是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。
【必须】避免直接访问不可信地址 1.服务器访问不可信地址时,禁止访问私有地址段及内网域名。 2.建议通过URL解析函数进行解析,获取host或者domain后通过DNS获取其IP,然后和内网地址进行比较。 3.对已校验通过地址进行访问时,应关闭跟进跳转功能。
运行
漏洞代码 - URLConnection方式
// url参数没做限制,可调用URLConnection发起任意请求,比如请求内网,或使用file等协议读取文件 public static String URLConnection(String url) { try { URL u = new URL(url); URLConnection conn = u.openConnection(); BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); String content; StringBuffer html = new StringBuffer(); while ((content = reader.readLine()) != null) { html.append(content); } reader.close(); return html.toString(); } catch (Exception e) { return e.getMessage(); } }
运行
漏洞代码 - 短链接绕过
// SSRF修复经常碰到的问题,虽然过滤了内网地址,但通过短链接跳转的方式可以绕过 public String URLConnectionSafe(String url) { if (!Security.is_http(url)){ return "不允许非http/https协议!!!"; }else if (Security.isIntranet(url)) { return "不允许访问内网!!!"; }else{ return Http.URLConnection(url); } }
运行
安全代码
// 判断是否是http类型 public static boolean isHttp(String url) { return url.startsWith("http://") || url.startsWith("https://"); } // 判断是否为内网 public static boolean isIntranet(String url) { Pattern reg = Pattern.compile("^(127\\.0\\.0\\.1)|(localhost)|(10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})|(172\\.((1[6-9])|(2\\d)|(3[01]))\\.\\d{1,3}\\.\\d{1,3})|(192\\.168\\.\\d{1,3}\\.\\d{1,3})$"); Matcher match = reg.matcher(url); Boolean a = match.find(); return a; } // 不允许跳转或判断跳转 HttpURLConnection conn = (HttpURLConnection) u.openConnection(); conn.setInstanceFollowRedirects(false); // 不允许重定向或者对重定向后的地址做二次判断 conn.connect();