jmeter file upload 变量_通达OA上传漏洞之变量覆盖分析
作者:kw0ng
開(kāi)始
通達(dá)OA上傳到包含漏洞分析的文章已經(jīng)有很多,本文重點(diǎn)分析,文件上傳處決定路徑信息是否回顯的UPLOAD_MODE參數(shù)是怎么傳遞的。
代碼分析
觸發(fā)文件上傳點(diǎn)位于/ispirit/im/upload.php中,服務(wù)端在接收文件信息的同時(shí)還需要幾個(gè)參數(shù),如不了解 multipart/form-data類(lèi)型如何傳遞參數(shù)的可以先去學(xué)習(xí)下,通達(dá)OA的PHP代碼采用了Zend54加密,但是我使用兩個(gè)不同的工具解密卻得到了不一致的代碼,這也導(dǎo)致了這篇文章差點(diǎn)難產(chǎn)。首先是第一段代碼:
$P = $_POST['P'];if (isset($P) || $P != '') { ob_start(); include_once 'inc/session.php'; //如果P不為空 session_id($P); session_start(); session_write_close();} else { include_once './auth.php';}這段代碼需要一個(gè)POST傳參獲取P值,且為空時(shí)將會(huì)包含auth.php進(jìn)行重認(rèn)證,因?yàn)槲覀兊腜OST包需要一個(gè)P值且不為空。
$DEST_UID = $_POST['DEST_UID']; $dataBack = array();if ($DEST_UID != '' && !td_verify_ids($ids)) { $dataBack = array('status' => 0, 'content' => '-ERR ' . _('接收方ID無(wú)效')); echo json_encode(data2utf8($dataBack)); exit;}if (strpos($DEST_UID, ',') !== false) { } else { $DEST_UID = intval($DEST_UID); }if ($DEST_UID == 0) { if ($UPLOAD_MODE != 2) { $dataBack = array('status' => 0, 'content' => '-ERR ' . _('接收方ID無(wú)效')); echo json_encode(data2utf8($dataBack)); exit; }}這段代碼中我們需要提供DEST_UID參數(shù),且如果DEST_UID為0,則觸發(fā)判斷UPLOAD_MODE是否等于2,不等于2則報(bào)error并退出,因此將DEST_UID不等于0可繞過(guò)。
if (1 <= count($_FILES)) { //返回?cái)?shù)組中元素的數(shù)目: if ($UPLOAD_MODE == '1') { //如果UPLOAD_MODE = 1 if (strlen(urldecode($_FILES['ATTACHMENT']['name'])) != strlen($_FILES['ATTACHMENT']['name'])) { $_FILES['ATTACHMENT']['name'] = urldecode($_FILES['ATTACHMENT']['name']); } } $ATTACHMENTS = upload('ATTACHMENT', $MODULE, false); if (!is_array($ATTACHMENTS)) { $dataBack = array('status' => 0, 'content' => '-ERR ' . $ATTACHMENTS); echo json_encode(data2utf8($dataBack)); exit; } ob_end_clean(); $ATTACHMENT_ID = substr($ATTACHMENTS['ID'], 0, -1); $ATTACHMENT_NAME = substr($ATTACHMENTS['NAME'], 0, -1); if ($TYPE == 'mobile') { $ATTACHMENT_NAME = td_iconv(urldecode($ATTACHMENT_NAME), 'utf-8', MYOA_CHARSET); }} else { $dataBack = array('status' => 0, 'content' => '-ERR ' . _('無(wú)文件上傳')); echo json_encode(data2utf8($dataBack)); exit;}判斷1 <= count($FILES) 就是$FILES是否取到上傳數(shù)據(jù)。
判斷UPLOAD_MODE是否等于1,如果等于1且文件名url解碼后的長(zhǎng)度不等于原長(zhǎng)度則將文件名url解碼。
調(diào)用upload函數(shù)$ATTACHMENTS = upload('ATTACHMENT', $MODULE, false);傳入3個(gè)參數(shù),$MODULE = 'im';。
使用PHP的$FILES函數(shù)來(lái)獲取我們上傳的文件信息$FILES['ATTACHMENT']['name'] $_FILES的第一個(gè)下標(biāo)必須是我們的input name值,因此我們的POST包的Content-Disposition: form-data; name="ATTACHMENT"; filename="jpg"中的name必須是'ATTACHMENT'。
本段代碼說(shuō)明了UPLOAD_MODE等于2或3的時(shí)候會(huì)返回$CONTENT或$ATTACHMENT_ID變量的值(1也可以),且返回值與最終文件上傳所在的路徑、文件名是相關(guān)的。
綜上所述我們得到了3個(gè)信息
存在P值且不為空 ($_POST["P"]獲取)
DEST_UID不為0?($POST["DEST_UID"]獲取)
UPLOAD_MODE = 1或2或3?(非$POST["UPLOAD_MODE"]獲取)
Content-Disposition中name值為"ATTACHMENT"
流程圖:
變量覆蓋
由于在upload.php中未找到取UPLOAD_MODE值的方法,但在實(shí)際測(cè)試中POST的UPLOAD_MODE值可以被正常帶入且影響文件上傳走向,因此判斷接收UPLOAD_MODE值的方法存在于被包含的文件中,在解密后使用搜索工具也僅發(fā)現(xiàn)UPLOAD_MODE這個(gè)參數(shù)名僅存在于upload.php中,開(kāi)始追溯之旅最后在common.inc.php文件中發(fā)現(xiàn)了UPLOAD_MODE的源頭.
具體調(diào)用為upload.php -> session.php -> coon.php -> td_config.php -> common.inc.php
漏洞代碼為:
if (0 < count($_POST)) { $arr_html_fields = array(); foreach ($_POST as $s_key => $s_value) { if (substr($s_key, 0, 7) == '_SERVER') { continue; } if (substr($s_key, 0, 15) != 'TD_HTML_EDITOR_') { if (!is_array($s_value)) { $_POST[$s_key] = addslashes(strip_tags($s_value)); } ${$s_key} = $_POST[$s_key]; } else { if ($s_key == 'TD_HTML_EDITOR_FORM_HTML_DATA' || $s_key == 'TD_HTML_EDITOR_PRCS_IN' || $s_key == 'TD_HTML_EDITOR_PRCS_OUT' || $s_key == 'TD_HTML_EDITOR_QTPL_PRCS_SET' || isset($_POST['ACTION_TYPE']) && ($_POST['ACTION_TYPE'] == 'approve_center' || $_POST['ACTION_TYPE'] == 'workflow' || $_POST['ACTION_TYPE'] == 'sms' || $_POST['ACTION_TYPE'] == 'wiki') && ($s_key == 'CONTENT' || $s_key == 'TD_HTML_EDITOR_CONTENT' || $s_key == 'TD_HTML_EDITOR_TPT_CONTENT')) { unset($_POST[$s_key]); $s_key = $s_key == 'CONTENT' ? $s_key : substr($s_key, 15); ${$s_key} = addslashes($s_value); $arr_html_fields[$s_key] = ${$s_key}; } else { $encoding = mb_detect_encoding($s_value, 'GBK,UTF-8'); unset($_POST[$s_key]); $s_key = substr($s_key, 15); ${$s_key} = addslashes(rich_text_clean($s_value, $encoding)); $arr_html_fields[$s_key] = ${$s_key}; } } } reset($_POST); $_POST = array_merge($_POST, $arr_html_fields);}首先一開(kāi)始對(duì)$_POST長(zhǎng)度進(jìn)行了判斷,這里$_POST實(shí)際是一個(gè)數(shù)組,存儲(chǔ)了客戶端傳遞的參數(shù)與值,接著使用foreach函數(shù)對(duì)數(shù)組進(jìn)行遍歷,foreach函數(shù)也是CTF變量覆蓋漏洞經(jīng)常考察的知識(shí)點(diǎn),在這里我們假設(shè)$_POST數(shù)組中key為"UPLOAD_MODE",value為"2",那么我們將會(huì)最終進(jìn)入這段代碼中:
if (substr($s_key, 0, 15) != 'TD_HTML_EDITOR_') { if (!is_array($s_value)) { $_POST[$s_key] = addslashes(strip_tags($s_value)); } ${$s_key} = $_POST[$s_key];關(guān)鍵代碼:
${$s_key}=$_POST[$s_key];方便大家理解我使用IDE將這段代碼運(yùn)行下.
可以看到最終數(shù)組鍵名UPLOAD_MODE成了了變量名,而他的對(duì)應(yīng)鍵值成為了變量值.
這也就是upload.php未直接接收UPLOAD_MODE值,而我們?nèi)钥梢詡鬟f此參數(shù)影響函數(shù)走向的原因.
RCE
在明白了上傳流程后,我們還需要配合本次的包含漏洞來(lái)包含我們上傳的代碼實(shí)現(xiàn)RCE,文件包含利用點(diǎn)在/ispirit/interface/gateway.php文件中. 首先
if ($P != "") { if (preg_match("/[^a-z0-9;]+/i", $P)) { echo _("非法參數(shù)"); exit(); }參數(shù)P要為空值.接著
if ($json) { $json = stripcslashes($json); $json = (array) json_decode($json); foreach ($json as $key => $val ) { if ($key == "data") { $val = (array) $val; foreach ($val as $keys => $value ) { $keys = $value; } } if ($key == "url") { $url = $val; } } if ($url != "") { if (substr($url, 0, 1) == "/") { $url = substr($url, 1); } if ((strpos($url, "general/") !== false) || (strpos($url, "ispirit/") !== false) || (strpos($url, "module/") !== false)) { include_once $url; } } exit();}由于存在json_decode($json);因此我們需要構(gòu)造一個(gè)json,以及一個(gè)key為url且含有g(shù)eneral/或ispirit/或module/的值,讓函數(shù)走到include_once $url;處就完成了文件包含,至于$json從哪來(lái),我想看到這你就明白了.
include_once "inc/session.php";include_once?"inc/conn.php"關(guān)于我們? ?
蛇獴攻防實(shí)驗(yàn)室成立于2019年11月,專(zhuān)注網(wǎng)絡(luò)攻防技術(shù)。
地點(diǎn):吉林·長(zhǎng)春
總結(jié)
以上是生活随笔為你收集整理的jmeter file upload 变量_通达OA上传漏洞之变量覆盖分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java hive配置_Hive配置项的
- 下一篇: 2020身高体重标准表儿童_2020年儿