日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > CSS >内容正文

CSS

CSS大会 | 打破常“规”:挖掘语法解析器规则漏洞

發(fā)布時(shí)間:2024/2/28 CSS 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CSS大会 | 打破常“规”:挖掘语法解析器规则漏洞 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.





2019年7月30-31日,第五屆互聯(lián)網(wǎng)安全領(lǐng)袖峰會(CSS 2019)在北京開幕。作為前沿技術(shù)安全研究團(tuán)隊(duì)代表,Tencent Blade Team兩位高級安全研究員受邀登臺,探討如何挖掘語法解析器規(guī)則漏洞。


許多基礎(chǔ)軟件中都包含有語法解析部分,一旦出現(xiàn)規(guī)則漏洞影響,范圍極大,而這塊領(lǐng)域的安全研究相對較為缺乏,此次Tencent Blade Team對如何挖掘語法解析器規(guī)則漏洞做了從理論到實(shí)戰(zhàn)的詳細(xì)分析,并提出了如何編寫安全的規(guī)則建議。


Tencent Blade Team由騰訊安全平臺部成立,專注于物聯(lián)網(wǎng),AI,移動(dòng)互聯(lián)網(wǎng),云技術(shù),區(qū)塊鏈等技術(shù)領(lǐng)域的前瞻性安全研究,積累了大量成果,包括發(fā)現(xiàn)首個(gè)谷歌TensorFlow AI框架漏洞、遠(yuǎn)程操控智能家居與商業(yè)樓宇、破解亞馬遜智能音箱Echo、Google Home,發(fā)現(xiàn)SQLite Magellan漏洞等,多次受邀參加Blackhat、DEF CON、CSS等海內(nèi)外頂級安全會議。


8月7號-11號,Tencent Blade Team也會前往美國拉斯維加斯參加BlachHat和DEFCON,一共有五場分享,涉及3個(gè)前沿議題:GoogleHome破解及麥哲倫漏洞利用,首次揭秘遠(yuǎn)程攻破高通Wi-Fi及Modem系統(tǒng),遠(yuǎn)程利用高通硬件視頻解碼器漏洞,歡迎各位小伙伴關(guān)注。


以下為此次Tencent Blade Team挖掘語法解析器規(guī)則漏洞的現(xiàn)場分享,內(nèi)容有刪減,如有偏頗,敬請指正:



大家好,我們是來自Tencent Blade Team安全研究員,這是我們第二次來CSS分享議題,今天的分享主要分為以下六塊內(nèi)容:

  • 研究背景、研究現(xiàn)狀;
  • 語法解析器概述,包括攻擊面等;
  • 如何人工挖掘語法規(guī)則的漏洞;
  • 使用結(jié)構(gòu)化fuzzer進(jìn)行漏洞挖掘;
  • 我們有關(guān)的研究成果;
  • 如何編寫安全的規(guī)則

  • 首先,先來介紹我們研究語法解析器安全的背景:


    一、研究背景及現(xiàn)狀



    不少基礎(chǔ)軟件的關(guān)鍵功能里,都能看到語法解析器的身影,例如SQLite,Chrome,PHP等,如果語法解析器存在安全問題,影響面很廣,而語法解析器的安全問題,大家可能關(guān)注不多,容易被忽略。


    二、語法解析器概述接下來我們來了解一些關(guān)于語法解析器的基礎(chǔ)知識。


    右邊的圖是一個(gè)簡單的編譯流程圖,在早期,編寫編譯器相當(dāng)耗時(shí),直到Lex和YACC的誕生,有了它們,開發(fā)者只需要關(guān)注如何設(shè)計(jì)詞法和語法規(guī)則,剩下的解析器代碼都由它們來生成處理,大大提高了程序編譯解析器開發(fā)的效率。


    我們的議題重點(diǎn)關(guān)注Lex&YACC和LEMON Parser Generator。



    在Lex YACC解析器中,生成解析器的流程如右圖所示。給定一段代碼,由該解析器進(jìn)行詞法/語法解析,生成最終的結(jié)果。


    介紹了有關(guān)語法解析器的基礎(chǔ)知識,接下來分析其中的安全風(fēng)險(xiǎn)。


    三、如何人工挖掘語法規(guī)則的漏洞

    首先是Lex和YACC歷史漏洞不多,但詞法/語法規(guī)則是由開發(fā)者定義的,雖然Lex 和YACC的代碼不多,漏洞較少,但規(guī)則就好比我們開發(fā)的插件,如果插件有問題,這個(gè)軟件也存在安全風(fēng)險(xiǎn)。因此規(guī)則上引入的漏洞是我們關(guān)注的重點(diǎn)。


    我們主要是對GLSL和SQL語法解析器進(jìn)行了研究,目標(biāo)確認(rèn)了兩個(gè)CVE和一些其他類型的多個(gè)crash。我們希望能夠給大家提供一個(gè)新的攻擊面和思路,以此拋磚引玉。


    接下來,我們來看一下Lex和YACC的攻擊模型。


    正如右圖所示,黃色部分表示可能被攻擊的攻擊面,分別對應(yīng)四個(gè)處理程序(Lex,YACC,yylex,yyparse)。但在實(shí)際攻擊場景,規(guī)則其實(shí)早已定義好,規(guī)則在程序中相當(dāng)于常量。所以,只有對yylex和yyparse的輸入代碼才是真正的攻擊面,這其中包括:編譯器的生成代碼以及開發(fā)者引入的規(guī)則代碼。我們重點(diǎn)關(guān)注規(guī)則代碼。



    正如右上圖的一個(gè)片段,解析器代碼風(fēng)格迥異,直接審計(jì)有些尷尬。由于我們更關(guān)心用戶規(guī)則引入的代碼,因此只需重點(diǎn)看switch分支的代碼,或者直接分析. l和. y后綴的規(guī)則文件進(jìn)行漏洞挖掘。


    接下來,我們以一個(gè)漏洞代碼為例,介紹根據(jù)規(guī)則找漏洞的方法。



    首先,我們先看右上圖,這是這個(gè)測試程序。該程序解析輸入的print語法,把print后面的內(nèi)容打印輸出,否則提示語法錯(cuò)誤。


    再來看詞法規(guī)則,詞法規(guī)則是對輸入文本的第一層過濾,處理完后會把內(nèi)容傳遞給語法解析器(yyparse),這其中可能會存在以下問題:


    1 ?錯(cuò)誤的正則表達(dá)式,使得本該非法的字符傳遞給給了語法解析器;
    2 ?錯(cuò)誤使用輸入的處理函數(shù),可能會把類型轉(zhuǎn)錯(cuò)傳遞給語法解析器。


    接著,來看語法規(guī)則的漏洞模式:


    正如右上圖代碼所示,print_console這個(gè)規(guī)則里,會把WORD(詞素)傳遞到printf函數(shù)里($2表示為WORD),那么在第一步詞法分析中,非法的輸入hello%已經(jīng)被當(dāng)做WORD(詞素),并且傳遞到了$2的位置。再加上語法規(guī)則代碼里直接通過不規(guī)范的printf輸出。那么兩者結(jié)合起來,這就是一個(gè)標(biāo)準(zhǔn)的格式化漏洞,能夠通過這個(gè)程序泄露出內(nèi)存數(shù)據(jù)。


    實(shí)際上,相比傳統(tǒng)漏洞代碼,語法規(guī)則從邏輯上看,malloc mencpy等內(nèi)存操作的邏輯相對較少。所以可以嘗試挖掘類型混淆漏洞。


    下面部分,我們給大家介紹怎么用結(jié)構(gòu)化模糊測試去挖掘語法規(guī)則漏洞。


    四、使用結(jié)構(gòu)化fuzzer進(jìn)行漏洞挖掘

    Fuzz是最常見的漏洞挖掘方式,目前常見的Fuzzer基本都是基于灰盒和白盒測試的。而這幾年fuzzer也逐漸從傻瓜化變得智能化。但是最近又提出了一個(gè)概念,結(jié)構(gòu)化。為什么要結(jié)構(gòu)化呢?



    哪些程序適合使用這種模糊測試方案呢?


    第一個(gè)就是:這個(gè)程序應(yīng)當(dāng)是高度結(jié)構(gòu)化的。如果是那種單純處理數(shù)據(jù),而不進(jìn)行Parse(解析)的處理程序,就不太適用于結(jié)構(gòu)化fuzz。另一個(gè),是基于文本的,像C語言的代碼、SQL語句,它們是以單詞為單位的,這和傳統(tǒng)的Fuzz以字節(jié)為單位有所不同,所以更適合用結(jié)構(gòu)化Fuzz。我們接下來要講的SQLite、SwiftShader、ANGLE之類的,都是符合這個(gè)條件的。


    五、已有研究


    谷歌的實(shí)現(xiàn)是基于libprotobuf-mutator?又叫LPM,或者LPMFuzzer。它進(jìn)一步用protobuf的格式,作出了一組通用的框架,來衍生出對其使用組件的一系列的fuzz,比如對SQLite的fuzz。在Blade Team去年報(bào)告了SQLite漏洞以后,可以看到谷歌把SQLite的代碼都加強(qiáng)了很多。


    但為什么谷歌不把所有的Fuzz都改成結(jié)構(gòu)化相關(guān)的呢?答案就在這里,SQLite的Fuzzer在谷歌的工程里,翻一下就可以看到。代碼有2700行,非常大。這個(gè)寫起來想必也是十分耗費(fèi)精力。而如果被測工具有了新的語法,Fuzzer就得同步更新,也就是說,通過用C++代碼定義語法,Fuzzer逐漸失去了它的靈活性,但是Fuzzer會變得非常專注。這個(gè)長期維護(hù)的人力,很有可能就是谷歌不愿意通篇全部替換的原因。


    另一種,則是類似Csmith這種生成式Fuzzer,其他例子還有Mozilla的jsfunfuzz,以及我之前模仿寫的一個(gè)lucky-js-fuzzer,它們都會基于一定規(guī)則生成符合目標(biāo)程序的指令,從而減少因?yàn)闊o效指令帶來的測試效率的損失。


    而我們的方案,則是用簡單的操作,把被測目標(biāo)拆分,降低結(jié)構(gòu)化fuzz的難度,同時(shí),又融合生成式Fuzzer的語句的生成方案。最后,不重復(fù)造輪子,比如Sanitizer,比如突變算法,還用原來的。我們做出來了一個(gè)介于Csmith和谷歌之間的,簡單的實(shí)現(xiàn)方案,我們會開源其中一個(gè)Fuzzer,后面會給出URL。



    這個(gè)就是libfuzzer原本的突變方式,在沒有什么特殊的指導(dǎo)的情況下,它可能會以比特為單位進(jìn)行增刪修改,這可能會產(chǎn)生大量無效用例。對SQL之類的,效率很低。



    這是另一個(gè)版本,按照語素為單位,不過大家應(yīng)該很快就能看出來,這和詞典模式幾乎沒什么區(qū)別,只是我們做了一個(gè)形如虛擬機(jī)一樣的東西,實(shí)現(xiàn)了一套我們自己的字節(jié)碼定義,很像x86-CPU的那種變長字節(jié)碼的感覺。這樣,我們一來可以減少測試數(shù)據(jù)的長度,可以按照語素為單位來變換輸出的內(nèi)容。


    相當(dāng)于Fuzz引擎提供原始字節(jié)碼,通過翻譯,翻譯出對應(yīng)的語句,再去Fuzz,通過這種方式來跑,對比直接按字符為單位,空跑效率大概提升了40%多。當(dāng)然,長時(shí)間以后收斂在一個(gè)比較接近的位置上。不過,這個(gè)情況下仍然能繼續(xù)優(yōu)化。



    這一頁展示的是用字節(jié)碼定義整個(gè)語義的策略,可以看到,用語義為單位,會導(dǎo)致字節(jié)碼變得十分長,但是也帶來一個(gè)好處就是,Fuzz引擎的突變,更多的可能是改變語句內(nèi)部的一些結(jié)構(gòu),但結(jié)果可能仍然是有效、完整的語句概率十分大。


    而上一張我們說到的情況則仍然可能產(chǎn)生大量無效語句。不過用語義去Fuzz有什么問題呢?對,就是復(fù)雜度的問題。你可以看到SELECT FROM僅僅這一句,就有大量可能,如果讓我們?nèi)ラ_發(fā)程序,給每種不同的完整語句定義字節(jié)碼,那幾乎是一個(gè)不可能完成的任務(wù)。


    所以我們在定義語義的時(shí)候,從關(guān)鍵字處,按語義將其拆分成最簡化的句子,后續(xù)的內(nèi)容采用類似生成式Fuzz的方案,盡量讓它們能夠在某個(gè)范圍內(nèi)成為一整條語句。這里語義的遞歸的邏輯就交給Fuzzer的突變引擎去隨機(jī)弄就好了。


    最終我們混合了上一頁的策略、以及剛剛我們說的以語義為單位的Fuzz兩種策略,做出了一套結(jié)構(gòu)化Fuzz的東西。這套系統(tǒng)有個(gè)好處就是,你不需要費(fèi)勁去搜集那么多初始樣本,只要空跑或者隨便給個(gè)什么文件當(dāng)初始用例,就可以跑出來比普通的基于樣本+詞典更好的效果。


    Tencent Blade Team去年在對Google Home進(jìn)行研究的時(shí)候,順便也對GPU進(jìn)程做了個(gè)Fuzz,然后就發(fā)現(xiàn)SwiftShader可能是一個(gè)比較好的入口,我們當(dāng)時(shí)做了很簡單的一個(gè)結(jié)構(gòu)化的模糊測試,很快我們就抓到了這樣一個(gè)漏洞。



    右邊是生成它的具體Fuzzer代碼。這樣一個(gè)PoC有什么玄機(jī)呢,讓我們繼續(xù)往后看。



    POC在第一張圖中。那么為什么會導(dǎo)致這樣的問題呢,讓我們閱讀一下layout相關(guān)的語法規(guī)則。GLSL的語法類似于C語言,也就是說,在一個(gè)數(shù)字后面加上u,這個(gè)數(shù)字就代表一個(gè)無符號數(shù)。


    讓我們先看第二個(gè)圖,在文法規(guī)則中,我們看到,在只要版本號符合要求,layout即被定義為大寫的LAYOUT。然后,在第三張圖中,我們可以看到.Y中引用了大寫的LAYOUT文法。再看第四張圖,在glslang.y中,layout的規(guī)則定義為layout_qualifier,第1030行,即: LAYOUT 左括號 layout_qualifier_id_list 右括號。


    不過這里要說明一下,因?yàn)樗菑淖笸乙粋€(gè)token 一個(gè)token掃描的,所以我們最簡PoC不寫右括號也沒事,因?yàn)樵诘接依ㄌ栔按a就出問題了。


    這里大寫的都是常量文本字符串,所以看第一個(gè)小寫的,畫紅色橫線的layout_qualifier_id_list,它的定義有兩種,一種是直接layout_qualifier_id,一種是list 逗號 id。id的定義我用藍(lán)色橫線畫出來了。


    我們的顯然是前一種,讓我們再看看layout_qualifier_id的定義,它有三個(gè)定義,最底下那個(gè)不就是我們的這個(gè)情況嘛!表達(dá)式等于無符號數(shù),直接調(diào)用parseLayoutQualifier,有符號數(shù)和無符號數(shù)的規(guī)則是一模一樣的。大部分情況下,有符號數(shù)無符號數(shù)一樣沒什么大問題。


    讓我們看一下它生成出的 C文件,case 154對應(yīng)無符號數(shù)規(guī)則。這里還需要介紹一下yyvsp和yylsp的概念。Yy就是yacc的那個(gè)y,大家可以讀一下它的代碼,他們寫的時(shí)候并不是十分規(guī)范,大量使用了全局變量,我猜測這個(gè)yy是為了避免生成的代碼。


    和它自己的代碼沖突而加上的一個(gè)模擬C++namespace的東西,如果覺得看著很礙眼,可以在閱讀的時(shí)候把yy全部刪掉。VSP,Value Stack Pointer,值棧指針;LSP,Location Stack Pointer,位置棧指針。它處理單詞時(shí),VSP永遠(yuǎn)指向正在處理的token。所以不難理解,現(xiàn)在它掃描到8686u,所以-1的位置就是等號,-2的位置就是location。



    讓我們看看最感興趣的第三個(gè)參數(shù),這也是他明顯寫錯(cuò)的地方。*Yyvsp[0],取出來的是數(shù)字,然后它將這個(gè)數(shù)字直接轉(zhuǎn)為了String,這個(gè).string的定義是Tstring對象,一個(gè)base_string,如果你傳給它的是一個(gè)數(shù)字,它會把它當(dāng)成const char*,也就是一個(gè)指針!


    而第四個(gè)參數(shù)則直接取出數(shù)字傳入下一層。



    讓我們對照代碼看看出了什么問題。Tstring由0x86868686直接構(gòu)造,也就是這個(gè)Tstring對象指向的是0x86868686這個(gè)地址,這里已經(jīng)有一個(gè)錯(cuò)誤了。


    還有哪里有錯(cuò)誤?我們可以看到,之前有符號數(shù)和無符號數(shù)共用了一個(gè)parseLayoutQualifier,而它的第四個(gè)參數(shù)是int ,有符號數(shù)。無符號數(shù)傳入后,直接變成了有符號數(shù)。但為什么有符號數(shù)的情況下不會觸發(fā)呢?


    答案就在下面的if處,這里intValue因?yàn)槭怯蟹枖?shù),而無符號數(shù)0x86868686的最高位是1,轉(zhuǎn)換符號以后,變成了一個(gè)小于0的數(shù),所以這個(gè)if被它自己這個(gè)強(qiáng)制符號轉(zhuǎn)換給繞過去了。而下面立刻會調(diào)用error輸出錯(cuò)誤語句,這個(gè)錯(cuò)誤語句中,直接調(diào)用了intValueString.c_str(),還記得intValueString現(xiàn)在是指向0x86868686的嗎?所以在這里直接讀取它的內(nèi)容時(shí),觸發(fā)一次存取違例或者SIGSEGV。


    右上角是我在VS里面調(diào)的,因?yàn)閏_str()實(shí)際上會偏移幾個(gè)字節(jié),所以這里你看到的是868A或者868E等等,都正常,和平臺相關(guān)。



    另一個(gè)則是SQLite的問題,這個(gè)是去年發(fā)現(xiàn)的,去年我們發(fā)現(xiàn)了麥哲倫漏洞,其實(shí)它一共有5個(gè)漏洞,一半是靠Fuzz出來的,一半是靠人工看出來的。雖然在數(shù)據(jù)庫系統(tǒng)上可以遠(yuǎn)程導(dǎo)致崩潰也是個(gè)嚴(yán)重問題,不過這個(gè)20505呢,嚴(yán)格意義上說它比另外4個(gè)弱很多。


    SQLite使用了Lemon Parser,它和Yacc&Lex很像,但是又不互相兼容,不過在右邊Call Stack中大家一樣能看到中間有個(gè)yy_reduce,最后它還是用了yy_這個(gè)標(biāo)準(zhǔn)開頭。


    左邊的是這個(gè)問題的最簡化的代碼,大家如果寫過SQL的話,很快就能發(fā)現(xiàn)這里有個(gè)詭異的地方,就是PRIMARY KEY里面有兩個(gè)一樣的主鍵。但是明顯SQLite在這個(gè)地方把它放行了,在下一行去查詢的時(shí)候,崩在右邊這個(gè)位置。



    這個(gè)漏洞可以看到主鍵處理的規(guī)則是:RIMARY KEY 左括號 列表 是否有自增 右括號 ON CONFLICT 沖突時(shí)怎么做,然后,直接調(diào)用sqlite3AddPrimaryKey。這個(gè)函數(shù)邏輯是添加主鍵的時(shí)候,先檢查要添加的列是否是表中已有的列;


    如果是已存在的列,則將其設(shè)置為主鍵。但是這個(gè)過程中并沒有判斷主鍵是否重復(fù);這樣,里面就有兩個(gè)主鍵,但是第二個(gè)主鍵添加的時(shí)候,因?yàn)榱斜砝镆呀?jīng)有一個(gè)同樣的主鍵,于是它雖然成了主鍵,但是卻指向一個(gè)空位置。


    在執(zhí)行搜索的時(shí)候,sqlite3ExprAffinity中試圖取出第二個(gè)主鍵對應(yīng)的項(xiàng)目,取出來的是空。就導(dǎo)致了這個(gè)CRASH。


    SQLite官方的修復(fù)是在添加完表以后,把這種主鍵從數(shù)據(jù)庫里清理出去。但我其實(shí)更覺得重復(fù)主鍵的時(shí)候就應(yīng)該直接報(bào)錯(cuò)。


    后續(xù),我們也會把我們對GLSL的Fuzz工具開源:

    GLSL Fuzzer (for Swiftshader / ANGLE , etc.)

    https://github.com/tencentbladeteam/css_2019_tools/glsl_fuzzer.cpp


    YACC規(guī)則轉(zhuǎn)詞典文件工具

    https://github.com/tencentbladeteam/css_2019_tools/yacc_to_dict.cpp


    大家可以把它用在Fuzz各個(gè)GLSL相關(guān)的地方,比如SwiftShader,ANGLE之類的地方。


    六、如何編寫安全的規(guī)則

    最后,我們簡單介紹一下如何編寫安全的規(guī)則。

    1.避免類型混用

    規(guī)則定義中,可能存在大量的類型轉(zhuǎn)換(顯式的和隱式的),需要對每種情況都做好單元測試,以防漏掉某個(gè)規(guī)則產(chǎn)生混用。


    2.避免過于寬泛的定義

    避免一個(gè)規(guī)則對應(yīng)多種類型的變量,C系列是強(qiáng)類型的語言,尤其是從Java移植過來的代碼,更要檢驗(yàn)是否存在某個(gè)規(guī)則過于寬泛。


    3.檢查邊界值

    規(guī)則定義中也存在類似邊界情況的問題,比如某些值未被規(guī)則包括,或者某些特殊情況會產(chǎn)生異常問題,這些都要考慮在內(nèi)。


    4.檢查不正確的值傳遞

    在嵌套調(diào)用時(shí),值可能會以不同類型的狀態(tài)傳遞。另外,值有可能以智能指針之類的形式傳遞,在處理多層嵌套調(diào)用時(shí),一定要仔細(xì)檢查結(jié)果是否正確。


    感謝大家的聆聽,我們在8月7號-11號也會前往美國拉斯維加斯參加Blackhat和DEFCON,一共有五場分享,涉及3個(gè)前沿議題:GoogleHome破解及麥哲倫漏洞利用,首次揭秘遠(yuǎn)程攻破高通Wi-Fi及Modem系統(tǒng),遠(yuǎn)程利用高通硬件視頻解碼器漏洞,也歡迎給大家關(guān)注blade的官網(wǎng):blade.tencent.com,或者通過郵箱:blade@tencent.com和我們交流!



    總結(jié)

    以上是生活随笔為你收集整理的CSS大会 | 打破常“规”:挖掘语法解析器规则漏洞的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。