越界寫入檢測)
靜態(tài)分析SAST應(yīng)用安全漏洞掃描代碼質(zhì)量【免費(fèi)下載鏈接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security項(xiàng)目地址https://gitcode.com/gh_mirrors/co/codeql點(diǎn)擊查看免費(fèi)下載導(dǎo)讀本文圍繞 CodeQL 倉庫中 C 查詢包 0.6.3 版本發(fā)布說明cpp/ql/src/change-notes/released/0.6.3.md引入的新查詢cpp/overrun-write展開深入解析它如何檢測 C 風(fēng)格緩沖區(qū)操作函數(shù)中的緩沖區(qū)溢出buffer overflow。讀完本文你將掌握該查詢的觸發(fā)原理、與cpp/overrunning-write系列查詢的分工差異、底層依賴的 ProductFlow 與范圍分析Range Analysis實(shí)現(xiàn)以及如何結(jié)合倉庫內(nèi)的示例與測試用例驗(yàn)證查詢行為。一、發(fā)布說明中的新查詢?cè)?cpp/ql/src/change-notes/released/0.6.3.md 中0.6.3 版本的發(fā)布說明只有一條核心變更Added a new query,cpp/overrun-write, to detect buffer overflows in C-style functions that manipulate buffers.即新增了cpp/overrun-write查詢用于檢測“在操作緩沖區(qū)的 C 風(fēng)格函數(shù)”中發(fā)生的緩沖區(qū)溢出。與之配套的正式 CHANGELOG 記錄見 cpp/ql/src/CHANGELOG.md。這里有兩個(gè)值得關(guān)注的關(guān)鍵詞C 風(fēng)格函數(shù)C-style functions指strcpy、strncpy、memset、sprintf、memcpy等以裸指針/字符數(shù)組方式操作緩沖區(qū)的 C 庫函數(shù)而非 C 的std::vector、std::string等自帶長度管理的容器。緩沖區(qū)溢出buffer overflow寫入或訪問超出分配范圍之外的內(nèi)存輕則導(dǎo)致段錯(cuò)誤segmentation fault重則成為可利用的安全漏洞。二、查詢定位cpp/overrun-write是什么2.1 查詢?cè)獢?shù)據(jù)該查詢的實(shí)現(xiàn)文件為 cpp/ql/src/Security/CWE/CWE-119/OverrunWriteProductFlow.ql其頭部元數(shù)據(jù)完整定義了查詢的身份信息元數(shù)據(jù)項(xiàng)值含義nameOverrunning write查詢名稱descriptionExceeding the size of a static array during write or access operations may result in a buffer overflow問題描述kindpath-problem輸出帶數(shù)據(jù)流路徑的問題problem.severityerror問題嚴(yán)重級(jí)別security-severity9.3安全嚴(yán)重級(jí)別CVSS 風(fēng)格評(píng)分precisionmedium檢出精度中等意味著存在一定誤報(bào)/漏報(bào)空間idcpp/overrun-write查詢唯一標(biāo)識(shí)tagsreliability、security、external/cwe/cwe-119、external/cwe/cwe-131關(guān)聯(lián) CWE-119緩沖區(qū)操作中的內(nèi)存破壞與 CWE-131緩沖區(qū)大小計(jì)算錯(cuò)誤與常見的problem類查詢不同cpp/overrun-write是path-problem查詢它不僅報(bào)告“哪里溢出”還會(huì)呈現(xiàn)從分配源頭source到寫入點(diǎn)sink的完整數(shù)據(jù)流路徑便于開發(fā)者定位根因。2.2 查詢套件歸屬從集成測試的套件清單cpp/ql/integration-tests/query-suite/cpp-security-and-quality.qls.expected 與 cpp/ql/integration-tests/query-suite/cpp-security-extended.qls.expected可以看到OverrunWriteProductFlow.ql同時(shí)被cpp-security-and-quality與cpp-security-extended兩個(gè)套件收錄即它默認(rèn)參與 C/C 代碼掃描的安全質(zhì)量檢查。三、工作原理從源碼看檢測機(jī)制3.1 核心依賴OverrunWriteProductFlow.ql頂部導(dǎo)入了以下關(guān)鍵庫import cpp import semmle.code.cpp.ir.dataflow.internal.ProductFlow import semmle.code.cpp.ir.IR import semmle.code.cpp.models.interfaces.Allocation import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import semmle.code.cpp.security.ProductFlowUtils.ProductFlowUtils import semmle.code.cpp.rangeanalysis.new.RangeAnalysisUtil import StringSizeFlow::PathGraph1 import codeql.util.Unit這些依賴揭示了查詢的三層機(jī)理IR 層基于 CodeQL 的中間表示IR進(jìn)行分析CallInstruction、LoadInstruction等指令級(jí)元素是分析的原子單位。ProductFlow 庫這是一個(gè)“雙投影”數(shù)據(jù)流框架同時(shí)追蹤緩沖區(qū)指針第一投影與緩沖區(qū)大小第二投影兩條獨(dú)立的數(shù)據(jù)流并將二者關(guān)聯(lián)成“緩沖區(qū) 大小”的配對(duì)約束。Range Analysis范圍分析新式范圍分析semmle.code.cpp.rangeanalysis.new用于推導(dǎo)分配大小的數(shù)值上下界判斷寫入長度是否會(huì)越界。3.2 源點(diǎn)提取分配大小表達(dá)式查詢通過hasSize謂詞從分配表達(dá)式中提取“大小變量”與“偏移量 delta”predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) { exists(VariableAccess va, Expr size, int delta | size alloc.getSizeExpr() and // Get the unique variable in a size expression like x in malloc(x 1). va unique( | | getAVariableAccess(size)) and // Compute delta as the constant difference between x and x 1. bounded(any(Instruction instr | instr.getUnconvertedResultExpression() size), any(LoadInstruction load | load.getUnconvertedResultExpression() va), delta) and n.asExpr() va and state delta ) }例如對(duì)malloc(x 1)查詢提取出變量x并計(jì)算出常量偏移delta 1作為數(shù)據(jù)流的狀態(tài)值state在后續(xù)傳播中攜帶。這保證了malloc(size 1)這類“多分配一個(gè)元素”的常見防御性寫法不會(huì)被誤判為越界。3.3 匯點(diǎn)識(shí)別帶大小參數(shù)的緩沖區(qū)函數(shù)isSinkPairImpl0謂詞通過ArrayFunction模型識(shí)別“緩沖區(qū) 大小”成對(duì)出現(xiàn)的調(diào)用predicate isSinkPairImpl0( CallInstruction c, DataFlow::Node bufSink, DataFlow::Node sizeSink, int delta, Expr eBuf, Instruction sizeBound, Instruction sizeInstr ) { exists(int bufIndex, int sizeIndex, Instruction bufInstr, ArrayFunction func | bufInstr bufSink.asInstruction() and c.getArgument(bufIndex) bufInstr and sizeBound sizeSink.asInstruction() and c.getArgument(sizeIndex) sizeInstr and c.getStaticCallTarget() func and pragmaonly_bind_into .hasArrayWithVariableSize(pragmaonly_bind_into, pragmaonly_bind_into) and bounded(sizeInstr, sizeBound, delta) and eBuf bufInstr.getUnconvertedResultExpression() ) }ArrayFunction是 CodeQL 中為 C 庫緩沖區(qū)操作函數(shù)建立的模型接口定義于 cpp/ql/lib 下的models/interfaces/ArrayFunction.qll它聲明了哪些參數(shù)是緩沖區(qū)、哪些參數(shù)是其大小。strncpy(dst, src, n)中dst與n、memset(p, c, n)中p與n均屬于這類配對(duì)。3.4 狀態(tài)傳播與越界判定查詢的核心在于StringSizeConfig這一ProductFlow::StateConfigSig實(shí)現(xiàn)。它把“大小”維度設(shè)計(jì)為一個(gè)整數(shù)狀態(tài)FlowState2源端hasSize(bufSource.asExpr(), sizeSource, state2)記錄分配時(shí)的偏移量。匯點(diǎn)isSinkPair中比較delta state2——即調(diào)用處實(shí)際傳入的大小參數(shù)超出分配時(shí)攜帶的大小狀態(tài)偏移時(shí)判定越界。屏障SizeBarrier與isBarrierOut2用于阻斷回邊back edge避免循環(huán)導(dǎo)致的無限數(shù)據(jù)流與誤報(bào)。最終的getOverflow謂詞計(jì)算“越過緩沖區(qū)邊界訪問的元素個(gè)數(shù)”并輸出形如以下的消息This write may overflow$by N elements.從select子句看查詢以path-problem形式報(bào)告CallInstruction對(duì)應(yīng)的表達(dá)式、雙源點(diǎn)、雙匯點(diǎn)及越界元素?cái)?shù)完整呈現(xiàn)從malloc到strncpy/memset的整條路徑。四、典型漏洞示例倉庫為查詢配套了示例文件 cpp/ql/src/Security/CWE/CWE-119/OverrunWriteProductFlow.cppint f(char * s, unsigned size) { char* buf (char*)malloc(size); strncpy(buf, s, size 1); // wrong: copy may exceed size of buf for (int i 0; i size; i) { // wrong: upper limit that is higher than size of buf cout buf[i]; } }兩處問題一目了然strncpy(buf, s, size 1)buf只分配了size字節(jié)卻可能寫入size 1字節(jié)越界 1 字節(jié)。for (int i 0; i size; i)循環(huán)訪問buf[0..size]共size 1個(gè)元素下標(biāo)i size時(shí)越界。官方 qhelp 文檔OverrunWriteProductFlow.qhelp給出的修復(fù)建議是檢查高亮操作中使用的偏移量與大小確保不會(huì)發(fā)生緩沖區(qū)溢出。安全做法是改為strncpy(buf, s, size)并將循環(huán)上界改為i size。五、測試用例驗(yàn)證查詢行為邊界查詢的自動(dòng)化測試位于 cpp/ql/test/query-tests/Security/CWE/CWE-119/SAMATE/對(duì)應(yīng).qlref為 OverrunWriteProductFlow.qlref測試源碼 test.cpp 用注釋標(biāo)注了預(yù)期結(jié)果$ Alert[cpp/overrun-write]/$ Source[cpp/overrun-write]/GOOD/MISSING是理解查詢能力邊界的絕佳素材跨函數(shù)傳遞mk_string_t分配緩沖區(qū)并保存size到結(jié)構(gòu)體strncpy(str-string, buf, str-size)被判定 GOOD而str-size 1觸發(fā) Alert證明查詢能跟蹤“分配→結(jié)構(gòu)體保存→讀取使用”的跨函數(shù)流。包裝函數(shù)strncpy_wrapper場景test2驗(yàn)證流經(jīng)中間調(diào)用層后大小關(guān)系仍被保留。條件約束if(anotherSize str-size)保護(hù)下的調(diào)用是 GOODif(anotherSize str-size 1)則是 BAD——查詢對(duì)/與1偏移的組合語義判斷細(xì)致。size與str-size的差異當(dāng)結(jié)構(gòu)體保存的大小與局部變量size不同源時(shí)test3/test4查詢對(duì)“直接使用局部變量大小”的某些越界如size 1標(biāo)注MISSING: Alert [NOT DETECTED]如實(shí)反映medium精度的漏報(bào)邊界。分配大小減一test5 中malloc(size - 1)配合str-size size - 1隨后strncpy(..., str-size 1)被檢出而strncpy(..., str-size)安全。memset與分配語義memset(p, 0, size 1)對(duì)malloc(size)的緩沖越界被檢出test_flow_through_setter、foorepeated_alerts中循環(huán)內(nèi)size導(dǎo)致的大小變化場景標(biāo)注NOT DETECTED體現(xiàn)對(duì)“大小在循環(huán)中可變”這一復(fù)雜情況的處理限度。誤報(bào)抑制test7 中malloc(n)后的memset(p, 0, n)被標(biāo)注為SPURIOUS: Alert ... GOOD [FALSE POSITIVE]說明當(dāng)前實(shí)現(xiàn)對(duì)該場景仍存在已知誤報(bào)。這些標(biāo)注讓查詢的“已知能力”與“已知局限”都以可驗(yàn)證的方式固化在倉庫中是評(píng)估該查詢精度時(shí)最重要的第一手資料。六、與同族查詢的分工overrun-write 在 CWE-119/CWE-120 家族中的位置cpp/overrun-write并非孤立存在它與 CWE-120緩沖區(qū)復(fù)制不當(dāng)下的多個(gè)查詢構(gòu)成互補(bǔ)的檢測家族查詢 ID實(shí)現(xiàn)文件特點(diǎn)cpp/overrun-writeSecurity/CWE/CWE-119/OverrunWriteProductFlow.qlpath-problem、ProductFlow 雙投影、追蹤“分配大小?寫入大小”跨函數(shù)流cpp/overrunning-writeSecurity/CWE/CWE-120/OverrunWrite.qlproblem 類基于BufferWrite模型要求getMaxDataLimited估計(jì)值超過目標(biāo)大小cpp/very-likely-overrunning-writeSecurity/CWE/CWE-120/VeryLikelyOverrunWrite.qlproblem 類、precision high僅采用ValueFlowAnalysis得出的高置信估計(jì)cpp/overrunning-write-with-floatSecurity/CWE/CWE-120/OverrunWriteFloat.ql專門覆蓋%f等浮點(diǎn)格式化導(dǎo)致的極端長度寫入從 OverrunWrite.ql 的源碼可見cpp/overrunning-write明確排除ValueFlowAnalysis原因的估計(jì)“we exclude ValueFlowAnalysis as it is reported in cpp/very-likely-overrunning-write”而 VeryLikelyOverrunWrite.ql 恰恰只接收ValueFlowAnalysis原因——兩者互補(bǔ)去重。歷史發(fā)布說明 cpp/ql/src/change-notes/released/0.0.8.md 也記載了cpp/very-likely-overrunning-write加入默認(rèn)套件后接管了cpp/overrunning-write的部分結(jié)果。相比之下cpp/overrun-write走的是另一條技術(shù)路線不依賴BufferWrite模型的“估計(jì)字節(jié)數(shù)”而是通過 ProductFlow 將分配點(diǎn)的大小表達(dá)式與調(diào)用點(diǎn)的大小參數(shù)做符號(hào)級(jí)關(guān)聯(lián)因此在“結(jié)構(gòu)體保存分配大小、經(jīng)包裝函數(shù)間接使用”這類場景下具備更強(qiáng)的跨函數(shù)追蹤能力。七、如何運(yùn)行與驗(yàn)證該查詢?cè)?CodeQL CLI 環(huán)境中可使用查詢套件或直接指定查詢文件運(yùn)行# 方式一通過安全套件運(yùn)行該查詢已收錄 codeql database analyze database codeql/cpp-queries --formatsarif-latest --outputresult.sarif # 方式二直接指定查詢文件 codeql database analyze database \ cpp/ql/src/Security/CWE/CWE-119/OverrunWriteProductFlow.ql \ --formatsarif-latest --outputresult.sarif倉庫內(nèi)驗(yàn)證該查詢的推薦方式是 CodeQL 查詢測試框架以 OverrunWriteProductFlow.qlref 指向查詢文件配合 test.cpp 中的GOOD/BAD標(biāo)注運(yùn)行codeql test run即可復(fù)現(xiàn)全部預(yù)期結(jié)果。八、小結(jié)cpp/overrun-write是 C 查詢包 0.6.3 引入的緩沖區(qū)溢出檢測利器其獨(dú)特價(jià)值在于path-problem 輸出給出從分配到寫入的完整路徑便于定位根因ProductFlow 雙投影同時(shí)追蹤緩沖區(qū)指針與大小值處理malloc(x 1)等帶偏移分配、跨結(jié)構(gòu)體/包裝函數(shù)的大小傳播與既有查詢家族互補(bǔ)與cpp/overrunning-write、cpp/very-likely-overrunning-write、cpp/overrunning-write-with-float按估計(jì)來源與置信度分工降低重復(fù)告警。值得注意的邊界該查詢精度為medium倉庫測試明確標(biāo)注了對(duì)“局部變量大小直接 1”與“循環(huán)內(nèi)大小遞增”等場景的漏報(bào)以及對(duì)malloc(n)場景的已知誤報(bào)。實(shí)際部署時(shí)建議將其與同族查詢尤其是 precision 更高的cpp/very-likely-overrunning-write組合使用并依據(jù)測試用例理解告警含義再結(jié)合代碼評(píng)審確認(rèn)修復(fù)方案。贊分享靜態(tài)分析SAST應(yīng)用安全漏洞掃描代碼質(zhì)量【免費(fèi)下載鏈接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security項(xiàng)目地址https://gitcode.com/gh_mirrors/co/codeql點(diǎn)擊查看免費(fèi)下載相關(guān)推薦CodeQL C/C 靜態(tài)緩沖區(qū)溢出檢測從 cpp/static-buffer-overflow 的精度升級(jí)看安全查詢工程化CodeQL C/C 靜態(tài)緩沖區(qū)溢出檢測從 cpp/static buffer overflow 的精度升級(jí)看安全查詢工程化 本篇文章圍繞 CodeQL靜態(tài)分析SAST應(yīng)用安全漏洞掃描代碼質(zhì)量終極窗口管理技巧5分鐘掌握跨平臺(tái)自動(dòng)化你是否曾經(jīng)在多個(gè)應(yīng)用窗口間頻繁切換卻總是找不到想要的那個(gè)或者想要自動(dòng)化管理窗口布局卻苦于沒有合適的工具今天我要向你介紹一款真正的窗口管理工具——get靜態(tài)分析SAST應(yīng)用安全漏洞掃描代碼質(zhì)量CodeQL C 查詢 cpp/bad-strncpy-size 0.3.2 更新strxfrm、wcsxfrm、stpncpy 等字符串復(fù)制函數(shù)納入緩沖區(qū)大小誤用檢測CodeQL C 查詢 cpp/bad strncpy size 0.3.2 更新strxfrm、wcsxfrm、stpncpy 等字符串復(fù)制函數(shù)納入緩沖靜態(tài)分析SAST應(yīng)用安全漏洞掃描代碼質(zhì)量上一篇helm/charts倉庫結(jié)構(gòu)全解stable與incubator的核心區(qū)別及Chart發(fā)布流程下一篇CopyQ 腳本命令Script Commands完全指南擴(kuò)展命令行接口與覆蓋剪貼板處理函數(shù)創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考