自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

用Domato通過Fuzzing對PHP進(jìn)行漏洞挖掘研究

安全 漏洞
最近,我一直在對PHP解釋器進(jìn)行Fuzzing,我探索了許多工具和技術(shù)(AFL,LibFuzzer,甚至是自定義的Fuzzing引擎),但是最近我決定嘗試Domato。

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

https://github.com/Rewzilla/domatophp

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

 https://github.com/googleprojectzero/domato

0x01  分析上下文語法

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

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

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

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

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

用Domato通過Fuzzing對php進(jìn)行漏洞挖掘研究

然后Domato使用上下文無關(guān)文法生成符合語言規(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ī)則分解為更多子規(guī)則,我們可以開始定義更復(fù)雜的語言,而不僅僅是簡單的搜索/替換。實(shí)際上,Domato還提供了一些內(nèi)置函數(shù),用于限制遞歸并生成基本類型(int,char,string等)。

例如,以下Domato語法,該語法生成偽代碼...

用Domato通過Fuzzing對php進(jìn)行漏洞挖掘研究

將其送入Domato會產(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)槊總€樣本都是不同的,并且仍然保證其在語法上是有效的!

0x02 列舉Attack Surface

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

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

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

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

用Domato通過Fuzzing對php進(jìn)行漏洞挖掘研究

這會產(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 ... 

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

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

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

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

用Domato通過Fuzzing對php進(jìn)行漏洞挖掘研究

0x03  設(shè)置Domato

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

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

用Domato通過Fuzzing對php進(jìn)行漏洞挖掘研究

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

用Domato通過Fuzzing對php進(jìn)行漏洞挖掘研究

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

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

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

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

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

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

  1. andrew@thinkpad ~/domato/php % python generator.py /dev/stdout 
  2. Writing a sample to /dev/stdout 
  3. <?php 
  4. $vars = array( 
  5.     "stdClass"                       => new stdClass(), 
  6.     "Exception"                      => new Exception(), 
  7.     "ErrorException"                 => new ErrorException(), 
  8.     "Error"                          => new Error(), 
  9.     "CompileError"                   => new CompileError(), 
  10.     "ParseError"                     => new ParseError(), 
  11.     "TypeError"                      => new TypeError(), 
  12.     ... etc ... 
  13. ); 
  14. try { try { $vars["SplPriorityQueue"]->insert(false, array("a" => 1, "b" => "2""c" => 3.0)); } catch (Exception $e) { } } catch(Error $e) { } 
  15. try { try { filter_has_var(1000, str_repeat("%s%x%n", 0x100)); } catch (Exception $e) { } } catch(Error $e) { } 
  16. 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) { } 
  17. try { try { rand(0, 0); } catch (Exception $e) { } } catch(Error $e) { } 
  18. 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) { } 
  19. try { try { $vars["ReflectionMethod"]->isAbstract(); } catch (Exception $e) { } } catch(Error $e) { } 
  20. 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) { } 
  21. try { try { utf8_encode(str_repeat("A", 0x100)); } catch (Exception $e) { } } catch(Error $e) { } 
  22. try { try { $vars["MultipleIterator"]->current(); } catch (Exception $e) { } } catch(Error $e) { } 
  23. try { try { dl(str_repeat("A", 0x100)); } catch (Exception $e) { } } catch(Error $e) { } 
  24. try { try { ignore_user_abort(true); } catch (Exception $e) { } } catch(Error $e) { } 

0x04  開始Fuzz

現(xiàn)在我們要處理的數(shù)據(jù)非常多,我們需要以一種最大化檢測任何類型的內(nèi)存損壞的機(jī)會的方式構(gòu)建PHP。為此,我強(qiáng)烈建議使用LLVM Address Sanitizer(ASAN),它將檢測任何無效的內(nèi)存訪問,即使它不會立即導(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)行之前,嘗試消除不必要地阻礙該過程的任何條件也是一個好主意。例如,像大多數(shù)語言一樣,PHP具有一個sleep()函數(shù),該函數(shù)接受一個整數(shù)參數(shù),并僅等待幾秒后才能繼續(xù)。用較大的值(例如INT_MAX)調(diào)用此函數(shù)將迅速占用較大的簇。

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

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

最后,經(jīng)過一番試驗(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. ); 

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

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

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

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

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

用Domato通過Fuzzing對php進(jìn)行漏洞挖掘研究

0x05  分析Crashs

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

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

用Domato通過Fuzzing對php進(jìn)行漏洞挖掘研究

此錯誤已在bug#79029中得到修復(fù),應(yīng)該包含在下一個版本中。在接下來的幾篇文章中,我將討論將其根本原因,實(shí)現(xiàn)任意代碼執(zhí)行的過程,以及在此過程中發(fā)現(xiàn)的一個巧妙的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)載,請注明原文地址。

 

責(zé)任編輯:姜華 來源: 嘶吼網(wǎng)
相關(guān)推薦

2020-09-29 10:44:51

漏洞

2017-09-19 15:01:06

PHP漏洞滲透測試

2020-12-18 09:49:48

iOS ChromiWKWebViewJavaScript

2010-05-19 14:13:12

MySQL存儲過程

2023-08-11 09:41:48

AFLfuzzingPatch

2010-02-22 15:13:01

Python模塊

2009-12-28 11:14:53

ADO 連接對象

2019-01-09 10:26:32

web安全漏洞挖掘前端打包

2020-09-25 10:14:54

漏洞

2009-12-09 16:52:51

VS 2003插件

2010-02-02 15:48:49

Python數(shù)據(jù)庫

2010-03-01 14:02:26

Python批處理語言

2010-03-10 18:29:57

2014-09-25 19:30:51

2021-02-23 10:43:42

Facebook Ga

2010-01-05 20:39:22

2016-05-03 09:51:08

2015-03-06 15:43:39

2020-09-27 14:23:36

AI

2011-04-14 09:05:07

ExcelMySQL數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號