在學(xué)習(xí)的過程中,了解到kkFileView存在任意文件讀取、SSRF、文件上傳漏洞。
為了更深刻的理解其原理,我從git拉取了項(xiàng)目,由于該漏洞在最新版本已經(jīng)修復(fù),所以這只是歷史版本中存在的。
寫這篇文章來提醒自己代碼中容易出問題的地方。
環(huán)境準(zhǔn)備
來到kkFileView官網(wǎng),發(fā)現(xiàn)支持Gitee,直接進(jìn)去用git clone下來
git clone https://gitee.com/kekingcn/file-online-preview.git
閑話少敘,直接開始看源代碼。
1.任意文件包含漏洞
根據(jù)其他文章介紹,版本<=3.6.0存在此漏洞。加上這個(gè)連接就可以讀取服務(wù)器上的文件//getCorsFile?urlPath=file:///etc/passwd
git tag # 查看所有標(biāo)簽
git checkout v3.6.0 # 切換分支
然后用idea打開這個(gè)項(xiàng)目,直接搜索到controller中的getCorsFile接口,源代碼如下。可以看到作者本意是為了解決跨域問題,沒有想到被利用讀取任意文件。
在代碼中也沒有任何的過濾,才會(huì)導(dǎo)致任意文件讀取漏洞。
byte[] bytes = NetUtil.downloadBytes(url.toString());罪魁禍?zhǔn)自谟谶@一行代碼,沒有對文件路徑做出任何限制。
/**
* 根據(jù)url獲取文件內(nèi)容
* 當(dāng)pdfjs讀取存在跨域問題的文件時(shí)將通過此接口讀取
*
* @param urlPath url
* @param response response
*/
@RequestMapping(value = "/getCorsFile", method = RequestMethod.GET)
public void getCorsFile(String urlPath, HttpServletResponse response) {
logger.info("下載跨域pdf文件url:{}", urlPath);
try {
URL url = WebUtils.normalizedURL(urlPath);
byte[] bytes = NetUtil.downloadBytes(url.toString());
IOUtils.write(bytes, response.getOutputStream());
} catch (IOException | GalimatiasParseException e) {
logger.error("下載跨域pdf文件異常,url:{}", urlPath, e);
}
}
本地復(fù)現(xiàn)一下,和預(yù)期完全一樣:
修復(fù)方法
現(xiàn)在我切換到下一個(gè)版本,來看看作者是如何修復(fù)的。
?沒想到下一個(gè)版本直接v4.0.0了
git checkout v4.0.0
我發(fā)現(xiàn)4.0.0并沒有修復(fù),4.2.0才開始修復(fù)這個(gè)漏洞。代碼如下,可以看到加了非常多的過濾。
最新版本我就不貼出來了,反正有更多的過濾。
@GetMapping("/getCorsFile")
public void getCorsFile(String urlPath, HttpServletResponse response) throws IOException {
try {
urlPath = WebUtils.decodeUrl(urlPath);
} catch (Exception ex) {
logger.error(String.format(BASE64_DECODE_ERROR_MSG, urlPath),ex);
return;
}
HttpURLConnection urlcon;
InputStream inputStream = null;
if (urlPath.toLowerCase().startsWith("file:") || urlPath.toLowerCase().startsWith("file%3")) {
logger.info("讀取跨域文件異常,可能存在非法訪問,urlPath:{}", urlPath);
return;
}
logger.info("下載跨域pdf文件url:{}", urlPath);
if (!urlPath.toLowerCase().startsWith("ftp:")){
try {
URL url = WebUtils.normalizedURL(urlPath);
urlcon=(HttpURLConnection)url.openConnection();
urlcon.setConnectTimeout(30000);
urlcon.setReadTimeout(30000);
urlcon.setInstanceFollowRedirects(false);
if (urlcon.getResponseCode() == 302 || urlcon.getResponseCode() == 301) {
urlcon.disconnect();
url =new URL(urlcon.getHeaderField("Location"));
urlcon=(HttpURLConnection)url.openConnection();
}
if (urlcon.getResponseCode() == 404 || urlcon.getResponseCode() == 403 || urlcon.getResponseCode() == 500 ) {
logger.error("讀取跨域文件異常,url:{}", urlPath);
return ;
} else {
if(urlPath.contains( ".svg")) {
response.setContentType("image/svg+xml");
}
inputStream=(url).openStream();
IOUtils.copy(inputStream, response.getOutputStream());
urlcon.disconnect();
}
} catch (IOException | GalimatiasParseException e) {
logger.error("讀取跨域文件異常,url:{}", urlPath);
return ;
} finally {
IOUtils.closeQuietly(inputStream);
}
} else {
try {
URL url = WebUtils.normalizedURL(urlPath);
if(urlPath.contains(".svg")) {
response.setContentType("image/svg+xml");
}
inputStream = (url).openStream();
IOUtils.copy(inputStream, response.getOutputStream());
} catch (IOException | GalimatiasParseException e) {
logger.error("讀取跨域文件異常,url:{}", urlPath);
return ;
} finally {
IOUtils.closeQuietly(inputStream);
}
}
}
引用文章來源:http://www.zghlxwxcb.cn/news/detail-847967.html
https://www.cnblogs.com/xbbth/p/17446987.html文章來源地址http://www.zghlxwxcb.cn/news/detail-847967.html
到了這里,關(guān)于網(wǎng)絡(luò)安全-kkFileViews任意文件讀取漏洞原理解析的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!