AFL實戰(zhàn):測試sudo提權漏洞CVE-2021-3156
最近sudo發(fā)現了一個嚴重的緩存溢出提權漏洞CVE-2021-3156,這很正常。不正常的是這個漏洞已經潛伏了10年之久,為什么10年才發(fā)現呢?如果用常規(guī)的測試方法需要多久才能發(fā)現?對此有人進行了Fuzz測試,請和蟲蟲一起學習一下過程。
概述
在本文試驗中,使用了AFL模糊器。AFL模糊器(American Fuzzy lop)是一種面向安全的模糊器,AFL使用新型編譯時檢測和遺傳算法,自動發(fā)現干凈有趣的測試用例,這些用例會在目標二進制文件中觸發(fā)新的內部狀態(tài)。用這樣的方法可以大大改善了模糊代碼的功能覆蓋范圍。
AFL模糊器生成的緊湊的合成語料庫還可以用于復現其他測試人員更耗費人力或資源的測試方案。
測試準備
sudo是setuid二進制文件,以root用戶隨機輸入運行潛在錯誤的二進制文件不是最安全的方法。為了避免任何潛在的意外系統(tǒng)損壞,此設置試驗中使用了虛擬機環(huán)境。并選擇最近一個涉及漏洞sudo版本sudo 1.9.5.p1。
AFL旨在將輸出生成到文件或stdout中,但是要模糊命令行參數。因此,需要自行修補sudo,忽略實際的argv并將其改為從stdin。
AFL提供了一個可以提供這樣功能的argv-fuzz-inl.h:
示例argv-fuzz-inl.h從stdin讀取NUL分隔的參數。注意,sudo在單個二進制文件中同時提供了sudo和sudoedit實用程序,因此要測試兩者,還需要向fuzzer公開argv[0]。輸入的代碼argv-fuzz-inl.h不會執(zhí)行此操作,因此需要對其進行修復:
- int rc = 0; /* start at argv[0] */
 
sudo本身補丁很簡單,只需在main的開頭連接AFL_INIT_ARGV即可:
- --- a/src/sudo.c
 - +++ b/src/sudo.c
 - @@ -66,6 +66,8 @@
 - #include "sudo_plugin.h"
 - #include "sudo_plugin_int.h"
 - +#include "argv-fuzz-inl.h"
 - +
 - /*
 - * Local variables
 - */
 - @@ -149,6 +151,7 @@ sudo_dso_public int main(int argc, char *argv[], char *envp[]);
 - int
 - main(int argc, char *argv[], char *envp[])
 - {
 - +AFL_INIT_ARGV();
 - int nargc, status = 0;
 - char **nargv, **env_add, **user_info;
 
快速測試表明sudo/sudoedit選擇無法從stdin中傳遞的測試用例正常工作,因為出于某種原因,它使用了__progname。一個快速解決方法:
- --- a/lib/util/progname.c
 - +++ b/lib/util/progname.c
 - @@ -83,7 +83,7 @@ void
 - initprogname2(const char *name, const char * const * allowed)
 - {
 - int i;
 - -# ifdef HAVE___PROGNAME
 - +# if 0
 - extern const char *__progname;
 - if (__progname != NULL && *__progname != '\0')
 
最后,設置無需等待密碼輸入,因此只需使其無條件失敗即可:
- --- a/plugins/sudoers/auth/sudo_auth.c
 - +++ b/plugins/sudoers/auth/sudo_auth.c
 - @@ -259,7 +259,7 @@ verify_user(struct passwd *pw, char *prompt, int validated,
 - "--disable-authentication configure option."));
 - debug_return_int(-1);
 - }
 - -
 - +return 0;
 - /* Enable suspend during password entry. */
 - sigemptyset(&sa.sa_mask);
 - sa.sa_flags = SA_RESTART;
 
由于某種原因afl-gcc工具無法正常工作,因此使用了基于LLVM的工具。需要重寫CC為./configure:
- CC=AFL-clang-fast ./configure
 
測試中使用了兩個簡單的測試用例,調用了兩個可用的實用程序:
- echo -ne 'sudo\0ls\0\0' > case1
 - echo -ne 'sudoedit\0test\0\0' > case2
 
準備就緒后,以并行模式啟動了四個AFL實例。半小時后,出現了一個crash:
結果:
確實在sudoedit -s是崩潰了。假設并行運行了4個實例,大約2小時的CPU時間。通過2小時的CPU時間測試,就可以在setuid中找到嚴重的安全漏洞。
總結
為什么在十年中,才能發(fā)現這樣的嚴重問題,其他重要的基礎系統(tǒng)是否是不是也存在類似類似的潛伏漏洞。不知道之前有沒有人對sudo做過模糊測試?或者社區(qū)大意了,只測試過sudo,而遺漏了不太引人注意的sudoedit了。
但是無論如何,需要指出的是,使用快速使用模糊測試程序可以發(fā)現廣泛使用的實用程序中仍然存在嚴重的錯誤。


















 
 
 









 
 
 
 