[英]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
命令,然后使用grep
, head
和awk
進行一些文本處理-使用管道機制將每個命令的輸出移至下一個命令。 它們的關鍵部分是我們使用環境變量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腳本。
第二個漏洞與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 ++程序以在系統上運行一些任意代碼。 很壞。
這只是聲明變量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.