一、环境搭建

项目地址:https://github.com/wuxinyu3366/smbms

这是狂神学Java的一个项目,拿过来做一次审计

我的环境配置:IDEA 2023.1、Tomcat 8.5.81、MySQL 5.7.26、JDK1.8.0_192

image-20250729142418817

在项目结构中配置JDK

image-20250729142513338

这两个地方都需要配置成同一个JDK 1.8的版本

在mysql中创建对应的数据库,修改mysql账号密码

image-20250729142716408

创建数据库时注意使用utf8 和 unicode,运行.sql 文件即可

image-20250729142832510

审计方法和思路参照:【基础知识】Java代码审计(持续更新)

二、pom.xml 文件审计

针对maven项目的Java项目,我们可以优先审计pom.xml 文件中第三方的风险组件

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>

以上两处均存在高危漏洞风险

三、SQL注入审计

在pom.xml 文件中无mybatis 第三方组件,且无Mapper.xml文件存在,则该项目并没有使用mybatis,使用常规的关键字搜索法。

搜索 prepareStatement 和 PreparedStatement 关键字发现大部分均使用预编译写法

image-20250729150506053

搜索select、update等关键字均未发现拼接写法

四、XSS审计

全局搜索 <%= 关键字

image-20250729151829344

发现是head.jsp,根据推断这个应该是后台的头部jsp 页,只要在后台就可以触发

image-20250729151728910

五、文件操作审计

搜索 file 关键字

image-20250729152235153

这一看都少的很,包括 include、read 等关键字是一样

六、代码/命令执行

搜索 exec(、system关键字

image-20250729152657311

并没有可利用的地方

七、请求参数关键字

该项目使用的是 servlet,可搜索的关键字有:

1
2
3
4
5
6
// Servlet中的请求参数处理
request.getParameter(String name)
request.getParameterValues(String name)
request.getParameterMap()
request.getAttribute(String name)
request.getHeader(String name)

在BillServlet.java接收前端传递的参数,简单做了一个空检查,就直接放到前端的value值

image-20250729191926849

在web.xml 中,BillServlet 对应的接口是/jsp/bill.do

1
2
3
4
<servlet-mapping>
<servlet-name>BillServlet</servlet-name>
<url-pattern>/jsp/bill.do</url-pattern>
</servlet-mapping>

根据上方逻辑,推算出payload

1
http://localhost:8080/smbss_war/jsp/bill.do?method=query&queryProductName=%22%3E%3Cscript%3Ealert(1)%3C/script%3E&queryProviderId=0&queryIsPayment=0

image-20250729194015346

同样原理的还有用户查询等

image-20250729194848711

在用户详情中,发现直接展示了用户信息,且添加用户时并未校验合理性

image-20250729205045036

直接添加一个带payload 的用户,造成存储型xss

image-20250729205141521

八、越权审计

在sysFilter中,看到只要有session均可通行

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;

//过滤器,从session中获取用户
User user = (User)request.getSession().getAttribute(Constants.USER_SESSION);
if(user == null) {//已经被移除或者注销了,或者未登录
response.sendRedirect(request.getContextPath()+"/error.jsp");
}else {
filterChain.doFilter(servletRequest, servletResponse);
}
}

且在其他高权限操作中,均未判断当前用户身份,拿创建用户举例

image-20250729210232825

我们以张华的身份创建了两个系统管理员

九、黑盒+白盒审计

看到密码修改处,当我们输入旧密码就直接做好了校验,此处逻辑有些问题

image-20250729221454125

在后端代码中,我们发现他直接对新密码就行了修改,而旧密码的校验是在前端通过ajax校验的

image-20250729221845362

直接构造请求,绕过旧密码校验

1
http://localhost:8080/smbss_war/jsp/user.do?method=savepwd&newpassword=123

image-20250729224217846

查看数据库确实已经修改了密码