name: pci-dss-compliance description: PCI DSS合规规划,用于支付卡处理,包括范围减少、SAQ选择和安全控制 allowed-tools: 读取、全局搜索、grep、写入、编辑、任务
PCI DSS合规规划
在开发开始前提供支付卡行业数据安全标准合规的全面指导。
何时使用此技能
- 构建电子商务或支付处理系统
- 与支付网关或处理器集成
- 设计范围减少策略(令牌化、P2PE)
- 为您的业务选择适当的SAQ
- 准备PCI DSS评估
PCI DSS基础
持卡人数据元素
| 数据元素 | 描述 | 允许存储? | 所需保护 |
|---|---|---|---|
| PAN | 主账号(16位数字) | 是,如果受保护 | 渲染不可读 |
| 持卡人姓名 | 卡上姓名 | 是 | 按需求保护 |
| 服务代码 | 3-4位代码 | 是 | 按需求保护 |
| 过期日期 | 月/年 | 是 | 按需求保护 |
| CVV/CVC | 卡验证值 | 认证后永不 | 不适用 - 永不存储 |
| PIN/PIN块 | 个人识别码 | 认证后永不 | 不适用 - 永不存储 |
| 完整磁道数据 | 磁条数据 | 认证后永不 | 不适用 - 永不存储 |
12项要求(PCI DSS 4.0)
目标1:构建和维护安全的网络和系统
1. 安装和维护网络安全控制
2. 对所有系统组件应用安全配置
目标2:保护账户数据
3. 保护存储的账户数据
4. 在传输期间使用强加密保护持卡人数据
目标3:维护漏洞管理程序
5. 保护所有系统和网络免受恶意软件侵害
6. 开发和维护安全的系统和软件
目标4:实施强访问控制措施
7. 根据业务需要限制对持卡人数据的访问
8. 识别用户并验证对系统组件的访问
9. 限制对持卡人数据的物理访问
目标5:定期监控和测试网络
10. 记录和监控对所有系统组件和持卡人数据的访问
11. 定期测试系统和网络的安全性
目标6:维护信息安全政策
12. 通过组织政策和程序支持信息安全
范围减少策略
理解PCI范围
在范围内: 任何存储、处理或传输持卡人数据的系统,或连接到此类系统的系统。
范围减少目标: 最小化处理原始持卡人数据的系统。
策略1:令牌化
用非敏感令牌替换PAN;处理器存储实际卡数据。
// 客户端令牌化流程
public class PaymentTokenization
{
private readonly IPaymentGateway _gateway;
public async Task<PaymentResult> ProcessPayment(
string clientToken, // 通过网关的JS在浏览器中创建的令牌
decimal amount,
string currency,
CancellationToken ct)
{
// 服务器从不看到原始卡数据 - 仅令牌
var request = new ChargeRequest
{
Token = clientToken,
Amount = amount,
Currency = currency,
MerchantReference = Guid.NewGuid().ToString()
};
// 在网关处用令牌交换支付
var result = await _gateway.Charge(request, ct);
// 仅存储交易参考,永不存储卡数据
return new PaymentResult
{
TransactionId = result.TransactionId,
Status = result.Status,
// 存储令牌用于定期支付(如果存入库)
VaultToken = result.VaultToken
};
}
}
// 范围:仅网关SDK在范围内,不是整个应用程序
策略2:托管支付页面(重定向)
客户在处理器页面上输入卡数据;您永不处理卡数据。
public class HostedPaymentFlow
{
private readonly IHostedPaymentProvider _provider;
public async Task<string> CreatePaymentSession(
Order order,
CancellationToken ct)
{
var session = await _provider.CreateSession(new SessionRequest
{
Amount = order.Total,
Currency = order.Currency,
SuccessUrl = $"https://example.com/payment/success?order={order.Id}",
CancelUrl = $"https://example.com/payment/cancel?order={order.Id}",
WebhookUrl = "https://example.com/api/payment-webhook",
Metadata = new Dictionary<string, string>
{
["order_id"] = order.Id.ToString()
}
}, ct);
// 重定向客户到处理器的托管页面
return session.RedirectUrl;
}
// Webhook接收支付确认 - 无卡数据
public async Task HandleWebhook(PaymentWebhook webhook, CancellationToken ct)
{
// 验证webhook签名
if (!_provider.VerifySignature(webhook))
throw new SecurityException("无效的webhook签名");
// 更新订单状态
var orderId = Guid.Parse(webhook.Metadata["order_id"]);
await _orderService.MarkPaid(orderId, webhook.TransactionId, ct);
}
}
策略3:iFrame/嵌入式字段
卡字段由处理器托管,但显示在您的页面上。
<!-- Stripe Elements示例 - 字段由Stripe托管 -->
<form id="payment-form">
<div id="card-element">
<!-- Stripe在此注入安全卡输入 -->
</div>
<button type="submit">支付</button>
</form>
<script>
// 卡数据永不触及您的服务器
const stripe = Stripe('pk_live_xxx');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
form.addEventListener('submit', async (e) => {
e.preventDefault();
// 客户端创建令牌,发送到您的服务器
const {token} = await stripe.createToken(cardElement);
// 仅令牌发送到您的服务器
await fetch('/api/payment', {
method: 'POST',
body: JSON.stringify({ token: token.id })
});
});
</script>
策略4:点对点加密(P2PE)
硬件在刷卡时加密卡数据;仅在处理器处解密。
卡刷卡 → P2PE终端 → 加密 → 您的系统 → 处理器
(无法解密)
优点:
- 您的系统仅处理加密数据
- 范围大幅减少
- 需要P2PE验证解决方案
范围减少比较
| 策略 | 您的PCI范围 | SAQ类型 | 复杂度 |
|---|---|---|---|
| 存储原始卡 | 全环境 | D | 非常高 |
| 令牌化(API) | 令牌处理系统 | A-EP或D | 中等 |
| iFrame/托管字段 | 最小(网页) | A或A-EP | 低 |
| 重定向到处理器 | 无(仅推荐) | A | 非常低 |
| P2PE硬件 | 终端+网络 | P2PE | 低 |
SAQ选择指南
SAQ类型概述
| SAQ | 适用对象 | 要求 | 问题数 |
|---|---|---|---|
| A | 电子商务,所有卡功能外包 | 您的系统无CHD | ~24 |
| A-EP | 电子商务,网站影响卡安全 | iFrame/JS方法 | ~191 |
| B | 仅压卡/独立拨号终端 | 无电子存储 | ~41 |
| B-IP | 独立IP连接终端 | 无电子存储 | ~82 |
| C | 互联网连接系统上的支付应用 | 无电子存储 | ~160 |
| C-VT | 虚拟终端,无电子存储 | 基于Web,无存储 | ~79 |
| D | 所有其他商户 | 全要求 | ~329 |
| D(SP) | 服务提供商 | 全要求 | ~400+ |
| P2PE | 使用验证P2PE解决方案 | 终端+P2PE | ~33 |
决策树
您是否以电子方式存储/处理/传输CHD?
├─ 否:您是否仅为电子商务?
│ ├─ 是:所有卡功能外包?
│ │ ├─ 是 → SAQ A
│ │ └─ 否:网站控制重定向/iFrame?
│ │ ├─ 是 → SAQ A-EP
│ │ └─ 否 → SAQ D
│ └─ 否:仅卡在场?
│ ├─ 压卡/独立拨号 → SAQ B
│ ├─ 独立IP终端 → SAQ B-IP
│ ├─ P2PE验证解决方案 → SAQ P2PE
│ └─ 其他 → SAQ C或D
└─ 是: → SAQ D(全评估)
安全控制实现
要求3:保护存储的账户数据
// PAN掩码(仅显示前6位、后4位)
public static class PanMasking
{
public static string Mask(string pan)
{
if (string.IsNullOrEmpty(pan) || pan.Length < 13)
return pan;
// 前6位(BIN)+ 掩码中间 + 后4位
var first6 = pan[..6];
var last4 = pan[^4..];
var maskedLength = pan.Length - 10;
return $"{first6}{new string('*', maskedLength)}{last4}";
}
// 示例:4111111111111111 → 411111******1111
}
// 存储PAN的强加密(当需要存储时)
public class PanEncryption
{
private readonly IKeyManagement _keyManager;
public async Task<EncryptedPan> Encrypt(string pan, CancellationToken ct)
{
// 使用AES-256最低
var key = await _keyManager.GetCurrentKey("pan-encryption", ct);
using var aes = Aes.Create();
aes.Key = key.KeyMaterial;
aes.GenerateIV();
using var encryptor = aes.CreateEncryptor();
var plainBytes = Encoding.UTF8.GetBytes(pan);
var encryptedBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
return new EncryptedPan
{
EncryptedData = Convert.ToBase64String(encryptedBytes),
KeyId = key.KeyId,
IV = Convert.ToBase64String(aes.IV)
};
}
}
要求4:加密传输
// 强制执行TLS 1.2+
public static class TlsConfiguration
{
public static void ConfigureSecureDefaults()
{
// 禁用旧协议
ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls12 |
SecurityProtocolType.Tls13;
}
}
// ASP.NET Core配置
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
options.ConfigureHttpsDefaults(https =>
{
https.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13;
});
});
// ... 其余配置
}
}
要求8:认证
// CDE访问的多因素认证
public class PciMfaPolicy
{
public bool RequiresMfa(string userId, string resourcePath)
{
// 所有CDE访问需要MFA
var cdeResources = new[]
{
"/admin/payments",
"/api/transactions",
"/reports/cardholder"
};
return cdeResources.Any(r =>
resourcePath.StartsWith(r, StringComparison.OrdinalIgnoreCase));
}
}
// 密码策略(PCI DSS 4.0)
public class PciPasswordPolicy : IPasswordPolicy
{
public PasswordRequirements GetRequirements()
{
return new PasswordRequirements
{
MinimumLength = 12, // 4.0从7增加
RequireComplexity = true, // 多字符类型
MaxAgeInDays = 90, // 每90天强制更改
HistoryCount = 4, // 不能重用最后4个
LockoutThreshold = 10, // 10次失败后锁定
LockoutDurationMinutes = 30,
IdleTimeoutMinutes = 15 // CDE访问会话超时
};
}
}
要求10:日志和监控
// PCI合规审计日志
public class PciAuditLogger
{
private readonly ILogger _logger;
private readonly TimeProvider _timeProvider;
public void LogCdeAccess(CdeAccessEvent accessEvent)
{
// PCI要求:谁、什么、何时、何地、成功/失败
var entry = new AuditEntry
{
Timestamp = _timeProvider.GetUtcNow(),
UserId = accessEvent.UserId,
UserName = accessEvent.UserName,
EventType = accessEvent.EventType.ToString(),
Resource = accessEvent.Resource,
Action = accessEvent.Action,
SourceIp = accessEvent.SourceIp,
Success = accessEvent.Success,
Details = accessEvent.Details
};
// 永不记录实际卡数据
_logger.LogInformation(
"CDE_ACCESS: 用户={UserId} 动作={Action} 资源={Resource} 成功={Success} IP={SourceIp}",
entry.UserId,
entry.Action,
entry.Resource,
entry.Success,
entry.SourceIp);
// 保留日志至少1年
// 3个月内立即可用
}
public void LogSecurityEvent(SecurityEvent secEvent)
{
// 安全事件记录:
// - 所有对CHD的访问
// - 管理员/root的所有操作
// - 所有无效访问尝试
// - 系统对象的创建/删除
// - 审计日志的初始化
// - 审计日志的停止/暂停
}
}
网络分段
CDE网络隔离
┌─────────────────────────────────────────────────────────────┐
│ 企业网络 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 持卡人数据环境 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ 支付 │ │ 数据库 │ │ 管理 │ │ │
│ │ │ 服务器 │────│ 服务器 │────│ 跳板机 │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ │ │ │ │
│ │ │ ← 防火墙/ACLs → │ │ │
│ └───────┼──────────────────────────────┼──────────────┘ │
│ │ │ │
│ ┌─────▼─────┐ ┌─────▼─────┐ │
│ │ 网页应用 │ │ 管理 │ │
│ │ (无CHD) │ │ 工作站 │ │
│ └───────────┘ └───────────┘ │
└─────────────────────────────────────────────────────────────┘
CDE防火墙规则
# 示例防火墙规则
CDE_入站:
- 允许:来自Web层的支付API(443)
- 允许:仅来自跳板机的SSH(22)
- 允许:仅来自支付服务器的数据库(5432)
- 拒绝:所有其他
CDE_出站:
- 允许:支付处理器API(443)
- 允许:到批准服务器的NTP(123)
- 允许:到SIEM的Syslog(514)
- 拒绝:所有其他
PCI合规清单
开发前
- [ ] 识别所有支付流程
- [ ] 选择范围减少策略
- [ ] 选择适当的SAQ类型
- [ ] 建立CDE边界
- [ ] 审查供应商PCI合规性(AOC)
架构与设计
- [ ] 文档化网络分段
- [ ] 定义加密策略(存储和传输)
- [ ] 设计访问控制模型
- [ ] 计划审计日志方法
- [ ] 确保无CVV/PIN存储
开发
- [ ] 永不记录卡数据
- [ ] 实施仅TLS 1.2+
- [ ] 应用PAN掩码用于显示
- [ ] 强制CDE访问的MFA
- [ ] 遵循安全编码(要求6)
测试与评估
- [ ] 漏洞扫描(内部/外部季度)
- [ ] 渗透测试(年度)
- [ ] 分段测试(如果分段)
- [ ] 应用安全测试
交叉参考
- 安全框架:
security-frameworks用于控制映射 - 数据分类:
data-classification用于CHD处理 - 许可证合规:
license-compliance用于支付SDK条款