目录
前言:
继上一篇博客,本篇博客记录下实际搭建XSS漏洞靶场环境。
2、项目配置
前端使用vue框架,后端使用springboot框架搭建
pom.xml
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.20</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
vue:vue.config.js
// 跨域配置
module.exports = {
devServer: { //记住,别写错了devServer//设置本地默认端口 选填
port: 8080,
proxy: { //设置代理,必须填
'/api': { //设置拦截器 拦截器格式 斜杠+拦截器名字,名字可以自己定
target: 'http://localhost:9090', //代理的目标地址
changeOrigin: true, //是否设置同源,输入是的
pathRewrite: { //路径重写
'^/api': '' //选择忽略拦截器里面的内容
}
}
}
}
}
3、编写XSS漏洞后端代码
经过小组讨论,我们决定实现反射型XSS漏洞和存储型XSS漏洞两个基本漏洞的靶场,对于反射型XSS漏洞,其实现较为简单,仅需将用户从前端输入到后端的payload返回到前端渲染,不进行过滤,即可构造XSS漏洞靶场。对于存储型XSS,可以通过将用户输入的payload存储到数据库中,待其他用户访问再次取出,即可触发XSS漏洞,类似于评论的功能点易出现此类型漏洞。我们采用存储到cookie的方式来实现存储型XSS漏洞,其基本原理与存储到数据库类型相似。
3.1、反射型XSS
package com.sducsrp.csrp.controller.BUGcontroller;
import com.sducsrp.csrp.common.Constants;
import com.sducsrp.csrp.common.Result;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
/**
* @author lhw 2022.04.07
*/
@RestController
@RequestMapping("/xss")
public class XssController {
/**
* Vuln Code.
* ReflectXSS
* http://localhost:8080/xss/reflect?xss=<script>alert(1)</script>
*
* @param xss unescape string
*/
@PostMapping("/reflect")
public @ResponseBody Result reflect(@RequestBody String xss) {
System.out.println(xss+":ok1");
Result res=new Result(Constants.CODE_200,null,xss);
return res;
}
3.2、存储型XSS
漏洞代码:
/**
* Vul Code.
* StoredXSS Step1
* http://localhost:8080/xss/stored/store?xss=<script>alert(1)</script>
*
* @param xss unescape string
*/
@RequestMapping("/stored/store")
public @ResponseBody Result store(@RequestBody String xss, HttpServletResponse response) {
Cookie cookie = new Cookie("xss", xss);
response.addCookie(cookie);
Result res=new Result(Constants.CODE_200,null,"Set param into cookie,访问/stored/show验证一下");
return res;
}
验证代码:
/**
* Vul Code.
* StoredXSS Step2
* http://localhost:8080/xss/stored/show
*
* @param xss unescape string
*/
@RequestMapping("/stored/show")
public @ResponseBody Result show(@CookieValue("xss") String xss) {
System.out.println(xss);
Result res=new Result(Constants.CODE_200,null,xss);
return res;
}
3.3、修复后的安全代码
/**
* safe Code.
* http://localhost:8080/xss/safe
*/
@RequestMapping("/safe")
@ResponseBody
public static String safe(String xss) {
return encode(xss);
}
private static String encode(String origin) {
origin = StringUtils.replace(origin, "&", "&");
origin = StringUtils.replace(origin, "<", "<");
origin = StringUtils.replace(origin, ">", ">");
origin = StringUtils.replace(origin, "\"", """);
origin = StringUtils.replace(origin, "'", "'");
origin = StringUtils.replace(origin, "/", "/");
return origin;
}
4、编写XSS漏洞前端代码
前端采用vue框架
4.1、反射型XSS
<!--题目名字:XSS-Reflect-->
<!--题目类型:XSS-->
<!--题目描述:反射型XSS漏洞-->
<!--题目难度:2星-->
<template>
<title>反射型XSS</title>
<p>该页面存在反射型XSS漏洞,能否构造payload,使得页面出现弹窗?</p>
<div style="margin-top: 100px">
<el-input v-model="xss_reflect" style="width: 250px;margin-right: 50px" placeholder="payload"></el-input>
<el-button @click="xss_reflect_fun" type="primary">submit</el-button>
</div
</template>
<script>
import request from "@/utils/request";
import router from "@/router";
export default {
data(){
return{
xss_reflect:'',
myresult:''
}
},
methods:{
xss_reflect_fun(){
request.post("/xss/reflect",this.xss_reflect).then(res =>{
this.myresult=res.data;
// alert(this.myresult)
// this.myresult
document.write(this.myresult);
//window.location.href="pro011";
router.push("/pro011");
//router.push("/pro011");
//self.location.href="/pro011"
})
}
}
}
</script>
4.2、存储型XSS
<!--题目名字:XSS-Store-->
<!--题目类型:XSS-->
<!--题目描述:存储型XSS漏洞-->
<!--题目难度:2星-->
<template>
<title>存储型XSS</title>
<p>该页面存在存储型XSS漏洞,能否构造payload,使得页面出现弹窗?</p>
<div style="margin-top: 100px">
<el-input v-model="xss_store" style="width: 250px;margin-right: 50px" placeholder="payload"></el-input>
<el-button @click="xss_store_fun" type="primary">submit</el-button>
</div>
<br>
<p> 点击按钮访问/stored/show </p>
<el-button @click="show"> 点击访问 </el-button>
</template>
<script>
import request from "@/utils/request";
import router from "@/router";
export default {
data(){
return{
xss_store:'',
myresult:'',
myresult_cookie:''
}
},
methods:{
xss_store_fun(){
request.post("/xss/stored/store",this.xss_store).then(res =>{
this.myresult=res.data;
alert(this.myresult)
})
},
show(){
request.post("/xss/stored/show").then(res =>{
this.myresult=res.data;
if(this.myresult==null){
alert("请先输入payload,再点击该按钮进行验证。")
}
else {
// alert(this.myresult)
// this.myresult
document.write(this.myresult);
//window.location.href="pro011";
router.push("/pro012");
//router.push("/pro011");
//self.location.href="/pro011"
}
})
}
}
}
</script>
5、运行测试
5.1、反射型XSS漏洞测试
进入反射型XSS
输入payload:
<script>alert(1)</script>
发现弹窗,XSS漏洞验证成功。
5.2、存储型XSS漏洞测试
进入存储型XSS
输入payload:
<script>alert(1)</script>
访问/stored/show验证
出现弹窗,存储型XSS验证成功。
5.3、修复后测试
访问修复的代码:http://localhost:8080/xss/safe
get请求:
xss=<script>alert(1)</script>
发现并没有将输入的内容解析,成功修复XSS漏洞代码。