关于CVE-2024-9047的分析

1 漏洞成因

  本文的分析基于 wp-file-upload.4.24.11。在wfu_file_downloader.php中存在可控变量$filepath,能够读取文件。漏洞代码如下所示:


if ( $fd = wfu_fopen_for_downloader($filepath, "rb") ) {$open_session = ( ( $wfu_user_state_handler == "session" || $wfu_user_state_handler == "" ) && ( function_exists("session_status") ? ( PHP_SESSION_ACTIVE !== session_status() ) : ( empty(session_id()) ) ) );if ( $open_session ) session_start();header('Content-Type: application/octet-stream');header("Content-Disposition: attachment; filename=\"".$disposition_name."\"");header('Content-Transfer-Encoding: binary');header('Connection: Keep-Alive');header('Expires: 0');header('Cache-Control: must-revalidate, post-check=0, pre-check=0');header('Pragma: public');header("Content-length: $fsize");$failed = false;// 读取文件内容while( !feof($fd) ) {$buffer = @fread($fd, 1024*8);echo $buffer;ob_flush();flush();if ( connection_status() != 0 ) {$failed = true;break;}}fclose ($fd);
}
// 省略部分代码/*** wfu_fopen_for_downloader* 当$filepath前7个字符不为"sftp://"时,打开文件*/
function wfu_fopen_for_downloader($filepath, $mode) {if ( substr($filepath, 0, 7) != "sftp://" ) return @fopen($filepath, $mode);// 省略
}

  下文所描述的代码行号均为4.24.11版本中 wfu_file_downloader.php的行号。为方便浏览,下方已将此版本源码折叠。

wfu_file_downloader.php源码
 <?php
if ( !defined("ABSWPFILEUPLOAD_DIR") ) DEFINE("ABSWPFILEUPLOAD_DIR", dirname(__FILE__).'/');
if ( !defined("WFU_AUTOLOADER_PHP50600") ) DEFINE("WFU_AUTOLOADER_PHP50600", 'vendor/modules/php5.6/autoload.php');
include_once( ABSWPFILEUPLOAD_DIR.'lib/wfu_functions.php' );
include_once( ABSWPFILEUPLOAD_DIR.'lib/wfu_security.php' );
$handler = (isset($_POST['handler']) ? $_POST['handler'] : (isset($_GET['handler']) ? $_GET['handler'] : '-1'));
$session_legacy = (isset($_POST['session_legacy']) ? $_POST['session_legacy'] : (isset($_GET['session_legacy']) ? $_GET['session_legacy'] : ''));
$dboption_base = (isset($_POST['dboption_base']) ? $_POST['dboption_base'] : (isset($_GET['dboption_base']) ? $_GET['dboption_base'] : '-1'));
$dboption_useold = (isset($_POST['dboption_useold']) ? $_POST['dboption_useold'] : (isset($_GET['dboption_useold']) ? $_GET['dboption_useold'] : ''));
$wfu_cookie = (isset($_POST['wfu_cookie']) ? $_POST['wfu_cookie'] : (isset($_GET['wfu_cookie']) ? $_GET['wfu_cookie'] : ''));
if ( $handler == '-1' || $session_legacy == '' || $dboption_base == '-1' || $dboption_useold == '' || $wfu_cookie == '' ) die();
else {$GLOBALS["wfu_user_state_handler"] = wfu_sanitize_code($handler);$GLOBALS["WFU_GLOBALS"]["WFU_US_SESSION_LEGACY"] = array( "", "", "", ( $session_legacy == '1' ? 'true' : 'false' ), "", true );$GLOBALS["WFU_GLOBALS"]["WFU_US_DBOPTION_BASE"] = array( "", "", "", wfu_sanitize_code($dboption_base), "", true );$GLOBALS["WFU_GLOBALS"]["WFU_US_DBOPTION_USEOLD"] = array( "", "", "", ( $dboption_useold == '1' ? 'true' : 'false' ), "", true );if ( !defined("WPFILEUPLOAD_COOKIE") ) DEFINE("WPFILEUPLOAD_COOKIE", wfu_sanitize_tag($wfu_cookie));wfu_download_file();
}function wfu_download_file() {global $wfu_user_state_handler;$file_code = (isset($_POST['file']) ? $_POST['file'] : (isset($_GET['file']) ? $_GET['file'] : ''));$ticket = (isset($_POST['ticket']) ? $_POST['ticket'] : (isset($_GET['ticket']) ? $_GET['ticket'] : ''));if ( $file_code == '' || $ticket == '' ) die();wfu_initialize_user_state();$ticket = wfu_sanitize_code($ticket);	$file_code = wfu_sanitize_code($file_code);//if download ticket does not exist or is expired dieif ( !WFU_USVAR_exists_downloader('wfu_download_ticket_'.$ticket) || time() > WFU_USVAR_downloader('wfu_download_ticket_'.$ticket) ) {WFU_USVAR_unset_downloader('wfu_download_ticket_'.$ticket);WFU_USVAR_unset_downloader('wfu_storage_'.$file_code);wfu_update_download_status($ticket, 'failed');die();}//destroy ticket so it cannot be used againWFU_USVAR_unset_downloader('wfu_download_ticket_'.$ticket);//if file_code starts with exportdata, then this is a request for export of//uploaded file data, so disposition_name wont be the filename of the file//but wfu_export.csv; also set flag to delete file after download operationif ( substr($file_code, 0, 10) == "exportdata" ) {$file_code = substr($file_code, 10);//$filepath = wfu_get_filepath_from_safe($file_code);$filepath = WFU_USVAR_downloader('wfu_storage_'.$file_code);$disposition_name = "wfu_export.csv";$delete_file = true;}//if file_code starts with debuglog, then this is a request for download of//debug_log.txtelseif ( substr($file_code, 0, 8) == "debuglog" ) {$file_code = substr($file_code, 8);//$filepath = wfu_get_filepath_from_safe($file_code);$filepath = WFU_USVAR_downloader('wfu_storage_'.$file_code);$disposition_name = wfu_basename($filepath);$delete_file = false;}else {//$filepath = wfu_get_filepath_from_safe($file_code);$filepath = WFU_USVAR_downloader('wfu_storage_'.$file_code);if ( $filepath === false ) {WFU_USVAR_unset_downloader('wfu_storage_'.$file_code);wfu_update_download_status($ticket, 'failed');die();}$filepath = wfu_flatten_path($filepath);if ( substr($filepath, 0, 1) == "/" ) $filepath = substr($filepath, 1);$filepath = ( substr($filepath, 0, 6) == 'ftp://' || substr($filepath, 0, 7) == 'ftps://' || substr($filepath, 0, 7) == 'sftp://' ? $filepath : WFU_USVAR_downloader('wfu_ABSPATH').$filepath );$disposition_name = wfu_basename($filepath);$delete_file = false;}//destroy file code as it is no longer neededWFU_USVAR_unset_downloader('wfu_storage_'.$file_code);//check that file existsif ( !wfu_file_exists_for_downloader($filepath) ) {wfu_update_download_status($ticket, 'failed');die('<script language="javascript">alert("'.( WFU_USVAR_exists_downloader('wfu_browser_downloadfile_notexist') ? WFU_USVAR_downloader('wfu_browser_downloadfile_notexist') : 'File does not exist!' ).'");</script>');}$open_session = false;@set_time_limit(0); // disable the time limit for this script$fsize = wfu_filesize_for_downloader($filepath);if ( $fd = wfu_fopen_for_downloader($filepath, "rb") ) {$open_session = ( ( $wfu_user_state_handler == "session" || $wfu_user_state_handler == "" ) && ( function_exists("session_status") ? ( PHP_SESSION_ACTIVE !== session_status() ) : ( empty(session_id()) ) ) );if ( $open_session ) session_start();header('Content-Type: application/octet-stream');header("Content-Disposition: attachment; filename=\"".$disposition_name."\"");header('Content-Transfer-Encoding: binary');header('Connection: Keep-Alive');header('Expires: 0');header('Cache-Control: must-revalidate, post-check=0, pre-check=0');header('Pragma: public');header("Content-length: $fsize");$failed = false;while( !feof($fd) ) {$buffer = @fread($fd, 1024*8);echo $buffer;ob_flush();flush();if ( connection_status() != 0 ) {$failed = true;break;}}fclose ($fd);}else $failed = true;if ( $delete_file ) wfu_unlink_for_downloader($filepath);if ( !$failed ) {wfu_update_download_status($ticket, 'downloaded');if ( $open_session ) session_write_close();die();}else {wfu_update_download_status($ticket, 'failed');if ( $open_session ) session_write_close();die('<script type="text/javascript">alert("'.( WFU_USVAR_exists_downloader('wfu_browser_downloadfile_failed') ? WFU_USVAR_downloader('wfu_browser_downloadfile_failed') : 'Could not download file!' ).'");</script>');}
}function wfu_update_download_status($ticket, $new_status) {require_once WFU_USVAR_downloader('wfu_ABSPATH').'wp-load.php';WFU_USVAR_store('wfu_download_status_'.$ticket, $new_status);
}function WFU_USVAR_exists_downloader($var) {global $wfu_user_state_handler;if ( $wfu_user_state_handler == "dboption" && WFU_VAR("WFU_US_DBOPTION_BASE") == "cookies" ) return isset($_COOKIE[$var]);else return WFU_USVAR_exists_session($var);
}function WFU_USVAR_downloader($var) {global $wfu_user_state_handler;if ( $wfu_user_state_handler == "dboption" && WFU_VAR("WFU_US_DBOPTION_BASE") == "cookies" ) return $_COOKIE[$var];else return WFU_USVAR_session($var);
}function WFU_USVAR_unset_downloader($var) {global $wfu_user_state_handler;if ( $wfu_user_state_handler == "session" || $wfu_user_state_handler == "" ) WFU_USVAR_unset_session($var);
}function wfu_file_exists_for_downloader($filepath) {if ( substr($filepath, 0, 7) != "sftp://" ) return file_exists($filepath);$ret = false;$ftpinfo = wfu_decode_ftpurl($filepath);if ( $ftpinfo["error"] ) return $ret;$data = $ftpinfo["data"];{$conn = @ssh2_connect($data["ftpdomain"], $data["port"]);if ( $conn && @ssh2_auth_password($conn, $data["username"], $data["password"]) ) {$sftp = @ssh2_sftp($conn);$ret = ( $sftp && @file_exists("ssh2.sftp://".intval($sftp).$data["filepath"]) );}}return $ret;
}function wfu_filesize_for_downloader($filepath) {if ( substr($filepath, 0, 7) != "sftp://" ) return filesize($filepath);$ret = false;$ftpinfo = wfu_decode_ftpurl($filepath);if ( $ftpinfo["error"] ) return $ret;$data = $ftpinfo["data"];{$conn = @ssh2_connect($data["ftpdomain"], $data["port"]);if ( $conn && @ssh2_auth_password($conn, $data["username"], $data["password"]) ) {$sftp = @ssh2_sftp($conn);if ( $sftp ) $ret = @filesize("ssh2.sftp://".intval($sftp).$data["filepath"]);}}return $ret;
}function wfu_fopen_for_downloader($filepath, $mode) {if ( substr($filepath, 0, 7) != "sftp://" ) return @fopen($filepath, $mode);$ret = false;$ftpinfo = wfu_decode_ftpurl($filepath);if ( $ftpinfo["error"] ) return $ret;$data = $ftpinfo["data"];{$conn = @ssh2_connect($data["ftpdomain"], $data["port"]);if ( $conn && @ssh2_auth_password($conn, $data["username"], $data["password"]) ) {$sftp = @ssh2_sftp($conn);if ( $sftp ) {//$ret = @fopen("ssh2.sftp://".intval($sftp).$data["filepath"], $mode);$contents = @file_get_contents("ssh2.sftp://".intval($sftp).$data["filepath"]);$stream = fopen('php://memory', 'r+');fwrite($stream, $contents);rewind($stream);$ret = $stream;}}}return $ret;
}function wfu_unlink_for_downloader($filepath) {if ( substr($filepath, 0, 7) != "sftp://" ) return @unlink($filepath);$ret = false;$ftpinfo = wfu_decode_ftpurl($filepath);if ( $ftpinfo["error"] ) return $ret;$data = $ftpinfo["data"];{$conn = @ssh2_connect($data["ftpdomain"], $data["port"]);if ( $conn && @ssh2_auth_password($conn, $data["username"], $data["password"]) ) {$sftp = @ssh2_sftp($conn);if ( $sftp ) $ret = @unlink("ssh2.sftp://".intval($sftp).$data["filepath"]);}}return $ret;
}

2 代码逻辑

2.1 分析思路

  本节描述漏洞的分析思路,从漏洞点开始,直至分析参数部分。

2.1.1 Part 1

  在漏洞点位置,文件路径变量 $filepath 首先会在第 77-80 行被检查。

if ( !wfu_file_exists_for_downloader($filepath) ) {wfu_update_download_status($ticket, 'failed');die('<script language="javascript">alert("'.( WFU_USVAR_exists_downloader('wfu_browser_downloadfile_notexist') ? WFU_USVAR_downloader('wfu_browser_downloadfile_notexist') : 'File does not exist!' ).'");</script>');
}

   由于存在 die(),因此 if 的判断条件必须为 false。查看 wfu_file_exists_for_downloader():

function wfu_file_exists_for_downloader($filepath) {if ( substr($filepath, 0, 7) != "sftp://" ) return file_exists($filepath);// 省略
}

  由代码可知,此处仅为检查 $filepath 是否存在。无需过多注意。继续推理逻辑。

2.1.2 Part 2

  在第44-73行有一个 if 判断。代码如下所示:

if ( substr($file_code, 0, 10) == "exportdata" ) {$file_code = substr($file_code, 10);//$filepath = wfu_get_filepath_from_safe($file_code);$filepath = WFU_USVAR_downloader('wfu_storage_'.$file_code);$disposition_name = "wfu_export.csv";$delete_file = true;
}
//if file_code starts with debuglog, then this is a request for download of
//debug_log.txt
elseif ( substr($file_code, 0, 8) == "debuglog" ) {$file_code = substr($file_code, 8);//$filepath = wfu_get_filepath_from_safe($file_code);$filepath = WFU_USVAR_downloader('wfu_storage_'.$file_code);$disposition_name = wfu_basename($filepath);$delete_file = false;
}
else {//$filepath = wfu_get_filepath_from_safe($file_code);$filepath = WFU_USVAR_downloader('wfu_storage_'.$file_code);if ( $filepath === false ) {WFU_USVAR_unset_downloader('wfu_storage_'.$file_code);wfu_update_download_status($ticket, 'failed');die();}$filepath = wfu_flatten_path($filepath);if ( substr($filepath, 0, 1) == "/" ) $filepath = substr($filepath, 1);$filepath = ( substr($filepath, 0, 6) == 'ftp://' || substr($filepath, 0, 7) == 'ftps://' || substr($filepath, 0, 7) == 'sftp://' ? $filepath : WFU_USVAR_downloader('wfu_ABSPATH').$filepath );$disposition_name = wfu_basename($filepath);$delete_file = false;
}

  该处 if 语句用于判断 $file_code的前几个字符是否为"exportdata"或者"debuglog",但是我们不想让可操控的文件路径受限,因此重点关注最后的 else 。

  首先,关注$filepath = WFU_USVAR_downloader('wfu_storage_'.$file_code);。查看WFU_USVAR_downloader()的代码:

function WFU_USVAR_downloader($var) {global $wfu_user_state_handler;if ( $wfu_user_state_handler == "dboption" && WFU_VAR("WFU_US_DBOPTION_BASE") == "cookies" ) return $_COOKIE[$var];else return WFU_USVAR_session($var);
}
  WFU_USVAR_downloader()判断全局变量 $wfu_user_state_handler 是否为 "dboption",并且 WFU_VAR("WFU_US_DBOPTION_BASE") 是否为 "cookies"。如果都为 true,则返回 cookie中的 $var的值。此处即返回 cookie中 'wfu_storage_'.$file_code的值。如果能够使 if 条件为真,再加上cookie可控,那么WFU_USVAR_downloader()的返回值也可控。下面详细分析 if 判断条件。
  • $wfu_user_state_handler == "dboption"
  首先,查看前面的判断内容。查找全局变量 $wfu_user_state_handler,发现其在第18行被定义:
$GLOBALS["wfu_user_state_handler"] = wfu_sanitize_code($handler);
wfu_sanitize_code的作用是删除所传参数中的非字母数字。继续查找 $handler,在第6行发现,且$handler可控:
$handler = (isset($_POST['handler']) ? $_POST['handler'] : (isset($_GET['handler']) ? $_GET['handler'] : '-1'));

  因此,$handler 可控 ==> $wfu_user_state_handler 可控 ==> $wfu_user_state_handler == "dboption" 为true。

  • WFU_VAR("WFU_US_DBOPTION_BASE") == "cookies"
  再来看后面的判断内容。WFU_VAR()代码如下:
function WFU_VAR($varname) {if ( !isset($GLOBALS["WFU_GLOBALS"][$varname]) ) return false;if ( $GLOBALS["WFU_GLOBALS"][$varname][5] ) return $GLOBALS["WFU_GLOBALS"][$varname][3];//in case the environment variable is hidden then return the default valueelse return $GLOBALS["WFU_GLOBALS"][$varname][2];
}

  WFU_VAR() 在此处的作用是:在 $GLOBALS["WFU_GLOBALS"]["WFU_US_DBOPTION_BASE"] 存在时,返回$GLOBALS["WFU_GLOBALS"]["WFU_US_DBOPTION_BASE"][3],否则返回$GLOBALS["WFU_GLOBALS"]["WFU_US_DBOPTION_BASE"][5]。追踪 "WFU_GLOBALS" 和 "WFU_US_DBOPTION_BASE",在第15行发现相关代码:

$GLOBALS["WFU_GLOBALS"]["WFU_US_DBOPTION_BASE"] = array( "", "", "", wfu_sanitize_code($dboption_base), "", true );

  继续追踪 $dboption_base,发现该变量在第8行被赋值且完全可控:

$dboption_base = (isset($_POST['dboption_base']) ? $_POST['dboption_base'] : (isset($_GET['dboption_base']) ? $_GET['dboption_base'] : '-1'));
  
  因此,$dboption_base 可控 ==> $GLOBALS["WFU_GLOBALS"]["WFU_US_DBOPTION_BASE"][3] 可控 ==> WFU_VAR("WFU_US_DBOPTION_BASE") == "cookies" 为true。
  根据以上分析可知,$wfu_user_state_handler == "dboption" && WFU_VAR("WFU_US_DBOPTION_BASE") == "cookies"可以为true,并且$_COOKIE[$var]可控。
  再来看第70行代码:
$filepath = ( substr($filepath, 0, 6) == 'ftp://' || substr($filepath, 0, 7) == 'ftps://' || substr($filepath, 0, 7) == 'sftp://' ? $filepath : WFU_USVAR_downloader('wfu_ABSPATH').$filepath );
  此处代码从cookie中获取 "wfu_ABSPATH"的值,并与 $filepath 拼接。
  $filepath 的值与 $file_code 有关,因此下面分析 $file_code。
 

2.1.3 Part 3

   $file_code相关代码如下所示:

global $wfu_user_state_handler;
$file_code = (isset($_POST['file']) ? $_POST['file'] : (isset($_GET['file']) ? $_GET['file'] : ''));
$ticket = (isset($_POST['ticket']) ? $_POST['ticket'] : (isset($_GET['ticket']) ? $_GET['ticket'] : ''));
if ( $file_code == '' || $ticket == '' ) die();wfu_initialize_user_state();$ticket = wfu_sanitize_code($ticket);	
$file_code = wfu_sanitize_code($file_code);
//if download ticket does not exist or is expired die
if ( !WFU_USVAR_exists_downloader('wfu_download_ticket_'.$ticket) || time() > WFU_USVAR_downloader('wfu_download_ticket_'.$ticket) ) {WFU_USVAR_unset_downloader('wfu_download_ticket_'.$ticket);WFU_USVAR_unset_downloader('wfu_storage_'.$file_code);wfu_update_download_status($ticket, 'failed');die();
}
  根据以上代码可知,$file_code 和 $ticket 可由 GET 或者 POST 方法赋值。
  wfu_initialize_user_state(),与cookie和session相关,具体分析放到 Part 4。
  WFU_USVAR_exists_downloader($var)的作用就是检查 cookie 中是否存在 $var 。
function WFU_USVAR_exists_downloader($var) {global $wfu_user_state_handler;if ( $wfu_user_state_handler == "dboption" && WFU_VAR("WFU_US_DBOPTION_BASE") == "cookies" ) return isset($_COOKIE[$var]);else return WFU_USVAR_exists_session($var);
}
  为了避免进入程序被 die(),cookie 中必须存在 'wfu_download_ticket_'.$ticket,且值必须大于当前的时间戳。

2.1.4 Part 4

  由于测试漏洞时,这里出现了一些bug,所以单开一个part分析wfu_initialize_user_state(),该函数的代码如下:

function wfu_initialize_user_state() {$a = func_get_args(); $a = WFU_FUNCTION_HOOK(__FUNCTION__, $a, $out); if (isset($out['vars'])) foreach($out['vars'] as $p => $v) $$p = $v; switch($a) { case 'R': return $out['output']; break; case 'D': die($out['output']); }global $wfu_user_state_handler;if ( $wfu_user_state_handler == "dboption" && WFU_VAR("WFU_US_DBOPTION_BASE") == "cookies" ) {if ( wfu_get_session_cookie() == "" ) wfu_set_session_cookie();}elseif ( WFU_VAR("WFU_US_SESSION_LEGACY") == "true" && !headers_sent() && ( function_exists("session_status") ? ( PHP_SESSION_ACTIVE !== session_status() ) : ( session_id() == "" ) ) ) { session_start(); }
}
  • Bug 由来

  要想触发漏洞, $wfu_user_state_handler == "dboption" && WFU_VAR("WFU_US_DBOPTION_BASE") == "cookies"一定成立,因此一定会触发判断:if ( wfu_get_session_cookie() == "" ) wfu_set_session_cookie();。这里再来看一下 wfu_get_session_cookie():

function wfu_get_session_cookie() {return isset($_COOKIE[WPFILEUPLOAD_COOKIE]) ? wfu_sanitize_code(substr($_COOKIE[WPFILEUPLOAD_COOKIE], 0, 32)) : "";
}

  wfu_get_session_cookie()会首先判断cookie中是否存在WPFILEUPLOAD_COOKIE,如果存在就取前32个字符,否则为空。

  一开始,我没有设置WPFILEUPLOAD_COOKIE,因为我以为就算为空, wfu_set_session_cookie() 会初始化有关内容,所以没有继续分析,结果在测试漏洞时报错了:

  只能分析报错的代码:

function wfu_set_session_cookie() {$a = func_get_args(); $a = WFU_FUNCTION_HOOK(__FUNCTION__, $a, $out); if (isset($out['vars'])) foreach($out['vars'] as $p => $v) $$p = $v; switch($a) { case 'R': return $out['output']; break; case 'D': die($out['output']); }if ( !headers_sent() ) {$cookie = wfu_create_random_string(32);setcookie(WPFILEUPLOAD_COOKIE,$cookie,time() + intval(WFU_VAR("WFU_US_COOKIE_LIFE")) * 3600,COOKIEPATH ? COOKIEPATH : '/',COOKIE_DOMAIN,false,false);$_COOKIE[WPFILEUPLOAD_COOKIE] = $cookie;}
}

  根据报错,COOKIEPATH未定义,而我也没找到COOKIEPATH到底在哪里定义的,所以只能尝试其他方法。

  • 另辟蹊径

  我的主要目的的分析漏洞,又不是写插件。既然wfu_set_session_cookie会触发漏洞,那么就尽可能不让它执行。所以,必须要使 wfu_get_session_cookie != "",而要使wfu_get_session_cookie != "",cookie中必须存在WPFILEUPLOAD_COOKIE。

  追踪 WPFILEUPLOAD_COOKIE,发现在 wfu_file_downloader.php 的第17行被定义:

if ( !defined("WPFILEUPLOAD_COOKIE") ) DEFINE("WPFILEUPLOAD_COOKIE", wfu_sanitize_tag($wfu_cookie));

  $wfu_cookie则在第10行:

$wfu_cookie = (isset($_POST['wfu_cookie']) ? $_POST['wfu_cookie'] : (isset($_GET['wfu_cookie']) ? $_GET['wfu_cookie'] : ''));

  因此,完全可以控制WPFILEUPLOAD_COOKIE,避免触发 wfu_set_session_cookie()

2.1.5 Part 5

   漏洞点的位置在wfu_download_file()中,因此分析wfu_download_file()的调用。代码如下所示:

<?php
if ( !defined("ABSWPFILEUPLOAD_DIR") ) DEFINE("ABSWPFILEUPLOAD_DIR", dirname(__FILE__).'/');
if ( !defined("WFU_AUTOLOADER_PHP50600") ) DEFINE("WFU_AUTOLOADER_PHP50600", 'vendor/modules/php5.6/autoload.php');
include_once( ABSWPFILEUPLOAD_DIR.'lib/wfu_functions.php' );
include_once( ABSWPFILEUPLOAD_DIR.'lib/wfu_security.php' );
$handler = (isset($_POST['handler']) ? $_POST['handler'] : (isset($_GET['handler']) ? $_GET['handler'] : '-1'));
$session_legacy = (isset($_POST['session_legacy']) ? $_POST['session_legacy'] : (isset($_GET['session_legacy']) ? $_GET['session_legacy'] : ''));
$dboption_base = (isset($_POST['dboption_base']) ? $_POST['dboption_base'] : (isset($_GET['dboption_base']) ? $_GET['dboption_base'] : '-1'));
$dboption_useold = (isset($_POST['dboption_useold']) ? $_POST['dboption_useold'] : (isset($_GET['dboption_useold']) ? $_GET['dboption_useold'] : ''));
$wfu_cookie = (isset($_POST['wfu_cookie']) ? $_POST['wfu_cookie'] : (isset($_GET['wfu_cookie']) ? $_GET['wfu_cookie'] : ''));
if ( $handler == '-1' || $session_legacy == '' || $dboption_base == '-1' || $dboption_useold == '' || $wfu_cookie == '' ) die();
else {$GLOBALS["wfu_user_state_handler"] = wfu_sanitize_code($handler);$GLOBALS["WFU_GLOBALS"]["WFU_US_SESSION_LEGACY"] = array( "", "", "", ( $session_legacy == '1' ? 'true' : 'false' ), "", true );$GLOBALS["WFU_GLOBALS"]["WFU_US_DBOPTION_BASE"] = array( "", "", "", wfu_sanitize_code($dboption_base), "", true );$GLOBALS["WFU_GLOBALS"]["WFU_US_DBOPTION_USEOLD"] = array( "", "", "", ( $dboption_useold == '1' ? 'true' : 'false' ), "", true );if ( !defined("WPFILEUPLOAD_COOKIE") ) DEFINE("WPFILEUPLOAD_COOKIE", wfu_sanitize_tag($wfu_cookie));wfu_download_file();
}

  $handler、$session_legacy、$dboption_base、$dboption_useold、$wfu_cookie均可通过GET或者POST传参。只要注意别被 die() 就行。

2.1.6 Part 6

  总结:

  • GET/POST 传递
    • handler = "dboption",固定值
    • session_legacy = 1,随意
    • dboption_base = "cookie",固定值
    • dboption_useold = 1,随意
    • wfu_cookie = abccc,与Cookie对应
    • file=abc123,与Cookie对应
    • ticket=bcd234,与Cookie对应
  • Cookie 传递
    • wfu_download_ticket_bcd234=很大的时间戳
    • wfu_storage_abc123=文件名,可以路径穿越
    • wfu_ABSPATH=目录
    • abccc=qwe,abccc与GET/POST对应,值随意

2.1.7 Part 7

  测试结果如下图所示:

 

3. 总结

  可以通过GET/POST传参控制 $file_code,再控制 Cookie,从而给$filepath赋值,最后输出 $filepath 的内容。过程中需要满足一些条件以免die()或者bug

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/869220.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华尔街日报无需登录查看不可查看内容

使用第三方接口来为当前页面提供服务的脚本,简单编写,使用应用程序接口调用保存页面实现永久存储及达到阅读某街日报内容(接口无需加速)对于那些可能很快变化的网页,这个脚本会非常有用。本站保存的网页不包含脚本和动态对象,所以是安全的,不会有弹窗或其他恶意程序。 油…

学习进度笔记⑧

Spark SQL基本操作 将下列 JSON 格式数据复制到 Linux 系统中,并保存命名为 employee.json。 { "id":1 , "name":" Ella" , "age":36 } { "id":2, "name":"Bob","age":29 } { "id"…

基于大数据分析的智能交通灯管理系统

在智慧交通领域,交通灯管理系统是城市交通流控制的核心。随着大数据技术的发展,基于大数据分析的智能交通灯管理系统正逐渐成为改善城市交通状况、提升道路使用效率的关键技术。今天,我们将深入探讨这一系统的建设内容,共同展望智慧交通的未来。系统概述基于大数据分析的智…

Shell程序设计语言

Shell程序设计语言 一、认识Shell 1.1 编程语言的种类 # 机器语言:站在计算机(奴隶)的角度,说计算机能听懂的语言,那就是直接用二进制编程,直接操作硬件;优点:执行效率最高缺点:1、二进制指令难以记忆,开发时极容易出错2、开发程序的复杂度高:即便是完成一个简单的功能…

logstash输出到loki

运行logstash # logstash version: 3 services:logstash:image: docker.elastic.co/logstash/logstash:8.12.0container_name: logstash_serverrestart: alwaysports:- 8065:8065environment:- LS_JAVA_OPTS=-Xmx1024m -Xms1024mvolumes:- ./config/logstash.conf:/etc/logstas…

【Electron 应用安全测试基础】Electron 框架介绍

免责声明 ⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!一、引言 跨平台桌面应用开发的演进带来了一系列独特的挑战,主要体现在如何确保在 Windows、macOS 和基于 Linux…

07jdk7u21原生利用链

JDK7u21 反序列化的关键在于找到可以动态方法执行的代码:例如CC链中的Transformer,CB链中的PropertyUtils#getPropertyJDK7u21中动态方法执行的点,AnnotationInvocationHandler#equalsImpl中的hisValue = memberMethod.invoke(o)。 private Boolean equalsImpl(Object o) {i…

英语语法(介词和连词)

认识介词 例子: 例子: 识别介词 时间介词 at 精确的时间 by 不缺定的时间 for 持续的时间 in 固定的时间 on 某一天的时间 since 开始时间 until 直到 空间介词 at 指一个点 by 近的意思 from 从别处到这里 in 一个封闭的区域 off 离开 on 开启 out 方向 远离…

一文读懂如何创建食品加工和包装 SOP

在食品行业中,确保产品的安全性和质量是至关重要的。为了实现这一目标,建立一套详尽且高效的标准操作程序(SOP)对于食品加工与包装环节来说不可或缺。本文将引导您深入理解如何高效创建食品加工与包装SOP,并巧妙融入helplook工具,以提升流程管理的精确性和效率。一、明确…

高性能、零内存分配的Go日志库--Zerolog

简介 Zerolog 是一个高性能、零内存分配的 Go 日志库。 它为不需要垃圾回收的延迟敏感型应用程序提供结构化日志记录功能。 您可以以完全零分配的方式使用,这样在初始化记录器对象后,堆上不会再分配其他对象,从而防止触发垃圾回收。 Zerolog 包提供了一个专用于 JSON 输出的…

Jar Analyzer:JAR包分析工具

工具介绍 一个JAR包分析工具,批量分析,SCA漏洞分析,方法调用关系搜索,字符串搜索,Spring组件分析,信息泄露检查,CFG程序分析,JVM栈帧分析,进阶表达式搜索,字节码指令级的动态调试分析,反编译JAR包一键导出,一键提取序列化数据恶意代码,一键分析BCEL字节码。 Jar A…

第二十次作业

1、对bluecms进行代码审计,分析复现文件上传、ssti模板注入、文件删除等漏洞 文件上传:ssti模板注入: bluecms采⽤了smarty模板引擎可以在模板中插⼊恶意的代码,从⽽执⾏任意命令。此处可知smarty使⽤的界定符为{#和#},参考smarty官⽅⽂档可知,可以使⽤{#php#}code{#/php…