【摘 要】 源代碼是軟件的根本,其存在的安全缺陷是導(dǎo)致軟件出現(xiàn)漏洞的根源所在,人為因素的影響使得每個(gè)應(yīng)用程序的源代碼都可能存在安全漏洞。從根本意義上來說,代碼審計(jì)就是挖掘源代碼中存在的代碼安全問題。本文對(duì)源代碼安全問題進(jìn)行分析,闡述了源代碼審計(jì)方法和流程,通過研究Java Web漏洞產(chǎn)生的原因及源代碼表現(xiàn)形式,給出了源代碼安全編碼原則,總結(jié)出消除相應(yīng)漏洞的安全編碼規(guī)范。
【關(guān)鍵詞】 源代碼安全審計(jì) 漏洞檢測(cè) 編碼規(guī)范 靜態(tài)檢測(cè)
1 引言
隨著計(jì)算機(jī)信息技術(shù)的發(fā)展,應(yīng)用軟件呈現(xiàn)開放化、智能化、融合化、多元化等發(fā)展趨勢(shì)。應(yīng)用軟件由于源代碼編寫不規(guī)范或引用的第三方框架、開源組件存在安全漏洞,從而導(dǎo)致軟件中隱藏著安全漏洞或質(zhì)量缺陷。這些安全漏洞或質(zhì)量缺陷一旦被攻擊者利用,將會(huì)威脅軟件系統(tǒng)和其應(yīng)用數(shù)據(jù)的機(jī)密性、完整性、可用性。開放式Web應(yīng)用程序安全項(xiàng)目(Open Web Application Security Project,OWASP)2017年發(fā)布的Web應(yīng)用安全十大漏洞中有8項(xiàng)和源代碼缺陷相關(guān)。
應(yīng)用軟件和信息系統(tǒng)的安全問題必須從底層源頭出發(fā),進(jìn)行源代碼安全審計(jì),檢查代碼的安全缺陷,編寫是否遵循安全編程規(guī)范,開發(fā)是否使用了不安全的第三方組件,從而在安全事件發(fā)生前或漏洞隱患尚未被利用前有效規(guī)避大部分應(yīng)用程序的代碼問題,提高系統(tǒng)的主動(dòng)安全防御能力。
2 源代碼安全審計(jì)的方法和流程
2.1 源代碼安全審計(jì)方法
源代碼安全審計(jì)的主要目的是提高源代碼質(zhì)量,通過對(duì)程序源代碼進(jìn)行檢查和分析,發(fā)現(xiàn)源代碼在軟件設(shè)計(jì)、測(cè)試、應(yīng)用部署等各階段中可能存在的安全缺陷或安全漏洞,從源頭上避免潛在的安全風(fēng)險(xiǎn)。源代碼審計(jì)技術(shù)可分為靜態(tài)檢測(cè)(Static Analysis Security Testing,SAST)、動(dòng)態(tài)檢測(cè)(Dynamic Analysis Security Testing,DAST)及動(dòng)靜結(jié)合檢測(cè)(Interactive Application Security Testing,IAST)。
靜態(tài)檢測(cè)是指在不運(yùn)行程序代碼的情況下,對(duì)程序中數(shù)據(jù)流、控制流、語義等信息進(jìn)行分析,配合數(shù)據(jù)流分析和污點(diǎn)分析等技術(shù),對(duì)程序代碼進(jìn)行抽象和建模,分析程序的控制依賴、數(shù)據(jù)依賴和變量受污染狀態(tài)等信息,通過安全規(guī)則檢查、模式匹配等方式挖掘程序源代碼中存在的漏洞。源代碼漏洞靜態(tài)檢測(cè)方法一般是將源代碼轉(zhuǎn)化為單詞(token)、樹、圖等代碼中間表示形式,結(jié)合不同的檢測(cè)算法和檢測(cè)模型進(jìn)行檢測(cè)。
動(dòng)態(tài)檢測(cè)是指向程序輸入人為構(gòu)造的測(cè)試數(shù)據(jù),根據(jù)系統(tǒng)功能或數(shù)據(jù)流向,對(duì)比實(shí)際輸出結(jié)果與預(yù)想結(jié)果,分析程序的正確性、健壯性等性能,判斷程序是否存在漏洞。動(dòng)態(tài)檢測(cè)技術(shù)主要分為3種:模糊測(cè)試、動(dòng)態(tài)符號(hào)執(zhí)行和動(dòng)態(tài)污點(diǎn)分析。
動(dòng)靜結(jié)合檢測(cè)是一種將靜態(tài)分析和動(dòng)態(tài)分析相結(jié)合的混合式漏洞檢測(cè)方法,先使用靜態(tài)檢測(cè)方法對(duì)大規(guī)模的軟件源代碼進(jìn)行檢測(cè),對(duì)大規(guī)模的軟件源代碼進(jìn)行切分,有針對(duì)性地進(jìn)行檢測(cè)。再使用動(dòng)態(tài)檢測(cè)方法對(duì)已劃分的程序代碼進(jìn)行數(shù)據(jù)輸入,根據(jù)數(shù)據(jù)流向來判斷漏洞是否存在。
2.2 源代碼靜態(tài)審計(jì)思路
源代碼審計(jì)的思路有以下3個(gè)。根據(jù)敏感函數(shù)來逆向追蹤參數(shù)的傳遞過程,即檢查敏感函數(shù)的參數(shù),然后回溯變量,判斷變量是否可控且是否經(jīng)過嚴(yán)格過濾;正向追蹤變量傳遞過程,觀察是否有變量輸入到高風(fēng)險(xiǎn)函數(shù)中,或傳遞的過程中是否有代碼邏輯漏洞;通讀全文代碼,根據(jù)自身的經(jīng)驗(yàn)判斷漏洞位置,直接挖掘功能點(diǎn)漏洞。
2.3 源代碼靜態(tài)審計(jì)流程
常見的靜態(tài)分析工具有: CodeQL、Fortify、CoBOT、Coverity、 RIPS、FindBugs、Cppcheck等。依據(jù)分析目標(biāo)的不同,靜態(tài)分析可分為:面向源代碼的靜態(tài)分析和面向二進(jìn)制代碼的靜態(tài)分析。面向源代碼的靜態(tài)分析以程序的源代碼作為輸入,對(duì)其進(jìn)行語法分析、語義分析,并轉(zhuǎn)換為某種特定形式的中間表示,基于該中間表示進(jìn)行數(shù)據(jù)流分析、控制流分析等。面向二進(jìn)制代碼的靜態(tài)分析則是以經(jīng)過反匯編等手段處理后的二進(jìn)制代碼作為輸入,運(yùn)用模式匹配或補(bǔ)丁對(duì)比等方式實(shí)現(xiàn)漏洞檢測(cè),當(dāng)程序是以二進(jìn)制形式發(fā)布的,需要使用面向二進(jìn)制代碼的漏洞分析。本文主要研究面向源代碼的靜態(tài)檢測(cè)技術(shù)的原理和流程。
源代碼通過編譯器進(jìn)行詞法分析、語法分析和語義分析,生成抽象的中間表示,這些中間表示蘊(yùn)含了源代碼的特定信息。例如,在語法分析階段,語法分析器會(huì)產(chǎn)生蘊(yùn)含豐富語法信息的抽象語法樹。抽象語法樹中葉子節(jié)點(diǎn)用于表示操作數(shù),非葉子節(jié)點(diǎn)用于表示操作符,樹的層次結(jié)構(gòu)表示代碼語句間的嵌套關(guān)系。為了更有效地捕獲代碼的語法、語義及上下文信息,學(xué)術(shù)界提出使用抽象語法樹、控制流程圖、程序依賴圖等代碼的中間抽象表示建立漏洞挖掘模型。源代碼審計(jì)流程如圖1所示。
圖1 源代碼審計(jì)流程
2.3.1 詞法分析
詞法分析階段是編譯前端的第一個(gè)階段,這個(gè)階段的任務(wù)就是從左到右逐個(gè)字符對(duì)構(gòu)成源程序的字符串進(jìn)行掃描,即對(duì)源代碼進(jìn)行掃描,并按照定義好的詞法規(guī)則進(jìn)行解析,識(shí)別出一個(gè)個(gè)token,將源代碼分割成由一個(gè)個(gè)token組成的數(shù)組,即形成一個(gè)token流。
2.3.2 語法分析
語法分析是在詞法分析生成的token序列基礎(chǔ)上,識(shí)別token序列之間的關(guān)系,并表示成一種后續(xù)程序處理過程中更容易理解和訪問的中間表示形式,我們也稱為抽象語法樹。同時(shí),將有關(guān)源代碼信息存放在符號(hào)表的數(shù)據(jù)結(jié)構(gòu)中,符號(hào)表和中間表示形式一起用來構(gòu)造目標(biāo)程序。
2.3.3語義分析
語義分析在抽象語法樹的基礎(chǔ)上進(jìn)行分析,分析時(shí)考慮被檢測(cè)程序的基本語義,根據(jù)上下文環(huán)境檢測(cè)源代碼中是否存在語義錯(cuò)誤。
2.3.4控制流圖構(gòu)建
控制流圖反映了程序中各語句之間的先后執(zhí)行順序。控制流圖是一個(gè)有向圖G=(V,E),其中V代表節(jié)點(diǎn)的集合,E是有向邊的集合。為了更清楚地標(biāo)識(shí)一個(gè)控制流圖,額外加入2個(gè)控制流節(jié)點(diǎn):START和STOP,其中START節(jié)點(diǎn)為控制流圖的入口節(jié)點(diǎn),STOP節(jié)點(diǎn)為控制流圖的出口節(jié)點(diǎn)?刂屏鲌D中的節(jié)點(diǎn)V代表程序的1條語句,有向邊E表示語句的控制流走向。
2.3.5數(shù)據(jù)流圖構(gòu)建
數(shù)據(jù)流圖可以通過分析抽象語法樹直接獲得,數(shù)據(jù)流圖能夠表示語句和變量之間的數(shù)據(jù)依賴關(guān)系。通過從控制流圖中提取控制依賴關(guān)系,從數(shù)據(jù)流圖中提取數(shù)據(jù)依賴關(guān)系,將2種關(guān)系融合到同一張圖中,進(jìn)而形成程序依賴圖。
2.3.6函數(shù)調(diào)用圖構(gòu)建
函數(shù)調(diào)用圖是對(duì)程序中函數(shù)調(diào)用關(guān)系的一種靜態(tài)描述,在函數(shù)調(diào)用圖中,節(jié)點(diǎn)表示函數(shù),邊表示函數(shù)之間的調(diào)用關(guān)系。通過函數(shù)調(diào)用圖可以了解程序中的函數(shù)及函數(shù)之間的調(diào)用關(guān)系。由于面向?qū)ο蟪绦蛟O(shè)計(jì)的多態(tài)性,程序的函數(shù)調(diào)用圖只能大致表示出實(shí)際運(yùn)行時(shí)函數(shù)的調(diào)用關(guān)系。
2.3.7數(shù)據(jù)流分析
數(shù)據(jù)流分析是指用來獲取有關(guān)數(shù)據(jù)如何沿著程序執(zhí)行路徑流動(dòng)的相關(guān)信息的集合。數(shù)據(jù)流分析的對(duì)象是控制流圖,通過對(duì)控制流圖的遍歷,從中收集變量的數(shù)值產(chǎn)生位置及使用情況等信息,檢測(cè)數(shù)據(jù)的賦值與使用是否發(fā)生不合理現(xiàn)象,從而檢測(cè)源代碼中潛在的安全漏洞。
2.3.8污點(diǎn)分析
污點(diǎn)分析是一種信息流分析技術(shù),通過對(duì)程序中的敏感數(shù)據(jù)進(jìn)行標(biāo)記,跟蹤標(biāo)記數(shù)據(jù)在程序中的傳播,從而檢測(cè)系統(tǒng)中存在的安全問題。污點(diǎn)分析被定義為三元組<Source, Sink, Sanitizer>,Source即污染源,表示程序從外界獲取的不可信輸入;Sink即污點(diǎn)匯聚點(diǎn),通常為一組安全敏感函數(shù),通過數(shù)據(jù)流分析跟蹤程序中污點(diǎn)數(shù)據(jù)的傳播;Sanitizer即無害處理,代表通過移除危害操作等手段使數(shù)據(jù)傳播不再對(duì)程序的安全性產(chǎn)生危害。污點(diǎn)分析則是在不運(yùn)行和不修改代碼的情況下,對(duì)程序進(jìn)行語句分析,運(yùn)用程序變量之間的數(shù)據(jù)依賴關(guān)系,找出污點(diǎn)源(Sources)和污點(diǎn)匯聚點(diǎn)(Sink)之間的傳播路徑,從而找出程序潛在的漏洞隱患,再通過驗(yàn)證數(shù)據(jù)方法進(jìn)行無害處理(Sanitizer)。
3 安全編碼原則和規(guī)范
本文給出了源代碼安全編碼原則和源代碼安全編碼規(guī)范,分析了Java Web漏洞的代碼缺陷及產(chǎn)生原因,給出了預(yù)防結(jié)構(gòu)化查詢語言(SQL)注入、跨站腳本攻擊、跨站請(qǐng)求偽造、文件上傳、命令執(zhí)行等漏洞的安全編碼規(guī)范。
3.1 安全編碼原則
3.1.1數(shù)據(jù)輸入驗(yàn)證原則
首先假設(shè)所有的輸入是惡意的,除非能夠證明輸入數(shù)據(jù)是安全的,包括來自傳感器、文件、用戶或數(shù)據(jù)庫(kù)等的輸入,不僅要限制輸入數(shù)據(jù)的類型、長(zhǎng)度、格式和范圍,還要驗(yàn)證輸入數(shù)據(jù)是否包含有害信息。
3.1.2身份驗(yàn)證原則
為防止身份信息被竊取,用戶身份驗(yàn)證信息在存儲(chǔ)、傳輸?shù)冗^程中應(yīng)采取保護(hù)措施。在通信通道采取身份驗(yàn)證信息加密保護(hù)機(jī)制,如使用安全套接層(SSL)方式進(jìn)行傳輸;口令的存儲(chǔ)不應(yīng)直接存儲(chǔ)密碼,而應(yīng)存儲(chǔ)密碼的單向散列值,使用用戶提供的密碼重新計(jì)算哈希值,從而減輕字典攻擊的威脅。同時(shí)限制用戶的口令長(zhǎng)度和復(fù)雜度,以及限制用戶登錄次數(shù)。
3.1.3 最小授權(quán)原則
如果惡意程序被注入軟件中,進(jìn)程被賦予的權(quán)限大小很大程度上決定了用戶能夠執(zhí)行操作的類型。因此,軟件中特定對(duì)象如進(jìn)程、用戶或計(jì)算機(jī)程序應(yīng)被賦予最小權(quán)限,任何需要提權(quán)的操作,應(yīng)盡可能保持最短的時(shí)間,一旦任務(wù)完成,應(yīng)該立刻收回權(quán)限,從而限制潛在的安全風(fēng)險(xiǎn)。
3.1.4配置管理原則
配置管理功能應(yīng)只有被授權(quán)的操作員和管理員才能訪問,若確需遠(yuǎn)程管理的,應(yīng)使用SSL或虛擬專業(yè)網(wǎng)(VPN)等加密通道進(jìn)行遠(yuǎn)程管理。對(duì)于配置文件、注冊(cè)表、數(shù)據(jù)庫(kù)等關(guān)鍵配置數(shù)據(jù)應(yīng)采取數(shù)據(jù)保護(hù)措施,保護(hù)關(guān)鍵配置數(shù)據(jù)的存儲(chǔ)和訪問的安全。
3.1.5會(huì)話管理原則
Cookie可能包括敏感信息,為防止攻擊者查看或修改Cookie內(nèi)容,使用密碼對(duì)Cookie內(nèi)容進(jìn)行加密,從而避免數(shù)據(jù)受到未經(jīng)授權(quán)的操作。盡量減少會(huì)話時(shí)長(zhǎng),會(huì)話時(shí)間越短,攻擊者在捕獲會(huì)話Cookie后,能使用Cookie來訪問應(yīng)用程序的時(shí)間就越少,因此可以減少重放攻擊和會(huì)話劫持風(fēng)險(xiǎn)。
3.1.6組件安全原則
在使用第三方開源組件時(shí),應(yīng)對(duì)開源組件安全性進(jìn)行評(píng)估,避免使用存在已知漏洞的開源組件或?qū)Π踩┒催M(jìn)行修補(bǔ)后使用。
3.1.7內(nèi)存安全原則
在編程過程中應(yīng)避免內(nèi)存出現(xiàn)緩沖區(qū)溢出、整數(shù)溢出、字符串格式化等問題。
3.2 常見漏洞分析及安全編碼規(guī)范
3.2.1 SQL注入
3.2.1.1 SQL注入描述
SQL注入漏洞是程序?qū)⒐粽叩妮斎雲(yún)?shù)拼接到了SQL語句中,從而構(gòu)造、改變SQL語義對(duì)數(shù)據(jù)庫(kù)進(jìn)行攻擊。
3.2.1.2 SQL注入安全編碼規(guī)范
(1)加強(qiáng)用戶輸入驗(yàn)證
在數(shù)據(jù)請(qǐng)求提交數(shù)據(jù)庫(kù)之前,使用處理函數(shù)或正則表達(dá)式匹配安全字符串的方法過濾用戶輸入內(nèi)容中不合法字符。如果返回值屬于特定的類型或有具體的格式,那么在拼接SQL語句之前就要進(jìn)行校驗(yàn),驗(yàn)證其有效性。未經(jīng)過濾的用戶輸入?yún)?shù)不能進(jìn)行SQL拼接或可擴(kuò)展語言(XML)拼接。如圖2所示,SQL語句將查詢字符串常量與用戶輸入進(jìn)行拼接來動(dòng)態(tài)構(gòu)建SQL查詢命令。僅當(dāng)id不包含單引號(hào)時(shí),上述查詢語句才會(huì)是正確的。
圖2 禁止未經(jīng)過濾的參數(shù)進(jìn)行SQL拼接示例
(2)參數(shù)化查詢
在使用JDBC或Hibernate框架時(shí),使用預(yù)編譯SQL語句的應(yīng)用程序接口(API)進(jìn)行參數(shù)化SQL查詢。使用MyBatis框架時(shí),使用#{}代替${}進(jìn)行參數(shù)化查詢,因?yàn)?{}會(huì)調(diào)用preparedStatement的set方法來賦值;而MyBatis只是將${}替換成變量的值,直接拼接到SQL語句中執(zhí)行。當(dāng)無法使用參數(shù)化查詢,可使用創(chuàng)建白名單規(guī)定拼接到SQL查詢語句中的數(shù)據(jù)集合,或使用正則校驗(yàn)限定拼接到SQL查詢語句中的數(shù)據(jù)中可包含的字符集。
使用預(yù)編譯語句prepared-Statement確保輸入值在數(shù)據(jù)庫(kù)中當(dāng)作字符串、數(shù)字、日期或布爾值(boolean)等類型,而不是被作為SQL語法的一部分去執(zhí)行,如圖3所示。
圖3 SQL語句參數(shù)化查詢示例
(3)避免直接向用戶顯示數(shù)據(jù)庫(kù)錯(cuò)誤信息
避免直接向用戶顯示數(shù)據(jù)庫(kù)錯(cuò)誤,如類型錯(cuò)誤、字段不匹配等,防止攻擊者利用這些錯(cuò)誤信息進(jìn)一步判斷數(shù)據(jù)庫(kù)的有關(guān)信息。
(4)控制訪問權(quán)限
將普通用戶與系統(tǒng)管理員用戶的權(quán)限嚴(yán)格區(qū)分開,堅(jiān)持最小授權(quán)原則,從而最大程度減少因越權(quán)而導(dǎo)致的SQL注入攻擊。
3.2.2 跨站腳本攻擊
3.2.2.1 跨站腳本攻擊描述
跨站腳本攻擊即XSS攻擊,是指前端和后端有交互但沒有做輸入輸出過濾,應(yīng)用程序?qū)⒂脩舭l(fā)送的不可信賴數(shù)據(jù)在未經(jīng)過濾、轉(zhuǎn)義,直接存入數(shù)據(jù)庫(kù)或直接輸出到頁面,從而導(dǎo)致用戶Cookie被劫持、構(gòu)建Get和Post請(qǐng)求、獲取用戶信息、惡意的JavaScript執(zhí)行、XSS蠕蟲攻擊等后果。
3.2.2.2 跨站腳本安全編碼規(guī)范
跨站腳本攻擊可分為持久型XSS、非持久型XSS和DOM型XSS3種類型。攻擊者通過XSS漏洞進(jìn)行劫持用戶Cookie、構(gòu)建Get和Post請(qǐng)求、獲取用戶信息、XSS蠕蟲攻擊等。
(1)加強(qiáng)用戶輸入驗(yàn)證
通過正則表達(dá)式限制輸入數(shù)據(jù)中可接受的字符集合。如果輸入數(shù)據(jù)為數(shù)字型參數(shù),進(jìn)行強(qiáng)制類型轉(zhuǎn)換來校驗(yàn)數(shù)據(jù)的合法性,當(dāng)輸入數(shù)據(jù)為字符型,則應(yīng)限制輸入數(shù)據(jù)的長(zhǎng)度。如果輸入數(shù)據(jù)存在惡意字符,則拒絕請(qǐng)求。
(2)客戶端輔助驗(yàn)證
輸入數(shù)據(jù)的驗(yàn)證首先要在服務(wù)端進(jìn)行,在客戶端只能作為輔助手段進(jìn)行輸入數(shù)據(jù)的驗(yàn)證。
(3)編碼處理
在不可信數(shù)據(jù)輸出到頁面之前,進(jìn)行編碼處理。使用addslashes()函數(shù)對(duì)字符串“’”“””“\”字符進(jìn)行轉(zhuǎn)義。使用htmispecialchars()函數(shù)對(duì)字符串“&”“””“<”“>”進(jìn)行html編碼。
(4)防止盜取Cookie
在重要的Cookie中加入HttpOnly屬性,使得通過JavaScript腳本無法讀取到Cookie信息,有效防止跨站腳本XSS攻擊。
3.2.3 跨站請(qǐng)求偽造
3.2.3.1跨站請(qǐng)求偽造描述
跨站請(qǐng)求偽造(Cross Site Request Forgery,CSRF)是指攻擊者通過偽裝成來自受信任用戶的請(qǐng)求,對(duì)受信任的網(wǎng)站執(zhí)行操作的一種攻擊方式。
3.2.3.2跨站請(qǐng)求偽造規(guī)范要求
(1)驗(yàn)證HTTP請(qǐng)求的Referer字段。Referer用于表明HTTP請(qǐng)求的來源地址。對(duì)每個(gè)HTTP請(qǐng)求驗(yàn)證其Referer值,如果Referer值是同一個(gè)域名下,則接受該請(qǐng)求;如果 Referer是其他網(wǎng)站,則有可能是CSRF攻擊,拒絕該請(qǐng)求。
(2)在請(qǐng)求地址中添加token并驗(yàn)證。攻擊者制造CSRF攻擊所使用的用戶驗(yàn)證信息均來自Cookie中,攻擊者可以在不知道用戶信息的情況下直接利用用戶Cookie來通過安全驗(yàn)證。要抵御CSRF,可在HTTP請(qǐng)求中加入1個(gè)隨機(jī)產(chǎn)生的token值,并在服務(wù)端校驗(yàn)token。正常訪問時(shí),客戶端瀏覽器能夠正確得到并傳回這個(gè)隨機(jī)數(shù);而通過CSRF傳來的欺騙性攻擊中沒有token或者token內(nèi)容不正確,則拒絕該請(qǐng)求。
3.2.4 XML外部實(shí)體注入
3.2.4.1 外部實(shí)體注入描述
當(dāng)開發(fā)人員配置XML解析功能允許外部實(shí)體引用時(shí),攻擊者通過發(fā)送惡意構(gòu)造的XML數(shù)據(jù)對(duì)應(yīng)用系統(tǒng)造成文件讀取、命令執(zhí)行、內(nèi)網(wǎng)端口探測(cè)、命令執(zhí)行、拒絕服務(wù)攻擊等,從而導(dǎo)致XML外部實(shí)體注入。
3.2.4.2 XML外部實(shí)體注入規(guī)范要求
XML文檔結(jié)構(gòu)包括XML聲明、DTD文檔類型定義(可選)、文檔元素。DTD文檔類型定義的作用是定義XML文檔的合法構(gòu)建模塊,它使用一系列合法的元素來定義文檔的結(jié)構(gòu),約束了XML文檔的結(jié)構(gòu)。DTD可以在XML文檔內(nèi)聲明,也可以外部引用。
(1)在應(yīng)用程序的所有XML解析器中禁用DTD文檔類型定義,如圖4所示。
圖4 禁用DTD文檔類型定義示例
(2)如果不可能完全禁用DTD文檔類型定義,則禁用外部實(shí)體和參數(shù)實(shí)體,如圖5所示。
圖5 禁用外部實(shí)體和參數(shù)實(shí)體示例
3.2.5 文件上傳漏洞
3.2.5.1文件上傳漏洞描述
文件上傳過程中,通常因?yàn)槲葱r?yàn)上傳文件后綴類型,導(dǎo)致用戶可上傳jsp等webshell文件。代碼審計(jì)時(shí)重點(diǎn)關(guān)注上傳文件類型校驗(yàn)及文件大小的限制。
3.2.5.2文件上傳漏洞規(guī)范要求
(1)使用白名單方式限制可上傳的文件類型,如圖6所示,只允許上傳擴(kuò)展名為“gif”“jpg”“jpeg”“png”的圖片文件。
圖6 限制上傳文件類型示例
(2)限制允許上傳的文件大小,如圖7所示,限制上傳文件大小最大為100KB。
圖7 限制上傳文件大小示例
(3)限制文件上傳目錄的權(quán)限,對(duì)于文件上傳目錄設(shè)置可讀、可寫、不可執(zhí)行權(quán)限,禁止用戶上傳的文件在后臺(tái)執(zhí)行。
3.2.6 命令執(zhí)行漏洞
3.2.6.1命令執(zhí)行漏洞描述
命令執(zhí)行漏洞就是攻擊者可以直接在應(yīng)用中執(zhí)行系統(tǒng)命令,從而獲取敏感信息或者拿到shell權(quán)限。命令執(zhí)行漏洞形成的原因是服務(wù)器對(duì)用戶輸入的命令沒有進(jìn)行驗(yàn)證和過濾,導(dǎo)致惡意代碼被執(zhí)行。
3.2.6.2命令執(zhí)行漏洞規(guī)范要求
(1)盡量不使用系統(tǒng)執(zhí)行命令,避免通過指定cmd /c或/bin/bash -c參數(shù)執(zhí)行系統(tǒng)命令。
(2)應(yīng)避免從客戶端獲取命令,無法避免時(shí),應(yīng)使用白名單對(duì)可執(zhí)行的命令進(jìn)行限制;白名單過大時(shí),應(yīng)使用正則校驗(yàn)限定用戶輸入數(shù)據(jù)中可包含的字符集。在系統(tǒng)命令需要接受用戶輸入時(shí),未對(duì)輸入?yún)?shù)作限制,允許任意命令輸入。攻擊者可以利用這個(gè)漏洞控制服務(wù)器,如圖8所示。
圖8 命令執(zhí)行漏洞示例
(3)對(duì)用戶輸入?yún)?shù)中的“&&”“|”“;”等字符進(jìn)行過濾。
3.2.7安全配置缺陷
3.2.7.1安全配置缺陷問題描述
安全配置缺陷通常是由于不安全的默認(rèn)配置、不完整的臨時(shí)配置、開源云存儲(chǔ)、錯(cuò)誤的HTTP標(biāo)頭配置,以及包含敏感信息的詳細(xì)錯(cuò)誤信息等問題造成的。
3.2.7.2安全配置缺陷規(guī)范要求
(1)刪除不需要的配置和文件夾,刪除Web目錄下存在敏感信息的備份文件、測(cè)試文件、臨時(shí)文件、舊版本文件等,關(guān)閉多余端口,停用不用的服務(wù),如FTP、Telnet、SMTP、SSH等,改默認(rèn)口令。
(2)對(duì)所使用的第三方組件進(jìn)行安全配置,使得第三方組件不存在已知漏洞。
3.2.8 敏感信息泄露
3.2.8.1敏感信息泄露描述
當(dāng)開發(fā)人員缺乏一定的安全意識(shí),未按照安全規(guī)范進(jìn)行編碼時(shí),會(huì)造成用戶敏感信息泄露和應(yīng)用程序信息的泄露。
3.2.8.2敏感信息泄露規(guī)范要求
(1)不在錯(cuò)誤信息頁泄露系統(tǒng)詳細(xì)信息、會(huì)話標(biāo)識(shí)符、用戶賬號(hào)信息、物理路徑、數(shù)據(jù)庫(kù)版本及路徑、SQL語句等相關(guān)信息。
(2)刪除注釋代碼,避免注釋代碼中存在遺留的測(cè)試賬號(hào)信息、敏感接口地址以及第三方服務(wù)的敏感信息泄露。
(3)禁止使用Get方法傳遞敏感參數(shù)(會(huì)話標(biāo)識(shí)、身份證號(hào)等),因?yàn)镚et方法會(huì)將參數(shù)顯示在URL中,傳輸過程中所有的代理及緩存服務(wù)器都可以直接獲取用戶數(shù)據(jù)。
(4)避免在前端代碼中存放敏感信息,如Hidden字段存在管理員賬號(hào)密碼等。
(5)禁止帶有敏感數(shù)據(jù)的Web頁面緩存,可以通過函數(shù)設(shè)置強(qiáng)制瀏覽器不進(jìn)行緩存,如圖9所示。
圖9 強(qiáng)制瀏覽器不進(jìn)行緩存示例
3.2.9第三方組件安全
3.2.9.1第三方組件安全
為節(jié)約成本、提高開發(fā)效率,大量開源組件被引入企業(yè)軟件開發(fā)過程中,因此避免使用存在安全隱患的組件對(duì)于保證軟件安全具有重大意義。
3.2.9.2第三方組件規(guī)范要求
從官方渠道獲取第三方組件,定期對(duì)第三方組件進(jìn)行安全性檢測(cè),確保組件不存在已知安全漏洞,并及時(shí)升級(jí)組件版本;建立第三方組件庫(kù),統(tǒng)一進(jìn)行維護(hù)和管理,避免個(gè)人從其他渠道獲;對(duì)第三方組件進(jìn)行完整性驗(yàn)證,確保所使用的第三方組件未被篡改。
4 結(jié)語
隨著云計(jì)算的普及、微服務(wù)等基礎(chǔ)架構(gòu)的成熟,企業(yè)開發(fā)模式也從傳統(tǒng)的瀑布模型演變到持續(xù)集成安全防護(hù)理念開發(fā)安全運(yùn)維一體化(Dev-SecOps)。DevSecOps理念將安全貫穿設(shè)計(jì)、開發(fā)、測(cè)試、運(yùn)營(yíng)生命周期的每個(gè)環(huán)節(jié),使源代碼安全漏洞能夠得到盡早發(fā)現(xiàn)、盡快解決。源代碼靜態(tài)審計(jì)技術(shù)在理論上性能優(yōu)異,自動(dòng)化程度高,可挖掘?qū)哟紊,但?shí)際使用中存在漏報(bào)率和誤報(bào)率偏高的缺陷。近年來,機(jī)器學(xué)習(xí)技術(shù)取得了重大突破,為靜態(tài)審計(jì)技術(shù)注入了新的活力,基于深度學(xué)習(xí)的漏洞檢測(cè)方法將會(huì)顯著提高漏洞檢測(cè)效率,減少誤報(bào)率,是源代碼安全審計(jì)下一步的研究方向。
(原載于《保密科學(xué)技術(shù)》雜志2023年2月刊)