1、總體流程圖
2、流程說明:
由以上流程圖可知,整個流程分為:訂單生成、支付和后支付驗證3個階段。
2.1、訂單生成:
威脅分析:
該階段最容易犯的錯誤是根據前端提交的參數來計算應付款額,比如:相信前端提交過來的產品單價,甚至直接在前端計算應付款額再提交給后台進行處理,這種方式的攻擊成本非常低,只需要簡單篡改數據即可。正確的做法應當是對物品進行編號,根據前端提交的物品編號和數量來計算應付款額,具體步驟如下:
2.1.1、步驟1:
為不同的物品生成物品編號,用戶在提交訂單時,攜帶用戶購買的物品編號和數量信息給后台生成訂單,如下圖所示:
2.1.2、步驟2:
電商后台根據用戶提交的訂單請求參數生成訂單數據,其中最重要的一個環節是:根據物品編號和數量計算用戶應該支付的款額。即 應付款額=物品編號×購買數量。
2.2、支付:
威脅分析:
支付階段基本上是按照第三方支付平台的要求進行接入,通過第三方支付平台的簽名和簽名驗證機制保證支付的安全性,但需要注意的是這些支付平台一般都會提供多種不同的簽名機制,比如:RSA和MD5,通過申請簽名的步驟可以從中分析出一些風險點。
申請RSA簽名步驟:
(1)、申請支付接入。
(2)、生成用於簽名的PKI證書,將公鑰證書上傳到第三方支付平台,並將私鑰證書和第三方支付平台的公鑰證書保存在自己的服務器。
(3)、使用支付SDK接入並產生支付簽名。
申請MD5簽名步驟:
(1)、申請支付接入。
(2)、在第三方支付平台上設置簽名和驗證簽名所使用的對稱密鑰。
(3)、使用支付SDK接入並產生支付簽名。
通過以上對比,兩者之間最大的差異在於第2步,即簽名所使用的密鑰。MD5簽名使用的是對稱密鑰,即雙方使用相同的密鑰,這意味着密鑰的存儲安全性由接入方和第三方支付平台共同保證,雙方任意一方泄漏了密鑰(比如外部攻擊和內部泄漏),都將導致支付安全性無法被保證。反之,RSA簽名使用的是非對稱的密鑰,簽名用的私鑰只保存在接入方的服務器上,第三方支付平台只保存了對應的公鑰,即便第三方平台泄漏了接入方的公鑰,也不會影響接入方支付的安全性。除此之外,MD5簽名的密鑰是通常是由用戶手動設置而不是隨機生成的,用戶可能會設置一個足夠長度但不夠復雜度的密鑰,比如:abcd…xyz012..789,因此很可能會被破解。但兩者在接入的難度上並無差別,因此,在可能的情況下,建議使用RSA的簽名方式,如果使用MD5的簽名方式,應使用足夠隨機復雜的對稱密鑰。
2.2.1、步驟3(調用支付平台SDK可實現):
對提交給第三方支付平台的數據進行簽名,里面的關鍵數據包括支付金額等,MD5類型的簽名過程如下:
(1)、計算提交參數的簽名:
sig= MD5(“amount=389¶m1=$val1¶m2=$val2&…¶mn=$valn”+MD5key);
(2)、組合提交給第三方支付平台的參數(包括簽名和簽名類型):
amount=389¶m1=val1¶m2=val2&…¶mn=valn& sign=$sig&sign_tpye=MD5
RSA類型的簽名過程如下:
(1)、計算提交參數的摘要:
hash = MD5(“amount=389¶m1=$val1¶m2=$val2&…¶mn=$valn”);
(2)、計算提交參數的簽名:
sig = RSAsign(hash,RSAprivKey); //此處使用接入方自己的私鑰簽名
(3)、組合提交給第三方支付平台的參數(包括簽名和簽名類型):
amount=389¶m1=val1¶m2=val2&…¶mn=valn& sign=$sig&sign_tpye=RSA
2.2.2、步驟4:
將步驟3組合的參數通過用戶瀏覽器重定向到第三方支付平台,以此告知用戶實際應付的款額。由於需要經過用戶客戶端跳轉,因此,用戶是能夠對提交的參數數據進行篡改的(比如篡改金額),由於提交參數經過了簽名,篡改參數將導致支付平台驗簽失敗而無法支付成功,但基於以上支付的威脅分析,如果使用的MD5簽名密鑰因復雜度低可被暴力破解或者密鑰通過第三方平台泄漏,那么攻擊者就可以在篡改數據后重新計算簽名值,成功實施攻擊。
2.2.3、步驟5:
由第三方平台實現的簽名驗證,略。
2.2.4、步驟7(調用支付平台SDK可實現):
用戶支付成功后,將調用接入方在第三方支付平台上設置的回調接口,告知接入方用戶支付成功,為保證該接口調用過程中數據沒有被篡改以及請求沒有被偽造,需要進行數據簽名驗證,MD5類型的簽名驗證如下:
(1)、獲取來自第三方支付平台的請求參數:
param1=val1¶m2=val2&…¶mn=valn& sign=$sig&sign_tpye=MD5
(2)、計算請求參數的簽名:
sigLocal= MD5(“param1=$val1¶m2=$val2&…¶mn=$valn”+MD5key);
(3)、對比兩者簽名sign和sigLocal是否一致
RSA類型簽名驗證如下:
a) 獲取來自第三方支付平台的請求參數:
param1=val1¶m2=val2&…¶mn=valn& sign=$sig&sign_tpye=RSA
b) 計算請求參數摘要:
hash = MD5(param1=val1¶m2=val2&…¶mn=valn)
c) 計算請求參數簽名:
sigLocal = RSAversign($sig,RSA3rdPubKey); //注意此處使用第三方支付平台公鑰驗簽
d) 對比兩者簽名sign和sigLocal是否一致。
2.3、后支付驗證(待確認):
威脅分析:
通過步驟4的分析可知,如果接入方的密鑰已經泄漏,那么攻擊者就可以任意篡改訂單數據和生成簽名,因此需要進行一次反向驗證(或者由支付平台回調告知),確保支付平台已支付的金額和接入方訂單數據內的預期金額是一致的,如果不一致表示該訂單存在異常,應予以作廢處理,這樣也符合產品縱深防御的安全設計。
2.3.1、步驟8:
(1)、接收並處理來自第三方支付平台的支付成功回調。
(2)、根據流水號去第三方支付平台查詢實際支付金額(或由支付平台回調告知)。
(3)、對比接入方的預期支付金額與實際支付金額是否一致
注:此過程同樣需要簽名和驗簽。

