初学 java 代码审计,跟着表哥们脚步,走一遍审计流程,就选了个没有使用 Java 框架的 java 系统,作为入门。

目的是为了熟悉代码审计流程,寻找漏洞的思路,入门记录。

准备工作

为了验证审计出的漏洞效果,还是要搭建起来系统,不然空说无凭。为了方便,使用 JspStudy 2016 一体化环境,选择 tomcat 8.0, jdk 1.8 搭建。查看代码使用 IDEA,当然,也可以用 jd-gui,反编译 class,不过 IDEA 自动就反编译了,比较方便。

值得注意的是,使用系统自带的安装功能搭建后,打开页面报错,事后想起来可能是自动导入 sql 文件的路径程序中写死了,和自己部署时根目录位置不一样导致的。

再次通过 install/index.html 页面重新安装,则显示数据库已经安装。原因是 WEB-INF/classes/liuxing_db.properties 中的 db_an=yes 变成了 db_an=no,表示数据库已经安装,不会再次安装。

最后发现使用安装提示里的第二种手工安装方法可以正常安装系统,人工导入数据库数据就行了。

为了审计代码时全局搜索方便,可以使用 jad 批量反编译 class 文件,使用命令如:

jad -r -d /path/to/store/java -s java -8 /path/to/classes/files/*/.class

最后,我将反编译出来的 java 文件,统一存放在了 WEB-INF/java 目录下,和 class 文件的原始目录 WEB-INF/classes 目录相对应。

发现漏洞

非框架的代码审计,按照 前台——后台,严重——低危,非交互——需交互,跟随代码流程尽量发现高危和易利用漏洞类型为主。

一:重安装漏洞

像在准备工作中说的一样,虽然我使用系统自带的安装功能失败了,但是 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/java/liuxing/util/Install.java 中,安装时会判断 db_an 的值,yes 可以安装,no 不安装;安装完后会把值置为 no,虽然 install 页面没删除,但是已经不能够再次安装了。

所以,当使用系统自带的 install 页面安装系统时,不存在重安装漏洞;如果使用手工导入 sql 文件安装系统,自己又没有把 db_an 的值写成 no,没删除 install 目录文件时,存在重安装漏洞。

二. SQL 注入漏洞

首先尝试搜索功能,进入 so.jsp,发现将搜索的参数值传入 Ruanjianguanli 的 so 方法中

进入 WEB-INF/java/liuxing/guanli/Ruanjianguanli.java 文件中,找到 so 方法;发现是调用了 ruanjianDao.so() 函数,

ruanjianDao 是什么呢?

在 Ruanjianguanli 类的构造函数里,可以找到,ruanjianDao 是 RuanjianMySQL 的一个实例,那么再接着往下跟

然后打开 WEB-INF/java/liuxing/dao/RuanjianMySQL.java 文件,搜索 so 方法,并发现最终是采用预编译来执行数据库操作,这里不存在 SQL 注入漏洞。

public pageModel so(int pageNo, int pageSize, String tiaojian, int lei, String name)

可想而知,有一处用了预编译,说明就有很多处用了预编译方式来执行 SQL 语句,基本都没有 SQL 注入漏洞。然后全局搜索 createStatement 关键字,看看有没有用拼接的SQL语句的。

如上图,最后也发现几个可以注入的地方,但是都需要登录后台,在 delete 语句中,可以用时间盲注,比如:

delete from user where id in('222') or if(ascii(substr(database(),1,1))>107,0,sleep(3));

语句来测试

利用:

但是后台都登录了,也没必要去纠结这个 SQL 注入漏洞了,进了后台应该有更容易利用的漏洞。

三. XSS 漏洞

由于系统较简单,前台能够产生 xss 的地方较少,会员注册后,登录;可以在修改邮箱处,用 Payload

""><script>alert(0)</script>

触发了前端会员的 xss。

而且在后台管理员修改用户资料处,尝试修改该用户资料,也会触发此 XSS。

代码层面,查看 denlu1.jsp 页面代码,跟踪 Userguanli 的 Xiugaiyonghu2 方法,里面传入了要修改成的邮箱和用户 ID

最终到 WEB-INF/java/liuxing/dao/UserDaoMySQL.java 文件中的 Xiugaiyonghu2 方法中,直接将前端传过来的 youxiang 值写入数据库中,没有任何安全防护,从而导致了存储型 xss。

四. 访问控制

没有登录管理员帐户,访问 /admin/admin.jsp 页面,会被重定向到 /buzai.htm 页面。打开 admin.jsp 页面,看看里面的跳转逻辑,搜索关键字:

RequestDispatcher

getRequestDispatcher

sendRedirect

setHeader

forward

没有发现跳转语句,判断是全局 Filter 的权限认证。查看 WEB-INF/web.xml,发现针对所有 jsp 文件的 AuthFilter 过滤器

顺着 filter-class,找到 WEB-INF/java/liuxing/util/AuthFilter.java 文件,分析 doFilter 函数:

关键语句在于以下两个 if 判断:

如果路径不是指定的四个安装系统相关的路径,会尝试从数据库中的 lujing 表中查询存储在数据库中的 web 路径。

这里一个坑被我踩到了,没看代码的情况下,认为找到路径时 bl 为 true,没找到路径时 bl 为 false,结果最后解释不通了。

重新进入 WEB-INF/java/liuxing/util/LuJing.java 文件翻看代码,发现原来是没查到路径才返回 true,找到返回 false。

所以对于数据库中不存在的管理员路径 /admin/admin.jsp,返回 true。如果这时候访问者没有 session,或者读不到 admin 的 session,就会返回 true,然后就被重定向到 /buzai.htm 页面了。

所以,这里也不存在越权访问页面什么的漏洞。程序用 session 中的 user 和 admin 属性区分普通用户和管理员用户,猜想也没有垂直越权之类的漏洞,没有仔细查看。根据 session 中的 id 属性区分普通用户,平行越权也放弃了查找。所以不存在访问控制方面的漏洞。

五. 后台任意文件上传漏洞

在"其它管理"—"添加友情链接"处、"软件管理"—"软件发布"页面,都可以上传文件,在 web.xml 中或者顺着 jsp 页面调用寻找,都能够找到具体的逻辑代码

内部代码看起来都是一样的,以 WEB-INF/java/liuxing/util/shangchuan2.java 文件为例,关键代码如下:

其中会判断上传的文件名,要符合正则表达式 ".+\\\\(.+)$",才能够正常上传。即形似 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 了。

吐槽一下,不清楚为什么要过滤 asp,不过滤 jsp? 其实正常上传 jsp 文件,注意 filename 参数的正则匹配就好了

六. 寻找其它漏洞

1、CSRF 漏洞

全系统都没有针对 CSRF 漏洞进行防御,应该存在不少 CSRF 漏洞,不一一分析了。

2、其它

命令执行漏洞,因系统没使用什么框架,所以全局搜索关键字 getRuntime,没发现存在执行系统命令的情况,不存在命令执行漏洞。XXE、反序列化等按照系统的需求,连相应功能估计也没有,所以放弃了。

附:

源码下载地址:

http://down.chinaz.com/soft/25711.htm

参考文章:

铁人下载系统代码审计:

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/

JAVA 代码审计之铁人下载系统 v1.0

http://foreversong.cn/archives/1005

JAVA 代码审计的一些Tips(附脚本)

https://xianzhi.aliyun.com/forum/topic/1633)

最新文章

  1. python3 爬虫
  2. JConsole监控远程Tomcat服务器
  3. @RequestMapping用法详解
  4. MySQL命令实例
  5. mac工具收藏
  6. 记录整合sprinmvc+log4j的的过程
  7. AIX 第4章 指令记录
  8. c# 判断窗体是否永在最前(TopMost),调用windows API
  9. PHPCMS实现文章置顶功能的方法
  10. BeanUtils包的学习
  11. 股票作手回忆录Digest(转)
  12. JAVA文件名命名规范
  13. MySQL中union和order by一起使用的方法
  14. 服务化改造实践 | 如何在 Dubbo 中支持 REST
  15. Ubuntu 下重启网络的方法
  16. 阿里云CentOS安装配置Python3.7及pip3
  17. php如何以post形式发送xm并返回xmll数据
  18. 【python】如何将ipdb的python解释器路径切换至虚拟环境中
  19. 深入学习 Java 序列化
  20. Java基础笔记(3) 进制与进制转换

热门文章

  1. 26、Nginx Uwsgi代理
  2. 2019.9.20使用kali中的metasploi获取windows 的权限
  3. linux 静态路由
  4. flask实现文件的上传
  5. 双向链表/list
  6. 第四章 生命周期函数--36 结合Node手写JSONP服务器剖析JSONP原理
  7. Centos安装nmap端口查看工具
  8. GitHub : Hello World
  9. mybatis 分页插件PageHelper的简单使用
  10. window下,nodejs安装http-server,并开启HTTP服务器