[羊城杯 2020]easyser
1.打开是一个ubuntu界面
查看源码没发现什么信息,扫目录看一下
得到了这四个文件,访问一下
index.php
flag.php
index.php/login/
robots.txt
都没啥信息,只有robots.txt中发现了一个文件
访问一下
star1.php
这页面 一出来,就知道 是ssrf了 ,在源码中发现了 新发现
说用不安全的协议从我家才能进ser.php
那么使用 本地回环地址127.0.0.1,访问一下ser.php
然后向下滑,发现了源码
2.分析代码
<?php error_reporting(0); if ( $_SERVER['REMOTE_ADDR'] == "127.0.0.1" ) { highlight_file(__FILE__); } $flag='{Trump_:"fake_news!"}'; class GWHT{ public $hero; public function __construct(){ $this->hero = new Yasuo; } public function __toString(){ if (isset($this->hero)){ return $this->hero->hasaki(); }else{ return "You don't look very happy"; } } } class Yongen{ //flag.php public $file; public $text; public function __construct($file='',$text='') { $this -> file = $file; $this -> text = $text; } public function hasaki(){ $d = '<?php die("nononon");?>'; $a= $d. $this->text; @file_put_contents($this-> file,$a); } } class Yasuo{ public function hasaki(){ return "I'm the best happy windy man"; } } ?>首先是一个if语句,只有remote_addr是127.0.0.1地址才能显示文件内容
然后定义了一个假flag
GWHT类
一个公共属性hero
construct方法,触发了会将本类的hero属性赋值一个Yasuo类的对象
一个toString方法,触发了会有一个if判断语句,检查是否有$this->hero,有的话,就return返回$this->hero调用它的hasaki方法
Yongen类
有个提示flag.php,两个公共属性,file,text
一个construct方法,里面接收两个参数$file和text,都赋值为空,触发了会让他们两个分别赋值给本类的file和text属性
hasaki方法,触发了会将<?php die("nonono");?>赋值给$d,然后再将$d和本类的text属性进行一个拼接赋值给$a,随后使用file_put_contents将$a的内容写入到$this->file中
Yasuo类
里面也要一个hasaki方法,会返回一段文字
3.开始构造
这里的链子也很容易
GWHT :: construct --> GWHT :: toString --> Yongen :: hasaki
然后再使用base64编码绕过die死亡绕过,也可以使用string.string.tags进行绕过
或者string.strip_tags去除标签也能进行
然后通过传参名c,传入上去这些序列化的字段
然后最后访问创建的这个文件,执行命令就行了
做题感觉到的疑惑的地方
解释一下为什么会使用c参数名进行传参,是使用arjun工具探测出来的
记得加上-m get 和 --include=?path=http://127.0.0.1/ 然后选择一个小字典,加上线程为64
然后还有就是toString方法是如何触发的,看了一圈只有一个人对此有解释,就是通过参数c传参然后触发的toString方法,有点没看懂,都是懵逼的地方
4.知识点
知道了一个参数探测工具arjun
https://github.com/s0md3v/Arjun/(工具地址)
还有一个die死亡绕过
可以使用rot13和base64还有string.strip_targs进行绕过
前两个的绕过原理都是利用解码将前面的<?php die();?>给解码掉,然后再将自己想写入的给先编码一下,最后的解码效果就是将 不想要的给解码成乱符了,想要的就变成正常的webshell了
string.strip_targs是利用去除标签,来将前面的去除掉
参考文章
https://syunaht.com/p/1492341886.html
https://tyskill.github.io/posts/ycb2020/#easyser
[HZNUCTF 2023 preliminary]ppppop
1.打开是个空白
扫目录看源码无果
抓包看一下
发现了两个cookie的user值,看着像base64编码,解码 一下
他这里面的isAdmin的值为0也就是 false,将他修改为1True
再传入,发现了源码,那么开始分析源码
2.分析代码
<?php error_reporting(0); include('utils.php'); class A { public $className; public $funcName; public $args; public function __destruct() { $class = new $this->className; $funcName = $this->funcName; $class->$funcName($this->args); } } class B { public function __call($func, $arg) { $func($arg[0]); } } if(checkUser()) { highlight_file(__FILE__); $payload = strrev(base64_decode($_POST['payload'])); unserialize($payload); }首先包含进来一个utils.php文件
一个A类
三个公共属性className、funcName、args
一个destruct方法,触发了是 一个任意实例化类,类名为本类的className属性,结果赋值给$class,然后将本类的funcName属性赋值给$funcName,然后让$class作为对象名,调用它里面的$funcName方法 ,$this->args属性是它的方法参数
B类:
一个call方法,里面 接收两个参数$func,$argc,触发了会一个动态函数调用,$func是函数名,$arg的索引值为0的值是它的参数
下面是一个if语句,检查checkUser方法是否存在 ,如果存在的话就将POST传参的payload进行一本base64解密,然后再让他们进行一个字符串反转,就像abc会反转为cba,然后赋值给$payload,最后反序列化$payload
2.开始构造
因为就两个类所以就不用过多分析了
让A类的className属性为B,这样就能实例化B类了,然后funcName为可以执行命令的值,使用system,args是要执行的命令,就正常ls或者其他的就行了,这样的$class->$funcName($this->args)就变成了B::system("ls")
然后到了call方法中,func是system,arg为ls,变成了system("ls");
还有就是下面的编码,它是先进行了一遍base64解密,再进行一次反转,那么我想要满足它的解密方式的话就是,先进行一个反转 ,再进行一个加密
然后传参 就行了
根目录下没发现flag,查看一下环境变量下
3.知识点
考验对信息收集的能力,注意观察cookie和其他的信息
[NSSRound#4 SWPU]1zweb(revenge)
1.开局一个上传框和查看文件框
然后通过查询文件,看看能不能查index.php
可以查询但是不全,使用伪协议进行一个读取
然后就成功获得了upload.php和index.php的源码
2.分析代码
index.php
<?php class LoveNss{ public $ljt; public $dky; public $cmd; public function __construct(){ $this->ljt="ljt"; $this->dky="dky"; phpinfo(); } public function __destruct(){ if($this->ljt==="Misc"&&$this->dky==="Re") eval($this->cmd); } public function __wakeup(){ $this->ljt="Re"; $this->dky="Misc"; } } $file=$_POST['file']; if(isset($_POST['file'])){ if (preg_match("/flag/", $file)) { die("nonono"); } echo file_get_contents($file); }首先是一个LoveNss类
里面三个公共属性ljt、dky、cmd
construct方法,触发了会给本类的ljt属性赋值一个ljt,然后给dky属性赋值一个dky,然后一个phpinfo函数
destruct方法,触发了,会if语句判断ljt属性是否强等于Misc,dky是否为Re,如果都满足,就eval执行本对象的cmd属性的值
wakeup方法,触发了会将本类的ljt赋值一个Re,dky赋值一个Misc
然后POST传参一个file,并赋值给$file,并检查是否存在file,然后使用正则表达式判断$file中是否flag,如果出现就die退出,否的话就文件读取 $file文件的内容
upload.php
<?php if ($_FILES["file"]["error"] > 0){ echo "上传异常"; } else{ $allowedExts = array("gif", "jpeg", "jpg", "png"); $temp = explode(".", $_FILES["file"]["name"]); $extension = end($temp); if (($_FILES["file"]["size"] && in_array($extension, $allowedExts))){ $content=file_get_contents($_FILES["file"]["tmp_name"]); $pos = strpos($content, "__HALT_COMPILER();"); if(gettype($pos)==="integer"){ echo "ltj一眼就发现了phar"; }else{ if (file_exists("./upload/" . $_FILES["file"]["name"])){ echo $_FILES["file"]["name"] . " 文件已经存在"; }else{ $myfile = fopen("./upload/".$_FILES["file"]["name"], "w"); fwrite($myfile, $content); fclose($myfile); echo "上传成功 ./upload/".$_FILES["file"]["name"]; } } }else{ echo "dky不喜欢这个文件 .".$extension; } } ?>直接分析吧,因为它的普通形式也就是1zweb也是这个上传代码,就是它会检查上传的文件,是否有包含phar文件的头部,和它定义了一个白名单,只能上传那几个图片,然后撒谎给你次成功了会将它上传 到upload目录 下
2.开始分析
他这题在原有的基础上,添加了一个不能出现flag字段,不过我是eval执行完命令,才进行读取,所以flag直接就使用通配符来代替了,没啥影响,检测文件头部使用gzip压缩绕过,然后绕过wakeup使用修改成员属性绕过,链子就跟简单了,就修改几个属性的值就行了
3.开始构造
首先看链子
下面是用来生成phar文件的,生成完的文件,在使用winhex将他的成员属性修改一下
蓝色的这个字段,修改为4就行了
这个时候修改了内容 ,他的签名就是废了,所以需要使用脚本来进行修改签名
修改完,这个时候还是没有绕过头部检测的 ,在使用gzip进行压缩一下
这个时候才是完全绕过的,然后就是上传上去,获得路径
然后再使用phar进行反序列化
phar://文件路径
4.知识点
这题再原有的 1zweb的基础上添加了一个检查flag字段操作,只不过没啥影响
还是phar反序列化 ,然后绕过wakeup,绕过头部检查,使用gzip绕过