PfSense命令注入漏洞分析

mssp299 · 2015/09/09 14:00php

翻譯:mssp299linux

原文地址:www.proteansec.com/linux/pfsen…shell

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的輸入值:ide

192.168.1.1";ifconfig>/usr/local/www/temp.txt;echo+"
複製代碼

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

enter image description here

圖1 發送給服務器的惡意請求spa

當上面所示的請求被執行時,Web瀏覽器會顯示以下所示的內容,其中含有一個錯誤信息,出錯緣由是沒有提供有效的主機名。翻譯

enter image description here

圖2 錯誤消息:invalid hostname3d

咱們已經在用戶提供的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中發現的一些命令注入漏洞,但願對讀者朋友們有所幫助。

相關文章
相關標籤/搜索