作者 | 愛吃小魚干
小編 | 吃不飽
01嵌入式軟件應(yīng)用程序所面臨的日益增多的網(wǎng)絡(luò)威脅
嵌入式軟件應(yīng)用面臨著越來越多的安全問題,在任何現(xiàn)代軟件開發(fā)環(huán)境中,考慮安全性都是非常重要的。即使經(jīng)過最好的審查和測(cè)試的軟件也可能存在BUG,而這些BUG可以讓惡意用戶進(jìn)入系統(tǒng)并造成巨大的物理和財(cái)務(wù)損失。
其攻擊范圍涵蓋很多領(lǐng)域:從機(jī)場(chǎng)的調(diào)度系統(tǒng)到醫(yī)療設(shè)備都可能受到攻擊,特別值得關(guān)注的是日益增加的自動(dòng)駕駛汽車或連接汽車、列車和飛機(jī)等計(jì)算機(jī)控制系統(tǒng)。任何與外界通信的系統(tǒng)都面臨著風(fēng)險(xiǎn),例如汽車可能被盜,更糟糕的情況是車輛的控制權(quán)被奪取。
Q
那么,BUG是如何進(jìn)入系統(tǒng)的呢?
C和C++語言存在未定義的行為和不確定的行為,這可能會(huì)導(dǎo)致問題,尤其是對(duì)于沒有經(jīng)驗(yàn)的開發(fā)人員來說,他們可能不知道代碼實(shí)際上并沒有執(zhí)行他們預(yù)期的操作。此類錯(cuò)誤可能會(huì)導(dǎo)致開發(fā)者錯(cuò)誤地認(rèn)為一切都很正常,因?yàn)橐郧笆褂眠^該代碼,所以不需要重新驗(yàn)證。但實(shí)際上并非如此。代碼的優(yōu)化可能看起來是一件好事,占用更少的空間,但代碼優(yōu)化可能會(huì)刪除優(yōu)化器認(rèn)為不必要但卻對(duì)安全至關(guān)重要的檢查,例如除以零和不可達(dá)代碼檢測(cè)。外部庫可能包含BUG,但是采用的代碼可能沒有經(jīng)過驗(yàn)證。因此,在使用外部庫時(shí),重要的是檢查公開BUG的已知數(shù)據(jù)庫,例如CV。而任何使用動(dòng)態(tài)內(nèi)存的地方都可能導(dǎo)致問題,特別是像內(nèi)存泄漏之類的問題。
更多的安全漏洞是由于假設(shè)輸入數(shù)據(jù)格式正確且無需驗(yàn)證,導(dǎo)致出現(xiàn)數(shù)據(jù)緩沖區(qū)溢出和使用未分配動(dòng)態(tài)內(nèi)存(即所謂的“use after free”)等問題。盡管人們普遍認(rèn)識(shí)到這些安全問題可能會(huì)出現(xiàn),但它們并沒有得到足夠的關(guān)注和解決。原因可能有很多,但最主要的原因是之前沒有真正推動(dòng)改變,增加新功能比花費(fèi)時(shí)間檢查安全問題更為重要??梢酝ㄟ^教育開發(fā)人員貫穿軟件開發(fā)生命周期考慮安全、改進(jìn)流程和工具來提高檢測(cè)安全漏洞的信心,以及針對(duì)安全的測(cè)試,來改善這種情況。
02CERT C和C++如何檢測(cè)軟件安全問題
如今可能有實(shí)施軟件安全的愿望,那么如何實(shí)現(xiàn)呢?我們將看看嵌入式系統(tǒng)中使用的語言,以及如何使用C和C++來檢測(cè)這些語言引起的安全問題。歷史上,嵌入式系統(tǒng)是用匯編語言編寫的,但現(xiàn)在情況已經(jīng)改變,大多數(shù)關(guān)鍵系統(tǒng)都是用C或C++編寫的。C++正在變得越來越受歡迎,但當(dāng)前C仍是首選語言。然而,這兩種語言都存在安全問題。
White Source知識(shí)庫顯示,在過去十年中發(fā)現(xiàn)的開源代碼安全漏洞中,47%是C,6%是C++。這可能會(huì)導(dǎo)致人們認(rèn)為C本質(zhì)上比其他語言更容易受到攻擊,但事實(shí)并非如此。因?yàn)?a href="http://wenjunhu.com/soft/data/21-24/" target="_blank">C語言編寫的代碼數(shù)量比任何其他語言都多,并且時(shí)間跨度較長,因此發(fā)現(xiàn)漏洞的機(jī)會(huì)更多。而在過去五年中發(fā)現(xiàn)了大量漏洞是好事情。高危漏洞的高比例(36%)在C++中被發(fā)現(xiàn),然后是C(26%)。但需要注意的是,隨著C++變得越來越流行,也會(huì)有更多的機(jī)會(huì)在兩種語言中發(fā)現(xiàn)漏洞,因此需要適當(dāng)評(píng)估這些數(shù)據(jù)。
在計(jì)算機(jī)安全中,最常見的漏洞是緩沖區(qū)溢出和輸入驗(yàn)證。緩沖區(qū)溢出是一個(gè)非常嚴(yán)重的問題,可能會(huì)導(dǎo)致嚴(yán)重的后果。C和C++特別容易受到溢出攻擊的影響,因?yàn)樗鼈儗⒆址x為未終止的字符數(shù)組,沒有隱式進(jìn)行邊界檢查,即使開發(fā)人員認(rèn)為已經(jīng)進(jìn)行了檢查,標(biāo)準(zhǔn)庫函數(shù)對(duì)字符串也不執(zhí)行任何邊界檢查。在某些函數(shù)(如向量、點(diǎn)、A-T)中,C++進(jìn)行了一些改進(jìn),并通過默認(rèn)進(jìn)行了邊界檢查。漏洞代碼允許惡意用戶覆蓋內(nèi)存中的其他值,例如CPU必須執(zhí)行的指令,從而更改代碼的行為。
Q
關(guān)于緩沖區(qū)溢出
那就不得不提到兩個(gè)常見的函數(shù):strcpy和gets。這兩個(gè)函數(shù)都存在潛在的安全風(fēng)險(xiǎn)。如果輸入字符串超過目標(biāo)數(shù)組的預(yù)定義長度,則strcpy函數(shù)會(huì)導(dǎo)致緩沖區(qū)溢出;而gets函數(shù)則永遠(yuǎn)不能被安全地使用,因?yàn)間ets函數(shù)沒有邊界檢查,當(dāng)輸入的字符串長度大于目標(biāo)數(shù)組的長度時(shí),將發(fā)生緩沖區(qū)溢出,可能會(huì)導(dǎo)致程序運(yùn)行異?;虮蝗肭终呃谩?/p>
此外,未受限制的格式化輸出字符串也可能會(huì)導(dǎo)致安全漏洞。這種漏洞是由于應(yīng)用程序?qū)⑤斎胱址臄?shù)據(jù)作為命令進(jìn)行評(píng)估。如果惡意用戶可以完全或部分地控制格式化字符串的內(nèi)容,則可能會(huì)導(dǎo)致應(yīng)用程序崩潰、堆棧內(nèi)容泄露、任意內(nèi)存寫入等后果。此外,攻擊者還可以執(zhí)行任意代碼并以易受攻擊進(jìn)程的權(quán)限運(yùn)行,從而破壞系統(tǒng)的安全和穩(wěn)定性。
即使是最有經(jīng)驗(yàn)的程序員也可能犯錯(cuò)。研究表明,他們通常只能以約50% 的效率發(fā)現(xiàn)自己的錯(cuò)誤。那么如何確保安全問題,例如緩沖區(qū)溢出的情況不會(huì)出現(xiàn)在最終產(chǎn)品中呢?編譯器可能會(huì)看到顯而易見的起點(diǎn),但它可能僅實(shí)現(xiàn)語言標(biāo)準(zhǔn)的子集,語言標(biāo)準(zhǔn)的解釋可能因編譯器而異,這可能導(dǎo)致未來的移植或語義錯(cuò)誤。最好的方法是根據(jù)編碼標(biāo)準(zhǔn)對(duì)代碼進(jìn)行檢查,例如CERT C或CERT C++。正如我們所看到的,C和C++都具有未定義和未指定的行為,應(yīng)該避免使用。而編碼標(biāo)準(zhǔn)正提供了一種做到這一點(diǎn)的方法。
編碼標(biāo)準(zhǔn)是一組規(guī)則,通常由一個(gè)團(tuán)隊(duì)根據(jù)多年的經(jīng)驗(yàn)制定,可以讓開發(fā)人員對(duì)其代碼更有信心。通過使用編碼標(biāo)準(zhǔn)遵循一組規(guī)則,降低引入錯(cuò)誤的可能性,使代碼更易于維護(hù)。任何安全系統(tǒng)的起點(diǎn)都是使用防御性實(shí)現(xiàn)技術(shù),使軟件即使在面臨不利情況時(shí)也能繼續(xù)運(yùn)行。公認(rèn)的編碼標(biāo)準(zhǔn)意味著其已經(jīng)考慮了常見的使用情況,因?yàn)镃和C++都具有可能導(dǎo)致關(guān)鍵或未指定行為的特性。編碼標(biāo)準(zhǔn)因此定義了一個(gè)語言子集,以防止使用會(huì)導(dǎo)致此類行為的構(gòu)造方式。此外,編碼標(biāo)準(zhǔn)將實(shí)現(xiàn)強(qiáng)類型,它確保對(duì)語言數(shù)據(jù)類型有所了解,從而防止某些類別的編程錯(cuò)誤。
CERT部門協(xié)助開發(fā)的編碼標(biāo)準(zhǔn)專注于安全,它們被認(rèn)為是一個(gè)全面的程序安全標(biāo)準(zhǔn),并在多個(gè)行業(yè)中使用。該標(biāo)準(zhǔn)由一個(gè)在線社區(qū)開發(fā),有單獨(dú)的標(biāo)準(zhǔn)適用于C、C++和Java。然而,由于C和C++之間存在重疊,許多CERT C規(guī)則已經(jīng)包括在內(nèi)。只需添加一些額外的規(guī)則,便可關(guān)注C++語言中沒有完全覆蓋的部分。如何通過限制使用某些庫函數(shù)來創(chuàng)建一個(gè)安全的C語言子集,以提高代碼的安全性?這可以通過引入一些規(guī)則來實(shí)現(xiàn),比如INTC和A-R等,這些規(guī)則旨在防止常見的安全問題,例如緩沖區(qū)溢出和輸入驗(yàn)證等。ARR30-C:不要形成或使用超出邊界的指針或數(shù)組。如果使用越界指針或數(shù)組,就可能會(huì)導(dǎo)致程序錯(cuò)誤和安全漏洞。因此,在編寫程序時(shí),應(yīng)該確保所有指針和數(shù)組的訪問都在其有效范圍內(nèi)。如果需要進(jìn)行指針或數(shù)組的操作,應(yīng)該先檢查其有效范圍,再進(jìn)行后續(xù)的處理。這樣可以避免因?yàn)樵浇缭L問而導(dǎo)致的程序錯(cuò)誤和安全漏洞。例如,如果使用指針訪問數(shù)組元素時(shí),應(yīng)該先檢查指針是否指向數(shù)組的有效范圍內(nèi),再進(jìn)行訪問操作。如果指針越界,就可能會(huì)導(dǎo)致程序崩潰或者被攻擊者利用。因此,ARR30-C規(guī)則的實(shí)踐可以提高程序的安全性和穩(wěn)定性。ARR38-C:保證庫函數(shù)不會(huì)形成無效指針。它要求在使用庫函數(shù)時(shí),必須保證傳遞給函數(shù)的指針參數(shù)是有效的,即指向已分配的內(nèi)存區(qū)域或NULL指針。如果傳遞給函數(shù)的指針參數(shù)是無效的,那么就可能會(huì)出現(xiàn)程序錯(cuò)誤和安全漏洞。
因此,在使用庫函數(shù)時(shí),應(yīng)該先檢查傳遞給函數(shù)的指針參數(shù)是否有效,再進(jìn)行后續(xù)的處理。這樣可以避免因?yàn)閭鬟f無效指針而導(dǎo)致的程序錯(cuò)誤和安全漏洞。例如,如果使用strcpy()函數(shù)將一個(gè)字符串復(fù)制到另一個(gè)字符串中,那么應(yīng)該先檢查目標(biāo)字符串的指針是否有效,再進(jìn)行復(fù)制操作。如果目標(biāo)字符串的指針無效,那么就可能會(huì)導(dǎo)致程序崩潰或者被攻擊者利用。因此,ARR38-C規(guī)則的實(shí)踐可以提高程序的安全性和穩(wěn)定性。
EXP39-C: 不要通過不兼容類型的指針訪問變量。如果使用不兼容類型的指針訪問變量,就可能會(huì)導(dǎo)致程序錯(cuò)誤和安全漏洞。因此,在訪問變量時(shí),應(yīng)該使用與變量類型兼容的指針。如果需要使用不兼容類型的指針,可以通過類型轉(zhuǎn)換來實(shí)現(xiàn)。但是,在進(jìn)行類型轉(zhuǎn)換時(shí),需要確保轉(zhuǎn)換后的指針仍然指向有效的內(nèi)存區(qū)域,否則就可能會(huì)出現(xiàn)程序錯(cuò)誤和安全漏洞。因此,EXP39-C規(guī)則的實(shí)踐可以提高程序的安全性和穩(wěn)定性。
FIO37-C: 在使用fgets()或fgetws()函數(shù)讀取輸入時(shí),不要假定函數(shù)返回的字符串非空。因?yàn)檫@兩個(gè)函數(shù)在讀取輸入時(shí)可能會(huì)遇到文件結(jié)束符或讀取錯(cuò)誤等情況,導(dǎo)致返回的字符串為空。如果程序在使用fgets()或fgetws()函數(shù)時(shí)假定返回的字符串非空,那么就可能會(huì)出現(xiàn)程序錯(cuò)誤和安全漏洞。因此,在使用fgets()或fgetws()函數(shù)時(shí),應(yīng)該先檢查返回的字符串是否為空,再進(jìn)行后續(xù)的處理。這樣可以避免因?yàn)榧俣ㄗ址强斩鴮?dǎo)致的程序錯(cuò)誤和安全漏洞。
STR31-C: 確保字符串存儲(chǔ)空間足夠容納字符數(shù)據(jù)和空字符終止符。這條規(guī)則的目的是防止緩沖區(qū)溢出和其他安全漏洞,從而提高代碼的安全性和可靠性。具體實(shí)現(xiàn)方法包括使用安全的字符串函數(shù)、檢查字符串長度和緩沖區(qū)大小、避免使用不安全的字符串拼接等。在編寫代碼時(shí),應(yīng)該遵循這條規(guī)則,并結(jié)合實(shí)際情況選擇相應(yīng)的實(shí)現(xiàn)方法,以確保代碼的安全性和可靠性。STR32-C: 不要將非零終止字符序列傳遞給期望字符串的庫函數(shù)。旨在防止將非空字符終止的字符序列傳遞給期望字符串的庫函數(shù)。這條規(guī)則的目的是防止緩沖區(qū)溢出和其他安全漏洞,從而提高代碼的安全性和可靠性。具體實(shí)現(xiàn)方法包括使用安全的字符串函數(shù)、檢查字符串長度和緩沖區(qū)大小、避免使用不安全的字符串拼接等。在編寫代碼時(shí),應(yīng)該遵循這條規(guī)則,并結(jié)合實(shí)際情況選擇相應(yīng)的實(shí)現(xiàn)方法,以確保代碼的安全性和可靠性。
03靜態(tài)代碼分析工具如何有效地實(shí)現(xiàn)安全編碼標(biāo)準(zhǔn)?
如何實(shí)施編碼標(biāo)準(zhǔn)以確保代碼的正確性和合規(guī)性呢?CERT C標(biāo)準(zhǔn)規(guī)定了確定性、不確定性和合規(guī)性的要求,并強(qiáng)制要求代碼不得違反任何規(guī)則。同時(shí),建議遵循推薦操作以便更容易符合規(guī)則。為了檢查代碼是否違反規(guī)則,該標(biāo)準(zhǔn)建議使用靜態(tài)代碼分析工具。
在軟件開發(fā)生命周期中,手動(dòng)和自動(dòng)代碼審查都有其適用的場(chǎng)景,例如自動(dòng)化工具無法知道代碼的實(shí)際意圖。然而,手動(dòng)代碼審查的結(jié)果會(huì)受到審核人員專業(yè)知識(shí)的影響。靜態(tài)代碼分析可以檢查很少被控制的代碼片段,這些代碼片段通常無法通過其他方法測(cè)試。這可以找出異常處理程序或日志系統(tǒng)中的缺陷。與手動(dòng)代碼審查相比,其速度更快,而且不占用開發(fā)人員的時(shí)間,使他們能夠更專注于開發(fā)。開發(fā)者廣泛認(rèn)為手動(dòng)審核和自動(dòng)靜態(tài)代碼分析的結(jié)合是最有效的方式,因?yàn)檫@是識(shí)別漏洞和弱點(diǎn)的最佳方式,CERT C 和CERT C++ 都應(yīng)該使用靜態(tài)代碼分析工具,最好是行業(yè)標(biāo)準(zhǔn)的工具,如Helix QAC,其對(duì)CERT編碼規(guī)范的覆蓋度達(dá)到100%。這款Perforce的靜態(tài)代碼分析工具可以驗(yàn)證代碼符合編碼指南,并提供這種符合性的證據(jù),以滿足網(wǎng)絡(luò)安全要求。Helix QAC 具有完整的第三方 C 和 C++ 語言庫的覆蓋,這使得開發(fā)人員更容易驗(yàn)證軟件是否免受常見代碼安全漏洞的影響。
04總結(jié)
總之,實(shí)施編碼標(biāo)準(zhǔn)是確保代碼質(zhì)量的重要步驟,它可以幫助開發(fā)人員避免常見的錯(cuò)誤和漏洞,從而提高軟件的可靠性和安全性。同時(shí),使用靜態(tài)分析工具進(jìn)行全面的代碼審查可以進(jìn)一步加強(qiáng)代碼的正確性和符合性。
-
軟件
+關(guān)注
關(guān)注
69文章
4958瀏覽量
87614 -
信息安全
+關(guān)注
關(guān)注
5文章
656瀏覽量
38912
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論