先找出風險邊界

顧客姓名、送貨備註及產品評語存於資料庫時只是資料;同一段文字匯出為 CSV,再由員工以試算表開啟,風險便改變。OWASP 把這類問題稱為 CSV 或公式注入:部分試算表程式會把特定符號開頭的儲存格當成公式執行。即使商戶沒有提供編輯試算表功能,出貨、退款或客服日常使用的匯出檔,仍可能包含外部人士輸入的內容。評估對象應是資料由顧客欄位流向員工電腦的整條路徑,而非只看下載按鈕。

先列出所有可由顧客、供應商、市集資料流或公開查詢表改動的欄位。姓名、地址之外,參考編號、自由文字指示,以及由其他系統複製的值也要包括。然後記下每款匯出檔由誰接收、以哪個程式開啟。只供程式匯入的檔案,跟供員工在 Excel 排序的工作表,要求並不一樣。匯出功能的負責人必須清楚說明用途,否則為改善顯示安全而加上的前綴,可能悄悄改動下游系統讀取的資料。

只用現有顧客記錄做目測,不足以驗收。外部人士可在日後輸入新內容;如果 CSV 產生器處理引號或分隔符出錯,看似普通的文字也可能被拆成另一個儲存格。OWASP 提醒要留意等號、加號、減號、@、控制字元,以及部分全形變體;分隔符與引號亦可能令危險符號落在新儲存格開頭。因此應檢查匯出後真正解析出的儲存格,並涵蓋開啟、儲存和重新開啟,而不是只檢查資料庫原值的第一個字元。

按實際用途選擇匯出方式

供人閱讀的工作表與供程式讀取的資料檔應分開考慮。員工工作表的重點,是在指定試算表程式中把外來欄位保持為純文字;系統整合檔的重點,則是忠實保存原始值及清楚的欄位規格。若同一個 CSV 同時承擔兩種用途,卻沒有交代取捨,便容易造成隱藏錯誤:用來阻止公式執行的定位字元或單引號,可能變成姓名、帳戶代碼或比對鍵的一部分。兩類使用者都存在時,應提供不同選項,或明確訂下匯入合約。

正確產生 CSV 結構是第一層必要工作,但並非完整保護。匯出程式要依所採用的 CSV 規格處理分隔符、引號及換行,確保原本同一欄的內容不會裂成多欄。OWASP ASVS 明確要求符合 RFC 4180 的跳脫規則,以及保護以公式符號開頭的欄位。第二層則要看目標試算表如何解讀儲存格。OWASP 指出,常見的引號和單引號做法,在 Microsoft Excel 儲存並重新開啟 CSV 後可能失效;它列出供 Excel 人手閱讀的帶定位字元做法,同時明言對其他程式及下游匯入並無通用保證。

不宜以拒絕所有特別格式的姓名,或默默刪去標點來處理。合法參考編號可能以加號開頭,地址也可能含逗號或換行。原始輸入應按正常業務驗證規則保存,再依輸出目的地處理。如果顯示用匯出值需要前綴,內部原值仍應在適當權限下保留。若員工編輯工作表後會重新匯入,還要寫清楚何時移除前綴、如何拒絕非預期公式。這條來回路徑屬另一個工作流程,應獨立測試。

以日常報表作演練

設想一間小店早上匯出已付款訂單安排出貨。測試記錄中,一位顧客的送貨指示以等號開頭;另一位提供含逗號及引號的參考資料;第三位姓名以全形加號開頭。這些只是測試例子,不是已發生的事件。倉庫員工需要看得懂指示,速遞匯入程式則需要未被改動的訂單編號。應分別產生員工報表和速遞資料檔,核對每宗訂單仍佔一個邏輯行、員工軟件把風險值顯示為文字,以及速遞檔保留合約列明的原值。

測試要跟隨員工實際操作:用一般權限帳戶下載,以指定桌面試算表開啟,儲存、關閉,再重新開啟。檢查解析後的儲存格和實際出現的安全提示,不應假設警告每次都會顯示。團隊若同時使用其他試算表或匯入工具,也要逐一測試,因為行為可能不同。記錄測試程式版本及匯出範本版本。開發人員只比較 CSV 原始位元組的單元測試,可驗證引號處理,卻不能單獨證明試算表會如何解讀。

測試資料還應包括危險符號出現在輸入值內的引號、分隔符或換行之後,以及一般標點、非拉丁文字姓名、長備註及空欄,避免修補後令報表無法使用。核對員工仍能找到正確訂單,系統資料檔亦能來回匯入而沒有不明的定位字元。如果某款程式無法同時滿足安全解讀與原值保真,應在匯出介面清楚說明支援範圍。選擇較窄但已驗證的流程,勝過宣稱任何 CSV 都安全。

把檢查納入日常維護

每款匯出檔應有業務及技術負責人。業務負責人決定檔案用於閱讀、編輯或系統傳送,並標出必須完全保留原值的欄位;技術負責人記錄產生 CSV 的方法及目的地處理,再以完成的檔案測試。顧客資料的存取權及保存期仍須按公司原有私隱流程決定;公式安全不會取代這些控制。日後新增欄位時,負責人要先判斷它是否可能含外部輸入,再納入範本。

有用的驗收記錄應具體列明匯出名稱、收件角色、試算表版本、風險測試值、儲存重開的結果,以及下游匯入是否受影響。若員工看到異常公式或安全提示,應暫停受影響用途,安全保存測試檔並交由負責人查明,不應因檔案來自內部系統便叫員工直接略過警告。內部匯出仍可能包含外部輸入。試算表產品、CSV 程式庫或匯入合約變動時,都要重新檢視原有判斷。

第一步可以只選一款常用匯出檔,追蹤其中一個顧客可改欄位,直到員工實際開啟的試算表,以及任何後續匯入。這會產生具體選擇:保留獨立的系統資料檔、對員工版採用已測試的文字處理,或以更清楚的格式取代用途含糊的匯出。中小企便有範圍明確的驗收方法,而非空泛承諾所有試算表都安全。OWASP 及 RFC 4180 支持正確 CSV 結構及目的地測試的必要性;最終做法仍須在員工真正使用的程式中驗證。

保存驗收結論

合格記錄不應只寫「已清洗」。應列明匯出路徑、顧客可改欄位、所採 CSV 規格、檢視程式及版本,以及匯入目的地。對每個刻意設計的特殊測試值,保存原始文字、最後解析出的儲存格、重開後的顯示結果,以及匯入時是否收到相同資料。如供人閱讀的檔案為了保持純文字而刻意改變顯示值,應在匯出規格寫明差別。這樣下一位維護者才理解兩款欄位相似的檔案為何有意不同,也避免日後整理程式時無意移除保護。

若測試儲存格被當成公式,應把它視為有負責人的工作流程缺陷;在指定程式路徑修正及重測前,暫停員工日常使用該匯出。如系統資料檔多了隱藏前綴,應改善檔案分流,不要叫收件者逐行手動清理。同一檔案可能跨部門使用:倉庫以畫面排序,會計則自動匯入,改格式前要確認兩邊需要。只有當各組都能說清楚應用哪款檔案、各欄位代表甚麼,以及看到異常儲存格時如何回報,決策才算完成。

如果團隊尚未指定使用哪款試算表,應先作出這個決定,再批准保護方法。於某個桌面程式通過的檔案,日後可能改由網頁檢視器開啟,或送往會計系統匯入。下載頁應列明支援的目的地、檔案供人閱讀還是交換資料,並為每條路徑保留含特殊測試值的樣本,讓規則可持續驗證。

推出前檢查

  • 是否已找出所有顧客可改欄位?
  • 是否已用指定程式開啟、儲存及重開報表?
  • 如原值要求不同,人手及系統匯出是否已分開?

資料來源及延伸閱讀