[BJDCTF2020]Mark loves cat |变量覆盖(三解)

简介: [BJDCTF2020]Mark loves cat |变量覆盖(三解)

信息收集

代码泄露

200     /.git/HEAD

200     /.git/index

200     /.git/config

200     /.git/description

200     /flag.php

python githack.py url:81/.git/

buu这边环境有点问题,我们直接拿wp里面的源码进行审计

  • flag.php
1. <?php
2. $flag = file_get_contents('/flag');
3. ?>
  • index.php
1. <?php
2. include 'flag.php';
3. $yds = "dog";
4. $is = "cat";
5. $handsome = 'yds';
6. 
7. foreach($_POST as $x => $y){
8. $$x = $y;
9. }
10. 
11. foreach($_GET as $x => $y){
12. $$x = $$y;
13. }
14. 
15. foreach($_GET as $x => $y){
16. if($_GET['flag'] === $x && $x !== 'flag'){
17. exit($handsome);
18.     }
19. }
20. 
21. if(!isset($_GET['flag']) && !isset($_POST['flag'])){
22. exit($yds);
23. }
24. 
25. if($_POST['flag'] === 'flag'  || $_GET['flag'] === 'flag'){
26. exit($is);
27. }
28. 
29. echo "the flag is: ".$flag;
30. ?>

$$ 导致的变量覆盖问题在CTF代码审计题目中经常在foreach中出现,如以下的示例代码,使用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。因此就产生了变量覆盖漏洞。请求?name=test 会将$name的值覆盖,变为test。

代码审计

定义了三个变量并对三个变量进行了输出,但是我们想要的是输出flag的值,这里就想到了变量覆盖的问题,源代码中存在多个变量输出的地方,应该是都可以覆盖成flag进行输出

payload1

?handsome=flag&flag=handsome

payload2

?yds=flag

payload3

is=flag&flag=flag

补充

全局变量覆盖

register_globals的意思是注册为全局变量,所以当为On的时候,传递过来的值会被直接注册为全局变量直接使用,而Off的时候,我们需要到特定的数组里去得到它

1. <?php
2. $id=0;
3. echo "Register_globals: ".(int)ini_get("register_globals")."<br/>";   
4. //ini_get — 获取一个配置选项的值
5. echo '$_GET["id"] :'.$_GET['id']."<br/>";
6. echo '$id :'.$id;
7. ?>

?id=4

Register_globals: 0

$_GET["id"] :4

$id :0

当register_globals=Off的时候,程序接收的时候应该用$_GET['id']来接受传递过来的值;

当register_globals=On的时候,程序可以直接使用$id来接受值,也可以用$_GET['id']来接受传递过来的值。

通过这种方式就可以向程序注册一个之前没有声明的变量,不过如果之前变量已经存在就无法覆盖掉,原已有变量值不变。

如,上面的代码中,已经对变量$id赋了初始值,比如$id=0,那么即使在URL中有/test.php?id=1,也不会将变量覆盖,id值为0

extract()变量覆盖

extract() 函数从数组中将变量导入到当前的符号表。

该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。

1. <?php
2. $a = "Original";
3. $my_array = array("a" => "Cat","b" => "Dog", "c" => "Horse");
4. extract($my_array);
5. echo "\$a = $a; \$b = $b; \$c = $c";
6. ?>
7. //运行结果:$a = Cat; $b = Dog; $c = Horse(Cat将Original覆盖了)

?auth=1

1. <?php
2. $auth = '0';  
3. // 这里可以覆盖$auth的变量值
4. extract($_GET);   
5. if($auth == 1){  
6. echo "private!";  
7.     } else{  
8. echo "public!";  
9.     }  
10. ?>
11. // 构造payload:?auth=1即可

parse_str()变量覆盖

1. // 把查询字符串解析到变量中:
2. <?php
3. parse_str("name=Peter&age=43");
4. echo $name."<br>";
5. echo $age;
6. ?>

Peter

43

目录
相关文章
|
3月前
|
PHP 开发工具 git
BUU [BJDCTF2020]Mark loves cat
BUU [BJDCTF2020]Mark loves cat
40 0
|
6月前
|
编译器
lesson2(补充)关于const成员函数
lesson2(补充)关于const成员函数
43 0
|
移动开发 Python
“ \r “导致print打印被覆盖
“ \r “导致print打印被覆盖
109 0
|
SQL 数据库
织梦DEDECMS添加新变量和删除新变量的方法详解
在用织梦建站时,有时候想调用自定义的某些信息,而织梦后台没有调用这些信息的地方,例如站长邮箱、站长QQ等,这时我们就可以用织梦后台添加新变量的方法调用自定义信息。本文主要讲解一下织梦添加新变量和删除新变量的方法。
|
容器
解析Obj-C中的assgin,copy,retain关键字的含义。
解析Obj-C中的assgin,copy,retain关键字的含义。
94 0
【WRF如何在输出的wrfoutput文件中设置添加/删除变量】
【WRF如何在输出的wrfoutput文件中设置添加/删除变量】
为什么要优先使用copy声明NSString属性?
至于为什么要优先使用copy声明NSString属性?首先科普一下:对象在内存中都有一个入口地址,当我们取到这个对象的地址(也就是指针),可以去改变这个对象的一些属性值,而当我们再次去取这个对象,使用这个对象的属性值(我们已修改过的)时,我们会发现这个值确实变成了我们修改的值,当然,前提是需要这个对象没有被销毁,在内存中还存在。选择使用copy的理由是:NSString属性可能被传入一个NSString实例,也可能是一个NSMutableString实例。当传入了一个NSMutableString实例时,字符串的值可能会在背后悄悄变化。
重构——15移除中间人(Remove Middle Man)
移除中间人(Remove Middle Man):某个类做了过多的简单委托动作;让客户直接调用受托类
1354 0