Java代码审计漏洞-SSRF服务器请求伪造
Java代码审计漏洞-SSRF服务器请求伪造
ssrf基础:https://www.cnblogs.com/-meditation-/p/16227632.html
补充一点:SSRF利用的协议PHP和JAVA的有区别,高版本的JAVA可以用file ftp mailto http https jar netdoc, 具体还没有研究。
漏洞代码
HttpURLConnection与URLConnection的区别:
URLConnection 可以使用邮件、文件传输协议,而HttpURLConnection 就单指浏览器的HTTP协议。URLConnection实例不会在创建时建立实际的网络连接。
可能存在漏洞的点
HttpURLConnection. getInputStream
URLConnection. getInputStream
Request.Get. execute
Request.Post. execute
URL.openStream
ImageIO.read
OkHttpClient.newCall.execute
HttpClients. execute
HttpClient.execute
……
HttpURLConnection
@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, HttpServletResponse response) throws ServletException, IOException {
String url = request.getParameter("url"); //接收url的传参
String htmlContent;
PrintWriter writer = response.getWriter(); //获取响应的打印流对象
URL u = new URL(url); //实例化url的对象
try {
//每次当调用此URL的协议处理程序的URLStreamHandler.openConnection(URL)方法时, 都会创建一个新的URLConnection实例。
//URLConnection实例不会在创建时建立实际的网络连接。 只会在调用URLConnection.connect()时发生。
URLConnection urlConnection = u.openConnection(); //打开一个URL连接,并运行客户端访问资源。
HttpURLConnection httpUrl = (HttpURLConnection) urlConnection; //强转为HttpURLConnection
BufferedReader base = new BufferedReader(new InputStreamReader(httpUrl.getInputStream(), "UTF-8")); //获取HttpURLConnection中的资源
StringBuffer html = new StringBuffer();
//把base里的资源传给htmlContent
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();
}
}
//openConnection:每次当调用此URL的协议处理程序的URLStreamHandler.openConnection(URL)方法时, 都会创建一个新的URLConnection实例。
//openStream():打开到此URL的连接并返回一个用于从该连接读入的InputStream。
String url = request.getParameter("picurl");//接收picurl的传参
StringBuffer response = new StringBuffer();
URL pic = new URL(url);
HttpURLConnection con = (HttpURLConnection) pic.openConnection();//创建一个新的URLConnection并强制转换为HttpURLConnection
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
modelMap.put("resp",response.toString());
return "getimg.htm";
URLConnection
public class SSRFServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String url = req.getParameter("url"); //接收url的传参
String htmlContent;
PrintWriter writer = resp.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();
//把base里的资源传给htmlContent
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();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
imageIO
public class ssrf {
public static BufferedImage read(URL url) throws IOException {
if (url == null) {
System.out.println("输入内容为空");
}
InputStream istream = url.openStream(); //打开到此URL的连接并返回一个用于从该连接读入的InputStream。
ImageInputStream stream = ImageIO.createImageInputStream(istream); //获取文件流
BufferedImage bi = ImageIO.read(stream); //返回 BufferedImage作为供给的解码结果
return bi;
}
}
@WebServlet("/httpclientServlet")
public class httpclientServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String geturl = request.getParameter("url");
//输出流 用于输出字符流数据或者二进制的字节流数据都可以
ServletOutputStream outputStream = response.getOutputStream();
//ByteArrayOutputStream对byte类型数据进⾏写⼊的类 相当于⼀个中间缓冲层,将类写⼊到⽂件等其他outputStream。
ByteArrayOutputStream os = new ByteArrayOutputStream();
URL url = new URL(geturl);
//获取文件流
BufferedImage image = ssrf.read(url);
//image流写到OS流
ImageIO.write(image, "png", os);
//os.toByteArray()将流转换为数组
InputStream input = new ByteArrayInputStream(os.toByteArray());
int len;
byte[] bytes = new byte[1024];
while ((len = input.read(bytes)) > 0) {
outputStream.write(bytes, 0, len);
}
}
}
HttpClient
//创建一个DefaultHttpClient的实例
CloseableHttpClient httpClient = HttpClients.createDefault();
//发送GET请求 POST: HttpPost httpPost = new HttpPost(url);
HttpGet getRequest = new HttpGet(url);
HttpResponse response = httpClient.execute(getRequest);
if(response.getStatusLine().getStatusCode() == 200)
{
HttpEntity entity = response.getEntity();
return EntityUtils.toByteArray(entity);
}
throw new IOException("Error:下载图片失败");
OkHttp
okhttp是一个第三方类库,用于android中请求网络
String url = request.getParameter("url");
OkHttpClient httpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Response response = httpClient.newCall(request).execute();
return response.body().string();
HttpRequest
HttpRequest request = HttpRequest.get("http://www.baidu.com",true,'q',"baseball gloves","size",100);
做代码审计的时候,一般直接用自动化工具扫,或全局搜关键字。
防御
- 限制协议只能为http/https,防止跨协议。就是用HttpURLConnection。
- 对获取的URL进行判断,设置url白名单。
参考文章
https://www.cnblogs.com/CoLo/p/15236424.html
https://www.freebuf.com/vuls/293473.html
本文来自博客园,作者:九天揽月丶,转载请注明原文链接:https://www.cnblogs.com/-meditation-/articles/16241921.html