简介
初学java代码审计,跟着大佬的审计方案,走一遍审计流程,这个系统没有使用java框架,作为入门不错。主要作为熟悉代码审计流程,寻找漏洞思路,学习记录。
环境准备
环境搭建使用了本地搭建环境,查看代码使用IDEA,配合tomcat8.0,因为IDEA会自动反编译,比较方便。我使用的是安装必看中的第二种方法,手动安装,修改数据库连接,然后手动将sql文件导入数据库,接着打开后台管理地址,安装完成。使用默认的管理员账号密码。
发现漏洞
非框架的代码审计,按照前台--后台,紧急--低危,非交互--交互,跟随代码流程尽量发现高危和易利用的漏洞类型为主。
重安装漏洞
因为我使用手动安装的方法进行安装,sql文件也是手工导入,直接导入sql文件,然后后台打开安装发现无法安装,需要将db_an设置为no,才能安装成功。使用系统自带的安装功能安装完成后,db_an会被设为no,虽然/install目录的重新安装页面没删除,但确实使用系统自带的安装功能不存在重新安装的漏洞。
跟随/install/index.html页面,找到了install.jsp文件,再根据form action,找到install_setup.jsp页面
然后再根据install_setup.jsp上的import语句
import="liuxing.util.Install,java.util.*"
找到安装的主要逻辑代码,在WEB-INF/class/liuxing/util/Install.class中,安装时会判断db_an的值,yes可以安装,no不安装;安装完成后会把值设置为no,虽然install页面没有被删除,但是已经不能再次安装了。
所以当使用系统自带的install方法安装时不存在重安装漏洞;如果使用手动导入sql文件,并且没有将db_an设置未no的话,且没删除install目录,就会存在重安装漏洞。
SQL注入
先尝试下搜索功能,随便输入关键字,点击搜索,跳转到so.jsp.查看so.jap
发现将搜索的值传入了Ruanjianguanli的so方法中,找到Ruanjianguanli的so方法
是调用了ruanjianDao.so()函数,我们接着来看看
同一个构造函数中可以发现ruanjianDao其实RuanjianMySQL的一个实例,接着再往下跟。打开WEB-INF/class/liuxing/dao/RuanjianMySQL.class文件 搜索so方法,最终使用预编译的方法来执行sql,所以这个地方不存在sql注入。
有一处使用了预编译方式,说明很多地方采用预编译的方式来执行sql语句,基本没有sql注入漏洞。所以换个思路,通过全局搜索createStatement关键字,看看有没有用拼接的SQL语句的。
如上图所示也有很多可以注入的地方,但是需要后台登陆,在delete语句中存在时间盲注,比如
delete from user where id in('222') or if(ascii(substr(database(),1,1))>107,0,sleep(3));
利用:
GET /admin/left6/Delete.jsp?pageNo=1&id=000')+or+if(ascii(substr(database(),1,1))>108,0,sleep(3))--+ HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost:8080/admin/left6/guanliyouhu.jsp
Connection: close
Cookie: Phpstorm-da0128c6=8686f169-5769-401c-a557-13b58accd387; JSESSIONID=29976F22C3B4A37F8BFEDEA123CB35C7
Upgrade-Insecure-Requests: 1
但是后台都已经登陆了,也没必要去纠结这种sql了,应该有更容易利用的漏洞,我们继续往下找。
存储型XSS
系统比较简单,所以前台能产生XSS的地方比较少。会员注册后修改个人资料,邮箱处
可以使用payload
""><script>alert(0)</script>
成功处罚XSS漏洞。我们来看denlu1.jsp代码
我们来找到Userguanli的Xiugaiyonghu2的方法。最终定位到WEB-INF/classliuxing/dao/UserDaoMySQL.class文件中的Xiugaiyonghu2方法中,直接将前端传过来的 youxiang值写入数据库中,导致存储型XSS。
后台任意文件上传漏洞
在"其它管理"—"添加友情链接"处、"软件管理"—"软件发布"页面,都可以上传文件,在web.xml中或者顺着jsp页面调用寻找,都能够找到具体的逻辑代码。
内部代码看起来都是一样的,以WEB-INF/class/liuxing/util/shangchuan2.class文件为例,关键代码如下:
List e = upload.parseRequest(req);
Iterator iter = e.iterator();
String regExp = ".+\\\\(.+)$";
String[] errorType = new String[]{".exe", ".com", ".cgi", ".asp"};
Pattern p = Pattern.compile(regExp);
while(true) {
FileItem item;
String name;
long size;
do {
do {
if(!iter.hasNext()) {
return;
}
item = (FileItem)iter.next();
if(item.isFormField() && item.getFieldName().equals("date")) {
date = item.getString();
}
} while(item.isFormField());
name = item.getName();
size = item.getSize();
} while((name == null || name.equals("")) && size == 0L);
Matcher m = p.matcher(name);
boolean result = m.find();
if(!result) {
throw new IOException("无法上传");
}
for(int e1 = 0; e1 < errorType.length; ++e1) {
if(m.group(1).endsWith(errorType[e1])) {
throw new IOException(name + ": wrong type");
}
}
try {
String var24 = m.group(1);
String men = this.getExt(var24);
item.write(new File(this.getServletContext().getRealPath("/") + "wen/" + date + men));
res.sendRedirect("../admin/left3/chenggong2.jsp?" + date + men);
} catch (Exception var21) {
out.println(var21);
}
}
} catch (IOException var22) {
out.println(var22);
} catch (FileUploadException var23) {
out.println(var23);
out.println("文件大小超出限制");
}
}
其中会判断上传的文件名,要符合正则表达式 ".+\(.+)$",才能够正常上传。即形似xxx\xx的文件名,估计是为了 匹配Windows路径中的\,比如C:\a.jpg。定义了内部禁止的后缀名".exe", ".com", ".cgi", ".asp",这就是唯一的过滤方式了。
继续往下看,写文件时,关键的一句代码:
item.write(new File((new StringBuilder(String.valueOf(getServletContext().getRealPath("/")))).append("wen/").append(date) .append(men).toString()));
即将文件存放在/wen目录下,保存为date+men形式的文件名,两者都是可以控制的,直接修改写shell了。
其他漏洞
未完待续