我非常了解 PCI 合规性,因此在结帐过程中,不需要在我们公司的数据库中存储 CC 编号(尤其是 CVV 编号)。
但是,我希望在处理敏感的消费者信息时尽可能安全,并且很好奇如何在尽可能不使用 SESSION 变量的情况下在页面之间传递 CC 编号。
我的网站是这样构建的:
- 第 1 步)领取信用卡 来自客户的信息 - 何时 客户点击提交, 信息首先通过JS运行 验证,然后通过 PHP 运行 验证,如果一切通过,他就会移动 到第 2 步。
- 第 2 步)信息显示在 供客户制作的评论页面 确定他们即将到来的细节 交易显示。只有 CC的前6个和后4个是 显示在此页面上,但卡片类型, 和 exp 日期完全显示。如果他 点击继续,
- 第 3 步)将信息发送至 另一个最后运行的 php 页面 验证,发送信息 通过安全的支付网关,以及 字符串返回详细信息。
- 第 4 步)如果一切顺利,则 消费者信息(个人,不是 CC)存储在数据库中并重定向 到完成页面。如果有什么 不好,他被告知并告知 重新访问 CC 处理页面 再试一次(最多 3 次)。
有什么建议吗?
编辑
我收到了很多关于这个问题的非常好的回答——大多数人似乎都同意以下几点:
- 在之后取 POST 变量 验证运行
- 加密 ccnum 和 cvv(不确定 您可以将 cvv 存储在数据库中 不过)
- 存储在临时数据库中
- “审核”后立即访问数据库 页面没问题
- 从数据库中解密详细信息
- 向处理者发送信息
- 收到回复
- 终止数据库
我认为总体而言这是有道理的。有没有人有很好的加密/解密方法以及创建临时数据库信息的最佳方法,这些信息会在以后调用时自动删除?
我正在使用 PHP 和 MySQL DB 编程
编辑#2
我遇到了 Packet General,这似乎是一个理想的解决方案,但我真的不想为实现这一目标而购买另一个软件许可证。
http://www.packetgeneral.com/pcigeneralformysql.html
编辑 #3 - 示例代码
我现在发布了一些示例代码,我将这些代码放在一起试图理解本文中提到的加密/解密/ key 和存储。希望已经有帮助的贡献者可以验证,其他人能够使用类似的功能。为了篇幅,我不会详细介绍用于实际 CC num 本身的验证方法。
表单输入
<form action="<?php $_SERVER['PHP_SELF']; ?>" method="POST">
<input type="text" name="CC" />
<input type="text" name="CVV" />
<input type="text" name="CardType" />
<input type="text" name="NameOnCard" />
<input type="submit" name="submit" value="submit" />
</form>
PHP 加密和存储数据
<?php
$ivs = mcrypt_get_iv_size(MCRYPT_DES,MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($ivs,MCRYPT_RAND);
$key = "1234"; //not sure what best way to generate this is!
$_SESSION['key'] = $key;
$ccnum = $_POST['CC'];
$cvv = $_POST['CVV'];
$cctype = $_POST['CardType'];
$ccname = $_POST['NameOnCard'];
$enc_cc = mcrypt_encrypt(MCRYPT_DES, $key, $ccnum, MCRYPT_MODE_CBC, $iv);
$enc_cvv = mcrypt_encrypt(MCRYPT_DES, $key, $cvv, MCRYPT_MODE_CBC, $iv);
$enc_cctype = mcrypt_encrypt(MCRYPT_DES, $key, $cctype, MCRYPT_MODE_CBC, $iv);
$enc_ccname = mcrypt_encrypt(MCRYPT_DES, $key, $ccname, MCRYPT_MODE_CBC, $iv);
//if we want to change BIN info to HEXIDECIMAL
// bin2hex($enc_cc)
$conn = mysql_connect("localhost", "username", "password");
mysql_select_db("DBName",$conn);
$enc_cc = mysql_real_escape_string($enc_cc);
$enc_cvv = mysql_real_escape_string($enc_cvv);
$enc_cctype = mysql_real_escape_string($enc_cctype);
$enc_ccname = mysql_real_escape_string($enc_ccname);
$sql = "INSERT INTO tablename VALUES ('$enc_cc', '$enc_cvv', '$enc_cctype', '$enc_ccname');
$result = mysql_query($sql, $conn) or die(mysql_error());
mysql_close($conn);
Header ("Location: review_page.php");
?>
PHP 解密数据并发送到网关
$conn = mysql_connect("localhost", "username", "password");
mysql_select_db("DBName",$conn);
$result = mysql_query("SELECT * FROM tablename");
echo mcrypt_decrypt (MCRYPT_DES, $_SESSION['key'], $enc_ccnum, MCRYPT_MODE_CBC, $iv);
echo mcrypt_decrypt (MCRYPT_DES, $_SESSION['key'], $enc_cvv, MCRYPT_MODE_CBC, $iv);
echo mcrypt_decrypt (MCRYPT_DES, $_SESSION['key'], $enc_cctype, MCRYPT_MODE_CBC, $iv);
echo mcrypt_decrypt (MCRYPT_DES, $_SESSION['key'], $enc_ccname, MCRYPT_MODE_CBC, $iv);
mysql_close($con);
?>
然后继续获取刚刚在字符串中发送的数据并在网关提交中使用。看起来对吗?
最佳答案
将卡详细信息存储到任何持久性介质(数据库等),但使用您存储在 session 中的唯一和随机 key 加密卡号。这样,如果 session 丢失, key 也会丢失 - 这让您有足够的时间来清除过期/废弃的数据。
还要确保您的 session 免受劫持。对此有硬件解决方案,但一种简单的代码内方法是将 session ID 绑定(bind)到 IP 的第一个八位字节加上用户代理的哈希值。不是万无一失,但它有帮助。
编辑: 将风险降到最低的关键是确保您尽快摆脱这些信息。交易完成后,立即从数据库中删除记录。您还需要一个滚 Action 业(例如每 5 分钟一次)来删除任何早于 session 超时(通常为 20 分钟)的记录。此外,如果您正在为这个非常临时数据使用数据库,请确保它不在自动备份系统上。
同样,此解决方案并非万无一失,我什至不能 100% 确定它是否符合 CC 安全要求。但是,它应该要求攻击者对您的环境具有完全的运行时控制权才能主动解密客户 CC 信息,并且如果您的数据库快照遭到破坏(更有可能/常见),一次只能暴力破解一个 CC,这是您所希望的最好结果。
关于php - 在 SESSION 中存储信用卡号 - 解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2900189/