日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
用Domato通過(guò)Fuzzing對(duì)PHP進(jìn)行漏洞挖掘研究

為了清楚和簡(jiǎn)潔起見,下面引用的代碼已精煉為最簡(jiǎn)單的形式。實(shí)際用于Fuzzing測(cè)試的完整版本可以在此處找到。

創(chuàng)新互聯(lián)憑借專業(yè)的設(shè)計(jì)團(tuán)隊(duì)扎實(shí)的技術(shù)支持、優(yōu)質(zhì)高效的服務(wù)意識(shí)和豐厚的資源優(yōu)勢(shì),提供專業(yè)的網(wǎng)站策劃、成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、網(wǎng)站優(yōu)化、軟件開發(fā)、網(wǎng)站改版等服務(wù),在成都10年的網(wǎng)站建設(shè)設(shè)計(jì)經(jīng)驗(yàn),為成都成百上千家中小型企業(yè)策劃設(shè)計(jì)了網(wǎng)站。

https://github.com/Rewzilla/domatophp

最近,我一直在對(duì)PHP解釋器進(jìn)行Fuzzing,我探索了許多工具和技術(shù)(AFL,LibFuzzer,甚至是自定義的Fuzzing引擎),但是最近我決定嘗試Domato。對(duì)于那些不知道的人,Domato是基于語(yǔ)法的DOM Fuzzer,旨在從復(fù)雜的代碼庫(kù)中挖掘復(fù)雜的bug。它最初是為瀏覽器而設(shè)計(jì)的,但是我認(rèn)為我可以將其用于Fuzzing PHP解釋器。

 https://github.com/googleprojectzero/domato

0x01  分析上下文語(yǔ)法

為了使用Domato,必須首先使用上下文無(wú)關(guān)的語(yǔ)法來(lái)描述語(yǔ)言,CFG只是一組定義語(yǔ)言構(gòu)造方式的規(guī)則。例如,如果我們的語(yǔ)言由以下形式的句子組成:

 
 
 
 
  1. [name] has [number] [adjective] [noun]s. 
  2. [name]'s [noun] is very [adjective]. 
  3. I want to purchase [number] [adjective] [noun]s. 

這些變量中的每一個(gè)都可以采用幾種形式,例如:

 
 
 
 
  1. Names: alice, bob, eve 
  2. Numbers: 1, 10, 100 
  3. Adjectives: green, large, expensive 
  4. Nouns: car, hat, laptop 

那么上下文無(wú)關(guān)文法可能看起來(lái)像...

然后Domato使用上下文無(wú)關(guān)文法生成符合語(yǔ)言規(guī)則的隨機(jī)組合。

 
 
 
 
  1. eve has 1 expensive laptops. 
  2. alice's hat is very green. 
  3. I want to purchase 100 expensive cars. 
  4. I want to purchase 10 large laptops. 
  5. bob has 100 expensive cars. 
  6. eve has 100 green laptops. 
  7. I want to purchase 100 large laptops. 
  8. bob has 1 large cars. 
  9. I want to purchase 1 large cars. 
  10. I want to purchase 1 large hats. 
  11. bob's laptop is very expensive. 

可以想象,通過(guò)將每個(gè)規(guī)則分解為更多子規(guī)則,我們可以開始定義更復(fù)雜的語(yǔ)言,而不僅僅是簡(jiǎn)單的搜索/替換。實(shí)際上,Domato還提供了一些內(nèi)置函數(shù),用于限制遞歸并生成基本類型(int,char,string等)。

例如,以下Domato語(yǔ)法,該語(yǔ)法生成偽代碼...

將其送入Domato會(huì)產(chǎn)生以下結(jié)果...

 
 
 
 
  1. if (var0 == var5) { int var5 = 915941154; } else { int var3 = 1848395349; }; if (var3 == -121615885) { int var7 = 1962369640;; int var1 = 196553597;;; int var6 = -263472135;; } else { int var2 == 563276937; }; 
  2. while (var9 = var8) { while (var0 == -2029947247) { int var7 = 1879609559; } }; char var0 = '';; 
  3. char var2 = '/'; 
  4. char var3 = 'P'; 
  5. if (var8 == var1) { int var7 = -306701547; } else { while (var3 == 868601407) { while (var0 == -1328592927) { char var10 = '^'; }; char var8 = 'L';;; int var9 = -1345514425;; char var5 = 'b';;; } } 
  6. int var8 = 882574440; 
  7. if (var8 == var9) { int var7 = 1369926086; } else { if (var9 != -442302103) { if (var3 != 386704757) { while (var4 != -264413007) { char var6 = 'C'; } } else { int var8 = 289431268; } } else { char var10 = '~'; } } 
  8. char var5 = '+'; 
  9. if (var9 == 1521038703) { char var2 = '&'; } else { int var7 = -215672117; } 
  10. while (var9 == var0) { char var9 = 'X';; int var7 = -1463788903;; }; if (var8 == var7) { int var10 = 1664850687;; char var6 = 'f';; } else { while (var5 == -187795546) { int var3 = -1287471401; } }; 

這非常適合Fuzzing解釋器,因?yàn)槊總€(gè)樣本都是不同的,并且仍然保證其在語(yǔ)法上是有效的!

0x02 列舉Attack Surface

然后,下一步就是將PHP語(yǔ)言描述為CFG。如果有興趣查看完整的CFG,請(qǐng)下載PHP源代碼,然后查看Zend/zend_language_parser.y。

但是,我對(duì)Fuzzing特定的代碼模式更感興趣。因此,我實(shí)現(xiàn)了CFG,使其僅使用“Fuzzing”參數(shù)生成對(duì)內(nèi)置函數(shù)和類方法的調(diào)用。為此,我們需要一個(gè)函數(shù),方法及其參數(shù)的列表。

有兩種獲取此數(shù)據(jù)的方法。最簡(jiǎn)單的方法是使用PHP的內(nèi)置Reflection類來(lái)遍歷所有已定義的函數(shù)和類,從而構(gòu)建一個(gè)列表。

以下代碼對(duì)所有內(nèi)部PHP函數(shù)進(jìn)行了演示...

這會(huì)產(chǎn)生類似如下代碼:

 
 
 
 
  1. andrew@thinkpad /tmp % php lang.php  
  2. zend_version(); 
  3. func_num_args(); 
  4. func_get_arg(arg_num); 
  5. func_get_args(); 
  6. strlen(str); 
  7. strcmp(str1, str2); 
  8. strncmp(str1, str2, len); 
  9. strcasecmp(str1, str2); 
  10. strncasecmp(str1, str2, len); 
  11. each(arr); 
  12. error_reporting(new_error_level); 
  13. define(constant_name, value, case_insensitive); 
  14. defined(constant_name); 
  15. get_class(object); 
  16. ... etc ... 

但是,此問(wèn)題在于此列表不包含類型信息。ReflectionParameter類包含一個(gè)getType方法,但是對(duì)于大多數(shù)函數(shù)而言,它目前似乎不起作用。:(也許這是一個(gè)bug?很難說(shuō)。無(wú)論如何,擁有類型信息將使我們的Fuzzing工作變得更加有效,因此值得花時(shí)間去尋找另一種獲取該數(shù)據(jù)的方法。

 https://www.php.net/manual/en/reflectionparameter.gettype.php

為了解析出我們需要的東西,PHP的文檔通常相當(dāng)不錯(cuò),可以在此處將其作為單個(gè)壓縮的HTML文檔下載。經(jīng)過(guò)數(shù)小時(shí)的辛苦編寫正則表達(dá)式后,我能夠?qū)⑵浣馕鰹榭捎玫暮瘮?shù),方法和參數(shù)類型列表。我將其留給讀者練習(xí),但是最終產(chǎn)品(以CFG形式)看起來(lái)像這樣……

 https://www.php.net/distributions/manual/php_manual_en.html.gz

0x03  設(shè)置Domato

為了使Domato使用我們的語(yǔ)法,我們還需要定義一些基本組件,例如:

經(jīng)過(guò)大量的調(diào)整和調(diào)整后,我的配置最終看起來(lái)像這樣……

我們還需要定義一個(gè)語(yǔ)法將被應(yīng)用到的模板。該模板將設(shè)置環(huán)境,實(shí)例化以后可能使用的所有對(duì)象,然后運(yùn)行每條線程。我的模板看起來(lái)像這樣...

最后一步是復(fù)制和修改Domato的generator.py文件。我發(fā)現(xiàn)只需進(jìn)行以下更改就足夠了...

· 第55和62行:將根元素更改為“

· 第78行:引用我自己的“ template.php”

· 第83行:在“ php.txt”中引用我自己的語(yǔ)法

· 第134行:將輸出名稱和擴(kuò)展名更改為“

然后,應(yīng)該能夠生成有效的Fuzzing輸入!

 
 
 
 
  1. andrew@thinkpad ~/domato/php % python generator.py /dev/stdout 
  2. Writing a sample to /dev/stdout 
  3. $vars = array( 
  4.     "stdClass"                       => new stdClass(), 
  5.     "Exception"                      => new Exception(), 
  6.     "ErrorException"                 => new ErrorException(), 
  7.     "Error"                          => new Error(), 
  8.     "CompileError"                   => new CompileError(), 
  9.     "ParseError"                     => new ParseError(), 
  10.     "TypeError"                      => new TypeError(), 
  11.     ... etc ... 
  12. ); 
  13. try { try { $vars["SplPriorityQueue"]->insert(false, array("a" => 1, "b" => "2", "c" => 3.0)); } catch (Exception $e) { } } catch(Error $e) { } 
  14. try { try { filter_has_var(1000, str_repeat("%s%x%n", 0x100)); } catch (Exception $e) { } } catch(Error $e) { } 
  15. try { try { posix_access(implode(array_map(function($c) {return "\\x" . str_pad(dechex($c), 2, "0");}, range(0, 255))), -1); } catch (Exception $e) { } } catch(Error $e) { } 
  16. try { try { rand(0, 0); } catch (Exception $e) { } } catch(Error $e) { } 
  17. try { try { fputcsv(fopen("/dev/null", "r"), array("a" => 1, "b" => "2", "c" => 3.0), str_repeat(chr(135), 65), str_repeat(chr(193), 17) + str_repeat(chr(21), 65537), str_repeat("A", 0x100)); } catch (Exception $e) { } } catch(Error $e) { } 
  18. try { try { $vars["ReflectionMethod"]->isAbstract(); } catch (Exception $e) { } } catch(Error $e) { } 
  19. try { try { $vars["DOMProcessingInstruction"]->__construct(str_repeat(chr(122), 17) + str_repeat(chr(49), 65537) + str_repeat(chr(235), 257), str_repeat(chr(138), 65) + str_repeat(chr(45), 4097) + str_repeat(chr(135), 65)); } catch (Exception $e) { } } catch(Error $e) { } 
  20. try { try { utf8_encode(str_repeat("A", 0x100)); } catch (Exception $e) { } } catch(Error $e) { } 
  21. try { try { $vars["MultipleIterator"]->current(); } catch (Exception $e) { } } catch(Error $e) { } 
  22. try { try { dl(str_repeat("A", 0x100)); } catch (Exception $e) { } } catch(Error $e) { } 
  23. try { try { ignore_user_abort(true); } catch (Exception $e) { } } catch(Error $e) { } 

0x04  開始Fuzz

現(xiàn)在我們要處理的數(shù)據(jù)非常多,我們需要以一種最大化檢測(cè)任何類型的內(nèi)存損壞的機(jī)會(huì)的方式構(gòu)建PHP。為此,我強(qiáng)烈建議使用LLVM Address Sanitizer(ASAN),它將檢測(cè)任何無(wú)效的內(nèi)存訪問(wèn),即使它不會(huì)立即導(dǎo)致崩潰。

 https://github.com/google/sanitizers/wiki/AddressSanitizer

用ASAN編譯PHP,下載最新版本的源代碼在這里,并運(yùn)行以下命令...

 https://www.php.net/downloads
 
 
 
 
  1. ./configure CFLAGS="-fsanitize=address -ggdb" CXXFLAGS="-fsanitize=address -ggdb" LDFLAGS="-fsanitize=address" 
  2. make 
  3. make install 

在Fuzzer運(yùn)行之前,嘗試消除不必要地阻礙該過(guò)程的任何條件也是一個(gè)好主意。例如,像大多數(shù)語(yǔ)言一樣,PHP具有一個(gè)sleep()函數(shù),該函數(shù)接受一個(gè)整數(shù)參數(shù),并僅等待幾秒后才能繼續(xù)。用較大的值(例如INT_MAX)調(diào)用此函數(shù)將迅速占用較大的簇。

還有一些函數(shù)可能會(huì)導(dǎo)致進(jìn)程合法地“崩潰”,例如posix_kill()或posix_setrlimit()。我們可能希望從測(cè)試語(yǔ)料庫(kù)中刪除這些內(nèi)容,以減少誤報(bào)的數(shù)量。

最后,由于PHP文檔中列出的許多函數(shù)和類實(shí)際上在核心安裝中不可用(而是從擴(kuò)展中提供),因此我們不妨從資料集中刪除其中的一些函數(shù)和類,以避免浪費(fèi)時(shí)間調(diào)用不存在的代碼。

最后,經(jīng)過(guò)一番試驗(yàn),我確定了以下清單...

 
 
 
 
  1. $class_blacklist = array( 
  2. // Can't actually instantiate 
  3.     "Closure", 
  4.     "Generator", 
  5.     "HashContext", 
  6.     "RecursiveIteratorIterator", 
  7.     "IteratorIterator", 
  8.     "FilterIterator", 
  9.     "RecursiveFilterIterator", 
  10.     "CallbackFilterIterator", 
  11.     "RecursiveCallbackFilterIterator", 
  12.     "ParentIterator", 
  13.     "LimitIterator", 
  14.     "CachingIterator", 
  15.     "RecursiveCachingIterator", 
  16.     "NoRewindIterator", 
  17.     "AppendIterator", 
  18.     "InfiniteIterator", 
  19.     "RegexIterator", 
  20.     "RecursiveRegexIterator", 
  21.     "EmptyIterator", 
  22.     "RecursiveTreeIterator", 
  23.     "ArrayObject", 
  24.     "ArrayIterator", 
  25.     "RecursiveArrayIterator", 
  26.     "SplFileInfo", 
  27.     "DirectoryIterator", 
  28.     "FilesystemIterator", 
  29.     "RecursiveDirectoryIterator", 
  30.     "GlobIterator", 
  31. ); 
  32.  
  33. $function_blacklist = array( 
  34.     "exit", // false positives 
  35.     "readline",    // pauses 
  36.     "readline_callback_handler_install", // pauses 
  37.     "syslog",    // spams syslog 
  38.     "sleep", // pauses 
  39.     "usleep", // pauses 
  40.     "time_sleep_until", // pauses 
  41.     "time_nanosleep", // pauses 
  42.     "pcntl_wait", // pauses 
  43.     "pcntl_waitstatus", // pauses 
  44.     "pcntl_waitpid", // pauses 
  45.     "pcntl_sigwaitinfo", // pauses 
  46.     "pcntl_sigtimedwait", // pauses 
  47.     "stream_socket_recvfrom", // pauses 
  48.     "posix_kill", // ends own process 
  49.     "ereg", // cpu dos 
  50.     "eregi", // cpu dos 
  51.     "eregi_replace", // cpu dos 
  52.     "ereg_replace", // cpu dos 
  53.     "similar_text", // cpu dos 
  54.     "snmpwalk", // cpu dos 
  55.     "snmpwalkoid", // cpu dos 
  56.     "snmpget", // cpu dos 
  57.     "split", // cpu dos 
  58.     "spliti", // cpu dos 
  59.     "snmpgetnext", // cpu dos 
  60.     "mcrypt_create_iv", // cpu dos 
  61.     "gmp_fact", // cpu dos 
  62.     "posix_setrlimit" 
  63. ); 

盡管一臺(tái)機(jī)器既可以單獨(dú)生成樣本,但我還是選擇了一小組來(lái)加快處理速度。我使用了在Intel NUC上運(yùn)行的 Proxmox 和10個(gè) Debian VM,其工作如下:

· 節(jié)點(diǎn)0:樣本生成,托管NFS共享。

· 節(jié)點(diǎn)1-8:Fuzzing節(jié)點(diǎn),從NFS共享中提取樣本進(jìn)行測(cè)試。

· 節(jié)點(diǎn)9:“分類”節(jié)點(diǎn):根據(jù)崩潰指標(biāo)對(duì)崩潰樣本進(jìn)行分類。

我創(chuàng)建了簡(jiǎn)單的原始shell腳本以在每個(gè)腳本上運(yùn)行以執(zhí)行這些職責(zé),這些腳本可以在上面鏈接的github repo中找到。

0x05  分析Crashs

幾分鐘內(nèi),該Fuzzer就生成了多個(gè)崩潰樣本,一夜之間就生成了2,000多個(gè)。

通過(guò)根據(jù)崩潰的指令地址對(duì)崩潰進(jìn)行分類,我能夠確定所有2,000個(gè)崩潰都是3個(gè)錯(cuò)誤造成的。其中,有2個(gè)顯然無(wú)法利用(兩個(gè)都是由于堆棧耗盡導(dǎo)致的OOM錯(cuò)誤),但是最后一個(gè)似乎是UAF!這是最小化的崩潰示例...

此錯(cuò)誤已在bug#79029中得到修復(fù),應(yīng)該包含在下一個(gè)版本中。在接下來(lái)的幾篇文章中,我將討論將其根本原因,實(shí)現(xiàn)任意代碼執(zhí)行的過(guò)程,以及在此過(guò)程中發(fā)現(xiàn)的一個(gè)巧妙的shellcode技巧。

 https://bugs.php.net/bug.php?id=79029

本文翻譯自:https://blog.jmpesp.org/2020/01/fuzzing-php-with-domato.html?m=1&fbclid=IwAR16VPIISd2dERbma9o5bmYrEo-iBS7gPhsr0UqjUJWLlctWiHO1zpmPjHg如若轉(zhuǎn)載,請(qǐng)注明原文地址。


當(dāng)前標(biāo)題:用Domato通過(guò)Fuzzing對(duì)PHP進(jìn)行漏洞挖掘研究
文章鏈接:http://www.dlmjj.cn/article/ccicjpo.html