0x00 前言
SSRF 形成的原因大都是由于服務(wù)端提供了從其他服務(wù)器應(yīng)用獲取數(shù)據(jù)的功能且沒(méi)有對(duì)目標(biāo)地址做過(guò)濾與限制。比如從指定 URL 地址獲取網(wǎng)頁(yè)文本內(nèi)容,加載指定地址的圖片,下載等等。這里主要介紹java中URLConnection()
和openStream()
兩個(gè)方法產(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();
}
}
跟進(jìn)URLConnection
方法,而URLConnection
里又調(diào)用了URL.openConnection()
來(lái)發(fā)起請(qǐng)求, 這個(gè)請(qǐng)求可以直接執(zhí)行url協(xié)議(偽協(xié)議)
漏洞利用:
使用file協(xié)議讀文件
使用http協(xié)議訪問(wèn)百度
修復(fù)方法:
這里先是對(duì)url調(diào)用了SecurityUtil.isHttp()
來(lái)進(jìn)行檢查
@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()比較簡(jiǎn)單,就是判斷url是否是以http://或https://開頭
public static boolean isHttp(String url) {
return url.startsWith("http://") || url.startsWith("https://");
}
單純的ban掉其他協(xié)議顯然是不夠的,還不能夠防止對(duì)內(nèi)網(wǎng)進(jìn)行探測(cè),于是在獲取url內(nèi)容之前,開啟了一個(gè)hook來(lái)對(duì)用戶行為進(jìn)行監(jiān)聽,SecurityUtil.startSSRFHook()
,就有效防止了ssrf攻擊
0x02 openStream
openStream()
方法的實(shí)現(xiàn)也是調(diào)用了openConnection
生成一個(gè)URLConnection
對(duì)象,然后再通過(guò)這個(gè)對(duì)象調(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();
}
}
}
通過(guò)WebUtils.getNameWithoutExtension(url) + "." + WebUtils.getFileExtension(url)
來(lái)獲取下載文件名,然后執(zhí)行inputStream = u.openStream();
來(lái)看一下openStream(),也是調(diào)用了openConnection()
,也會(huì)根據(jù)傳入的協(xié)議的不同來(lái)進(jìn)行處理
public final InputStream openStream() throws java.io.IOException {
return openConnection().getInputStream();
}
由此可以得知,openStream()
方法同樣也可以進(jìn)行ssrf來(lái)探測(cè)內(nèi)網(wǎng)以及文件下載,修復(fù)方案同上
0x03 總結(jié)
關(guān)鍵詞:URLConnection、openConnection、openStream
漏洞利用:
關(guān)于SSRF漏洞利用相關(guān)可以看這篇文章,總結(jié)的很詳細(xì)!
從一文中了解SSRF的各種繞過(guò)姿勢(shì)及攻擊思路
審核編輯 :李倩
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
8953瀏覽量
85066 -
URL
+關(guān)注
關(guān)注
0文章
139瀏覽量
15297
原文標(biāo)題:0x03 總結(jié)
文章出處:【微信號(hào):哆啦安全,微信公眾號(hào):哆啦安全】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論