jshERP代码审计(一)
P4r4d1se 发表于 广东 漏洞分析 1293浏览 · 2024-05-07 05:38

1.概述

SpringBoot+Mybatis的一个erp系统,项目结构如下:

2.SQL时间盲注

MaterialMapperEx.xml中,发现两个没有预编译的字段:

跟到service层的MaterialService.java

public int getListWithStockCount(List<Long> depotList, List<Long> idList, String position, String materialParam, Integer zeroStock) {
        return materialMapperEx.getListWithStockCount(depotList, idList, position, materialParam, zeroStock);
    }

再跟到controller层的MaterialController.java,发现这两个参数经过了StringUtil.safeSqlParse()的过滤:

跟过去StringUtil.java,看到过滤了引号、注释符、分号和一些SQL关键字,但是没有过滤括号、sleep、case之类的,可以尝试时间盲注:

public static String safeSqlParse(String originStr){
        return originStr.replaceAll("(?i)" + regex, "");
    }

    public final static String regex = "'|#|%|;|--| and | and|and | or | or|or | not | not|not " +
            "| use | use|use | insert | insert|insert | delete | delete|delete | update | update|update " +
            "| select | select|select | count | count|count | group | group|group | union | union|union " +
            "| create | create|create | drop | drop|drop | truncate | truncate|truncate | alter | alter|alter " +
            "| grant | grant|grant | execute | execute|execute | exec | exec|exec | xp_cmdshell | xp_cmdshell|xp_cmdshell " +
            "| call | call|call | declare | declare|declare | source | source|source | sql | sql|sql ";

部署环境测试一下,果然可以时间盲注:


看看后端MySQL执行日志:

SQLMap跑一下:

3.存在限制的文件上传

全局搜upload,在SystemConfigController.java找到文件上传的路由,这里没有对文件名进行过滤,fileUploadType在配置文件里默认为1,所以走的是systemConfigService.uploadLocal()


跟踪uploadLocal()函数到service层的SystemConfigService.java,这里的bizPath是可控的且没有过滤,filepath在配置文件里默认为/opt/jshERP/upload,文件名处理也没有过滤后缀名:

但有一点小问题,在于这段,bizPath拼接了一个根据token截取的租户id,这会导致最后上传的目录受到影响:

String token = request.getHeader("X-Access-Token");
Long tenantId = Tools.getTenantIdByToken(token);
bizPath = bizPath + File.separator + tenantId;
/**
     * 根据token截取租户id
     * @param token
     * @return
     */
    public static Long getTenantIdByToken(String token) {
        Long tenantId = 0L;
        if(StringUtil.isNotEmpty(token) && token.indexOf("_")>-1) {
            String[] tokenArr = token.split("_");
            if (tokenArr.length == 2) {
                tenantId = Long.parseLong(tokenArr[1]);
            }
        }
        return tenantId;
    }

这个拼接大大影响了利用,但我暂时没找到绕过的办法,虽然getFileName()没有过滤文件后缀名,但是过滤了斜杠,导致没办法从文件名这里跨目录,同时用户的token也是不可控的:

public static String getFileName(String fileName){
    //判断是否带有盘符信息
    // Check for Unix-style path
    int unixSep = fileName.lastIndexOf('/');
    // Check for Windows-style path
    int winSep = fileName.lastIndexOf('\\');
    // Cut off at latest possible point
    int pos = (winSep > unixSep ? winSep : unixSep);
    if (pos != -1)  {
        // Any sort of path separator found...
        fileName = fileName.substring(pos + 1);
    }
    //替换上传文件名字的特殊字符
    fileName = fileName.replace("=","").replace(",","").replace("&","");
    return fileName;
}

部署测试:

4.Swagger未授权访问

系统集成了swagger,在Swagger2Config.java配置了@EnableSwagger2注解但没有启用@EnableSwaggerBootstrapUI注解,所以有API接口但没有UI页面:

没有在application.properties给swagger接口配置认证,并且在FilterLogCostFilter.java里把API加到了白名单,所以可以在不登录的情况下直接访问:

部署测试:

5.攻心为上的Fastjson

在pom.xml中看到fastjson的版本为1.2.83:

搜一下parseObject,serach可控,可以利用的路由很多,就不细说了:


1.2.83的fastjson暂时没有公开的利用方式,只能通过java.net.InetSocketAddress来进行dnslog,没什么用,但可以在HW的时候折磨防守方。根据我的经验,你只需要在晚上8点40左右交班的前夕,挑两个关键资产打个dnslog让他们应急,可以有效延长白班兄弟的工作时间,搞他心态:

0 条评论
某人
表情
可输入 255