Java audit SSRF
Java audit SSRF
0x00 Preface
This article will record the audit learning related content of Java SSRF.
0x01 SSRF vulnerability details
Principle:
The server provides the function of obtaining data from other server applications without filtering and limiting the target address.
In most web server architectures, the web server itself can access the Internet and the intranet where the server is located.
SSRF function:
Scan the internal network and local port of the external network server to obtain the banner information of some services.
Attack applications running on the intranet or local.
Fingerprint identification of Intranet web application is realized by accessing the default file.
Attack web applications inside and outside the network. SQL injection, struct2, redis, etc.
Use File protocol to read local files, etc.
Pseudo protocol in PHP SSRF:
file dict sftp ldap tftp gopher
Pseudo protocol in Java SSRF:
file ftp mailto http https jar netdoc
0x02 SSRF generation process
In Java, SSRF can be divided into many scenarios. Unlike PHP, it supports various pseudo protocols and can be used directly.
Intranet detection in SSRF
@WebServlet("/ssrfServlet")
public class ssrfServlet extends HttpServlet {
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
this.doGet(request,response);
}
protected void doGet(HttpServletRequest request,IOException {
String url = request.getParameter("url"); //接收url的传参
String htmlContent;
PrintWriter writer = response.getWriter(); //获取响应的打印流对象
URL u = new URL(url); //实例化url的对象
try {
URLConnection urlConnection = u.openConnection();//打开一个URL连接,并运行客户端访问资源。
HttpURLConnection httpUrl = (HttpURLConnection) urlConnection; //强转为HttpURLConnection
BufferedReader base = new BufferedReader(new InputStreamReader(httpUrl.getInputStream(),"UTF-8")); //获取url中的资源
StringBuffer html = new StringBuffer();
while ((htmlContent = base.readLine()) != null) {
html.append(htmlContent); //htmlContent添加到html里面
}
base.close();
writer.println(html);//响应中输出读取的资源
writer.flush();
} catch (Exception e) {
e.printStackTrace();
writer.println("请求失败");
writer.flush();
}
}
In the code, httpurlconnection httpurl = (httpurlconnection) urlconnection;, This place was forcibly converted, and I went to a certain degree to search for the specific purpose. come to conclusion:
URLConnection:可以走邮件、文件传输协议。
HttpURLConnection 只能走浏览器的HTTP协议
In other words, after the strong conversion to httpurlconnection is used, only HTTP protocol can be used to detect other applications in the server's intranet.
http://localhost:8080/ssrfServlet?url=http://www.baidu.com
Here we use Baidu to do a demonstration, because we are too lazy to build an environment in the intranet.
In the code, we did not verify the received URL. We directly created a URL object to access and read resources without verifying whether the URL is a whitelist URL, resulting in the generation of SSRF.
Try to read the file
You will find that you can't read it at all, because only HTTP and HTTPS protocols are supported here.
Let's try it. Try it without forcing it to httpurlconnection.
The code is as follows:
@WebServlet("/ssrfServlet")
public class ssrfServlet extends HttpServlet {
protected void doPost(HttpServletRequest request,IOException {
String url = request.getParameter("url"); //接收url的传参
String htmlContent;
PrintWriter writer = response.getWriter(); //获取响应的打印流对象
URL u = new URL(url); //实例化url的对象
try {
URLConnection urlConnection = u.openConnection();//打开一个URL连接,并运行客户端访问资源。
// HttpURLConnection httpUrl = (HttpURLConnection) urlConnection; //强转为HttpURLConnection
BufferedReader base = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(),"UTF-8")); //获取url中的资源
StringBuffer html = new StringBuffer();
while ((htmlContent = base.readLine()) != null) {
html.append(htmlContent); //htmlContent添加到html里面
}
base.close();
writer.println(html);//响应中输出读取的资源
writer.flush();
} catch (Exception e) {
e.printStackTrace();
writer.println("请求失败");
writer.flush();
}
http://localhost:8080/ssrfServlet?url=file:///c:%5c%5cwindows%5c%5cwin.ini
You can successfully read C: \ windows \ win INI file.
Read file in SSRF
The code is as follows:
@WebServlet("/readfileServlet")
public class downloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request,IOException {
String url = request.getParameter("url");
int len;
OutputStream outputStream = response.getOutputStream();
URL file = new URL(url);
byte[] bytes = new byte[1024];
InputStream inputStream = file.openStream();
while ((len = inputStream.read(bytes)) > 0) {
outputStream.write(bytes,len);
}
}
}
Compared with the above code, it is found that they are basically the same. The only difference is that one is to obtain objects with openstream method and the other is to obtain objects with openconnection. The two methods are similar.
Official documentation:
openConnection():返回一个实例,该实例表示与所引用的远程对象的连接。 返回类型: URLConnection
openStream():打开与此连接,并返回一个值以从该连接读取。 返回类型: InputStream
detailed description:
openConnection:返回一个URLConnection对象,它表示到URL所引用的远程对象的连接。每次调用此URL的协议处理程序的openConnection方法都打开一个新的连接。如果URL的协议(例如,HTTP或JAR)存在属于以下包或其子包之一的公共、专用URLConnection子类:java.lang、java.io、java.util、java.net,返回的连接将为该子类的类型。例如,对于HTTP,将返回HttpURLConnection,对于JAR,将返回JarURLConnection。(返回到该URL的URLConnection!)
openStream():打开到此URL的连接并返回一个用于从该连接读入的InputStream。
Here, start the server and test it.
http://127.0.0.1:8080//downloadServlet?url=file:///C:%5c%5c1.txt
Note: here are three oblique bars, and the backslash needs URL code, otherwise an error will be reported
Pass in the backslash without URL encoding
File download in SSRF
Vulnerability Code:
@WebServlet("/downloadServlet")
public class downloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request,IOException {
String filename = "1.txt";
String url = request.getParameter("url");
response.setHeader("content-disposition","attachment;fileName=" + filename);
int len;
OutputStream outputStream = response.getOutputStream();
URL file = new URL(url);
byte[] bytes = new byte[1024];
InputStream inputStream = file.openStream();
while ((len = inputStream.read(bytes)) > 0) {
outputStream.write(bytes,len);
}
}
}
Input:
http://localhost:8080/downloadServlet?url=file:///c:%5c%5c1.txt
In this way, the file is downloaded. The difference between file downloading and file reading in SSRF lies in the response header.
response.setHeader("content-disposition","attachment;fileName=" + filename);
This code sets the MIME type to the file type and will be downloaded when accessing the browser.
Reference articles
https://xz.aliyun.com/t/2761#toc-1
https://xz.aliyun.com/t/206/
https://xz.aliyun.com/t/7186
0x03 end
Some of the generation of SSRF is not just as mentioned in the article, including some third-party components. If a remote request is initiated without verification, there may be SSRF vulnerabilities.
Later, I plan to find a set of source code to audit SSRF.