这两天在网上看到一个在java中ssrf绕过的小trick,主要就是以黑名单过滤了file协议的情况下,如何绕过!
jdk:11.0.11
demo:
@RequestMapping("/ssrf")
public String ssrf(String url) {
String urlContent = "";
try {
// 检查URL是否以"file://"开头
if (url.startsWith("file://")) {
return "URL can't start with 'file://'";
}
// 读取URL内容
URL u = new URL(url);
BufferedReader in = new BufferedReader(new InputStreamReader(u.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
urlContent += inputLine + "\n";
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
return urlContent;
}
直接使用file协议,黑名单直接过滤,然后返回
poc:
url:file://xxx
成功读取到文件!
可以看到我们传入的路径url:file:///D://flag在经过URL()处理之后返回了file:///D://flag
new URL()的作用是创建一个 URL 对象,该对象表示一个统一资源定位符(URL)。在Java中,URL类提供了一种方便的方式来处理URL,可以用于定位到互联网上的各种资源,例如网页、图像、视频等。
通过
new URL(String spec)构造函数,可以将一个字符串形式的URL转换为URL对象。这个字符串通常包含了URL的各个组成部分,如协议、主机名、端口、路径等。
具体的绕过逻辑就在URL(String spec)中,Alt+Shift+F7跟进去瞅瞅,一路向下走到java.net.URL#URL(java.net.URL, java.lang.String, java.net.URLStreamHandler)
在593行这段代码是在检查 URL 字符串是否以 "url:" 开头,并在匹配成后start+4(此时start=4)
在603行,截取从start开始到了字符串 spec (即我们输入的地址url:file://xxx)的结尾或者下一个 / 字符,最终我们输入的url:file://xxx之类的构造会被解析为file
在对ssrf使用黑名单过过滤,我们可以使用正则匹配等手段来防御,但黑名单终归是不稳妥的!
想在java中若发起的请求时只支持使用HTTP/HTTPS协议,则可以使用以下几种方法!
HttpURLConnection
HttpClient
OkHttpClient.newCall.execute