<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    調試httpd通過fork+execute調用的cgibin程序

    VSole2023-04-18 09:41:26

    在調試dlink的httpd時,漏洞可能發生在httpd通過fork+execute調用的cgibin中,其中httpd解析網絡請求中的字段,并且以環境變量的形式傳遞給cgibin進行處理。那么要調試cgibin就有兩種方式:

    ① 設置環境變量,然后直接調試cgibin。

    ② 了解httpd是如何調用cgibin的,然后通過設置gdb調試子進程、catch exec,調試cgibin。

    方法1的優點是簡單直接,缺點是需要了解httpd是如何處理、傳遞數據到環境變量,以免使用了實際上通不過httpd校驗的環境變量;方法2的優點是直觀,但是需要熟練掌握gdb調試子進程相關的知識。

    一、httpd調用CGI上下文說明

    和許多典型的httpdserver一樣,傳入到函數process_cgi中的參數a1是httpd所定義的數據結構,其中包含了一個網絡請求的數據集合,例如請求方式REQUEST_METHOD、URI、SESSION等等。a1傳遞到process_cgi函數中進行處理,獲取到需要調用的cgi,以及將需要處理的數據轉化成環境變量集合到cgi中。在dir 850l的固件中,幾乎所有的cgi都是通過鏈接的形式到程序cgibin,cgibin根據請求的不同來采用不同的接口(函數)進行處理。

    int __fastcall process_cgi(_DWORD *a1){......  v77 = spawn(*filename, filename, argv, v79, v75, v9, v8, a1 + 992);......}
    

    spawn函數則是一個典型的封裝了fork+execve的函數,通過fork函數創建子進程,設置子進程的進程組、資源限制、重定向輸入輸出等。

    __pid_t __fastcall spawn(const char *filename, char *const *argv, char *const *envp, int a4, int a5, int a6, int a7, char *path){  __pid_t result; // $v0  int v13; // $a0  int v14[4]; // [sp+18h] [-18h] BYREF  __pid_t v15; // [sp+28h] [-8h]   result = fork();  // 創建子進程,此時的子進程依舊是httpd的程序鏡像  if ( result == -1 )  {    v15 = -1;    lerror("spawn: failed to create child process");    goto LABEL_6;  }  if ( !result )  {    setpgid(0, 0);  // 改變子進程的進程組    sub_409C9C(13, 0);    if ( coredir )    {      v14[3] = 0;      v14[2] = 0;      v14[1] = 0;      v14[0] = 0;      setrlimit64(4, v14);  // 設置資源限制    }    dup2(a4, 0);  // 復制文件描述符:標準輸入和標準輸出    dup2(a4, 1);    if ( a5 != -1 )      dup2(a5, 2);    if ( chdir(path) == -1 )    {      v13 = 5;    }    else    {      execve(filename, argv, envp);  // 執行cgibin,將cgibin加載并替換掉子進程的httpd      v13 = 6;    }    exit(v13);  }  ++dword_42350C;  if ( debug )  {    v15 = result;    log_d("child process %d created", result);LABEL_6:    result = v15;  }  return result;}
    

    那么到此,回想之前的標題:如何調試httpd通過execute調用的cgibin,該問題就可以抽象為:如何調試子進程中通過execute調用的可執行文件。

    二、調試原理

    默認情況下,gdb在調試多進程的時候,只會追蹤父進程,例如執行完fork函數,fork的返回值是子進程的pid,gdb中實際上在調試的是父進程。如果要調試子進程,則需要在gdb中使用如下的命令:

    set follow-fork-mode child
    

    上面命令解決了讓gdb調試到子進程,但是有時候還需要同時調試父進程和子進程,如果僅僅是gdb在子進程中,父進程依舊會正常運行。那么,就可以使用如下的命令,使得在調試子進程的時候,父進程也暫停處于掛起的狀態:

    set detach-on-fork off # 默認是on
    

    上面兩條命令結合起來就實現了同時調試父進程和子進程,那么這個時候也還有一個問題:在子進程中,execute調用cgibin是作為一個函數來實現的,單步步過該函數達不到調試目的,步進該函數更加容易陷入到函數的細節實現中。

    對于調試cgibin,可以通過catch exec命令,來捕獲執行新進程的事件。當進程使用execute重新執行一個程序時,gdb會中斷程序的運行,到ld加載器start函數中。除此之外,還可以使用例如catch exec /bin/ls來指定需要捕獲的具體進程加載程序事件。

    綜上所述,調試通過fork+execute調用的程序,可以使用如下步驟:

    ① 在fork的時候,執行gdb命令:set follow-fork-mode child,使得gdb開始調試子進程。

    ② 同時,可以執行gdb命令:set detach-on-fork off,讓在調試子進程的同時,父進程掛起。這樣執行完子進程也可以返回到父進程中。

    ③ 執行gdb命令:catch exec,捕獲子進程通過execute加載執行新程序的事件。

    三、調試過程

    現在回歸到具體的調試過程中。

    當httpd執行到調用cgi的spawn函數中,此時準備執行fork函數,可以看到只有httpd一個進程,也就是父進程PID=1444:

    pwndbg> info inferiors  Num  Description       Executable* 1    process 1444      /home/utest/app/FirmAE/firmwares/_DIR850L_FW115KRb07.bin.extracted/squashfs-root/sbin/httpd
    

    第一步需要保證在執行到spawn的時候,fork之后是進入了子進程,

      0x409d2c 56>     move   $s3, $a2? 0x409d30 60>     jalr   $t9                           <fork>
    

    此時,執行gdb命令:

    set follow-fork-mode childset detach-on-fork off
    

    再查看進程信息,也可以確認此時gdb處于子進程中。此時也可以通過inferiors Num切換到父進程。

    pwndbg> info inferiors  Num  Description       Executable  1    process 1444      /home/utest/app/FirmAE/firmwares/_DIR850L_FW115KRb07.bin.extracted/squashfs-root/sbin/httpd* 2    process 31740     /home/utest/app/FirmAE/firmwares/_DIR850L_FW115KRb07.bin.extracted/squashfs-root/sbin/httpd
    

    繼續在子進程中執行到execute函數,可以看到此時正準備加載執行/htdocs/web/session.cgi,該cgi實際上是一個鏈接到cgibin。

      0x409e68     addiu  $a0, $zero, 5  0x409e6c     lw     $t9, -0x7d7c($gp)  0x409e70     move   $a0, $s2? 0x409e74     jalr   $t9                                  path: 0x7ed330 ?— '/htdocs/web/session.cgi'       argv: 0x4280f0 —? 0x7ed330 ?— '/htdocs/web/session.cgi'       envp: 0x0
    

    那么此時就應該執行gdb命令:catch exec,用來捕獲子進程加載cgi的事件:

    這個時候可以查看棧,來看httpd傳遞給cgi哪些環境變量(也就是需要處理的數據):

    pwndbg> stack 3000:0000│ fp sp 0x7fe2b4a0 ?— 0x101:0004│       0x7fe2b4a4 —? 0x7fe2bd23 ?— '/htdocs/web/session.cgi'02:0008│       0x7fe2b4a8 ?— 0x003:000c│       0x7fe2b4ac —? 0x7fe2bd3b ?— 'HTTP_HOST=192.168.0.1'04:0010│       0x7fe2b4b0 —? 0x7fe2bd51 ?— 'HTTP_USER_AGENT=Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0'05:0014│       0x7fe2b4b4 —? 0x7fe2bdb0 ?— 'HTTP_ACCEPT=*/*'06:0018│       0x7fe2b4b8 —? 0x7fe2bdc0 ?— 'HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.5'07:001c│       0x7fe2b4bc —? 0x7fe2bde4 ?— 'HTTP_ACCEPT_ENCODING=gzip, deflate'08:0020│       0x7fe2b4c0 —? 0x7fe2be07 ?— 'HTTP_ORIGIN=http://192.168.0.1'09:0024│       0x7fe2b4c4 —? 0x7fe2be26 ?— 'HTTP_REFERER=http://192.168.0.1/index.php'0a:0028│       0x7fe2b4c8 —? 0x7fe2be50 ?— 'HTTP_COOKIE=uid=bjtsPYnEJz'0b:002c│       0x7fe2b4cc —? 0x7fe2be6b ?— 'GATEWAY_INTERFACE=CGI/1.1'0c:0030│       0x7fe2b4d0 —? 0x7fe2be85 ?— 'CONTENT_LENGTH=31'0d:0034│       0x7fe2b4d4 —? 0x7fe2be97 ?— 'CONTENT_TYPE=application/x-www-form-urlencoded'0e:0038│       0x7fe2b4d8 —? 0x7fe2bec6 ?— 'SCRIPT_FILENAME=/htdocs/web/session.cgi'0f:003c│       0x7fe2b4dc —? 0x7fe2beee ?— 'REQUEST_URI=/session.cgi'10:0040│       0x7fe2b4e0 —? 0x7fe2bf07 ?— 'REMOTE_ADDR=192.168.0.2'11:0044│       0x7fe2b4e4 —? 0x7fe2bf1f ?— 'REMOTE_PORT=45050'12:0048│       0x7fe2b4e8 —? 0x7fe2bf31 ?— 'REQUEST_METHOD=POST'13:004c│       0x7fe2b4ec —? 0x7fe2bf45 ?— 'SCRIPT_NAME=/session.cgi'14:0050│       0x7fe2b4f0 —? 0x7fe2bf5e ?— 'SERVER_NAME=192.168.0.1'15:0054│       0x7fe2b4f4 —? 0x7fe2bf76 ?— 'SERVER_ADDR=192.168.0.1'16:0058│       0x7fe2b4f8 —? 0x7fe2bf8e ?— 'SERVER_PORT=80'17:005c│       0x7fe2b4fc —? 0x7fe2bf9d ?— 'SERVER_SOFTWARE=Mathopd/1.6b9'18:0060│       0x7fe2b500 —? 0x7fe2bfbb ?— 'SERVER_ID=LAN-1'19:0064│       0x7fe2b504 —? 0x7fe2bfcb ?— 'SERVER_PROTOCOL=HTTP/1.1'1a:0068│       0x7fe2b508 ?— 0x0
    

    以前做畢設的時候,要實現對cgi的模糊測試,就是將AFL生產的數據通過設計的數據結構轉換成環境變量到cgi 中去執行。

    四、小結

    如何調試httpd使用fork+execute執行的cgibin,本質上可以抽象為:如何調試通過fork+execute調用的程序,辦法是:

    ① 執行到fork函數,執行gdb命令:set follow-fork-mode child,使得gdb調試到子進程中。

    ② 執行gdb命令:set detach-on-fork off,使得gdb在調試子進程的時候掛起父進程,這樣也方便并行調試。

    ③ 執行到execute函數處,執行gdb命令:catch exec,捕獲子進程通過execute調用執行cgi的事件。

    forkcgi
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    在調試dlink的httpd時,漏洞可能發生在httpd通過fork+execute調用的cgibin中,其中httpd解析網絡請求中的字段,并且以環境變量的形式傳遞給cgibin進行處理。② 了解httpd是如何調用cgibin的,然后通過設置gdb調試子進程、catch exec,調試cgibin。在dir 850l的固件中,幾乎所有的cgi都是通過鏈接的形式到程序cgibin,cgibin根據請求的不同來采用不同的接口(函數)進行處理。
    cgiHandler函數中,將用戶的HTTP請求參數作為環境變量,通過諸如LD_PRELOAD即可劫持進程的動態鏈接庫,實現遠程代碼執行。代碼首先拼接出用戶請求的cgi完整路徑并賦予cgiPath,然后檢查此文件是否存在以及是否為可執行文件。隨后代碼將cgiPath、envp、stdIn與stdOut作為參數傳入launchCgi函數中。
    關于MIPS架構的寄存器及指令集請自行查閱資料,這里就不多作介紹了。,則也會在prologue處保存下來,并在epilogue處取出。流水線指令集相關特性MIPS架構存在“流水線效應”,簡單來說,就是本應該順序執行的幾條命令卻同時執行了,其還存在緩存不一致性(cache
    簡介閑來沒事,做一個自動化recon的工具,簡化操作流程。可以對域名或ip進行whois查詢,dns記錄查詢,ip端口掃描,http屏幕快照。最終生成markdown格式的報告,可使用Obsidian或vscode的markdown notes插件打開,借助雙向鏈接功能,方便跳轉查看。依賴的程序amass子域名查找 下載地址masscan掃描全部端口,發現開放端口。nmap服務掃描,針對masscan發現的端口進行具體的服務掃描。
    nmap -PN -sS -sV --script=vulscan –script-args vulscancorrelation=1 -p80 target. nmap -PN -sS -sV --script=all –script-args vulscancorrelation=1 target. NetCat,它的實際可運行的名字叫nc,應該早很就被提供,就象另一個沒有公開但是標準的Unix工具。
    主要的環境準備參見上一篇文章,這里介紹本篇文章中會用的的模擬工具以及另一個靜態分析工具。
    微服務架構中,API網關充當著非常重要的一環,它不僅要負責外部所有的流量接入,同時還要在網關入口處根據不同類型請求提供流量控制、日志收集、性能分析、速率限制、熔斷、重試等細粒度的控制行為。API網關一方面將外部訪問與微服務進行了隔離,保障了后臺微服務的安全,另一方面也節省了后端服務的開發成本,有益于進行應用層面的擴展。與此同時,API網關也具備解決外界訪問帶來的安全問題,如TLS加密、數據丟失、跨
    PHP disable_functions disable_functions是php.ini中的一個設置選項。相當一個黑名單,可以用來設置PHP環境禁止使用某些函數,通常是網站管理員為了安全起見,用來禁用某些危險的命令執行函數等。
    disable_functions是php.ini中的一個設置選項。相當一個黑名單,可以用來設置PHP環境禁止使用某些函數,通常是網站管理員為了安全起見,用來禁用某些危險的命令執行函數等。
    相當一個黑名單,可以用來設置PHP環境禁止使用某些函數,通常是網站管理員為了安全起見,用來禁用某些危險的命令執行函數等。高ini_restore()可用于恢復 PHP 環境配置參數到其初始值
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类