系列文章专栏地址:
山东大学网络安全靶场实验平台
随着项目的扩展,原本的手风琴页面已经显得过于简陋,我们需要对靶场页面进行重写,使得更加美观,功能也更多
(也许这不会是最后一次)
左侧卡片是走马灯,播放图片和文字介绍
右侧有多个靶机等待开启
上面有十个按钮,点击切换漏洞,右侧有一个展开按钮,展开抽屉,内容如下:
打开靶机页面:依次出现转圈圈然后进度条走到100%时方可进入创建的靶机环境。
这里背后需要开启docker或本地部署内容。
上方按钮集合的代码
<el-row>
<!--题目选择-->
<el-col :span="22">
<div class="select" >
<el-button class="btn-group" @click="getprobleminfo('force')"> 暴力破解</el-button>
<el-button class="btn-group" @click="getprobleminfo('rce')"> RCE</el-button>
<el-button class="btn-group" @click="getprobleminfo('sqli')"> sql注入</el-button>
<el-button class="btn-group" @click="getprobleminfo('fileupload')"> 文件上传漏洞</el-button>
<el-button class="btn-group" @click="getprobleminfo('filedownload')"> 文件下载漏洞</el-button>
<el-button class="btn-group" @click="getprobleminfo('xss')"> XSS</el-button>
<el-button class="btn-group" @click="getprobleminfo('xxe')"> XXE</el-button>
<el-button class="btn-group" @click="getprobleminfo('javadeser')"> JAVA反序列化漏洞</el-button>
<el-button class="btn-group" @click="getprobleminfo('urlredirect')"> 重定向漏洞</el-button>
<el-button class="btn-group" @click="getprobleminfo('BAC')"> 逻辑越权</el-button>
<el-button class="btn-group" @click="getprobleminfo('csrf')"> CSRF</el-button>
</div>
</el-col>
<!--靶场介绍-->
<el-col :span="2">
<el-button
style="height: 120px;
/*background-color: #475669;*/
border-style: none;
background-color: rgba(0,0,0,0);
margin-top: 10px;
display: inline;
text-align: left;
border-style: none;"
@click="drawer=true"
>
<i style="position:relative; color: #99a9bf; font-size:60px;margin-bottom: 0px;padding-bottom: 0px" class="el-icon-s-fold"></i>
</el-button>
</el-col>
<el-drawer
v-model="drawer"
direction="rtl"
:before-close="handleClose"
>
<template #title>
<h1 style="color:wheat;font-size: 60px;">靶场介绍</h1>
</template>
<p id="intro_p">  本靶场含有众多的靶机,它们场景各异、所含漏洞不尽相同。<br/>  点击上方按钮,可以显示该漏洞的简介,
右边是若干靶机,每个靶机都集成了该漏洞。<br/>  你需要阅读提示,利用靶机环境中存在的漏洞,破解它并找出隐藏在其中的一串随机字符串,我们称之
为FLAG。当你找到了FLAG,别忘记将它提交,此时你便成功、完整的征服了该靶机!
</p>
</el-drawer>
</el-row>
下方的靶机处对卡片进行CSS调整
<el-card class="problem-card" v-for="(problem, problemid) in problemlist" :key="problemid" @click="gotopro(problem.problemid)">
<i style="float:left;font-size: 50px;color: #8cc5ff;" :class="iconurl"></i>
<h2 style="color: white;margin: 50px;font-size: 25px;"> 靶机代号:{{problem.problemname}}</h2>
</el-card>
js控制代码如下:
getprobleminfo(type){
request.get("/problem/getinfobytype",{
params:{
problemtype:type
}
}).then(res =>{
this.problemlist={};
this.problemlist=res.data;
})
this.introduction=this.introductionlist[type];
this.iconurl=this.iconurllist[type];
this.introimg='';
this.introimg=this.introimglist[type];
},
进入页面后
点击按钮创建环境和关闭环境是通过v-if控制
<div v-if="dialogVisible==false" style="text-align: left;height:150px;margin-top: 20px;">
<el-button v-loading="loading" style="background-color: #292421;color: white;width: 200px;border-color: #8cc5ff;" @click="openenviorment()">
<h3>点击创建靶机环境</h3>
</el-button>
</div>
<!-- 打开docker容器创建靶机-->
<div v-if="dialogVisible==true" class="btn2" >
<el-progress class="progress" v-if="link==0" :text-inside="true" :stroke-width="20" :percentage="percentage" :color="customColorMethod(percentage)" />
<p @click="gotopage" v-if="link==1" style="cursor: pointer;display: block;color: white;padding-top:10px;text-align: left;font-size: 20px;height:35px">
<i class="el-icon-s-platform" style="margin-right: 10px;margin-left: 10px;"></i>
点击此链接进入环境
</p>
<el-button class="closebtn" @click="closeenviorment">
关闭当前靶机环境
</el-button>
</div>
</div>
创建时进度条自己设置延时控制,语法规则是setTimeout(function(){}),1000)
openenviorment(){
this.loading=true;
var that=this;
setTimeout(function(){
that.loading=false;
that.dialogVisible=true;
},1000)
if (this.probleminfo.url=='3'){
//动态创建docker
this.createdocker();
setTimeout(function(){that.percentage=that.percentage+3;},2000)
setTimeout(function(){that.percentage=that.percentage+7;},3000)
setTimeout(function(){that.percentage=that.percentage+15;},5000)
setTimeout(function(){that.percentage=that.percentage+25;},7000)
setTimeout(function(){that.percentage=that.percentage+40;},9000)
setTimeout(function(){that.percentage=that.percentage+10;},12000)
setTimeout(function(){
that.link=1;
},14000)
}else{
setTimeout(function(){
that.percentage=that.percentage+100;
},1000)
setTimeout(function(){
that.link=1;
},2000)
}
},
创建docker是向后端发送请求,然后接收到后端的端口,便可以开启对应页面
createdocker(){
request.get("/docker/create",{
params:{
problemName:this.probleminfo.problemid,
username:this.user.username
}
}).then(res =>{
//返回的是创建的docker的地址
let url='http://82.157.124.157:'+res.data+'/'+this.probleminfo.problemname;
this.dockerurl=url;
console.log(this.dockerurl)
})
},
@RequestMapping("create")
public Result docker_create(@RequestParam("problemName") String problemName,
@RequestParam("username") String username){
// DockerClientUtils dockerClientUtils;
DockerClient client;
String containerIdVue;
String containerIdSpringboot;
System.out.println("problemName:"+problemName+";username:"+username);
String ret = null;
//判断该用户是否有正在使用的容器
try {
Connection connection = dataSource.getConnection();
// 预编译
String sql = "select containerId from stucontainer where username = ?";
PreparedStatement st = connection.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
st.setString(1, username);
ResultSet rs = st.executeQuery();
// 通过此对象可以得到表的结构,包括,列名,列的个数,列数据类型
rs.last();
int row = rs.getRow();
rs.beforeFirst();
System.out.println("查找到行数为"+row);
if(row==1){
rs.next();
String problemName1 = rs.getString("problemName");
System.out.println("用户"+username+"已创建容器:"+problemName1);
ret = "1;"+problemName1;
}
else {
System.out.println("为用户"+username+"创建容器中");
//连接Docker服务器
client = dockerClientUtils.connectDocker("tcp://82.157.124.157:2375");
System.out.println("连接docker成功");
port_vue+=1;
port_springboot+=1;
containerNum+=1;
//================================================================
System.out.println("创建后端项目中");
dockerClientUtils = new DockerClientUtils();
//创建容器
CreateContainerResponse container_springboot = dockerClientUtils.createContainer(
client,
"csrp_"+problemName+"_springboot_"+containerNum,
// "csrp_"+problemName+"_springboot",
"csrp_csrf",
10000,port_springboot);
System.out.println("创建springboot容器成功");
//启动容器
dockerClientUtils.startContainer(client, container_springboot.getId());
System.out.println("启动springboot容器成功");
containerIdSpringboot = container_springboot.getId();
//================================================================
// System.out.println("创建前端项目中");
// dockerClientUtils = new DockerClientUtils();
// //创建容器
// CreateContainerResponse container_vue = dockerClientUtils.createContainer(
// client,
// "csrp_"+problemName+"_vue_"+containerNum, "csrp_"+problemName+"_vue",
// 80,port_vue);
// System.out.println("创建vue容器成功");
// //启动容器
// dockerClientUtils.startContainer(client, container_vue.getId());
// System.out.println("启动vue容器成功");
// containerIdVue = container_vue.getId();
//
// //把容器ID存入数据库
// sql = "insert into stucontainer (`username`, `problemName`, `containerId`) values ('"+username+
// "', '"+problemName+"', '"+containerIdVue+"');";
// System.out.println(sql);
// //PreparedStatement st1 = connection.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
// Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
// ResultSet.CONCUR_UPDATABLE);
// stmt.executeUpdate(sql);
String dockerUrl = "http://82.157.124.157:"+port_springboot;
// +";"+port_springboot;
ret = "标识号:2;靶机地址:"+dockerUrl;
}
rs.close();
connection.close();
} catch (SQLException e) {
System.out.println("输入内容错误,数据库查询错误");
System.out.println(e.toString());
ret = "3;数据库错误";
}
// Result res=new Result(Constants.CODE_200,null,ret);
return Result.success(port_springboot);
}