可能会导致变量覆盖漏洞的函数有parse_str(),extract(),import_request_variables()以及$$。
1.parse_str()导致的漏洞
<!--
parse_str($a = $_GET['flag']);
if ($bdctf == "BCDEF") {
echo $flag;
}
-->
源码分析:a获得一个get值$flag ,如果$bdctf == "BCDEF"输出flag。
思路:由代码知,如果想要得到flag必须先输入一个flag。看到 parse_str()想到变量覆盖,构造payloa ?flag=&bdctf=BDCTF 得到flag
parse_str()定义和用法
parse_str() 函数把查询字符串解析到变量中。
注释:如果未设置 array 参数,则由该函数设置的变量将覆盖已存在的同名变量。
注释:php.ini 文件中的 magic_quotes_gpc 设置影响该函数的输出。如果已启用,那么在 parse_str() 解析之前,变量会被 addslashes() 转换。
语法
parse_str(string,array)
参数 | 描述 |
---|---|
string | 必需。规定要解析的字符串。 |
array | 可选。规定存储变量的数组的名称。该参数指示变量将被存储到数组中。 |
2.extract()漏洞
<?php
$flag='xxx';
extract($_GET);
if(isset($shiyan))
{
$content=trim(file_get_contents($flag));
if($shiyan==$content)
{
echo'flag{xxx}';
}
else
{
echo'Oh.no';
}
}
?>
源码分析: extract() 获得一个get值是shiyan。content从flag里获得一个去空的flag字符串。如果相等,输出flag。
思路:: 看到extract(),想到变量覆盖,构造payload ?shiyan=&flag= 得到flag
extract()定义和用法
extract() 函数从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
第二个参数 type 用于指定当某个变量已经存在,而数组中又有同名元素时,extract() 函数如何对待这样的冲突。
该函数返回成功导入到符号表中的变量数目。
语法
extract(array,extract_rules,prefix)
参数 | 描述 |
---|---|
array | 必需。规定要使用的数组。 |
extract_rules | 可选。extract() 函数将检查每个键名是否为合法的变量名,同时也检查和符号表中已存在的变量名是否冲突。对不合法和冲突的键名的处理将根据此参数决定。 |
prefix | 可选。请注意 prefix 仅在 extract_type 的值是 EXTR_PREFIX_SAME,EXTR_PREFIX_ALL,EXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS 时需要。如果附加了前缀后的结果不是合法的变量名,将不会导入到符号表中。 前缀和数组键名之间会自动加上一个下划线。 |
3.$$漏洞
1.<?php
2.include “flag.php”;
3.$_403 = “Access Denied”;
4.$_200 = “Welcome Admin”;
5.if ($_SERVER["REQUEST_METHOD"] != “POST”)
6. die(“BugsBunnyCTF is here :p…”);
7.if ( !isset($_POST["flag"]) )
8. die($_403);
9.foreach ($_GET as $key => $value)
10. $$key = $$value;
11.foreach ($_POST as $key => $value)
12. $$key = $value;
13.if ( $_POST["flag"] !== $flag )
14. die($_403);
15.echo “This is your flag : “. $flag . “\n”;
16.die($_200);
17.?>
源码分析:
1、 Include 调用了flag.php文件
2、$_200,$403 定义两个参数,以及参数值。
3、接着是两个判断语句,判断访问页面的方法是否为post方法和有没有参数flag。
4、再接着两个foreach函数遍历数组函数,这里就是把我们用get方法传输的数据当做数组进行遍历,并将遍历的参数赋值给key,将参数值复制给value。
5、还有一个if判断语句,判断用post方法传输的数据是不是和$flag的值相同,如果相同,输出flag。
6、最后输出$200的内容。
解题思路:
由于第7,11-14行间的代码会将$flag的值给覆盖掉,所以只能利用第一个foreach先将$flag的值赋给$_200,然后利用die($_200)将原本的flag值打印出来。
payload:
Get方法传输:?_200=flag
Post方法传输:flag=abcde