國家保密局網(wǎng)站>>保密科技

源代碼安全審計研究

2023年10月12日    來源:國家保密科技測評中心【字體: 打印

【摘 要】 源代碼是軟件的根本,其存在的安全缺陷是導致軟件出現(xiàn)漏洞的根源所在,人為因素的影響使得每個應用程序的源代碼都可能存在安全漏洞。從根本意義上來說,代碼審計就是挖掘源代碼中存在的代碼安全問題。本文對源代碼安全問題進行分析,闡述了源代碼審計方法和流程,通過研究Java Web漏洞產生的原因及源代碼表現(xiàn)形式,給出了源代碼安全編碼原則,總結出消除相應漏洞的安全編碼規(guī)范。

【關鍵詞】 源代碼安全審計 漏洞檢測 編碼規(guī)范 靜態(tài)檢測

1 引言

隨著計算機信息技術的發(fā)展,應用軟件呈現(xiàn)開放化、智能化、融合化、多元化等發(fā)展趨勢。應用軟件由于源代碼編寫不規(guī)范或引用的第三方框架、開源組件存在安全漏洞,從而導致軟件中隱藏著安全漏洞或質量缺陷。這些安全漏洞或質量缺陷一旦被攻擊者利用,將會威脅軟件系統(tǒng)和其應用數(shù)據(jù)的機密性、完整性、可用性。開放式Web應用程序安全項目(Open Web Application Security Project,OWASP)2017年發(fā)布的Web應用安全十大漏洞中有8項和源代碼缺陷相關。

應用軟件和信息系統(tǒng)的安全問題必須從底層源頭出發(fā),進行源代碼安全審計,檢查代碼的安全缺陷,編寫是否遵循安全編程規(guī)范,開發(fā)是否使用了不安全的第三方組件,從而在安全事件發(fā)生前或漏洞隱患尚未被利用前有效規(guī)避大部分應用程序的代碼問題,提高系統(tǒng)的主動安全防御能力。

2 源代碼安全審計的方法和流程

2.1 源代碼安全審計方法

源代碼安全審計的主要目的是提高源代碼質量,通過對程序源代碼進行檢查和分析,發(fā)現(xiàn)源代碼在軟件設計、測試、應用部署等各階段中可能存在的安全缺陷或安全漏洞,從源頭上避免潛在的安全風險。源代碼審計技術可分為靜態(tài)檢測(Static Analysis Security Testing,SAST)、動態(tài)檢測(Dynamic Analysis Security Testing,DAST)及動靜結合檢測(Interactive Application Security Testing,IAST)。

靜態(tài)檢測是指在不運行程序代碼的情況下,對程序中數(shù)據(jù)流、控制流、語義等信息進行分析,配合數(shù)據(jù)流分析和污點分析等技術,對程序代碼進行抽象和建模,分析程序的控制依賴、數(shù)據(jù)依賴和變量受污染狀態(tài)等信息,通過安全規(guī)則檢查、模式匹配等方式挖掘程序源代碼中存在的漏洞。源代碼漏洞靜態(tài)檢測方法一般是將源代碼轉化為單詞(token)、樹、圖等代碼中間表示形式,結合不同的檢測算法和檢測模型進行檢測。

動態(tài)檢測是指向程序輸入人為構造的測試數(shù)據(jù),根據(jù)系統(tǒng)功能或數(shù)據(jù)流向,對比實際輸出結果與預想結果,分析程序的正確性、健壯性等性能,判斷程序是否存在漏洞。動態(tài)檢測技術主要分為3種:模糊測試、動態(tài)符號執(zhí)行和動態(tài)污點分析。

動靜結合檢測是一種將靜態(tài)分析和動態(tài)分析相結合的混合式漏洞檢測方法,先使用靜態(tài)檢測方法對大規(guī)模的軟件源代碼進行檢測,對大規(guī)模的軟件源代碼進行切分,有針對性地進行檢測。再使用動態(tài)檢測方法對已劃分的程序代碼進行數(shù)據(jù)輸入,根據(jù)數(shù)據(jù)流向來判斷漏洞是否存在。

2.2 源代碼靜態(tài)審計思路

源代碼審計的思路有以下3個。根據(jù)敏感函數(shù)來逆向追蹤參數(shù)的傳遞過程,即檢查敏感函數(shù)的參數(shù),然后回溯變量,判斷變量是否可控且是否經過嚴格過濾;正向追蹤變量傳遞過程,觀察是否有變量輸入到高風險函數(shù)中,或傳遞的過程中是否有代碼邏輯漏洞;通讀全文代碼,根據(jù)自身的經驗判斷漏洞位置,直接挖掘功能點漏洞。

2.3 源代碼靜態(tài)審計流程

常見的靜態(tài)分析工具有: CodeQL、Fortify、CoBOT、Coverity、 RIPS、FindBugs、Cppcheck等。依據(jù)分析目標的不同,靜態(tài)分析可分為:面向源代碼的靜態(tài)分析和面向二進制代碼的靜態(tài)分析。面向源代碼的靜態(tài)分析以程序的源代碼作為輸入,對其進行語法分析、語義分析,并轉換為某種特定形式的中間表示,基于該中間表示進行數(shù)據(jù)流分析、控制流分析等。面向二進制代碼的靜態(tài)分析則是以經過反匯編等手段處理后的二進制代碼作為輸入,運用模式匹配或補丁對比等方式實現(xiàn)漏洞檢測,當程序是以二進制形式發(fā)布的,需要使用面向二進制代碼的漏洞分析。本文主要研究面向源代碼的靜態(tài)檢測技術的原理和流程。

源代碼通過編譯器進行詞法分析、語法分析和語義分析,生成抽象的中間表示,這些中間表示蘊含了源代碼的特定信息。例如,在語法分析階段,語法分析器會產生蘊含豐富語法信息的抽象語法樹。抽象語法樹中葉子節(jié)點用于表示操作數(shù),非葉子節(jié)點用于表示操作符,樹的層次結構表示代碼語句間的嵌套關系。為了更有效地捕獲代碼的語法、語義及上下文信息,學術界提出使用抽象語法樹、控制流程圖、程序依賴圖等代碼的中間抽象表示建立漏洞挖掘模型。源代碼審計流程如圖1所示。

圖1 源代碼審計流程

2.3.1 詞法分析

詞法分析階段是編譯前端的第一個階段,這個階段的任務就是從左到右逐個字符對構成源程序的字符串進行掃描,即對源代碼進行掃描,并按照定義好的詞法規(guī)則進行解析,識別出一個個token,將源代碼分割成由一個個token組成的數(shù)組,即形成一個token流。

2.3.2 語法分析

語法分析是在詞法分析生成的token序列基礎上,識別token序列之間的關系,并表示成一種后續(xù)程序處理過程中更容易理解和訪問的中間表示形式,我們也稱為抽象語法樹。同時,將有關源代碼信息存放在符號表的數(shù)據(jù)結構中,符號表和中間表示形式一起用來構造目標程序。

2.3.3語義分析

語義分析在抽象語法樹的基礎上進行分析,分析時考慮被檢測程序的基本語義,根據(jù)上下文環(huán)境檢測源代碼中是否存在語義錯誤。

2.3.4控制流圖構建

控制流圖反映了程序中各語句之間的先后執(zhí)行順序。控制流圖是一個有向圖G=(V,E),其中V代表節(jié)點的集合,E是有向邊的集合。為了更清楚地標識一個控制流圖,額外加入2個控制流節(jié)點:START和STOP,其中START節(jié)點為控制流圖的入口節(jié)點,STOP節(jié)點為控制流圖的出口節(jié)點?刂屏鲌D中的節(jié)點V代表程序的1條語句,有向邊E表示語句的控制流走向。

2.3.5數(shù)據(jù)流圖構建

數(shù)據(jù)流圖可以通過分析抽象語法樹直接獲得,數(shù)據(jù)流圖能夠表示語句和變量之間的數(shù)據(jù)依賴關系。通過從控制流圖中提取控制依賴關系,從數(shù)據(jù)流圖中提取數(shù)據(jù)依賴關系,將2種關系融合到同一張圖中,進而形成程序依賴圖。

2.3.6函數(shù)調用圖構建

函數(shù)調用圖是對程序中函數(shù)調用關系的一種靜態(tài)描述,在函數(shù)調用圖中,節(jié)點表示函數(shù),邊表示函數(shù)之間的調用關系。通過函數(shù)調用圖可以了解程序中的函數(shù)及函數(shù)之間的調用關系。由于面向對象程序設計的多態(tài)性,程序的函數(shù)調用圖只能大致表示出實際運行時函數(shù)的調用關系。

2.3.7數(shù)據(jù)流分析

數(shù)據(jù)流分析是指用來獲取有關數(shù)據(jù)如何沿著程序執(zhí)行路徑流動的相關信息的集合。數(shù)據(jù)流分析的對象是控制流圖,通過對控制流圖的遍歷,從中收集變量的數(shù)值產生位置及使用情況等信息,檢測數(shù)據(jù)的賦值與使用是否發(fā)生不合理現(xiàn)象,從而檢測源代碼中潛在的安全漏洞。

2.3.8污點分析

污點分析是一種信息流分析技術,通過對程序中的敏感數(shù)據(jù)進行標記,跟蹤標記數(shù)據(jù)在程序中的傳播,從而檢測系統(tǒng)中存在的安全問題。污點分析被定義為三元組<Source, Sink, Sanitizer>,Source即污染源,表示程序從外界獲取的不可信輸入;Sink即污點匯聚點,通常為一組安全敏感函數(shù),通過數(shù)據(jù)流分析跟蹤程序中污點數(shù)據(jù)的傳播;Sanitizer即無害處理,代表通過移除危害操作等手段使數(shù)據(jù)傳播不再對程序的安全性產生危害。污點分析則是在不運行和不修改代碼的情況下,對程序進行語句分析,運用程序變量之間的數(shù)據(jù)依賴關系,找出污點源(Sources)和污點匯聚點(Sink)之間的傳播路徑,從而找出程序潛在的漏洞隱患,再通過驗證數(shù)據(jù)方法進行無害處理(Sanitizer)。

3 安全編碼原則和規(guī)范

本文給出了源代碼安全編碼原則和源代碼安全編碼規(guī)范,分析了Java Web漏洞的代碼缺陷及產生原因,給出了預防結構化查詢語言(SQL)注入、跨站腳本攻擊、跨站請求偽造、文件上傳、命令執(zhí)行等漏洞的安全編碼規(guī)范。

3.1 安全編碼原則

3.1.1數(shù)據(jù)輸入驗證原則

首先假設所有的輸入是惡意的,除非能夠證明輸入數(shù)據(jù)是安全的,包括來自傳感器、文件、用戶或數(shù)據(jù)庫等的輸入,不僅要限制輸入數(shù)據(jù)的類型、長度、格式和范圍,還要驗證輸入數(shù)據(jù)是否包含有害信息。

3.1.2身份驗證原則

為防止身份信息被竊取,用戶身份驗證信息在存儲、傳輸?shù)冗^程中應采取保護措施。在通信通道采取身份驗證信息加密保護機制,如使用安全套接層(SSL)方式進行傳輸;口令的存儲不應直接存儲密碼,而應存儲密碼的單向散列值,使用用戶提供的密碼重新計算哈希值,從而減輕字典攻擊的威脅。同時限制用戶的口令長度和復雜度,以及限制用戶登錄次數(shù)。

3.1.3 最小授權原則

如果惡意程序被注入軟件中,進程被賦予的權限大小很大程度上決定了用戶能夠執(zhí)行操作的類型。因此,軟件中特定對象如進程、用戶或計算機程序應被賦予最小權限,任何需要提權的操作,應盡可能保持最短的時間,一旦任務完成,應該立刻收回權限,從而限制潛在的安全風險。

3.1.4配置管理原則

配置管理功能應只有被授權的操作員和管理員才能訪問,若確需遠程管理的,應使用SSL或虛擬專業(yè)網(wǎng)(VPN)等加密通道進行遠程管理。對于配置文件、注冊表、數(shù)據(jù)庫等關鍵配置數(shù)據(jù)應采取數(shù)據(jù)保護措施,保護關鍵配置數(shù)據(jù)的存儲和訪問的安全。

3.1.5會話管理原則

Cookie可能包括敏感信息,為防止攻擊者查看或修改Cookie內容,使用密碼對Cookie內容進行加密,從而避免數(shù)據(jù)受到未經授權的操作。盡量減少會話時長,會話時間越短,攻擊者在捕獲會話Cookie后,能使用Cookie來訪問應用程序的時間就越少,因此可以減少重放攻擊和會話劫持風險。

3.1.6組件安全原則

在使用第三方開源組件時,應對開源組件安全性進行評估,避免使用存在已知漏洞的開源組件或對安全漏洞進行修補后使用。

3.1.7內存安全原則

在編程過程中應避免內存出現(xiàn)緩沖區(qū)溢出、整數(shù)溢出、字符串格式化等問題。

3.2 常見漏洞分析及安全編碼規(guī)范

3.2.1 SQL注入

3.2.1.1 SQL注入描述

SQL注入漏洞是程序將攻擊者的輸入?yún)?shù)拼接到了SQL語句中,從而構造、改變SQL語義對數(shù)據(jù)庫進行攻擊。

3.2.1.2 SQL注入安全編碼規(guī)范

(1)加強用戶輸入驗證

在數(shù)據(jù)請求提交數(shù)據(jù)庫之前,使用處理函數(shù)或正則表達式匹配安全字符串的方法過濾用戶輸入內容中不合法字符。如果返回值屬于特定的類型或有具體的格式,那么在拼接SQL語句之前就要進行校驗,驗證其有效性。未經過濾的用戶輸入?yún)?shù)不能進行SQL拼接或可擴展語言(XML)拼接。如圖2所示,SQL語句將查詢字符串常量與用戶輸入進行拼接來動態(tài)構建SQL查詢命令。僅當id不包含單引號時,上述查詢語句才會是正確的。

圖2 禁止未經過濾的參數(shù)進行SQL拼接示例

(2)參數(shù)化查詢

在使用JDBC或Hibernate框架時,使用預編譯SQL語句的應用程序接口(API)進行參數(shù)化SQL查詢。使用MyBatis框架時,使用#{}代替${}進行參數(shù)化查詢,因為#{}會調用preparedStatement的set方法來賦值;而MyBatis只是將${}替換成變量的值,直接拼接到SQL語句中執(zhí)行。當無法使用參數(shù)化查詢,可使用創(chuàng)建白名單規(guī)定拼接到SQL查詢語句中的數(shù)據(jù)集合,或使用正則校驗限定拼接到SQL查詢語句中的數(shù)據(jù)中可包含的字符集。

使用預編譯語句prepared-Statement確保輸入值在數(shù)據(jù)庫中當作字符串、數(shù)字、日期或布爾值(boolean)等類型,而不是被作為SQL語法的一部分去執(zhí)行,如圖3所示。

圖3 SQL語句參數(shù)化查詢示例

(3)避免直接向用戶顯示數(shù)據(jù)庫錯誤信息

避免直接向用戶顯示數(shù)據(jù)庫錯誤,如類型錯誤、字段不匹配等,防止攻擊者利用這些錯誤信息進一步判斷數(shù)據(jù)庫的有關信息。

(4)控制訪問權限

將普通用戶與系統(tǒng)管理員用戶的權限嚴格區(qū)分開,堅持最小授權原則,從而最大程度減少因越權而導致的SQL注入攻擊。

3.2.2 跨站腳本攻擊

3.2.2.1 跨站腳本攻擊描述

跨站腳本攻擊即XSS攻擊,是指前端和后端有交互但沒有做輸入輸出過濾,應用程序將用戶發(fā)送的不可信賴數(shù)據(jù)在未經過濾、轉義,直接存入數(shù)據(jù)庫或直接輸出到頁面,從而導致用戶Cookie被劫持、構建Get和Post請求、獲取用戶信息、惡意的JavaScript執(zhí)行、XSS蠕蟲攻擊等后果。

3.2.2.2 跨站腳本安全編碼規(guī)范

跨站腳本攻擊可分為持久型XSS、非持久型XSS和DOM型XSS3種類型。攻擊者通過XSS漏洞進行劫持用戶Cookie、構建Get和Post請求、獲取用戶信息、XSS蠕蟲攻擊等。

(1)加強用戶輸入驗證

通過正則表達式限制輸入數(shù)據(jù)中可接受的字符集合。如果輸入數(shù)據(jù)為數(shù)字型參數(shù),進行強制類型轉換來校驗數(shù)據(jù)的合法性,當輸入數(shù)據(jù)為字符型,則應限制輸入數(shù)據(jù)的長度。如果輸入數(shù)據(jù)存在惡意字符,則拒絕請求。

(2)客戶端輔助驗證

輸入數(shù)據(jù)的驗證首先要在服務端進行,在客戶端只能作為輔助手段進行輸入數(shù)據(jù)的驗證。

(3)編碼處理

在不可信數(shù)據(jù)輸出到頁面之前,進行編碼處理。使用addslashes()函數(shù)對字符串“’”“””“\”字符進行轉義。使用htmispecialchars()函數(shù)對字符串“&”“””“<”“>”進行html編碼。

(4)防止盜取Cookie

在重要的Cookie中加入HttpOnly屬性,使得通過JavaScript腳本無法讀取到Cookie信息,有效防止跨站腳本XSS攻擊。

3.2.3 跨站請求偽造

3.2.3.1跨站請求偽造描述

跨站請求偽造(Cross Site Request Forgery,CSRF)是指攻擊者通過偽裝成來自受信任用戶的請求,對受信任的網(wǎng)站執(zhí)行操作的一種攻擊方式。

3.2.3.2跨站請求偽造規(guī)范要求

(1)驗證HTTP請求的Referer字段。Referer用于表明HTTP請求的來源地址。對每個HTTP請求驗證其Referer值,如果Referer值是同一個域名下,則接受該請求;如果 Referer是其他網(wǎng)站,則有可能是CSRF攻擊,拒絕該請求。

(2)在請求地址中添加token并驗證。攻擊者制造CSRF攻擊所使用的用戶驗證信息均來自Cookie中,攻擊者可以在不知道用戶信息的情況下直接利用用戶Cookie來通過安全驗證。要抵御CSRF,可在HTTP請求中加入1個隨機產生的token值,并在服務端校驗token。正常訪問時,客戶端瀏覽器能夠正確得到并傳回這個隨機數(shù);而通過CSRF傳來的欺騙性攻擊中沒有token或者token內容不正確,則拒絕該請求。

3.2.4 XML外部實體注入

3.2.4.1 外部實體注入描述

當開發(fā)人員配置XML解析功能允許外部實體引用時,攻擊者通過發(fā)送惡意構造的XML數(shù)據(jù)對應用系統(tǒng)造成文件讀取、命令執(zhí)行、內網(wǎng)端口探測、命令執(zhí)行、拒絕服務攻擊等,從而導致XML外部實體注入。

3.2.4.2 XML外部實體注入規(guī)范要求

XML文檔結構包括XML聲明、DTD文檔類型定義(可選)、文檔元素。DTD文檔類型定義的作用是定義XML文檔的合法構建模塊,它使用一系列合法的元素來定義文檔的結構,約束了XML文檔的結構。DTD可以在XML文檔內聲明,也可以外部引用。

(1)在應用程序的所有XML解析器中禁用DTD文檔類型定義,如圖4所示。

圖4 禁用DTD文檔類型定義示例

(2)如果不可能完全禁用DTD文檔類型定義,則禁用外部實體和參數(shù)實體,如圖5所示。

圖5 禁用外部實體和參數(shù)實體示例

3.2.5 文件上傳漏洞

3.2.5.1文件上傳漏洞描述

文件上傳過程中,通常因為未校驗上傳文件后綴類型,導致用戶可上傳jsp等webshell文件。代碼審計時重點關注上傳文件類型校驗及文件大小的限制。

3.2.5.2文件上傳漏洞規(guī)范要求

(1)使用白名單方式限制可上傳的文件類型,如圖6所示,只允許上傳擴展名為“gif”“jpg”“jpeg”“png”的圖片文件。

圖6 限制上傳文件類型示例

(2)限制允許上傳的文件大小,如圖7所示,限制上傳文件大小最大為100KB。

圖7 限制上傳文件大小示例

(3)限制文件上傳目錄的權限,對于文件上傳目錄設置可讀、可寫、不可執(zhí)行權限,禁止用戶上傳的文件在后臺執(zhí)行。

3.2.6 命令執(zhí)行漏洞

3.2.6.1命令執(zhí)行漏洞描述

命令執(zhí)行漏洞就是攻擊者可以直接在應用中執(zhí)行系統(tǒng)命令,從而獲取敏感信息或者拿到shell權限。命令執(zhí)行漏洞形成的原因是服務器對用戶輸入的命令沒有進行驗證和過濾,導致惡意代碼被執(zhí)行。

3.2.6.2命令執(zhí)行漏洞規(guī)范要求

(1)盡量不使用系統(tǒng)執(zhí)行命令,避免通過指定cmd /c或/bin/bash -c參數(shù)執(zhí)行系統(tǒng)命令。

(2)應避免從客戶端獲取命令,無法避免時,應使用白名單對可執(zhí)行的命令進行限制;白名單過大時,應使用正則校驗限定用戶輸入數(shù)據(jù)中可包含的字符集。在系統(tǒng)命令需要接受用戶輸入時,未對輸入?yún)?shù)作限制,允許任意命令輸入。攻擊者可以利用這個漏洞控制服務器,如圖8所示。

圖8 命令執(zhí)行漏洞示例

(3)對用戶輸入?yún)?shù)中的“&&”“|”“;”等字符進行過濾。

3.2.7安全配置缺陷

3.2.7.1安全配置缺陷問題描述

安全配置缺陷通常是由于不安全的默認配置、不完整的臨時配置、開源云存儲、錯誤的HTTP標頭配置,以及包含敏感信息的詳細錯誤信息等問題造成的。

3.2.7.2安全配置缺陷規(guī)范要求

(1)刪除不需要的配置和文件夾,刪除Web目錄下存在敏感信息的備份文件、測試文件、臨時文件、舊版本文件等,關閉多余端口,停用不用的服務,如FTP、Telnet、SMTP、SSH等,改默認口令。

(2)對所使用的第三方組件進行安全配置,使得第三方組件不存在已知漏洞。

3.2.8 敏感信息泄露

3.2.8.1敏感信息泄露描述

當開發(fā)人員缺乏一定的安全意識,未按照安全規(guī)范進行編碼時,會造成用戶敏感信息泄露和應用程序信息的泄露。

3.2.8.2敏感信息泄露規(guī)范要求

(1)不在錯誤信息頁泄露系統(tǒng)詳細信息、會話標識符、用戶賬號信息、物理路徑、數(shù)據(jù)庫版本及路徑、SQL語句等相關信息。

(2)刪除注釋代碼,避免注釋代碼中存在遺留的測試賬號信息、敏感接口地址以及第三方服務的敏感信息泄露。

(3)禁止使用Get方法傳遞敏感參數(shù)(會話標識、身份證號等),因為Get方法會將參數(shù)顯示在URL中,傳輸過程中所有的代理及緩存服務器都可以直接獲取用戶數(shù)據(jù)。

(4)避免在前端代碼中存放敏感信息,如Hidden字段存在管理員賬號密碼等。

(5)禁止帶有敏感數(shù)據(jù)的Web頁面緩存,可以通過函數(shù)設置強制瀏覽器不進行緩存,如圖9所示。

圖9 強制瀏覽器不進行緩存示例

3.2.9第三方組件安全

3.2.9.1第三方組件安全

為節(jié)約成本、提高開發(fā)效率,大量開源組件被引入企業(yè)軟件開發(fā)過程中,因此避免使用存在安全隱患的組件對于保證軟件安全具有重大意義。

3.2.9.2第三方組件規(guī)范要求

從官方渠道獲取第三方組件,定期對第三方組件進行安全性檢測,確保組件不存在已知安全漏洞,并及時升級組件版本;建立第三方組件庫,統(tǒng)一進行維護和管理,避免個人從其他渠道獲;對第三方組件進行完整性驗證,確保所使用的第三方組件未被篡改。

4 結語

隨著云計算的普及、微服務等基礎架構的成熟,企業(yè)開發(fā)模式也從傳統(tǒng)的瀑布模型演變到持續(xù)集成安全防護理念開發(fā)安全運維一體化(Dev-SecOps)。DevSecOps理念將安全貫穿設計、開發(fā)、測試、運營生命周期的每個環(huán)節(jié),使源代碼安全漏洞能夠得到盡早發(fā)現(xiàn)、盡快解決。源代碼靜態(tài)審計技術在理論上性能優(yōu)異,自動化程度高,可挖掘層次深,但實際使用中存在漏報率和誤報率偏高的缺陷。近年來,機器學習技術取得了重大突破,為靜態(tài)審計技術注入了新的活力,基于深度學習的漏洞檢測方法將會顯著提高漏洞檢測效率,減少誤報率,是源代碼安全審計下一步的研究方向。

(原載于《保密科學技術》雜志2023年2月刊)