簡體   English   中英

需要幫助以支持這個簡短的C ++程序及其漏洞

[英]Need help understing this short C++ program and its vulnerability

如果有人可以向我確切解釋代碼的功能,我將非常樂意。 我知道這里有一個緩沖區溢出和bash命令執行漏洞-但是由於我是一名網絡專家,而不是程序員,所以我確實可以使用一些幫助來理解整個代碼。 提前致謝!

int main () {
    int status;
    char t[1024]="ps -eo lstart,cmd | grep ";
    cout << "Content-type:text/html\r\n\r\n"<<endl;
    char *value = getenv("QUERY_STRING");
    strcat(t,value);
    status = system(strcat(t," | grep -v grep | head -n 1 | awk '{ print $1\" \"$3\" \"$2\" \"$5\" \"$4}'"));

    return 0;
}

tl; dr:這是您的代碼作為shell腳本執行的操作:

#!/bin/bash
echo -en "Content-type:text/html\r\n\r\n"
ps -eo lstart,cmd | grep init | grep -v $QUERY_STRING | \
head -n 1 | awk '{ print $1" "$3" "$2" "$5" "$4}'

現在為更長的答案。

重寫代碼

首先,通過一些錯誤處理,將其放入C ++而不是C中(就像您的標簽提示您所詢問的那樣),然后進行一些錯誤處理:

#include <iostream>
#include <string>
#include <string_view>

int main () {
    auto query_string = getenv("QUERY_STRING");
    if (query_string == nullptr) {
        std::cerr << "Couldn't obtain QUERY_STRING environment variable\n";
        return EXIT_FAILURE;
    }
    if (std::string_view{query_string}.empty()) {
        std::cerr << "Empty query string (QUERY_STRING environment variable)\n";
        return EXIT_FAILURE;
    }
    std::stringstream command_line;
    command_line 
        << "ps -eo lstart,cmd | grep "
        << query_string 
        << " | grep -v grep | head -n 1 | awk '{ print $1\" \"$3\" \"$2\" \"$5\" \"$4}'";
    std::cout << "Content-type:text/html\r\n\r\n";
    return system(command_line.str()); // security vulnerability, see below
}

我們在這里做什么?

因此,我們在此處創建一個命令行,然后使用system()函數執行該命令行。 這是通過一些開關調用ps命令,然后使用grepheadawk進行一些文本處理-使用管道機制將每個命令的輸出移至下一個命令。 它們的關鍵部分是我們使用環境變量QUERY_STRING來過濾ps結果,即,我們列出與某些短語匹配的過程。 如果我們編譯該程序,請設置環境變量並運行,結果如下所示:

$ export QUERY_STRING=init
$ ./the_program
Content-type:text/html


Sun 3 Jun 2018 21:48:56

這給了我們第一個進程的開始時間,該進程的命令行不包含短語“ init”。 所以現在您可以猜測我的系統從昨天開始就已啟動...

最終,作為網絡專家,您可能意識到“ Content-type” mumbo-jumbo,並且雙換行符是MIME頭,因此此輸出可能打算用作HTTP響應。 可能這是某種CGI腳本。

安全漏洞

  1. 在原始代碼中,緩沖區大小被任意限制為1024-而沒有任何限制QUERY_SIZE的長度不超過該長度。 如果更長,則將導致內存損壞,這可能會帶來安全隱患。 攻擊者很可能就能弄清楚您的內存布局,因此更加危險。 C ++版本已不復存在。
  2. 第二個漏洞與system命令有關。 我們在創建的字符串中注入了任意字符串; 並沒有阻止某人設置

     $export QUERY_STRING="dummy; rm -rf $HOME ; echo" 

    在這種情況下,您將運行:

     ps -eo lstart,cmd | grep dummy; rm -rf $HOME ; echo | grep -v init | head -n 1 | awk '{ print $1" "$3" "$2" "$5" "$4}' 

    這會刪除有效用戶主目錄下的所有內容。 也可以是任何命令,包括編譯自定義C / C ++程序以在系統上運行一些任意代碼。 很壞。

  3. 即使您將QUERY_STRING消毒為僅一個有效的grep模式,但如果有人以某種方式提供復雜的超長grep'ing模式,仍然可能會出現拒絕服務攻擊。 因此,限制長度也是一個好主意。

這只是聲明變量status

int status;

這用C字符串“ ps -eo lstart,cmd | grep”聲明為t。 t的最大容量為1024字節(字符串1023 + 1字節\\0

char t[1024]="ps -eo lstart,cmd | grep ";

在下面打印字符串

cout << "Content-type:text/html\r\n\r\n"<<endl;

獲取環境變量QUERY_STRING

char *value = getenv("QUERY_STRING");

將上面的值連接到t 在這里您可能會有緩沖區溢出,因為您不知道字符串value的大小,並且它可能長於1024個字節

strcat(t,value);

使用所有這些grep等命令調用system()函數以與前一個t進行另一次串聯,等等……在這里,您可能會有另一個緩沖區溢出,一旦t也可能在這里溢出它的1024個字節。

status = system(strcat(t," | grep -v grep | head -n 1 | awk '{ print $1\" \"$3\" \"$2\" \"$5\" \"$4}'"));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM