1 <?php 2 3 error_reporting(0); 4 $text = $_GET["text"]; 5 $file = $_GET["file"]; 6 if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){ 7 echo "<br><h1>".file_get_contents($text,'r')."</h1></br>"; 8 if(preg_match("/flag/",$file)){ 9 die("Not now!"); 10 } 11 12 include($file); //next.php 13 14 } 15 else{ 16 highlight_file(__FILE__); 17 } 18 ?>
首先打开题目看看,屏蔽了flag。
然后首先是要绕过第一个if判断,用data协议或者php伪协议也可以。
方法一:
方法二:
payload:?text=data://text/plain,I have a dream&file=php://filter/convert.base64-encode/resource=next.php
得到next.php源代码以后。
<?php $id = $_GET['id']; $_SESSION['id'] = $id; function complex($re, $str) { return preg_replace( '/(' . $re . ')/ei', 'strtolower("//1")', $str ); } foreach($_GET as $re => $str) { print("$re /n $str/n"); echo complex($re, $str). "/n"; } function getFlag(){ @eval($_GET['cmd']); }
这里的/1是反向引用
反向引用
反向引用是匹配正则表达式或者其他模式里面,()里面的被缓存存起来,用/加上数字来访问。
https://blog.csdn.net/Xxy605/article/details/117425141#:~:text=%E5%8F%8D%E5%90%91%E5%BC%95%E7%94%A8%EF%BC%8C%E5%B0%B1%E6%98%AF%E4%BE%9D,12n%E7%9A%84%E5%BD%A2%E5%BC%8F%E5%87%BA%E7%8E%B0
preg_replace()方法用/e修饰第一个参数就会导致第二个参数变成代码进行执行。
这个题目中允许用户控制的变量是 $re 和 $string
其实实质上是能控制三个。
①
然后是为什么要用.*,在正则表达式中.*表示能够匹配所有的表达式。而结合前面的反向引用,就可以使得在执行的时候preg_replace()能够把第二个参数里面的内容变成第三个参数。(因为第三个参数的内容被正则表达式.*匹配
到了就进入到了缓存里面这样用/1就可以读取到内容);
②
加{}的原因。
因为对于php只有双引号能够解析变量,而单引号不行,比如说
$a = 1; echo "$a";打印的是: 1 而不是$a
所以加上{}是用来解析变量的
这里的'strtolower("{${phpinfo()}}")'执行后相当于 strtolower("{}") 又相当于 strtolower("{null}") 又相当于 '' 空字符串,意味着就不会用任何字符串进行替换。(虽然这个题目用不到,但是这是个知识点)
原创文章,作者:,如若转载,请注明出处:https://blog.ytso.com/273098.html