신용카드 번호를 세션에 저장하는 것 - 그 주변의 방법?
저는 PCI 컴플라이언스에 대해 잘 알고 있으므로 체크아웃 과정에서 회사 데이터베이스에 CC 번호(특히 CVV 번호)를 저장할 필요가 없습니다.
하지만 민감한 소비자 정보를 취급할 때 최대한 안전하고 싶고, 가능하면 SESSION 변수를 사용하지 않고 페이지마다 CC 번호를 전달하는 방법이 궁금합니다.
내 사이트는 다음과 같은 방식으로 구축됩니다.
- 1단계) 고객으로부터 신용 카드 정보를 수집합니다. 고객이 제출한 항목을 클릭하면 먼저 JS 검증을 통해 정보를 실행한 다음 PHP 검증을 거쳐 모든 패스가 2단계로 이동합니다.
- 2단계) 고객이 향후 거래에 대한 세부 정보를 보여줄 수 있도록 리뷰 페이지에 정보를 표시합니다.이 페이지에는 CC의 처음 6개와 마지막 4개만 표시되지만 카드 종류와 날짜는 모두 표시됩니다.만약 그가 클릭하면,
- 3단계) 정보는 다른 php 페이지로 전송되며, php 페이지는 마지막 검증을 실행하고, secure payment gateway를 통해 정보를 전송하며, string은 세부 정보와 함께 반환됩니다.
- 4단계) 모든 것이 양호한 경우 소비자 정보(CC가 아닌 개인정보)를 DB에 저장하고 완료 페이지로 리디렉션합니다.문제가 있는 경우 CC 처리 페이지를 다시 방문하여 재시도하라는 안내를 받습니다(최대 3회).
좋은 의견이라도 있나?
편집
저는 이 질문에 대해 정말 좋은 답변을 많이 받았습니다. 대다수는 다음 사항에 동의하는 것 같습니다.
- 유효성 검사가 실행된 후 POST 변수 가져오기
- ccnum 및 cvv를 암호화합니다(DB에 cvv를 저장할 수 있는지 전혀 알 수 없음).
- 임시DB에 저장
- '검토' 페이지 확인 후 DB 바로 접속
- DB에서 세부 정보 암호 해독
- 정보를 프로세서에 보냅니다.
- 회답을 받다
- DB를 종료합니다.
저는 이게 전체적으로 말이 된다고 생각합니다.나중에 통화할 때 자동으로 삭제되는 임시 DB 정보를 만드는 가장 좋은 방법과 함께 암호화/복호화를 위한 좋은 방법을 가진 사람이 있습니까?
저는 PHP와 MySQL DB에서 프로그래밍을 하고 있습니다.
편집 #2
이상적인 솔루션인 것처럼 보이는 Packet General을 발견했지만 이 목표를 달성하기 위해 다른 소프트웨어 라이센스를 지불하고 싶지는 않습니다.http://www.packetgeneral.com/pcigeneralformysql.html
EDIT #3 - 샘플 코드
저는 이 게시물에 언급된 암호화/복호화/키와 저장을 이해하기 위해 제가 만든 예시적인 코드를 올렸습니다.이미 도움이 되는 기여자들이 검증할 수 있고 다른 기여자들도 비슷한 기능을 사용할 수 있기를 바랍니다.길이상으로 실제 CC 번호 자체에 사용되는 검증 방법에는 들어가지 않겠습니다.
양식 입력
<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);
?>
그런 다음 문자열로 방금 전송된 데이터를 가져와 게이트웨이 제출에 사용합니다.맞나요?
지속성 매체(데이터베이스 등)에 카드 세부 정보를 저장하되, 세션에 저장하는 고유하고 임의적인 키로 카드 번호를 암호화합니다.이렇게 하면 세션이 손실된 경우 키도 손실됩니다. 이를 통해 만료/폐기된 데이터를 삭제할 수 있는 충분한 시간을 확보할 수 있습니다.
또한 세션을 하이재킹으로부터 보호해야 합니다.이에 대한 하드웨어 솔루션이 있지만 간단한 인코드 방식은 세션 ID를 IP의 첫 옥텟과 사용자 에이전트의 해시에 연결하는 것입니다.완벽하진 않지만 도움이 됩니다.
편집: 위험을 최소화하기 위한 핵심 요소는 가능한 한 빨리 해당 정보를 제거하는 것입니다.거래가 완료되면 바로 데이터베이스에서 레코드를 삭제합니다.세션 제한 시간(보통 20분)보다 오래된 레코드를 삭제하는 롤링 작업(5분마다 있음)도 필요합니다.또한 이 매우 임시적인 데이터에 데이터베이스를 사용하는 경우 자동 백업 시스템에 데이터베이스가 없는지 확인합니다.
다시 말하지만, 이 솔루션은 완벽하지 않으며 CC 보안 요구사항을 100% 준수하는지도 확신할 수 없습니다.그러나 공격자가 고객 CC 정보를 능동적으로 해독하려면 환경에 대한 전체 런타임 제어가 필요하며, 데이터베이스의 스냅샷이 손상될 가능성이 매우 높거나 일반적인 경우 한 번에 하나의 CC만 강제로 사용할 수 있으므로 원하는 최선의 방법입니다.
신용카드 정보를 저장할 필요성을 없애기 위해 체크아웃 과정을 수정하는 것을 고려해 보세요.
: 및 등합니다. 1 :
외 후 " 결제 수정을 클릭합니다2페이지: 사용자는 신용카드 외 주문 정보를 확인하고 신용카드 정보를 입력한 후 "지금 결제"(또는 변경을 원하는 경우 "주문 수정")을 클릭합니다.
3단계: $_POST 요청을 통해 SSL 페이지로 정보를 전송하고, SSL 페이지는 서버측 체크를 완료하고, 신용카드 데이터를 프로세서에 제출하며, 응답에 따라 성공 또는 오류 페이지로 안내합니다.
이렇게 하면 기술적인 문제와 규정 준수 문제가 발생하지 않게 됩니다.신용 카드 데이터를 데이터베이스나 쿠키에 짧은 기간 동안(암호화된 경우에도) 저장한다는 것은 더 높은 수준의 PCI 컴플라이언스를 책임져야 한다는 것을 의미합니다.유일한 절충점은 신용 카드 세부 정보가 포함된 "주문 검토" 페이지를 보여줄 수 없다는 것입니다."주문 검토" 페이지에 전체 신용카드 번호조차 표시할 수 없다는 점을 감안하면 얼마나 큰 절충안입니까?
PCI 컴플라이언스에 대해 알고 있다고 말씀하신 것은 잘 알고 있지만, 이미 설명한 모든 방법(예: 카드 번호를 디스크에 저장하는 방법)을 사용하면 PCI를 위반할 수 있으며, 규정 준수 문제에 대한 악몽을 꾸게 됩니다.정말로 카드 번호를 디스크에 계속 저장해야 한다면 지금 PCI 감사관을 불러 프로세스 진행을 돕고 조언을 제공하는 것이 좋습니다.궁극적으로 사용자가 취한 방법이 적절한지 검증해야 합니다.
예를 들어, 여기에 있는 많은 답변들은 암호화를 사용하는 것에 대해 이야기합니다.그게 쉬운 부분입니다.그들은 상당히 어려운 키 관리에 대해 이야기한 적이 없습니다.
따라서 카드 내역이 취합되는 대로 결제 게이트웨이에 제출하는 것이 더 좋은 방법이 될 것 같습니다.상당수의 결제 게이트웨이를 통해 '스토어 전용' 방식의 트랜잭션을 수행할 수 있습니다. 이 트랜잭션은 카드 세부 정보의 기본 검증을 수행하고 카드 번호를 (이미 PCI 호환) 서버에 저장하고 대신 토큰 ID를 반환합니다.이 방법은 전체 카드 번호/cvvv2를 서버의 어느 곳에나 저장하지 않음을 의미하며, PCI 컴플라이언스가 엄청나게 쉬워집니다.
체크아웃 과정의 후반부에서 토큰 ID를 사용하여 승인 및 정산서를 제출합니다.
PCI를 사용하면 카드 번호의 처음 6자리/마지막 4자리(및 만료 날짜)를 일반 텍스트로 저장할 수 있으므로 사용자가 편한 곳에 안전하게 캡처하여 마지막 단계 직전에 다시 표시할 수 있습니다.
확인 절차를 생략하고 바로 거래서를 제출할 수 없는 이유가 있나요?
데이터베이스에 보관하는 것이 세션 변수에 보관하는 것보다 더 안전한 이유가 무엇인지 모르겠습니다. 서버 손상으로 인해 신용 카드 번호가 여전히 제공되지만 세션에 보관할 경우 디스크에 기록될 가능성이 훨씬 낮습니다.원하는 경우 암호화할 수 있지만 유용성이 의심됩니다(디스크로 스왑됩니다).암호화된 저장을 수행하기 위해 다른 컴퓨터를 추가하는 것도 도움이 되지 않습니다. 손상된 컴퓨터는 다른 컴퓨터에게 암호 해독을 요청할 수 있기 때문입니다.
편집: 생각만 해도 됩니다.
- 임의 128비트 키를 생성합니다.세션에 저장합니다.
- 키로 데이터를 암호화합니다.<입력형="숨김">으로 클라이언트에게 전송
- 확인되면 데이터를 해독하고 트랜잭션을 제출합니다.
공격자는 신용 카드 번호를 얻기 위해 클라이언트와 서버 모두를 손상시켜야 합니다(이러한 공격자는 어쨌든 이미 번호를 가지고 있을 것입니다).온라인 서버 손상으로 인해 향후 거래의 신용카드 번호가 여전히 획득되지만, 이를 실제로 중단할 수는 없습니다.
편집: 그리고 세부사항들을 잊어버렸습니다.이 모든 계획(내 계획 뿐만 아니라)에 대해서도 다시 보기 공격을 방지하기 위한 MAC가 필요합니다(또는 이브가 앨리스의 주의를 딴 데로 돌리고, 쇼핑 바구니와 청구 주소를 수정하고, "확인" 페이지를 누름).일반적으로 보유하고 있는 모든 거래 데이터(CC, CVV, 거래 ID, 거래 금액, 청구 주소 등)에 대해 MAC를 보유하기를 원합니다.
맞습니다. 세션을 사용하는 것은 민감한 데이터를 저장하는 데 매우 안전하지 않습니다. 다음과 같이 알려진 것을 사용하여 세션을 시작하는 방법은 다음과 같습니다.
가장 안전하게 떠오르는 방법은 데이터베이스에 정보를 저장한 후(임시 시간 동안) 필요한 페이지에서 해당 값을 읽는 것입니다.작업을 모두 완료한 후에는 다시 삭제할 수 있습니다.
참고:
- 데이터베이스에 저장하기 전에 암호화해야 합니다.
- 공유 호스팅을 사용할 경우 주의해야 합니다.
- 작업이 완료되면 다시 삭제해야 합니다.
이것이 반사적으로 유용하다는 것을 알 수 있습니다 :)
아무리 만져봐도 안전한 신용카드 번호 저장 기능을 제공해야 할 것 같습니다.서버가 손상되면 언제든지 현재 저장된 신용 카드 번호(즉, 키 및 암호화된 번호)를 해독할 수 있는 충분한 정보를 포함하게 됩니다.잠재적인 해결책은 "암호화/해독기" 서비스 역할을 하는 내부 서버를 사용하는 것이며, 다른 것은 사용하지 않는 것입니다.이렇게 하면 한 기계를 손상시켜도 신용카드 번호가 노출되지 않습니다.
다른 방법도 있지만, 아약스가 필요합니다.신용카드 번호 및 리뷰 페이지 저장 금지.
1페이지 : 배송, 청구 및 신용카드 정보를 캡처하는 양식양식을 포함한 페이지의 "본문"이 고유 ID를 가진 DIV에 있는지 확인하여 자바스크립트로 참조할 수 있도록 합니다.
2페이지: 양식 필드가 포함된 GET/POST 요청을 수락하고 적절한 형식의 "검토" 페이지를 원하는 대로 반환하는 서버의 파일.
체크아웃 프로세스:
- 양식을 확인합니다.
- 신용카드 관련 필드를 글로벌 자바스크립트 변수로 복사합니다.
- 양식 필드를 루프스루하고 양식 필드로 쿼리/데이터 문자열을 작성합니다(신용카드 관련 필드 제외).
- Ajax 요청을 "review" 페이지에 수행하여 양식 필드/값의 쿼리 문자열을 전달합니다.서버에서 렌더링하고 Ajax 함수 호출로 돌아갑니다.
- Ajax 요청에서 반환된 렌더링된 HTML 검토 페이지를 가져와 "DIV" 컨테이너의 내용을 해당 내용으로 바꿉니다(양식 및 기타 요소를 검토 HTML로 효과적으로 바꿉니다).
- 자바스크립트를 사용하여 글로벌 JS 변수에 저장된 신용카드 데이터를 리뷰 페이지의 적절한 위치에 복사합니다.사용자가 "검토" 페이지에서 주문을 "완료"할 때 제출할 숨겨진 양식 필드에 카드 데이터를 복사할 수도 있습니다.
- 사용자는 검토 페이지에서 서버로 주문을 제출하고, 프로세서의 게이트웨이로 카드 유효성 검사를 수행한 다음 주문을 넣거나, 카드 세부 정보를 저장하지 않은 오류 처리 페이지로 돌아갑니다.
- 글로벌 JS 변수에 카드 데이터가 더 이상 저장되지 않은 페이지로 브라우저를 다시 로드하기 위해 "place order" 함수가 (Ajax가 아닌) 전체 HTTP 요청을 수행하는 것을 권장합니다.
약간의 해킹이지만, 제대로 실행되면 사용자에게 100% 완벽하고 임시 DB 저장 등으로 위험을 감수할 필요 없이 카드 데이터를 한 번에 전송할 수 있습니다.
이것이 데이터베이스의 목적입니다.국가와 지역에 따라 다른 법적 영향에 대해서는 잘 모르지만, 한 가지 방법은 CC 번호를 암호화하여 사용자로부터 받는 즉시 데이터베이스에 저장하는 것입니다.필요할 때 사용자에게 표시할 수 있도록 마지막 4자리를 별도의 필드에 저장할 수 있습니다.서버의 카드 프로세서와 상호 작용해야 할 경우 데이터베이스에서 카드 번호를 검색하고 암호를 해독합니다.
제가 계획하는 방법은 이렇습니다. 물론 ssl을 사용하는 https의 모든 것입니다.
1단계. 사용자가 CC 정보를 입력하고 다음 버튼을 누릅니다.CC 정보는 즉시 자신의 DB가 아닌 CC 프로세서의 DB에 저장됩니다. 그렇지 않으면 PCI 컴플라이언스가 중단됩니다.이 단계에서 CC는 실제로 충전되지 않습니다.하지만 당신은 CC 정보를 식별하는 프로세서로부터 어떤 고유 ID를 받아야 합니다. (당신이 원한다면 당신의 db에 고유 ID를 저장하세요.)
2단계. 확인 페이지에서 CC 프로세서가 알려준 고유 ID를 사용하여 CC 정보를 가져옵니다.제 프로세서는 어쨌든 제가 CC의 마지막 4개 번호만 검색할 수 있게 해줍니다.
3단계. 구매 확인 후 지금 구매 버튼을 누르면 고유 아이디로 신용카드를 충전합니다.
4단계 CC 뒷자리 4자리만 있는 인보이스/영수증이 포함된 감사 페이지로 리디렉션합니다(물론 CC 뒷자리 4자리를 표시하지 않아도 되지만 보여주는 것도 좋다고 생각합니다).
session에 카드 nr의 해시를 저장할 수 있고, 같은 해시와 실제 숫자와 사용자의 session id를 데이터베이스에 저장할 수 있습니다.그런 다음 각 페이지마다 해시와 세션 정보를 확인하여 카드 nr을 받을 수 있습니다.
나중의 어느 시점에 결제 처리(3단계의 마지막 부분)에서 CC#(및 CVC)를 암호화해야 결제 처리자에게 전송할 수 있습니다(추정).
확인 페이지에 필요한 난독화 옆에 있는 정보를 받을 때 암호화 작업을 제대로 수행하지 않는 이유는 무엇입니까?(이것은 1단계의 마지막 부분입니다.)
이제부터는 암호화된 데이터나 난독화된 데이터만 사용하여 전체 데이터를 실제로 해독할 수 있는 유일한 사람이 CC-기업이 됩니다.
세션이나 데이터베이스가 정보를 보관할 필요가 없습니다.
모든 페이지는 데이터를 게시하는 양식입니다.각 후속 페이지에서 이전 페이지의 게시 변수가 숨겨진 양식 필드에 추가되어 다음 양식 제출에서 데이터를 다시 게시합니다.이렇게 하면 아무것도 저장되지 않지만 페이지마다 정보가 전달됩니다.이는 또한 사용자가 단계를 건너뛸 시도 없이 처음부터 끝까지 프로세스를 완료하도록 강제합니다.
양식이 HTTPS를 통해 제출되는 한 데이터는 자동으로 암호화되며 보안 부담은 SSL 인증서 공급자에게 있습니다.
많은 인기 커머스 사이트에서 이를 구현하고 있습니다.예를 들어 OSCommerce.
토큰화를 사용합니다.PCI DSS를 완벽하게 준수합니다.
더 많은 정보는 여기 https://www.pcisecuritystandards.org/documents/Tokenization_Guidelines_Info_Supplement.pdf 에서 확인할 수 있습니다.
언급URL : https://stackoverflow.com/questions/2900189/storing-credit-card-numbers-in-session-ways-around-it
'programing' 카테고리의 다른 글
| MySQL이 SET 절에서 SELECT를 사용하여 UPDATE 쿼리에 인덱스 사용을 거부함 (0) | 2023.09.19 |
|---|---|
| jQuery 구문 오류: #/ (0) | 2023.09.19 |
| 페이지에서 연락처 양식 7 쇼트코드를 사용하지 않는 한 연락처 양식 7 CSS 및 JS 제거 (0) | 2023.09.19 |
| SQL 삽입 문 반환 "0/무개 행 삽입" (0) | 2023.09.19 |
| 부트스트랩 3과 함께 부트스트랩-테마.css를 사용하는 방법? (0) | 2023.09.14 |