



样本大约 52 MB,表面叫星* 一类名字(显示名里还夹了零宽字符),实际是原生客户端,挂了腾讯 IM、音视频,再加另一套 RTC SDK。后端则是常见开源管理框架改装的业务。
因为刚打到后台网站就被关了,所以留存的一些信息不是很全面,也没有什么图片,为了连贯性下面内容由AI整理(已经过人工核验)。
1. 拿到 APK 之后先看样本
slv.rfbbve.…) | |
….imchat.launcher.LauncherActivity | |
先做常规静态:算哈希、aapt 看权限与组件、apktool / jadx 解包。
ZIP 里三千多项,大量路径伪装在 AndroidManifest.xml/ 下,文件名编码怪异——给人工和解包工具添堵的资源混淆,不是重壳。一方 Java 大量短名(AbstractC2598M、m5940e 一类),但 API 路径、JSON 字段、业务域名是明文。Native 十几枚 .so 基本归到 IM、音视频 SDK,没看到二次解密 DEX 的壳。
静态里更刺眼的是客户端能力:读短信、枚举已装应用、压缩上传相册、精确定位再逆地理、批量同步通讯录。开关多来自远端配置接口;联系人权限文案和真实用途也不一致。全局允许明文 HTTP,没有证书固定,token 进 SharedPreferences——业务能跑就行的风格。
这一步的收获很实在:服务端一定会存这些采集结果,后面业务接口大概率能对上。
2. 三个子域轮询,协议很眼熟
一方业务 API 硬编码在主机池里,用 /healthz 做探活切换,形态类似:
https://houses.1886.example.comhttps://99.encounter.example.comhttps://sso.meet.example.com对象存储另有 oss.example.com 一类域名,上传后的 HTML 可以以 text/html 直接访问。
协议是常见管理框架变体:
GET /captchaImage;→ base64 验证码图 + uuidPOST /login;→username / password / code / uuid;超管再多一个googleCode(TOTP)之后 Authorization: Bearer <JWT>,payload 里是会话键,真正会话在服务端 Redis
路径习惯带尾部分号(/login;、/user/list;、/getInfo;)。本机开着 Fake-IP 类代理时,这些域名会解析到 198.18.0.x,对这个地址段扫端口得到的开放情况与真实主机无关;请求侧关掉环境代理(例如 Session.trust_env = False)之后,流量才回到业务站。
SQL、栈报错会把部署形态漏出来,例如:
jar:file:/www/wwwroot/moos/admin.jar !/BOOT-INF/lib/system-3.8.0.jar !/mapper/moos/MoosUserProfileMapper.xml还能看到云主机命名痕迹、业务 jar 路径。画像很清晰:开源后台 3.8.x,外面再包一层 moos 业务。
公网几乎没有完整的管理前端:根路径 403/404,swagger、actuator、监控页基本 401/403/404。对外可见的,主要是 JSON API。
3. 运营号弱口令打开第一道门
App 注册是开放的,但用户名被强制成 app_*,权限经常为空——适合当普通用户,不适合碰 system。
真正打开用户列表的是一批运营账号。试的时候发现大量规律:用户名等于密码,例如(示意):
afeng01 / afeng01以及 chendalei01、mow01、若干haibodong…、xiaomifeng一类
登录后 getInfo 典型是:
{"permissions": ["my:user:select"],"roles": ["common"]}能做的事很克制:
GET /user/list;(分页、排序——后面注入就在这里)GET /system/user/1;(仅个别 uid 可读,其它常报没有权限访问用户数据)部分业务读接口、上传、群列表
不能做:system 写、重置密码、定时任务、配置明文、角色分配。
3.1 把 IDOR 读到的超管对象当成进了后台
看到 GET /system/user/1 返回完整超管对象(角色里有超级管理员、googleStatus: 1),一度以为已经进后台了。其实 password、二次验证密钥字段被序列化成 null,会话仍是 common,只是只读到了元数据。
3.2 对 login 喷字典把自己封了
风控按真实出口 IP 计数,伪造 X-Forwarded-For 没用;大约连续失败几次就变成当前登录IP已被临时封禁,请1小时后再试。验证码用 OCR 能过,错密一样计入封禁。
JWT 形态上是 HS512 一类,常见 secret 重签走不通,服务端还校验 Redis 里的会话键。
4. OrderBy 布尔盲注
注入点就在运营能调的列表接口:
GET /user/list;?pageNum=1&pageSize=1&orderByColumn=PAYLOAD&isAsc=descAuthorization: Bearer <运营token>报错把 SQL 骨架漏得很清楚:
SELECT p.*, u.user_id, u.moos_id, u.nick_name, u.phonenumber, u.avatarFROM moos_user_profile pLEFTJOIN sys_user u ON u.user_name = p.user_nameWHERE1 = 1ORDERBY ${orderByColumn} descLIMIT ?布尔不靠报错文案,靠首行是谁:
user_id between 1 and 1 and 1 | |
user_id between 1 and 1 and 0 | app_* → False |
在 ORDER BY 里塞布尔表达式,引擎把真假当成 0/1 排序,再配合 isAsc=desc 和 pageSize=1,就能稳定读一位信息。
4.1 过滤器实际卡什么
() | betweenlikerlikeregexp |
=><<>!= | andorxordivmod |
--#/* | case when ... end |
sleepbenchmarkoutfiledumpfile | is nullis not null |
u.passwordu.google_secret … | |
updatexml()extractvalue()(要括号) | 0x... |
单独写 SELECT 有时只是语法错,但子查询要括号,实质没有子查询,也没有跨表一把梭。UNION 和 ORDER BY 叠在一起直接报用法错误。
所以这条洞的定位是:同一张 join 结果上的列值布尔抽取,不是经典 error-based 或 union。
4.2 抽出密码哈希与二次验证密钥
u.password、u.google_secret 可以进 order 子句。前缀扩展用 rlike 加 hex,例如确认 bcrypt 形态:
user_id between 1 and 1 and password rlike 0x5e5c243261# 语义接近 password RLIKE '^\$2a'或:
... and case when password rlike 0x24 then 1 else 0 end逐字符(或逐前缀)扩到完整 60 字符 bcrypt(cost 10),以及 Base32 的 TOTP secret。超管侧手机、邮箱、最近登录 IP 等也能盲注,或靠个别 uid 的 IDOR 补齐;二次验证处于开启状态。
离线撞 bcrypt 后常见词表、主题变体、规则跑过一轮没有命中。在没离线验证哈希之前继续对公网 login 试密,会再次触发封禁。
历史上还有过一个曾是全权限的业务号,盲注读到的密码字面量变成了 disabled,账号不可登——像是网站方清过高权号。
5. 业务 IDOR,数据真正开始往外流
运营 token 对 system 写死,但业务读接口宽松得多:
POST /moos/info/sms;POST /moos/info/contact;POST /moos/info/album;POST /moos/info/app;Content-Type: application/json{"userId": <N>}按 userId 遍历,就能把客户端上传过的短信、通讯录、相册元数据、安装应用列表整包拿走。这和 APK 静态结论完全对得上:客户端采什么,这里就有什么。
同一套只读权限下,列表与日志类接口还能覆盖更广的运营视角:普通用户之外,管理员相关对象、异常或诈骗相关账号的登录与行为痕迹,也可以按权限边界被读出来(具体字段因接口而异,本质仍是鉴权只卡了写,读面过宽)。对复盘谁在什么时间从哪登录、运营号怎么排布很有用,不单是受害人侧资料。
全量用户资料一轮统计口径(约一次完整会话):
单用户内容大致是:基础信息、原始或整理后的短信、通讯录、相册 URL 列表、应用列表、导出摘要。
到这一步,已经可以稳定查看网站数据,于是将管理员、子管理者的登录日志、登陆IP等详细信息打包提交给相关部门。
6. 其它尝试,以及踩过的弯路
6.1 上传与 XSS
通用上传、相册上传都能落到可执行的 HTML(业务域名或 OSS)。可以挂脚本读浏览器里的 token、cookie,打到外带地址。实战里外带长期空——没有证据表明有人在管理场景里点开了这些页;公网又几乎没有完整管理前端,这条路径期望值偏低。
6.2 接口返回操作成功,不等于提权成功
给个人资料接口塞角色、管理员标记、权限数组,常回成功,再查 getInfo 权限不变。改成超管手机号、邮箱会报已存在。重置密码类接口存在,但无权限或方法不对。
6.3 监控、JWT、旁站
定时任务、常见监控组件大多 404 或无权限。JWT 常见 secret 重签失败,且依赖服务端会话。群口令一类 OR 1=1 无效。
admin.、manage.、www. 等子域经常直接不存在。本机 Fake-IP 把业务域名指到 198.18.0.0/16 时,对这段地址做端口扫描,扫到的开放端口对应的是代理虚拟网段,不是业务机真实监听面。
历史公告、字典里出现过表达式注入字符串,没观察到服务端真正执行——更像试探残留或诱饵。
7. 可复现的请求链(摘要)
# 1) 验证码GET /captchaImage;# 2) 运营登录(弱口令示意)POST /login;{"username":"ops01","password":"ops01","code":"...","uuid":"..."}# 3) 盲注烟测GET /user/list;?pageNum=1&pageSize=1 &orderByColumn=user_id between 1 and 1 and 1 &isAsc=desc→ 首行是否为超管账号# 4) 前缀读 password / google_secretorderByColumn=user_id between 1 and 1 and password rlike 0x...# 5) 业务与日志向导出POST /moos/info/sms; {"userId":N}POST /moos/info/contact; {"userId":N}POST /moos/info/album; {"userId":N}POST /moos/info/app; {"userId":N}# 以及列表、登录信息等只读接口(视权限返回管理员、异常账号痕迹)8. 数据已经在手,站点先没了
到导出稳定跑通的时候,手里已经不只有受害人维度的短信和通讯录,也包括运营视角下能看到的管理员相关信息、异常账号的登录与行为痕迹等只读数据。技术路径上,下一步很自然会去碰更高权限:离线继续磨超管哈希,有明文后再带验证码和 TOTP 登录,或者在写权限打开后看定时任务、表达式、文件写入一类能否走到命令执行。
还没来得及把这一截做实,站点先关了。
表现很干脆:业务子域陆续解析失败,根域 whois 上出现停用类状态,DNS 不再给出可用地址。不是换了个新 host 让你追,而是整片直接不解析。在线利用窗口关掉之后,本地只剩已经落盘的导出、静态报告和离线哈希材料。
目前已将管理员、子管理者的登录日志等详细信息打包提交给相关部门。
9. 几点收束
客户端逆向的价值,常常是主机池、路径习惯,以及服务端一定存了什么,而不是藏一个隐藏管理首页。
这类后台要习惯尾部分号、验证码、Redis 会话,以及 HTTP 200 操作成功不等于权限真改了。
OrderBy 注入在禁括号、禁比较符时仍可能活,靠 between、rlike、case when 和排序侧信道。
弱口令运营号往往比硬撞超管 bcrypt 便宜;但 common 会把你锁在读面——读面本身已经足够危险。
风控按真实 IP:字典优先打离线哈希;在线试密前先本地验证。
XSS 在缺少管理前端、缺少人工点附件的环境里,期望值要放低。
免责声明:
本文所有黑产相关信息、登录IP等均已提交至相关公安机关备案,涉及内容已做严格脱敏处理。文章所提及的技术均为网络安全领域的常规渗透测试方法,不包含任何框架 0day 漏洞、新型攻击手段及未公开的技术细节。
请务必遵守国家法律法规及网络安全相关规定,严禁利用本文所述技术从事任何非法测试、攻击等危害网络安全的行为。因传播、使用本文信息而导致的任何直接或间接损失、法律责任,均由使用者自行承担,与文章作者及发布方无涉。本文允许转载,但转载时需在显著位置标明原文出处及作者信息。
夜雨聆风