0x00 前言
SSRF 形成的原因大都是由于服務(wù)端提供了從其他服務(wù)器應(yīng)用獲取數(shù)據(jù)的功能且沒有對目標(biāo)地址做過濾與限制。比如從指定 URL 地址獲取網(wǎng)頁文本內(nèi)容,加載指定地址的圖片,下載等等。這里主要介紹java中URLConnection()
和openStream()
兩個方法產(chǎn)生SSRF的原理和修復(fù)方法
0x01 URLConnection
@RequestMapping(value = "/urlConnection/vuln", method = {RequestMethod.POST, RequestMethod.GET})
public String URLConnectionVuln(String url) {
return HttpUtils.URLConnection(url);
}
這里調(diào)用的是HttpUtils.URLConnection(url)
public static String URLConnection(String url) {
try {
URL u = new URL(url);
URLConnection urlConnection = u.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //send request
// BufferedReader in = new BufferedReader(new InputStreamReader(u.openConnection().getInputStream()));
String inputLine;
StringBuilder html = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
html.append(inputLine);
}
in.close();
return html.toString();
} catch (Exception e) {
logger.error(e.getMessage());
return e.getMessage();
}
}
跟進URLConnection
方法,而URLConnection
里又調(diào)用了URL.openConnection()
來發(fā)起請求, 這個請求可以直接執(zhí)行url協(xié)議(偽協(xié)議)
漏洞利用:
使用file協(xié)議讀文件
使用http協(xié)議訪問百度
修復(fù)方法:
這里先是對url調(diào)用了SecurityUtil.isHttp()
來進行檢查
@GetMapping("/urlConnection/sec")
public String URLConnectionSec(String url) {
// Decline not http/https protocol
if (!SecurityUtil.isHttp(url)) {
return "[-] SSRF check failed";
}
try {
SecurityUtil.startSSRFHook();
return HttpUtils.URLConnection(url);
} catch (SSRFException | IOException e) {
return e.getMessage();
} finally {
SecurityUtil.stopSSRFHook();
}
}
SecurityUtil.isHttp()比較簡單,就是判斷url是否是以http://或https://開頭
public static boolean isHttp(String url) {
return url.startsWith("http://") || url.startsWith("https://");
}
單純的ban掉其他協(xié)議顯然是不夠的,還不能夠防止對內(nèi)網(wǎng)進行探測,于是在獲取url內(nèi)容之前,開啟了一個hook來對用戶行為進行監(jiān)聽,SecurityUtil.startSSRFHook()
,就有效防止了ssrf攻擊
0x02 openStream
openStream()
方法的實現(xiàn)也是調(diào)用了openConnection
生成一個URLConnection
對象,然后再通過這個對象調(diào)用的getInputStream()
方法的
@GetMapping("/openStream")
public void openStream(@RequestParam String url, HttpServletResponse response) throws IOException {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
String downLoadImgFileName = WebUtils.getNameWithoutExtension(url) + "." + WebUtils.getFileExtension(url);
// download
response.setHeader("content-disposition", "attachment;fileName=" + downLoadImgFileName);
URL u = new URL(url);
int length;
byte[] bytes = new byte[1024];
inputStream = u.openStream(); // send request
outputStream = response.getOutputStream();
while ((length = inputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, length);
}
} catch (Exception e) {
logger.error(e.toString());
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
通過WebUtils.getNameWithoutExtension(url) + "." + WebUtils.getFileExtension(url)
來獲取下載文件名,然后執(zhí)行inputStream = u.openStream();
來看一下openStream(),也是調(diào)用了openConnection()
,也會根據(jù)傳入的協(xié)議的不同來進行處理
public final InputStream openStream() throws java.io.IOException {
return openConnection().getInputStream();
}
由此可以得知,openStream()
方法同樣也可以進行ssrf來探測內(nèi)網(wǎng)以及文件下載,修復(fù)方案同上
0x03 總結(jié)
關(guān)鍵詞:URLConnection、openConnection、openStream
漏洞利用:
關(guān)于SSRF漏洞利用相關(guān)可以看這篇文章,總結(jié)的很詳細!
從一文中了解SSRF的各種繞過姿勢及攻擊思路
審核編輯 :李倩
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
9272瀏覽量
85809 -
URL
+關(guān)注
關(guān)注
0文章
139瀏覽量
15405
原文標(biāo)題:0x03 總結(jié)
文章出處:【微信號:哆啦安全,微信公眾號:哆啦安全】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論