关于 audit-compliance
面向 ServiceNow 管理员和安全团队的技能,涵盖审计数据查询、用户活动调查、合规报告和异常识别,并提供表与 MCP 工具的操作示例。
主要功能
- 01查询审计与删除记录
- 02跟踪用户和会话活动
- 03合规报告操作流程
- 04检测异常及权限变更
- 05审计仪表板与告警指引
适用场景
- 01审查 SOX、HIPAA 或 PCI-DSS 控制
- 02调查可疑账户活动
- 03追踪角色与访问规则变更
MCP 相关
介绍使用 SN-Query-Table 和 SN-Execute-Background-Script 等 ServiceNow MCP 工具检查审计数据、生成报告和创建告警。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ happy-technologies-llc/ happy-platform-skills --skill audit-compliance安装后在 Claude Code 中输入/audit-compliance确认已加载。
详细介绍
审计与合规
概述
此技能涵盖 ServiceNow 中全面的审计与合规功能:
- 查询 sys_audit 表中的配置和数据变更
- 跟踪整个平台上的用户活动
- 生成满足监管要求的合规报告
- 检测可能表明存在安全威胁的异常模式
- 构建审计仪表板和警报
适用场景:
- 定期合规审计(SOX、HIPAA、PCI-DSS、GDPR)
- 安全调查
- 用户活动取证
- 变更跟踪与问责
- 异常检测和警报
前提条件
- 角色:
security_admin、audit_admin或admin - 访问权限: sys_audit、syslog、sys_audit_delete 表
- 知识: 了解适用于所在组织的合规框架
- 相关技能: 使用
security/incident-response处理检测到的异常
关键审计表
| 表 | 用途 | 保留期限 |
|---|---|---|
sys_audit | 字段级变更跟踪 | 可配置 |
sys_audit_delete | 已删除记录跟踪 | 可配置 |
syslog | 系统和脚本日志记录 | 7-90 天 |
sysevent | 系统事件和触发器 | 可配置 |
syslog_transaction | 事务级日志记录 | 7 天 |
操作步骤
阶段 1:审计跟踪查询
1.1 查询关键表的近期变更
识别用户账户变更:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: tablename=sys_user^sys_created_onONLast 24 hours
fields: documentkey,fieldname,oldvalue,newvalue,user,sys_created_on
limit: 200
跟踪角色分配:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: tablename=sys_user_has_role^sys_created_onONLast 7 days
fields: documentkey,fieldname,oldvalue,newvalue,user,sys_created_on
limit: 100
监控 ACL 变更:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: tablename=sys_security_acl^sys_created_onONLast 30 days
fields: documentkey,fieldname,oldvalue,newvalue,user,sys_created_on
limit: 100
1.2 编码审计查询
使用编码查询:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: tablename=sys_user^fieldnameINuser_name,roles,active,locked_out^newvalueLIKEadmin^sys_created_on>=javascript:gs.daysAgoStart(7)^NQtablename=sys_user^fieldnameINuser_name,roles,active,locked_out^oldvalueLIKEadmin^sys_created_on>=javascript:gs.daysAgoStart(7)
limit: 50
查找密码变更:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: fieldnameLIKEpassword^sys_created_on>=javascript:gs.hoursAgo(24)
limit: 100
阶段 2:用户活动跟踪
2.1 登录活动分析
查询登录事件:
Tool: SN-Query-Table
Parameters:
table_name: syslog
query: messageLIKElogin^sys_created_onONLast 24 hours
fields: level,message,source,sys_created_on
limit: 500
登录失败尝试:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: tablename=sys_user^fieldname=failed_attempts^sys_created_onONLast 24 hours
fields: documentkey,oldvalue,newvalue,user,sys_created_on
limit: 100
2.2 用户会话分析
查询活动会话:
Tool: SN-Query-Table
Parameters:
table_name: v_user_session
query: statusISNOTEMPTY
fields: user,status,last_activity,client_ip,browser
limit: 100
识别并发会话(可能存在账户共享):
Tool: SN-Execute-Background-Script
Parameters:
script: |
var users = {};
var gr = new GlideRecord('v_user_session');
gr.addQuery('status', 'active');
gr.query();
while (gr.next()) {
var userId = gr.user.toString();
if (!users[userId]) users[userId] = [];
users[userId].push({
ip: gr.client_ip.toString(),
browser: gr.browser.toString()
});
}
for (var uid in users) {
if (users[uid].length > 1) {
var userGr = new GlideRecord('sys_user');
userGr.get(uid);
gs.info('CONCURRENT SESSIONS: ' + userGr.user_name +
' has ' + users[uid].length + ' active sessions from: ' +
JSON.stringify(users[uid]));
}
}
description: "Audit: Identify users with concurrent sessions"
2.3 特权用户监控
跟踪管理员用户活动:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: userLIKEadmin^sys_created_onONLast 7 days^tablenameNOT INsyslog,sys_cache,sys_email
fields: tablename,fieldname,oldvalue,newvalue,user,sys_created_on
limit: 500
监控模拟身份使用情况:
Tool: SN-Query-Table
Parameters:
table_name: syslog
query: messageLIKEimpersonat^sys_created_onONLast 30 days
fields: level,message,source,sys_created_on
limit: 100
阶段 3:生成合规报告
3.1 SOX 合规报告
生成用户访问审查数据:
Tool: SN-Execute-Background-Script
Parameters:
script: |
var report = [];
// Get all active users with sensitive roles
var sensitiveRoles = ['admin', 'security_admin', 'itil', 'catalog_admin'];
var userRoles = new GlideRecord('sys_user_has_role');
userRoles.addQuery('role.name', 'IN', sensitiveRoles.join(','));
userRoles.addQuery('user.active', true);
userRoles.orderBy('user');
userRoles.query();
while (userRoles.next()) {
report.push({
user_name: userRoles.user.user_name.toString(),
user_email: userRoles.user.email.toString(),
role: userRoles.role.name.toString(),
granted_date: userRoles.sys_created_on.toString(),
granted_by: userRoles.sys_created_by.toString(),
last_login: userRoles.user.last_login_time.toString(),
manager: userRoles.user.manager.name.toString()
});
}
gs.info('SOX User Access Report: ' + JSON.stringify(report, null, 2));
description: "Compliance: Generate SOX user access report"
3.2 数据访问审计报告
跟踪对敏感表的访问:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: tablenameINsys_user,customer_account,hr_core_profile,ast_license^sys_created_onONLast 30 days
fields: tablename,documentkey,fieldname,user,sys_created_on
limit: 1000
3.3 配置变更报告
生成配置变更摘要:
Tool: SN-Execute-Background-Script
Parameters:
script: |
var configTables = [
'sys_script', 'sys_script_include', 'sys_ui_policy',
'sys_ui_action', 'sys_security_acl', 'sys_properties',
'sys_scheduled_job', 'wf_workflow', 'wf_activity'
];
var changes = {};
var audit = new GlideRecord('sys_audit');
audit.addQuery('tablename', 'IN', configTables.join(','));
audit.addQuery('sys_created_on', '>=', gs.daysAgo(30));
audit.query();
while (audit.next()) {
var table = audit.tablename.toString();
if (!changes[table]) changes[table] = { insert: 0, update: 0, delete: 0 };
if (audit.reason.toString().indexOf('INSERT') >= 0) changes[table].insert++;
else if (audit.reason.toString().indexOf('DELETE') >= 0) changes[table].delete++;
else changes[table].update++;
}
gs.info('CONFIGURATION CHANGE REPORT (Last 30 Days):');
for (var tbl in changes) {
gs.info(tbl + ': ' + JSON.stringify(changes[tbl]));
}
description: "Compliance: Generate configuration change report"
阶段 4:异常检测模式
4.1 暴力破解检测
识别可能的暴力破解攻击:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: tablename=sys_user^fieldname=failed_attempts^newvalueGT3^sys_created_onONLast 1 hours
fields: documentkey,oldvalue,newvalue,user,sys_created_on
limit: 50
为暴力破解模式创建警报:
Tool: SN-Execute-Background-Script
Parameters:
script: |
var threshold = 5;
var timeWindow = 3600000; // 1 hour in ms
var now = new GlideDateTime();
var hourAgo = new GlideDateTime();
hourAgo.subtract(timeWindow);
var audit = new GlideRecord('sys_audit');
audit.addQuery('tablename', 'sys_user');
audit.addQuery('fieldname', 'failed_attempts');
audit.addQuery('sys_created_on', '>=', hourAgo);
audit.orderBy('documentkey');
audit.query();
var userAttempts = {};
while (audit.next()) {
var userId = audit.documentkey.toString();
var newVal = parseInt(audit.newvalue.toString()) || 0;
if (newVal > threshold) {
userAttempts[userId] = newVal;
}
}
// Create security incidents for each
for (var uid in userAttempts) {
var userGr = new GlideRecord('sys_user');
userGr.get(uid);
gs.warn('ANOMALY DETECTED: Brute force attempt on user: ' +
userGr.user_name + ' (' + userAttempts[uid] + ' failed attempts)');
// Optional: Create security incident
// var si = new GlideRecord('sn_si_incident');
// si.initialize();
// si.short_description = 'Potential brute force attack: ' + userGr.user_name;
// si.insert();
}
description: "Anomaly: Detect brute force login attempts"
4.2 非工作时间活动检测
查找非工作时间的管理员活动:
Tool: SN-Execute-Background-Script
Parameters:
script: |
// Business hours: 8 AM - 6 PM, Monday-Friday
var businessStart = 8;
var businessEnd = 18;
var audit = new GlideRecord('sys_audit');
audit.addQuery('sys_created_on', '>=', gs.daysAgo(7));
audit.addEncodedQuery('userLIKEadmin^ORuserLIKEsystem');
audit.query();
var offHoursActivity = [];
while (audit.next()) {
var created = new GlideDateTime(audit.sys_created_on.toString());
var hour = created.getLocalTime().getHourOfDay();
var dayOfWeek = created.getDayOfWeek();
// Check if outside business hours (1=Sunday, 7=Saturday)
if (dayOfWeek == 1 || dayOfWeek == 7 || hour < businessStart || hour >= businessEnd) {
offHoursActivity.push({
user: audit.user.toString(),
table: audit.tablename.toString(),
field: audit.fieldname.toString(),
time: created.toString()
});
}
}
if (offHoursActivity.length > 0) {
gs.warn('OFF-HOURS ACTIVITY DETECTED: ' + offHoursActivity.length + ' actions');
gs.info(JSON.stringify(offHoursActivity.slice(0, 20), null, 2));
}
description: "Anomaly: Detect off-hours admin activity"
4.3 批量数据访问检测
识别异常的数据访问模式:
Tool: SN-Execute-Background-Script
Parameters:
script: |
var threshold = 100; // More than 100 records accessed in 10 minutes
var sensitiveTables = ['sys_user', 'customer_account', 'hr_core_profile', 'ast_contract'];
var audit = new GlideRecord('sys_audit');
audit.addQuery('tablename', 'IN', sensitiveTables.join(','));
audit.addQuery('sys_created_on', '>=', gs.minutesAgo(10));
audit.query();
var userAccess = {};
while (audit.next()) {
var user = audit.user.toString();
var table = audit.tablename.toString();
var key = user + '::' + table;
if (!userAccess[key]) userAccess[key] = { user: user, table: table, count: 0 };
userAccess[key].count++;
}
for (var k in userAccess) {
if (userAccess[k].count > threshold) {
gs.warn('BULK ACCESS DETECTED: ' + userAccess[k].user +
' accessed ' + userAccess[k].count + ' records in ' +
userAccess[k].table);
}
}
description: "Anomaly: Detect bulk data access patterns"
4.4 权限提升检测
监控未经授权的角色变更:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: tablename=sys_user_has_role^sys_created_onONLast 24 hours
fields: documentkey,oldvalue,newvalue,user,reason,sys_created_on
limit: 100
敏感角色授予时发出警报:
Tool: SN-Execute-Background-Script
Parameters:
script: |
var sensitiveRoles = ['admin', 'security_admin', 'maint', 'personalize_dictionary'];
var audit = new GlideRecord('sys_audit');
audit.addQuery('tablename', 'sys_user_has_role');
audit.addQuery('reason', 'LIKE', 'INSERT');
audit.addQuery('sys_created_on', '>=', gs.daysAgo(1));
audit.query();
while (audit.next()) {
// Get the role record
var roleRec = new GlideRecord('sys_user_has_role');
if (roleRec.get(audit.documentkey)) {
var roleName = roleRec.role.name.toString();
if (sensitiveRoles.indexOf(roleName) >= 0) {
var userName = roleRec.user.user_name.toString();
var grantedBy = audit.user.toString();
gs.warn('PRIVILEGE ESCALATION: ' + userName +
' granted ' + roleName + ' role by ' + grantedBy);
}
}
}
description: "Anomaly: Detect sensitive role grants"
阶段 5:已删除记录跟踪
查询已删除记录:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit_delete
query: sys_created_onONLast 7 days
fields: tablename,documentkey,display_name,deleted_by,sys_created_on
limit: 100
跟踪已删除的敏感记录:
Tool: SN-Query-Table
Parameters:
table_name: sys_audit_delete
query: tablenameINsys_user,sys_user_has_role,sys_security_acl^sys_created_onONLast 30 days
fields: tablename,documentkey,display_name,deleted_by,sys_created_on
limit: 100
合规框架映射
SOX 控制项
| 控制项 | 审计查询 |
|---|---|
| 用户访问审查 | 查询 sys_user_has_role 变更 |
| 职责分离 | 查询相互冲突的角色分配 |
| 变更管理 | 查询 sys_update_set 和 sys_update_xml |
| 审计跟踪完整性 | 验证 sys_audit 保留期限 |
HIPAA 要求
| 要求 | 实施方式 |
|---|---|
| 访问控制 | ACL 审计 + 角色跟踪 |
| 审计控制 | sys_audit + syslog 保留 |
| 完整性控制 | 跟踪 PHI 表上的变更 |
| 传输安全 | SSL/TLS 验证 |
PCI-DSS 要求
| 要求 | 审计方法 |
|---|---|
| 10.1 - 审计跟踪 | 为所有表启用 sys_audit |
| 10.2 - 日志事件 | syslog 捕获系统事件 |
| 10.3 - 审计内容 | 记录 documentkey、用户和时间戳 |
| 10.7 - 日志保留 | 配置 sys_audit 保留期限 |
工具使用摘要
| 操作 | MCP 工具 | REST 端点 |
|---|---|---|
| 查询审计 | SN-Query-Table | GET /sys_audit |
| 自然语言搜索 | SN-Natural-Language-Search | N/A |
| 复杂分析 | SN-Execute-Background-Script | POST /sys_trigger |
| 架构发现 | SN-Discover-Table-Schema | GET /sys_dictionary |
| 创建警报 | SN-Create-Record | POST /sn_si_incident |
最佳实践
- 保留策略: 为 sys_audit 配置适当的保留期限(为满足合规要求,至少保留 1 年)
- 表审计: 通过 sys_dictionary.audit=true 为所有敏感表启用审计
- 实时警报: 为关键变更(角色授权、ACL 变更)创建业务规则
- 定期报告: 每周/每月自动生成合规报告
- 基线行为: 在检测异常之前建立正常活动模式
- 日志完整性: 通过严格的 ACL 保护审计表(大多数用户仅可读取)
故障排除
缺少审计记录
症状: 预期的变更未显示在 sys_audit 中 原因: 未为该表或字段启用审计 解决方案:
Tool: SN-Query-Table
Parameters:
table_name: sys_dictionary
query: name=[table_name]^element=[field_name]
fields: name,element,audit
启用审计:在字典记录上设置 audit=true。
查询性能问题
症状: 审计查询超时 原因: 审计表数据量大且未正确建立索引 解决方案:
- 使用日期范围筛选器(始终包含 sys_created_on)
- 适当限制结果集
- 对历史查询考虑使用已归档的审计数据
合规报告缺漏
症状: 合规报告中缺少数据 原因: 保留策略删除了历史记录 解决方案:
- 检查 sys_properties 中的审计保留设置
- 在下次清理前延长保留期限
- 考虑将数据归档到外部,以满足长期合规要求
示例
示例 1:每周安全审计报告
Tool: SN-Execute-Background-Script
Parameters:
script: |
var report = {
generated: new GlideDateTime().toString(),
period: 'Last 7 days',
summary: {
total_changes: 0,
user_changes: 0,
role_changes: 0,
acl_changes: 0,
failed_logins: 0
},
anomalies: []
};
// Count total changes
var audit = new GlideAggregate('sys_audit');
audit.addQuery('sys_created_on', '>=', gs.daysAgo(7));
audit.addAggregate('COUNT');
audit.query();
if (audit.next()) {
report.summary.total_changes = parseInt(audit.getAggregate('COUNT'));
}
// Count by category
var categories = {
'sys_user': 'user_changes',
'sys_user_has_role': 'role_changes',
'sys_security_acl': 'acl_changes'
};
for (var table in categories) {
audit = new GlideAggregate('sys_audit');
audit.addQuery('tablename', table);
audit.addQuery('sys_created_on', '>=', gs.daysAgo(7));
audit.addAggregate('COUNT');
audit.query();
if (audit.next()) {
report.summary[categories[table]] = parseInt(audit.getAggregate('COUNT'));
}
}
gs.info('WEEKLY SECURITY AUDIT REPORT:\n' + JSON.stringify(report, null, 2));
description: "Generate weekly security audit report"
示例 2:用户活动时间线
Tool: SN-Query-Table
Parameters:
table_name: sys_audit
query: user=john.doe^sys_created_onONLast 30 days
fields: tablename,fieldname,oldvalue,newvalue,sys_created_on
limit: 500
orderBy: sys_created_on
orderByDesc: true
相关技能
security/incident-response- 处理检测到的安全事件security/acl-management- 访问控制配置security/data-classification- 识别敏感数据admin/update-set-management- 跟踪配置变更
参考资料
评论
支持 Markdown