简介:面向SAP系统审计人员及企业内控、IT合规岗位的一份程序清单,将审计流程按阶段拆解:先从组织架构、安全策略、系统架构、接口与版本模块等维度完成总体了解,再细化到SAP客户端、公司代码、业务范围、工厂、采购组织、销售组织等配置对象的核对,并延伸至设计实施阶段的规划、人员配备、变更控制与项目治理评估。资源为1个doc文档,约112KB,内容以列表式检查项呈现,同时标明了T000、T001、T024W等常用配置表的查询路径,适合在正式审计前逐项梳理证据、制定访谈与测试计划。已有408人学习/下载。通过这套框架,可快速定位需要获取的制度文档、系统表与配置参数,形成可复用的SAP审计工作底稿基础,尤其适合初次承担SAP审计任务或需要完善审计程序的团队参考。
1. 审计程序没那么玄:先在表里把“痕迹”找齐
很多同事一提 SAP 审计程序,就觉得应该有一套现成报表点一下就能导出“谁改了什么”。真实情况恰恰相反:SAP 系统里的登录记录、权限变更、配置修改散落在几十张表里,不同模块还有各自的日志切换开关,直接看表经常得到一段零散的凭证号,拼不出完整证据链。所谓审计程序,本质是把这些痕迹按审计期间串成一条可验证的线索,交给 Basis、财务审计和权限整改项目去回答“谁、在什么时候、通过什么入口、动过什么”。这篇文章不适合只想看概念的人,适合已经接到审计任务、需要立刻知道先从哪些表入手,以及准备自己写一段 ABAP 报表把审计结果固化下来的从业者。
2. 审计程序要看哪些表?从登录日志到变更凭证的取证地图
2.1 登录、密码和锁定状态:审计程序先查的几张表
一次正经的 SAP 审计,通常从“用户是否存在未使用的权限”开始。最常用的是USR02,它是用户主数据里登录相关信息的汇总表。审计时重点关注几个字段:UFLAG是用户的锁定状态,很多系统里存在大量“已锁定但权限仍然有效”的账号,这类账号在权限矩阵审计里是灰点;USTYP是用户类型,Dialog、Service、System、CPIC 等不同类型,审计策略完全不同;TRDAT是用户上次直接登录日期,结合当前日期一算,就能找出长期未登录但还没被锁定的账号;GLTGV和GLTGB是账号的有效期起止。审计程序里最常做的一类检查,就是把这些字段组合成一张“用户清单报表”,再按日期区间过滤。
表USR40则是系统级的非法密码表。严格的信息安全审计会要求把常见弱密码、默认密码往里灌,但实际操作中很多项目只是象征性放几条,审计程序应该把USR40的内容导出来核对入口配置。密码规则相关的参数也不该漏,比如登录失败次数限制、密码有效期,这些参数在 RZ11 里可以查到,最好把参数名和当前值一并打印进审计底稿,否则审计报告里写“密码策略未见异常”会显得没有依据。真正做过 SAP 审计的人都会先做这一层“用户画像盘点”,再往下钻配置。
| 表名 | 作用 | 审计关注点 |
|---|---|---|
| USR02 | 用户登录状态与主数据信息 | 锁定状态、最后登录日期、有效期 |
| USR40 | 系统级拒绝密码表 | 是否覆盖弱密码、密码是否未过期 |
| AGR_USERS | 用户与角色的直接分配关系 | 角色分配是否超过有效期 |
| AGR_AGRS | 角色之间的组合关系 | 是否存在角色互相嵌套、聚合后放大权限 |
登录日志这块还有一个容易漏掉的细节:USR02只能看到最近一次的登录日期,历史登录行为要依赖系统安全审计日志,也就是事务代码 SM19 和 SM20 的配置。审计人员通常要求 Security Audit Log 至少打开到中等级别,否则只能证明“账号当前没登录过”,无法证明“这个用户之前没做违规操作”。很多项目在初期实施时不考虑审计,等到内审要求提供近三个月的登录记录才去补,结果只能补到开关打开之后的数据,这就是审计程序最典型的踩坑场景。
2.2 变更文档:谁改过配置和主数据,靠 CDHDR/CDPOS 还原
用户权限之外,审计程序另一个硬需求是“谁改了什么”。SAP 里记录配置和主数据变更的标准机制是 change document,也就是变更文档。表头是CDHDR,记录了这一次变更发生在哪个对象类、哪个对象 ID、什么时间、哪个用户名、什么事务代码;明细表是CDPOS,记录到字段级:旧值、新值、字段名。审计程序把这两张表关联起来,才能还原出“张三在昨天上午十点把销售订单类型 A 的号码范围从 100000 改成了 200000”。
但变更文档不是所有表都自动记录。很多开发者自己建的自定义表,如果建表时没勾“记录数据更改”,那这张表的任何修改都不会进CDHDR。这时候你在审计程序里查不到记录,不代表没人改过,只是系统根本没有留痕。判断方法非常简单:在数据字典 SE11 里打开这张表,看“更改文档”字段有没有打勾;没勾的话,要么补上这个设置并重新激活,要么把这张表列入“无审计轨迹”的清单,明确告诉业务方这属于审计盲区。
业务表的变更文档检查和定位,常用事务代码是SCAT,它按对象类别列出哪个业务对象开启了变更文档。像是通过 SM30 维护的配置表,只要对象本身支持变更文档,入口方式其实不太重要,不管你是用传统 SM30 还是 Fiori 里的配置维护应用,落到后台都是同样的对象写日志。审计程序在制作“变更轨迹报表”时,通常会要求把CDHDR的事务代码、用户、时间作为维度,再挂CDPOS的字段级 diff。直接在CDHDR单表查会很空,容易漏掉关键数据。
2.3 权限审计起点:SUIM 信息中心和标准用户清单报表
权限审计如果从零手写,工作量会失控,因为 SAP 授权模型本身很复杂:用户直接拿到角色,角色里有复合角色,复合角色展开到单角色,单角色再映射到权限对象和字段级权限约束。真正决定用户能干哪些事务的是经过合法展开后的用户主权限。好在 SAP 给了现成的信息中心 SUIM,官方定位就是给审计和权限管理员用的查询入口,不用每一段都自己拼 SQL。
操作层面,用 SUIM 可以按事务代码查“哪些用户拥有某事务的执行权限”、按权限对象查“哪些角色拥有 S_TCODE 之外的敏感对象”、按角色查“角色分配给谁、继承关系是什么”。配合标准报表 RSUSR002、RSUSR003 等,可以直接出用户列表和权限列表。实际项目里最常做的检查是“拥有敏感事务代码的用户清单”,敏感事务代码通常包括创建用户、修改角色、直接修改表数据、传输请求导入等。即使是权限设置再混乱的 client,也能通过 SUIM 把带S_TCODE的敏感项筛出来,再回到USR02判断这些用户是否还在用。这样做的好处是审计程序不用完全从零造轮子,先拿 SUIM 做初筛,再用 ABAP 报表做二次加工和留档。
3. 自己写一个 SAP 审计报表:从数据探查到 ABAP 代码骨架
3.1 先用 SE16N 做数据探查:别急着写代码
写审计程序之前,我会建议先在 SE16N 里把目标表的字段构成、数据量级、日期范围摸一遍。直接写代码容易遇到“字段名写错但编译通过”“筛选条件把关键数据过滤掉”这类问题,翻车成本比想象中高。SE16N 的入口路径是事务代码 SE16N,输入表名后进入查询界面,左侧点击字段选择,可以把自己关心的字段添加到输出列表,再在下方设置过滤条件。
比如查USR02时,先只过滤UFLAG = '01'之类表示锁定的标志,看看锁定用户有多少;再清空条件,按TRDAT区间查最近登录用户数量。这个过程是为了确认审计程序需要处理的数据形态。要注意的是 SE16N 默认虽然能改数据,但审计场景下千万不要用它在界面里直接更新字段,那本身会成为新的审计风险点。观察数据时也建议使用按需读取字段,不要一次把明细字段全部选中,否则几百万行数据会把报表会话拖死。
3.2 一个可跑的查用户清单报表:用户类型、有效期、最后登录一次查清
做审计报表时不会被翻车惯?一个相对标准的 ABAP 骨架长这样。它的作用是把用户主数据、最后登录时间、当前有效期和角色分配塞进一张内表,再输出 ALV 清单。以下代码是一段可编译的演示版本,正式环境请加权限检查和错误处理。
REPORT z_audit_users. TABLES: usr02, agr_users. SELECT-OPTIONS: s_bname FOR usr02-bname DEFAULT '*', s_trdat FOR usr02-trdat, s_ustyp FOR usr02-ustyp. TYPES: BEGIN OF ty_user, bname TYPE usr02-bname, ustyp TYPE usr02-ustyp, trdat TYPE usr02-trdat, uflag TYPE usr02-uflag, gltgv TYPE usr02-gltgv, gltgb TYPE usr02-gltgb, roles TYPE string, END OF ty_user. DATA: gt_user TYPE TABLE OF ty_user, gs_user LIKE LINE OF gt_user, ls_agr TYPE agr_users, lv_roles TYPE string. START-OF-SELECTION. SELECT bname ustyp trdat uflag gltgv gltgb FROM usr02 INTO CORRESPONDING FIELDS OF TABLE gt_user WHERE bname IN s_bname AND trdat IN s_trdat AND ustyp IN s_ustyp. LOOP AT gt_user ASSIGNING FIELD-SYMBOL(<fs_user>). CLEAR: lv_roles, ls_agr. SELECT agr_name FROM agr_users INTO ls_agr-agr_name WHERE uname = <fs_user>-bname AND agr_type = 'S' AND from_dat <= sy-datum AND to_dat >= sy-datum. IF lv_roles IS INITIAL. lv_roles = ls_agr-agr_name. ELSE. CONCATENATE lv_roles ls_agr-agr_name INTO lv_roles SEPARATED BY ','. ENDIF. ENDSELECT. <fs_user>-roles = lv_roles. ENDLOOP. LOOP AT gt_user INTO gs_user. WRITE: / gs_user-bname, gs_user-ustyp, gs_user-trdat, gs_user-uflag, gs_user-roles. ENDLOOP.这段代码核心是先按参数过滤USR02,再通过AGR_USERS把每个用户直接分配的有效单角色拼成一串。AGR_TYPE = 'S'表示只看单角色,复合角色先不展开,这正是审计上常用的“先看直接分配,再做派生分析”的思路。FROM_DAT和TO_DAT是角色有效期,审计时通常只取当前生效的角色,避免把过期角色也计算进去导致权限虚高。输出没有走 ALV,真实场景建议把gs_user传进 SALV 模型,审计人员可以按角色列过滤。
3.3 把报表跑成变式:审计期间、用户组、敏感权限过滤
这套 ABAP 代码在不同审计口径下需要反复跑,比如常规季度审计、专项权限整改、离任账号盘点。没必要每次都手工改筛选条件,用变式存储参数就够了。执行程序进入选择屏幕后,在浏览器或 SAP GUI 8.10 的工具栏里找“变式”按钮,选择“保存”,把当前筛选条件存成一个有业务含义的名字,比如AUDIT_2025_Q1_EXCLUDE_GWS。我这边从老版本 GUI 到 8.10 都跑过类似程序,关键是变式名要规范,否则一年下来几十个变式没人分得清。
参数设计上,S_TRDAT是审计期间最常用的过滤项,传日期区间就能看出谁在那段时间登录过。S_USTYP建议留空,除非你想要专门排除通信用户。S_BNAME默认*,但做离任审计时可以直接传一个用户名列表,也可以排除 VIP 用户组。变式保存好之后,后续还要配合后台作业做周期性审计留档,这就能把“临时查一下”变成“每月定时出底稿”。从审计证据完整性角度看,变式里最好固定一个“导出报告标题”,把程序名、变式名、运行时间打进去,免得后期对不上号。
4. SAP 审计程序落地避坑指南:日志丢失、结果脏、磁盘爆掉的真相
4.1 日志查不到:SM30 变更文档没开、CDHDR 进了归档
现象:审计程序跑完,发现某个配置表在CDHDR里一张凭证都查不到,但业务人员坚持说上个月改过。
原因有两层。第一层是变更文档根本没开,尤其是自定义表和部分维护视图,系统从设计上就没有记录痕迹。第二层是历史数据被归档,CDHDR和CDPOS这类日志表的数据量起来之后会做归档,归档后再通过 SE16N 直查当然查不到旧数据,它只是被挪到了归档文件里。这是 SAP Basis 体系中非常常见的仓库清理策略,不是数据丢失。
解决:先查SCAT,确认这个业务对象是否支持且开启了变更文档;如果没开,补上配置并让相关事务代码重新激活。如果是归档原因,用事务代码SARA去查归档文件,不能指望审计程序直接读在线表。遇到归档场景,审计底稿里应同时保存“查询时间”和“数据可追溯区间”,否则这张报表会被审计委员会判定为证据不完整。
4.2 报表结果与实际权限不一致:角色缓存和派生角色
现象:SUIM 或自写报表显示某用户拥有一个高危角色,但用户在实际测试时打开事务代码提示没有权限,反过来也出现过报表里看不到角色,用户真能执行的情况。
原因:权限检查的运行时数据,也就是用户主权限,来源于角色展开后的授权配置,不是简单的一张表。角色改了菜单、删了权限对象,如果没做用户比较和权限生成,用户主权限里还残留着旧授权;相反,如果通过后端表直接插了权限数据,而没有走标准角色生成,内存里可能已经用了新配置,查询表里还没有。官方有一个比较过程,一般通过 SU01 或权限调整批次去同步,现场经常看到这一层没跑就去查表,结果自然对不上。
解决:先做一次完整的用户权限比较,让角色变更正确展开并写回USR04、UST04等相关表,再重新跑审计报表。自写报表建议明确标注“来源:权限主数据表”,不要直接声称这就是有效权限。作为审计底稿,要用实际事务代码的AUTHORITY-CHECK做抽样验证,靠表结果一言堂很容易翻车。
4.3 审计日志磁盘爆掉:SM19/SM20 只开后不清理
现象:开启安全审计日志之后,系统过几周突然出现大量写日志失败告警,登录变慢,甚至部分批处理报错。进 SM20 一看,审计日志文件已经占满独立盘。
原因:安全审计日志本身受到严格写入保护,不像普通应用日志能随便删除。很多人开了 SM19 审计级别后没有同步留意文件保留策略。审计日志按天写盘,量小一天几百 MB,量大的 client 一天几个 GB 都不奇怪,一旦空间耗尽,后面的证据会直接缺一段。
解决:做审计程序的人要把“日志留档策略”也当成程序的一部分。建议先确认审计日志所在挂载目录,SAP Basis 收到空间告警时不要急着扩容,先看 SM20 里的日志跨越时间段和文件大小。要把保留周期做成参数,比如只保留 180 天,超期文件转入归档系统。还要注意跨 client 场景,多个 client 的日志会按不同规则写入,只清理一个 client 不够。日志缺失时段要记录原因,审计底稿里主动说明,比被动被发现要好得多。
4.4 传输请求和配置变更对不上:E070 只看请求头没用
现象:审计时想验证“这个配置到底走没走传输”,查 E070 能看到请求头,但打开传输任务单,里面只有程序对象,没有业务配置数据,于是断言该对象没有传输。
原因:传输请求分好几种对象类型,程序、类、表结构走的是对象列表,而配置表内容通常通过E071K记录“表名加表键”。E070 是请求头,E071 是对象清单,还要压到 E071K 才能看到具体是哪些配置条目被发到目标系统。很多业务配置表本身就是跨系统覆盖的,请求头显示导入成功,目标系统里却因为覆盖顺序问题被别的请求冲掉了。
解决:审计传输链路时,至少同时核对E070、E071、E071K三段数据。还要检查目标系统侧的导入日志,以及导入之后的覆盖规则。传输日志里带着修改者、请求任务、导入时间和系统 ID,这才是审计上最硬的证据。只看 E070 的结果往往只能证明“有人建了请求”,证明不了“目标系统真的生效”。
4.5 直连数据库查表:跨 client 与归档数据双重复合
现象:为了快速出审计数据,有人不通过 SAP 应用层,直接用外部工具连接底层数据库执行 SQL。结果发现同一张日志表的数据量和 SE16N 能看到的对不上,最终审计结果被质疑。
原因:底层表几乎都带MANDT字段,不同 client 的数据是按字段区分的。直连数据库时如果漏写 client 条件,会把所有 client 的数据混在一张结果集里;SE16N 则是默认登录 client 后自动带上的。此外,直连数据库看不到逻辑归档状态,可能在读已标记删除的历史行。对 SAP 审计场景而言,这样的数据既不能通过标准权限控制,也无法追踪用户登录上下文,严格讲不应直接作为审计凭证。
解决:除非做紧急数据救援,审计程序统一走应用层,要么 SE16N、SUIM,要么 ABAP 自写报表。这样系统中保留的授权检查、变更文档逻辑、client 上下文都会自动生效。如果确实必须底层取数,要在导出脚本里强制限定MANDT = 800,并且和 SE16N 结果做抽样比对,比对过关后再放进底稿。
5. 把审计程序变成每月留档:后台作业、路径命名、证据固化
5.1 用后台作业把审计报表定期导出到应用服务器
一个能重复执行的审计程序,最后一定要能自动落地成文件。最简单的方式是先把程序输出打成 ABAP 列表,通过打印到外部系统再转文本,但这种方式在特殊字符多时不够稳。常见做法是直接在 ABAP 里用OPEN DATASET把结果写到应用服务器目录,再通过后台作业每天或每月跑一次。
DATA(lv_path) = `/usr/sap/audit/` && sy-datlo && `_users.txt`. OPEN DATASET lv_path FOR OUTPUT IN TEXT MODE ENCODING DEFAULT. LOOP AT gt_user INTO gs_user. TRANSFER gs_user-bname TO lv_path. ENDLOOP. CLOSE DATASET lv_path.这里注意不要用GUI_DOWNLOAD这类依赖前端会话的函数,后台作业没有输入窗口,用它会直接报错。路径里带上系统日期,文件名规范成“程序名_日期_变式名”,是审计底稿管理里最省心的习惯。防止一次后台作业异常导致文件覆盖,比较好的做法是先写临时文件,成功后再改名成正式文件名。
5.2 给导出的审计结果算一个哈希值,相当于给底稿吃了后悔药
定期导出 ALV 列表只是第一步,主持人还会问“你怎么证明这份文件没被事后改过”。我的做法是在导出文件旁边放一个摘要值,用 SHA-256 之类算法跑一遍,把摘要存进另一个人管理的路径或审计平台。等下次审计时再对一次摘要,两边对不上就说明中间被改动过。SAP 里有哈希类函数可以调用,也可以把文件拉下来后用独立脚本生成摘要。关键是这个动作必须在导出后立刻完成,并和底稿分开放,否则它就不叫证据链固化。
做过的项目里,最容易翻车的一环不是报表逻辑,而是没人关心“这份数据到底有没有留下操作人”。我习惯在底稿第一页就写明:程序名、变式名、运行时间、系统 ID、client、导出路径、文件哈希值。后来即使业务方和审计组吵架,这串记录也能拿出来反推“当时谁按了什么条件跑了什么程序”。希望这一套步骤能帮你把 SAP 审计程序从临时报表变成真正的证据工具。
本文还有配套的精品资源,点击获取