Implement a basic SNMP listener

All community strings are logged as they are sent to the server.
This initial implementation only supports SNMPv1 and SNMPv2c.

`pyasn1` is required for this server to function.
This commit is contained in:
Stephen Shkardoon 2022-11-06 01:27:28 +13:00
parent 59daf46b93
commit 9d4f919b39
No known key found for this signature in database
GPG key ID: ADFF3AD7A96CACFF
5 changed files with 58 additions and 0 deletions

View file

@ -15,6 +15,7 @@ DNS = On
LDAP = On LDAP = On
DCERPC = On DCERPC = On
WINRM = On WINRM = On
SNMP = Off
; Custom challenge. ; Custom challenge.
; Use "Random" for generating a random challenge for each requests (Default) ; Use "Random" for generating a random challenge for each requests (Default)

View file

@ -365,6 +365,10 @@ def main():
threads.append(Thread(target=serve_thread_udp, args=('', 53, DNS,))) threads.append(Thread(target=serve_thread_udp, args=('', 53, DNS,)))
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 53, DNSTCP,))) threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 53, DNSTCP,)))
if settings.Config.SNMP_On_Off:
from servers.SNMP import SNMP
threads.append(Thread(target=serve_thread_udp, args=('', 161, SNMP,)))
for thread in threads: for thread in threads:
thread.daemon = True thread.daemon = True
thread.start() thread.start()

50
servers/SNMP.py Executable file
View file

@ -0,0 +1,50 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from utils import *
if settings.Config.PY2OR3 == "PY3":
from socketserver import BaseRequestHandler
else:
from SocketServer import BaseRequestHandler
from pyasn1.codec.der.decoder import decode
class SNMP(BaseRequestHandler):
def handle(self):
data = self.request[0]
received_record, rest_of_substrate = decode(data)
snmp_version = int(received_record['field-0'])
if snmp_version > 1:
# TODO: Add support for SNMPv3 (which will have a field-0 value of 2)
print(text("[SNMP] Unsupported SNMPv3 request received from %s" % self.client_address[0].replace("::ffff:","")))
return
community_string = str(received_record['field-1'])
SaveToDb(
{
"module": "SNMP",
"type": "Cleartext",
"client": self.client_address[0],
"user": community_string,
"cleartext": community_string,
"fullhash": community_string,
}
)

View file

@ -99,6 +99,7 @@ class Settings:
self.DCERPC_On_Off = self.toBool(config.get('Responder Core', 'DCERPC')) self.DCERPC_On_Off = self.toBool(config.get('Responder Core', 'DCERPC'))
self.WinRM_On_Off = self.toBool(config.get('Responder Core', 'WINRM')) self.WinRM_On_Off = self.toBool(config.get('Responder Core', 'WINRM'))
self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos')) self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos'))
self.SNMP_On_Off = self.toBool(config.get('Responder Core', 'SNMP'))
# Db File # Db File
self.DatabaseFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'Database')) self.DatabaseFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'Database'))
@ -178,6 +179,7 @@ class Settings:
self.SMBClearLog = os.path.join(self.LogDir, 'SMB-Clear-Text-Password-%s.txt') self.SMBClearLog = os.path.join(self.LogDir, 'SMB-Clear-Text-Password-%s.txt')
self.SMTPClearLog = os.path.join(self.LogDir, 'SMTP-Clear-Text-Password-%s.txt') self.SMTPClearLog = os.path.join(self.LogDir, 'SMTP-Clear-Text-Password-%s.txt')
self.MSSQLClearLog = os.path.join(self.LogDir, 'MSSQL-Clear-Text-Password-%s.txt') self.MSSQLClearLog = os.path.join(self.LogDir, 'MSSQL-Clear-Text-Password-%s.txt')
self.SNMPLog = os.path.join(self.LogDir, 'SNMP-Clear-Text-Password-%s.txt')
self.LDAPNTLMv1Log = os.path.join(self.LogDir, 'LDAP-NTLMv1-Client-%s.txt') self.LDAPNTLMv1Log = os.path.join(self.LogDir, 'LDAP-NTLMv1-Client-%s.txt')
self.HTTPNTLMv1Log = os.path.join(self.LogDir, 'HTTP-NTLMv1-Client-%s.txt') self.HTTPNTLMv1Log = os.path.join(self.LogDir, 'HTTP-NTLMv1-Client-%s.txt')

View file

@ -509,6 +509,7 @@ def StartupMessage():
print(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled)) print(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled))
print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.DCERPC_On_Off else disabled)) print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.DCERPC_On_Off else disabled))
print(' %-27s' % "WinRM server" + (enabled if settings.Config.WinRM_On_Off else disabled)) print(' %-27s' % "WinRM server" + (enabled if settings.Config.WinRM_On_Off else disabled))
print(' %-27s' % "SNMP server" + (enabled if settings.Config.SNMP_On_Off else disabled))
print('') print('')
print(color("[+] ", 2, 1) + "HTTP Options:") print(color("[+] ", 2, 1) + "HTTP Options:")