
靜態(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)下載本篇技術(shù)指南聚焦 CodeQL 倉庫中 C# 分析庫Modifiable類的三個(gè)可見性謂詞——isEffectivelyPrivate、isEffectivelyInternal與isEffectivelyPublic。這一組謂詞曾在 2021-06-15 的變更說明csharp/old-change-notes/2021-06-15-effective-visibility.md中宣告重做核心目的是正確處理 C# 的private protected、internal protected組合可見性以及顯式接口實(shí)現(xiàn)成員的可見性。讀完本文你將理解有效可見性effective visibility與聲明可見性的區(qū)別、三個(gè)謂詞的判定規(guī)則與實(shí)現(xiàn)細(xì)節(jié)以及如何通過測(cè)試用例驗(yàn)證這些規(guī)則從而在你的自定義查詢中準(zhǔn)確過濾掉實(shí)際上不可從當(dāng)前程序集外部訪問的成員。變更背景從聲明修飾符到有效可見性在 C# 中一個(gè)成員的實(shí)際可訪問范圍并不總是與它聲明的訪問修飾符一一對(duì)應(yīng)。典型例子包括嵌套類型中的成員一個(gè)聲明為public的成員如果它所在的類型本身是internal或private那么該成員實(shí)際上不可能被程序集外部引用受保護(hù)成員的可重寫性protected成員雖然可以被派生類訪問但private protected與protected internal在跨程序集場(chǎng)景下行為不同顯式接口實(shí)現(xiàn)void I.Foo() { }這樣的成員沒有普通意義上的可見性它只能通過接口引用訪問因此其有效可見性取決于被實(shí)現(xiàn)的接口本身。為此CodeQL 的 C# 庫在 csharp/ql/lib/semmle/code/csharp/Member.qll 的Modifiable類中提供了三個(gè)有效可見性謂詞回答的不是這個(gè)成員寫了什么修飾符而是這個(gè)成員在程序語義上到底能被誰引用。謂詞語義三個(gè)判定規(guī)則有效私有isEffectivelyPrivate在 Member.qll 中isEffectivelyPrivate()的定義為該聲明只能從以下位置引用——聲明它的類型及其嵌套類型與普通private一致以及它的封閉類型enclosing types。其實(shí)現(xiàn)包含三條判定路徑predicate isEffectivelyPrivate() { this.isReallyPrivate() or this.getDeclaringType().(Modifiable).isReallyPrivate() or this.(Virtualizable).getExplicitlyImplementedInterface().isEffectivelyPrivate() }自身為私有isReallyPrivate()是一個(gè)私有輔助謂詞要求isPrivate()且不是isProtected()同時(shí)排除極少數(shù)同名成員跨程序集以不同可見性定義的情況Member.qll封閉類型鏈私有this.getDeclaringType()沿聲明類型逐級(jí)向上查找表示一個(gè)或多個(gè)步驟只要任一封閉類型真正私有成員即視為有效私有顯式接口實(shí)現(xiàn)通過getExplicitlyImplementedInterface()取得顯式實(shí)現(xiàn)的接口若接口本身有效私有則該實(shí)現(xiàn)成員同樣有效私有。文檔注釋特別強(qiáng)調(diào)兩點(diǎn)顯式接口實(shí)現(xiàn)在接口本身有效私有時(shí)被視為有效私有而private protected成員不被視為有效私有因?yàn)樗梢栽诼暶鞒绦蚣瘍?nèi)被重寫override。有效內(nèi)部isEffectivelyInternalisEffectivelyInternal()的語義是該聲明只能從聲明它的程序集內(nèi)部引用Member.qllpredicate isEffectivelyInternal() { this.isReallyInternal() or this.getDeclaringType().(Modifiable).isReallyInternal() or this.(Virtualizable).getExplicitlyImplementedInterface().isEffectivelyInternal() }其輔助謂詞isReallyInternal()判定兩條路徑Member.qllinternal且非protected即普通internalprivate且protected即private protected——注意它與internal的可達(dá)范圍相同都限于本程序集。同樣需要排除同名成員跨程序集不同可見性的稀有情況。文檔注釋中的兩個(gè)關(guān)鍵限定通過InternalsVisibleToAttribute聲明的友元程序集friend assemblies不在考慮范圍內(nèi)——即只要理論上可能被其他程序集看到就歸為有效內(nèi)部之外internal protected即protected internal成員不被視為有效內(nèi)部因?yàn)樗梢栽诼暶鞒绦蚣獗慌缮愔貙戯@式接口實(shí)現(xiàn)成員若實(shí)現(xiàn)的接口本身有效內(nèi)部則該成員同樣被視為有效內(nèi)部。有效公開isEffectivelyPublicisEffectivelyPublic()是一個(gè)兜底定義Member.qll凡不是有效私有、也不是有效內(nèi)部的聲明即可從程序集外部引用predicate isEffectivelyPublic() { not this.isEffectivelyPrivate() and not this.isEffectivelyInternal() }因此對(duì)任意Modifiable三個(gè)謂詞構(gòu)成窮盡且互斥的三分任何成員必然恰好落在有效私有有效內(nèi)部有效公開之一。測(cè)試驗(yàn)證庫測(cè)試 Modifiers倉庫在 csharp/ql/test/library-tests/modifiers/ 提供了完整的庫測(cè)試來鎖定這些語義。被測(cè)代碼Modifiers.csModifiers.cs 構(gòu)造了覆蓋各類修飾符組合的樣例其中與本次重做直接相關(guān)的成員包括internal protected readonly int F3; // 內(nèi)部保護(hù)字段 public int P1 { get; set; } // 公開屬性 public int P2 { get; private set; } // 公開屬性、私有 setter internal interface I2 { void M1(); } // 內(nèi)部接口 public class C2 : I2 { void I2.M1() throw null; // 顯式接口實(shí)現(xiàn) protected private void M2() { } // private protected protected internal void M3() { } // internal protected }測(cè)試查詢Effectively.qlEffectively.ql 專門用于本組謂詞它找出三種聲明可見性與有效可見性不一致的情況并標(biāo)記實(shí)際的有效可見性from Modifiable m, string s where m.fromSource() and ( m.isEffectivelyInternal() and not m.isInternal() and s internal or m.isEffectivelyPrivate() and not m.isPrivate() and s private or m.isEffectivelyPublic() and s public ) select m, s即對(duì)每個(gè)源碼中的聲明若isEffectivelyInternal()成立但聲明中并沒有internal修飾符就報(bào)告為internal若isEffectivelyPrivate()成立但沒有private修飾符報(bào)告為private凡有效公開者報(bào)告為public。預(yù)期結(jié)果Effectively.expected對(duì)照 Effectively.expected可以看到重做后的判定結(jié)果Modifiers.cs:12:14的M1注釋標(biāo)記的私有方法→internal因?yàn)槠浞忾]類型C默認(rèn)是internalunsafe class C無可見性修飾符默認(rèn)為 internal成員隨類型被限制在程序集內(nèi)Modifiers.cs:24:22的C1被同時(shí)報(bào)告為internal與privatesealed class C1聲明于internal類內(nèi)其構(gòu)造器C1()是public但隨類型降至 internal而類本身隨內(nèi)部類 C 降至有效私有Modifiers.cs:52:19的Spublic struct→publicModifiers.cs:68:14的I2.M1內(nèi)部接口的默認(rèn)實(shí)現(xiàn)方法→internalModifiers.cs:73:17的顯式接口實(shí)現(xiàn)void I2.M1()→internal這正是本次重做新增的判定——顯式實(shí)現(xiàn)成員的可見性繼承自被實(shí)現(xiàn)接口I2的可見性Modifiers.cs:75:32的protected private void M2()private protected→internal證明private protected被納入有效內(nèi)部而非有效私有Modifiers.cs:76:33的protected internal void M3()→public因?yàn)閕nternal protected可以被程序集外的派生類重寫故不歸為有效內(nèi)部。這些預(yù)期輸出同時(shí)驗(yàn)證了重做后的三條核心規(guī)則顯式接口實(shí)現(xiàn)的可見性跟隨接口、private protected歸入有效內(nèi)部、internal protected歸入有效公開。謂詞在查詢中的實(shí)際應(yīng)用這一組謂詞在倉庫的多個(gè)查詢與庫模塊中被廣泛使用用于過濾從外部實(shí)際不可達(dá)的成員提升查詢精度。csharp/ql/lib/semmle/code/csharp/telemetry/ExternalApi.qll在統(tǒng)計(jì)外部 API 使用情況時(shí)需要區(qū)分真正暴露給外部的成員與內(nèi)部實(shí)現(xiàn)細(xì)節(jié)isEffectivelyPublic()等謂詞正是判定的基礎(chǔ)csharp/ql/src/Useless code/DefaultToStringQuery.qll、csharp/ql/src/Language Abuse/MissedReadonlyOpportunity.ql、csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql這些查詢?cè)谂袛喑蓡T是否可被外部觀察時(shí)使用有效可見性避免把僅程序集內(nèi)部可見的成員當(dāng)作公開 API 處理csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll 與 csharp/ql/src/utils/modeleditor/ModelEditor.qll模型生成工具需要按可見性決定是否為成員生成數(shù)據(jù)流模型csharp/ql/lib/semmle/code/csharp/dataflow/internal/Steps.qll、csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll數(shù)據(jù)流與派發(fā)分析中跨程序集邊界的數(shù)據(jù)流需要以有效可見性為準(zhǔn)private protected/internal protected的可重寫性直接影響跨程序集調(diào)用圖的構(gòu)造。從源碼結(jié)構(gòu)看重做后的謂詞通過統(tǒng)一收斂到isReallyPrivate/isReallyInternal兩個(gè)私有輔助謂詞并把封閉類型鏈與顯式接口實(shí)現(xiàn)兩類場(chǎng)景顯式建模使得三個(gè)公開謂詞在所有Modifiable聲明上構(gòu)成互斥且完備的劃分任何后續(xù)查詢只需選擇其一即可得到精確的可見性分類。小結(jié)isEffectivelyPrivate、isEffectivelyInternal、isEffectivelyPublic是 CodeQL C# 庫中關(guān)于成員可見性的核心抽象。2021-06-15 的重做補(bǔ)齊了三個(gè)此前處理不準(zhǔn)確的場(chǎng)景private protected歸入有效內(nèi)部、internal protected因其可跨程序集重寫而歸入有效公開、以及顯式接口實(shí)現(xiàn)可見性繼承自被實(shí)現(xiàn)接口。理解這三條規(guī)則不僅有助于讀懂ExternalApi、Dispatch等庫模塊的實(shí)現(xiàn)也能幫助你在編寫自定義安全查詢時(shí)正確判斷一個(gè)成員是否真正暴露在程序集外部從而減少誤報(bào)、提升分析的準(zhǔn)確性。贊分享靜態(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 溢出分析庫 SimpleRangeAnalysisexprMightOverflow* 謂詞如何變得更可靠CodeQL C 溢出分析庫 SimpleRangeAnalysisexprMightOverflow 謂詞如何變得更可靠 本文以 CodeQL C靜態(tài)分析SAST應(yīng)用安全漏洞掃描代碼質(zhì)量CodeQL C 庫 0.0.10 新增特性Variable::isStructuredBinding 謂詞詳解CodeQL C 庫 0.0.10 新增特性 Variable::isStructuredBinding 謂詞詳解 CodeQL 的 C 查詢庫在版本靜態(tài)分析SAST應(yīng)用安全漏洞掃描代碼質(zhì)量CodeQL C/C 查詢庫通過 Function 新謂詞精確分析 virtual、override 與 final 聲明CodeQL C/C 查詢庫通過 Function 新謂詞精確分析 virtual、override 與 final 聲明 導(dǎo)讀 在編寫 C 安全查詢靜態(tài)分析SAST應(yīng)用安全漏洞掃描代碼質(zhì)量上一篇BadPods項(xiàng)目深度挖掘can-they.sh腳本實(shí)現(xiàn)集群令牌自動(dòng)化審計(jì)下一篇javascript-mini-projects深度剖析從貪吃蛇游戲看Canvas API的實(shí)戰(zhàn)應(yīng)用創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考