照着前辈大佬的审计过程走了一遍,,还是很有收获的!代码是几年以前的,,而且也没有用到MVC框架,整个来说也不是很复杂,但是对于java入门,,我觉得够用了!
下载地址:http://down.chinaz.com/soft/25711.htm
这里环境搭建用的tomcat+mysql,安装包里有安装说明,不再赘述~
还有一点要说的就是由于没有设置默认打开页,因此我们在安装时需要手动输入安装的url,不然直接进入install目录可能会显示没有此页!
0x01 sql注入漏洞
由于省事,这里也没有登进后台,添加几个测试页面,,因此页面功能较少,慢慢来吧!
首页上有一个搜索的功能,这里常见的话就是反射型的xss漏洞和sql注入漏洞,下面跟进代码去看看代码的逻辑
进行搜索后,页面进行了跳转http://127.0.0.1:8080/liuxing/so.jsp
下面进入so.jsp源码中去看看怎么写的,这里由于eclipse的jad反编译插件一直没有安装成功,因此审计IDEA采用的是是sublime+jd-gui,一个用来看jsp源码,一个用来反编译class文件,因此java里面的功能几乎都是写在class文件内,这倒有点像php里mvc框架的class.php
1
2
3
4
5
6
|
String name = request.getParameter(“name”);
if(name == null ) {
name = “”;
}
pageModel pagemodel = Ruanjianguanli.getInstance().so(pageNo,pageSize,tiaojian,lei,name);
|
这里可以看到name参数即为搜索参数,进入了Ruanjianguanli.getInstance().so()这个函数
根据刚才的描述,因为功能都写在class文件里,下面到jd-gui里去找找搜索的sql语句怎么写的
guanli目录下我们找到了Ranjianguanli这个class文件,跟进去找找~
100行找到了这个so函数,又调用了ruanjianDao这个函数,,那下面只能一步一步跟进去看看
跟进ruanjianDao,又看到这只是一个调用接口,并没有实际的sql语句,但是观察这个目录下的文件
可以看到这个RuanjianDao的sql语句就在下面这个RuanjianMySQL,下面跟进去找找sql语句
这里就找到了这里的sql查询,然后我们输入的参数为最后的string类型Name
那下面我们就应该重点关注Name这个参数如何进行传参的,但是如上图所示,,sql语句里面出现了很多?,这其实跟php的机制是类似的,那就是预编译机制,防止sql语句的语义被改变,,简言之就是防止sql注入的
进入下面的数据库查询,可以看到采用的是prepareStatement语句,,典型的预编译,因此这里不存在sql注入漏洞,其他的sql语句我也没找,因为根据经验来看,,如果有那就是大片大片的注入,,如果没有,,那可能大片大片的没有!
0x02 重安装漏洞
像php里安装后会生成一个lock文件,然后安装程序会判断lock文件是否存在,然后再决定是否进入安装流程,这个cms因为比较早,,因此存在一个重安装的问题
找到了安装的class文件,,没有任何逻辑判断,因此可以直接进入安装界面
0x03 后台管理员的session问题
在php或是asp中,有一类常见的漏洞就是后台的权限绕过,,这里漏洞问题比较多,,大抵都是管理员的cookie可以伪造,从而让任何人伪造成管理员进入后台,,这里尝试了一下,权限采用的jsp的session,不是明文存储,因此不太可能出现问题,关键是找一下判断源码吧!
在这里没找到重定向的语句,,那只有一个可能,就是写在class文件里了。。
写在了后台的Authfilter里(认证的过滤器,过滤器应该算是java web的一个特性吧)
可以看到这里是从session中提取admin属性,,然后进行判断,,无果,这里不存在漏洞!
0x03 存储型xss漏洞
回到前台,因为开放了会员注册的功能,因此我们可以尝试修改会员的个人资料,然后插入xss语句,最后我们到源码中看看参数是如何传递的!
这里只有一个邮箱可以修改,但是经过测试,,是存在xss漏洞的且没有任何语句的检查
下面回到源码里看看是如何入库的
value就是我们可控的邮箱参数,这里参数名为youxiang,下面去找找youxiang这个参数如何传递的
1
2
3
4
5
6
|
if(gai != null && gai.equals(“xugai”)){
int id = user1.getId();
String youxiang = request.getParameter(“youxiang”);
Userguanli.getInstance().Xiugaiyonghu2(youxiang,id);
response.sendRedirect(“denlu1.jsp”);
}
|
这里能看到进入了Userguanli.getInstance().Xiugaiyonghu2这个函数,这其实也是class文件,下面跟进这个class文件
1
2
3
4
|
public void Xiugaiyonghu2(String youxiang, int id)
{
this.userDao.Xiugaiyonghu2(youxiang, id);
}
|
这里跟刚才一样,又回到了这个Dao文件下的函数,根据刚才经验我们可以直接跟进到SQL的class文件里去看看代码逻辑
这里可以看到youxiang这个参数没有任何的过滤或是检查机制,,但是可惜的是采用的预编译,因此不存在sql注入,只能当做存储型xss漏洞
0x04 后台任意文件上传
这个洞其实有点鸡肋,,但是配合前面的存储型xss还是能进后台的
这里可以看到文件目录,然后跟进这个shangchuanwen2.jsp文件去看看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<%
String date = request.getParameter(“date”);
if(date == null || date.trim().equals(“”)) {
out.println(“<font size=2>”+“请重新上传!”+“</font>”);
return;
}
%>
<HTML><head><title>图片上传</title>
<meta http–equiv=“Content-Type” content=“text/html; charset=gb2312” />
<LINK href=“../css/index.css” type=“text/css” rel=“stylesheet”>
<script language=“javascript”>
function upload() {
with(document.getElementById(“form1”)) {
method=“post”;
action=“../../servlet/shangchuan2”;
submit();
}
}
</script>
|
可以看到这里仍然没有一个具体的上传逻辑代码,因此只能到class文件里去找了
这里一下就找到了,shangchuan2和shangchuan3,这里其实代码是一样的,只是功能点可能不相同
下面跟进这个shangchuan2文件
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
|
res.setContentType(“text/html; charset=GB2312”);
PrintWriter out = res.getWriter();
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(4096);
File tempPath = new File(getServletContext().getRealPath(“/”) + “temp/”);
factory.setRepository(tempPath);
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(536870912L);
String date = “”;
try {
List fileItems = upload.parseRequest(req);
Iterator iter = fileItems.iterator();
String regExp = “.+\(.+)$”;
String[] errorType = { “.exe”, “.com”, “.cgi”, “.asp” };
Pattern p = Pattern.compile(regExp);
while (iter.hasNext()) {
FileItem item = (FileItem)iter.next();
if ((item.isFormField()) &&
(item.getFieldName().equals(“date”))) {
date = item.getString();
}
if (!item.isFormField()) {
String name = item.getName();
long size = item.getSize();
if (((name != null) && (!name.equals(“”))) || (size != 0L))
{
Matcher m = p.matcher(name);
boolean result = m.find();
if (result) {
for (int temp = 0; temp < errorType.length; temp++) {
if (m.group(1).endsWith(errorType[temp])) {
throw new IOException(name + “: wrong type”);
}
}
try
{
String names = m.group(1);
String men = getExt(names);
item.write(new File(getServletContext().getRealPath(“/”) + “wen/” + date + men));
res.sendRedirect(“../admin/left3/chenggong2.jsp?” + date + men);
}
catch (Exception e) {
out.println(e);
}
}
else {
throw new IOException(“无法上传”);
}
}
}
|
代码有点长,,找其中的关键点进行分析
首先是一个黑名单机制,如果后缀为exe,asp等后缀,则会跳进wrong type这里
然后是一个正则匹配,这里逻辑上简直就是胡扯。。
String regExp = “.+\\(.+)$”;这里如果学过正则匹配的人就知道,四个转义字符,前一个转义字符为后一个转义,那么剩下来两个转义字符,然后前一个为后一个转义,那么最后的匹配样式则是******
也就是说这里的上传文件必须是c:\123.txt这一样,平常的单个文件名这里上传的话就是进入最后一个选择:无法上传
然后下面来分析文件后缀怎么形成的?
item.write(new File(getServletContext().getRealPath(“/”) + “wen/” + date + men));
这里给出了解释,文件名=data+men,data这里其实就是时间戳,men是我们上传文件名的后缀
那么文件名后缀我们可控,data时间戳又是可以修改的,,下面附上测试截图
可以看到这里res.sendRedirect(“../admin/left3/chenggong2.jsp?” + date + men);
实际上?后面的就是data+men,也就是说这就是文件名加文件后缀,这里data我设置的为1.jpg,文件名为c:\1.qwer
那么data+men=1.jpg+qwer=1.jpg.qwer
那么这里构造shell就应该是十分简单了吧,,只要保证后缀为jsp即可~
其他功能没有看,,上述如有不当之处,敬请指出~
最后附上参考链接:http://www.codersec.net/2016/12/%E9%93%81%E4%BA%BA%E4%B8%8B%E8%BD%BD%E7%B3%BB%E7%BB%9F%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/
这个是利用aircrack-ng进行WPA2的破解,现在无线密钥机制由最老的WEP变为现在的WPA2,针对WEP只要能够拿到足够多的IVS,利用其头部相似的信息就可以还原出密码,不过针对WPA2这种方法则不行。 目前主流的破解无线网密码都是利用抓握手包来暴力破…
请登录后发表评论
注册