Apex 5复用模态页展示同结构表的防SQL注入方案问询
安全复用Apex 5模态报表页展示同结构表的解决方案
Hey there! 直接传递表名作为参数确实是个高危操作,攻击者很容易篡改参数来访问你不想暴露的表。针对你有12张结构一致表的场景,这里有一套通用、安全的实现方案,既能复用模态页,又彻底规避SQL注入风险:
1. 先搞个合法表名白名单
首先把所有允许访问的表名维护成一个安全列表,确保只有你指定的表能被调用:
- 你可以在Apex里创建一个应用级静态LOV,把
copper、explain、fated、truck、neat、unite、branch、educated、tenuous、hum、decisive、notice这些表名加进去,设置成仅内部使用(别对外暴露这个LOV)。 - 或者在PL/SQL里直接定义一个映射数组,把表名和对应的ID绑定起来,后面会用到。
2. 传表的映射ID,而非直接传表名
别直接把表名当页面参数传!改成传数字ID,比如用1对应copper,2对应explain,以此类推。
- 比如每个页面打开模态页的按钮,设置跳转参数为
PXX_TABLE_ID(XX是你的模态页页面号),值就填对应表的ID。 - 这样就算攻击者乱改ID,超出你定义的范围就会被拦截,还避免了直接暴露表名的风险。
3. 模态页内做验证+安全构建动态SQL
在模态页的报表区域,绝对不能直接用用户传入的参数拼SQL!必须先验证参数合法性,再用安全方式构建查询:
方案A:用PL/SQL动态生成报表(推荐)
把报表类型改成PL/SQL动态内容,然后写下面的逻辑:
DECLARE l_table_id NUMBER := :PXX_TABLE_ID; -- 替换成你的模态页参数名 l_table_name VARCHAR2(100); l_sql VARCHAR2(4000); -- 定义ID和表名的映射白名单 TYPE table_map_rec IS RECORD ( id NUMBER, name VARCHAR2(100) ); TYPE table_map_tab IS TABLE OF table_map_rec; l_table_maps table_map_tab := table_map_tab( table_map_rec(1, 'copper'), table_map_rec(2, 'explain'), table_map_rec(3, 'fated'), table_map_rec(4, 'truck'), table_map_rec(5, 'neat'), table_map_rec(6, 'unite'), table_map_rec(7, 'branch'), table_map_rec(8, 'educated'), table_map_rec(9, 'tenuous'), table_map_rec(10, 'hum'), table_map_rec(11, 'decisive'), table_map_rec(12, 'notice') ); BEGIN -- 根据ID找对应的表名,找不到就报错 SELECT name INTO l_table_name FROM TABLE(l_table_maps) WHERE id = l_table_id; -- 用DBMS_ASSERT验证表名合法性,再拼SQL(列名固定,因为表结构一致) l_sql := 'SELECT col1, col2, col3 -- 替换成你的实际列名 FROM ' || DBMS_ASSERT.SQL_OBJECT_NAME(l_table_name); -- DBMS_ASSERT会确保这个表名是数据库里合法存在的,进一步防注入 -- 执行查询并输出报表 APEX_EXEC.REPORT(l_sql); EXCEPTION WHEN NO_DATA_FOUND THEN HTP.P('非法请求,请返回重试'); END;
方案B:用应用项+授权规则
- 模态页加载时,根据传入的
PXX_TABLE_ID,把对应的合法表名赋值给一个隐藏应用项(比如APP_ALLOWED_TABLE),赋值前必须验证ID是否在白名单里。 - 然后报表的SQL源这么写(必须用DBMS_ASSERT包裹):
SELECT col1, col2, col3 -- 替换成你的实际列名 FROM DBMS_ASSERT.SQL_OBJECT_NAME(:APP_ALLOWED_TABLE)
- 再给模态页加个授权规则,只有当
APP_ALLOWED_TABLE的值在白名单内时,页面才能访问。
4. 额外的安全加固小技巧
- 禁用直接URL访问:在模态页的页面属性里,把“会话状态保护”设为“必须通过会话状态保护访问”,防止攻击者直接构造URL篡改参数。
- 加审计日志:把每次访问模态页的用户、请求的表ID/名称记录下来,方便后续排查问题。
- 最小权限原则:确保Apex用的数据库用户只有这12张表的SELECT权限,没有其他表的访问权限——就算万一出问题,攻击者也摸不到敏感数据。
这套方案完全满足你的需求:既复用了同一个模态页,又彻底堵死了SQL注入的漏洞,而且适用于所有同结构表的场景。
内容的提问来源于stack exchange,提问作者nocapo
相关产品推荐
相关产品推荐

