0x01 背景说明
我们在渗透测试过程中,可以很容易发现weblogic的 server name
一旦被修改,其web应用有一个目录就会发生改变,导致我们在部署war拿shell时受阻。
比如bea_wls_internal这个weblogic自带web应用的web目录物理路径为:
weblogic10.3.6.0\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_internal\bea_wls_internal\9j4dqk\war
PS:为了后面的讨论,这里统一下概念,域名为base_domain
,server name
为AdminServer
,web应用名为bea_wls_internal
,伪随机目录为9j4dqk
。
这时如果server name
修改为c0ny1
的话,经过测试其伪随机目录会变成qn64ct
,即该web应用物理路径变为:
weblogic10.3.6.0\user_projects\domains\base_domain\servers\c0ny1\tmp\_WL_internal\bea_wls_internal\qn64ct\war
0x02 真随机 or 伪随机?
在此前我一直以为改目录是随机的无法。直到我做了下面的测试,将两个域的server name
都改为c0ny1
。
发现两个域下相同web应用的随机目录名相同,这说明随机数目录其实是伪随机,它是有算法来生成的。而通过结果我们很容易就判断出该随机数和域名无关,和server name
与application name
有关!
0x03 探究生成算法
于是我打算跟踪下weblogic源码,扒出负责生产伪随机数的算法函数。由于其生成伪随机目录在weblogic未启动完全情况下,故通过weblogic配置的调试比较难。这种情况下更好的思路是插桩,但要插哪个函数的桩呢?
我在翻阅weblogic的源码(weblogic.jar)时,着重关注文件操作和部署接口的代码,发现了一个相关性很大的方法。该函数就在weblogic的路径工具类(weblogic.application.utils.PathUtils)中。
在判断不失误的情况下,我们只要知道其传入的参数值就知道改函数如何使用了。为此我编写了如下代码,使用javassist将打印函数参数值的代码注入到该函数中。
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
| import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod;
public class Test { public static void changeMethode() { try { ClassPool.getDefault().insertClassPath("/Users/c0ny1/IdeaProjects/weblogic-path-test/lib/weblogic.jar");
CtClass cls = ClassPool.getDefault().getCtClass("weblogic.application.utils.PathUtils"); CtMethod m = cls.getDeclaredMethod("generateTempPath"); m.setBody("{StringBuffer var3 = new StringBuffer();\n" + " if ($1 != null) {\n" + " var3.append($1);\n" + " }\n" + "\n" + " if ($2 != null) {\n" + " var3.append(\"_\").append($2);\n" + " }\n" + "\n" + " if ($3 != null) {\n" + " var3.append(\"_\").append($3);\n" + " }\n" + "\n" + " String str = $2 + java.io.File.separator + Long.toString((long)Math.abs(var3.toString().hashCode()), 36);\n" + " System.out.println(\"[+] p1:\" + $1);\n" + " System.out.println(\"[+] p2:\" + $2);\n" + " System.out.println(\"[+] p3:\" + $3);\n" + " System.out.println(\"[+] \" + str);\n" + " return str;}"); cls.defrost(); cls.writeFile("./PathUtils.class");
} catch (Exception e) { e.printStackTrace(); } }
public static void main(String[] args) { changeMethode(); } }
|
将插桩后的PathUtils类通过Winrar软件覆盖weblogic.jar原来的类,然后重新启动weblogic,即可从控制台查看到如下:
由此我们知道web应用bea_wls9_async_response的随机目录被生成时,该函数被调用并传入server name
和application name
,这也验证我们之前的猜想。
1
| generateTempPath("c0ny1","bea_wls9_async_response","bea_wls9_async_response.war")
|
0x04 伪随机目录生成代码编写
到这里写计算伪随机目录生成程序就是很简单的事了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class WeblogicPathBuilder { public static String generateTempPath(String paramString1, String paramString2, String paramString3) { StringBuffer stringBuffer = new StringBuffer();
if (paramString1 != null) stringBuffer.append(paramString1);
if (paramString2 != null) { stringBuffer.append("_").append(paramString2); }
if (paramString3 != null) { stringBuffer.append("_").append(paramString3); } return Long.toString(Math.abs(stringBuffer.toString().hashCode()), 36); }
public static void main(String[] args) { String ServerName = args[0]; String AppName = args[1]; String AppWarName = AppName + ".war"; System.out.println(generateTempPath(ServerName,AppName,AppWarName)); } }
|
计算结果和weblogic实际生成完全吻合!!!
之后的几天逛Github时,发现早就有人发现其规律。
https://github.com/dr0op/WeblogicScan/blob/master/app/plugins/CVE-2019-2618.py