def walk(self, query=".1.3.6.1.2.1.2.2.1.2"): """ Methode pour parcourir la MIB. """ if not query.startswith("."): query = "." + query snmp = self.version result = [] monOid = asn1.OBJECTID() monOid.encode(query) req = v2c.GETNEXTREQUEST() req['community'] = self.community req['encoded_oids'] = [monOid.encode()] rsp = v2c.RESPONSE() current_oid = monOid while 1: try: (answer, src) = self.handle.send_and_receive(req.encode()) except role.NoResponse, e: raise TimeOutException(e) except role.NetworkError, n: raise NetworkError(n)
def getValue(self, query): req = v2c.GETREQUEST() rsp = v2c.RESPONSE() req['encoded_oids'] = [asn1.OBJECTID().encode(query)] req['community'] = self.community (answer, src) = self.handle.send_and_receive(req.encode()) rsp.decode(answer) if req != rsp: raise 'Unmatched response: %s vs %s' % (str(req), str(rsp)) oids = map(lambda x: x[0], map(asn1.OBJECTID().decode, rsp['encoded_oids'])) vals = map(lambda x: x[0](), map(asn1.decode, rsp['encoded_vals'])) if rsp['error_status']: raise 'SNMP error #' + str(rsp['error_status']) + ' for OID #' \ + str(rsp['error_index']) #for (oid, val) in map(None, oids, vals): # print oid + ' ---> ' + str(val) return vals[0]
def get(self, query="1.3.6.1.2.1.1.1.0"): """ Does snmpget query on the host. query: OID to use in the query returns the result as a string. """ if not query.startswith("."): query = "." + query # Choose protocol version specific module try: snmp = eval('v' + self.version) except (NameError, AttributeError): raise UnsupportedSnmpVersionError(self.version) objectid = asn1.OBJECTID() oid = objectid.encode(query) # Create SNMP GET request req = snmp.GETREQUEST() req['community'] = self.community req['encoded_oids'] = [oid] # Create SNMP response message framework rsp = snmp.RESPONSE() # Encode SNMP request message and try to send it to SNMP agent and # receive a response try: (answer, _src) = self.handle.send_and_receive(req.encode(), dst=(self.host, self.port)) except role.NoResponse as err: raise TimeOutException(err) except role.NetworkError as err: raise NetworkError(err) # Decode raw response/answer rsp.decode(answer) # Check for errors in the response self._error_check(rsp) # Fetch the value from the response rsp_value = asn1.decode(rsp['encoded_vals'][0])[0] # Return the value as a proper Python type: return rsp_value()
def bulkwalk(self, query="1.3.6.1.2.1.1.1.0", strip_prefix=False): """ Performs an SNMP walk on the host, using GETBULK requests. Will raise an UnsupportedSnmpVersionError if the current version is anything other than 2c. query: OID to use in the query strip_prefix: If True, strips the query OID prefix from the response OIDs. returns an array containing key-value-pairs, where the returned OID is the key. """ if str(self.version) != "2c": raise UnsupportedSnmpVersionError( "Cannot use BULKGET in SNMP version " + self.version) if not query.startswith("."): query = "." + query # Choose protocol version specific module snmp = v2c result = [] root_oid = asn1.OBJECTID() root_oid.encode(query) # Create SNMP GETNEXT request req = snmp.GETBULKREQUEST() req['community'] = self.community req['encoded_oids'] = [root_oid.encode()] req['max_repetitions'] = 256 # Create a response message framework rsp = snmp.RESPONSE() current_oid = root_oid # Traverse agent MIB while 1: # Encode SNMP request message and try to send it to SNMP agent and # receive a response try: (answer, src) = self.handle.send_and_receive(req.encode(), dst=(self.host, self.port)) except role.NoResponse, e: raise TimeOutException(e) except role.NetworkError, n: raise NetworkError(n)
def walk(self, query="1.3.6.1.2.1.1.1.0"): """ Does snmpwalk on the host. query: OID to use in the query returns an array containing key-value-pairs, where the returned OID is the key. """ if not query.startswith("."): query = "." + query # Choose protocol version specific module try: snmp = eval('v' + self.version) except (NameError, AttributeError): raise UnsupportedSnmpVersionError(self.version) result = [] root_oid = asn1.OBJECTID() root_oid.encode(query) # Create SNMP GETNEXT request req = snmp.GETNEXTREQUEST() req['community'] = self.community req['encoded_oids'] = [root_oid.encode()] # Create a response message framework rsp = snmp.RESPONSE() current_oid = root_oid # Traverse agent MIB while 1: # Encode SNMP request message and try to send it to SNMP agent and # receive a response try: (answer, src) = self.handle.send_and_receive(req.encode(), dst=(self.host, self.port)) except role.NoResponse, e: raise TimeOutException(e) except role.NetworkError, n: raise NetworkError(n)
def get(self, query="1.3.6.1.2.1.1.1.0"): """ Does snmpget query on the host. query: OID to use in the query returns the result as a string. """ if not query.startswith("."): query = "." + query # Choose protocol version specific module try: snmp = eval('v' + self.version) except (NameError, AttributeError): raise UnsupportedSnmpVersionError(self.version) objectid = asn1.OBJECTID() oid = objectid.encode(query) # Create SNMP GET request req = snmp.GETREQUEST() req['community'] = self.community req['encoded_oids'] = [oid] # Create SNMP response message framework rsp = snmp.RESPONSE() # Encode SNMP request message and try to send it to SNMP agent and # receive a response try: (answer, src) = self.handle.send_and_receive(req.encode(), dst=(self.host, self.port)) except role.NoResponse, e: raise TimeOutException(e)
def bulkwalk(self, query="1.3.6.1.2.1.1.1.0", strip_prefix=False): """ Performs an SNMP walk on the host, using GETBULK requests. Will raise an UnsupportedSnmpVersionError if the current version is anything other than 2c. query: OID to use in the query strip_prefix: If True, strips the query OID prefix from the response OIDs. returns an array containing key-value-pairs, where the returned OID is the key. """ if str(self.version) != "2c": raise UnsupportedSnmpVersionError( "Cannot use BULKGET in SNMP version " + self.version) if not query.startswith("."): query = "." + query # Choose protocol version specific module snmp = v2c result = [] root_oid = asn1.OBJECTID() root_oid.encode(query) # Create SNMP GETNEXT request req = snmp.GETBULKREQUEST() req['community'] = self.community req['encoded_oids'] = [root_oid.encode()] req['max_repetitions'] = 256 # Create a response message framework rsp = snmp.RESPONSE() current_oid = root_oid # Traverse agent MIB while 1: # Encode SNMP request message and try to send it to SNMP agent and # receive a response try: (answer, _src) = self.handle.send_and_receive(req.encode(), dst=(self.host, self.port)) except role.NoResponse as err: raise TimeOutException(err) except role.NetworkError as err: raise NetworkError(err) # Decode raw response/answer rsp.decode(answer) # Check for errors in the response try: self._error_check(rsp) except EndOfMibViewError: # Since we are retrieving multiple values, this SNMP # exception must be handled in the loop below instead pass last_response_oid = None for encoded_oid, encoded_val in \ zip(rsp['encoded_oids'], rsp['encoded_vals']): rsp_oid = asn1.decode(encoded_oid)[0] rsp_value = asn1.decode(encoded_val)[0] # Check for reasons to stop walking if isinstance(rsp_value, asn1.endOfMibView): # Nothing more to see here, move along return result if not root_oid.isaprefix(rsp_oid()): # If the current value came from outside the tree we # are traversing, get the hell out of here, we're done # walking the subtree. return result elif rsp_oid == current_oid: # If the GETNEXT response contains the same object # ID as the request, something has gone wrong, and # we didn't see it further up. Just return # whatever results we got. return result else: oid = rsp_oid() if strip_prefix: oid = oid[len(query) + 1:] result.append((oid, rsp_value())) last_response_oid = rsp_oid # Update request ID req['request_id'] += 1 # Load the next request with the last OID received in the # last response req['encoded_oids'] = rsp['encoded_oids'][-1:] current_oid = last_response_oid
def walk(self, query="1.3.6.1.2.1.1.1.0"): """ Does snmpwalk on the host. query: OID to use in the query returns an array containing key-value-pairs, where the returned OID is the key. """ if not query.startswith("."): query = "." + query # Choose protocol version specific module try: snmp = eval('v' + self.version) except (NameError, AttributeError): raise UnsupportedSnmpVersionError(self.version) result = [] root_oid = asn1.OBJECTID() root_oid.encode(query) # Create SNMP GETNEXT request req = snmp.GETNEXTREQUEST() req['community'] = self.community req['encoded_oids'] = [root_oid.encode()] # Create a response message framework rsp = snmp.RESPONSE() current_oid = root_oid # Traverse agent MIB while 1: # Encode SNMP request message and try to send it to SNMP agent and # receive a response try: (answer, _src) = self.handle.send_and_receive(req.encode(), dst=(self.host, self.port)) except role.NoResponse as err: raise TimeOutException(err) except role.NetworkError as err: raise NetworkError(err) # Decode raw response/answer rsp.decode(answer) # Check for errors in the response try: self._error_check(rsp) except EndOfMibViewError: # We just fell off the face of the earth (or walked outside the # agent's MIB view). Return whatever results we got. return result # Fetch the (first) Object ID and value pair from the response, # (there shouldn't be more than one pair) rsp_oid = asn1.decode(rsp['encoded_oids'][0])[0] rsp_value = asn1.decode(rsp['encoded_vals'][0])[0] # Check for reasons to stop walking if not root_oid.isaprefix(rsp_oid()): # If the current GETNEXT response came from outside the # tree we are traversing, get the hell out of here, we're # done walking the subtree. return result elif rsp_oid == current_oid: # If the GETNEXT response contains the same object ID as the # request, something has gone wrong, and we didn't see it # further up. Just return whatever results we got. return result else: result.append((rsp_oid(), rsp_value())) # Update request ID req['request_id'] += 1 # Load the next request with the OID received in the last response req['encoded_oids'] = rsp['encoded_oids'] current_oid = rsp_oid
def set(self, query, type, value): """ Does snmpset query on the host. query: oid to use in snmpset type: type of value to set. This may be i: INTEGER u: unsigned INTEGER t: TIMETICKS a: IPADDRESS o: OBJID s: OCTETSTRING U: COUNTER64 (version 2 and above) x: OCTETSTRING value: the value to set. Must ofcourse match type: i = 2, s = 'string' Heavily influenced by: http://pysnmp.sourceforge.net/examples/2.x/snmpset.html """ if not query.startswith("."): query = "." + query # Choose protocol version specific module try: snmp = eval('v' + self.version) except (NameError, AttributeError): raise UnsupportedSnmpVersionError(self.version) # Translate type to fit asn1 library if type == 'i': type = 'INTEGER' if type == 'u': type = 'UNSIGNED32' if type == 't': type = 'TIMETICKS' if type == 'a': type = 'IPADDRESS' if type == 'o': type = 'OBJECTID' if type == 's': type = 'OCTETSTRING' if type == 'U': type = 'COUNTER64' if type == 'x': type = 'OCTETSTRING' # Make request and responsehandler req = snmp.SETREQUEST() req['community'] = self.community rsp = snmp.GETRESPONSE() # Encode oids and values encoded_oids = [] encoded_vals = [] encoded_oids.append(asn1.OBJECTID().encode(query)) encoded_vals.append(eval('asn1.' + type + '()').encode(value)) # Try to send query and get response try: (answer, _src) = self.handle.send_and_receive( req.encode(encoded_oids=encoded_oids, encoded_vals=encoded_vals), dst=(self.host, self.port)) # Decode response (an octet-string) into an snmp-message rsp.decode(answer) if rsp['error_status']: raise AgentError(str(snmp.SNMPError(rsp['error_status']))) except (role.NoResponse, role.NetworkError) as err: raise NetworkError(err)
def showOid(self, head_oids): # Create SNMP manager object client = role.manager((self.target, self.port)) # Pass it a few options client.timeout = self.timeout client.retries = self.retries # Create a SNMP request&response objects from protocol version # specific module. try: req = v1.GETREQUEST() nextReq = v1.GETNEXTREQUEST() rsp = v1.GETRESPONSE() except (NameError, AttributeError): print sys.exc_info()[1] return False # Store tables headers #head_oids = ["1.3.6.1."] try: # BER encode initial SNMP Object IDs to query encoded_oids = map(asn1.OBJECTID().encode, head_oids) except: print "Error.", sys.exc_info()[1] return # Traverse agent MIB while 1: # Encode SNMP request message and try to send it to SNMP agent # and receive a response (answer, src) = client.send_and_receive(\ req.encode(community=self.community, encoded_oids=encoded_oids)) # Attempt to decode SNMP response rsp.decode(answer) # Make sure response matches request (request IDs, communities, etc) if req != rsp: raise Exception('Unmatched response: %s vs %s' % (str(req), str(rsp))) # Decode BER encoded Object IDs. oids = map(lambda x: x[0], map(asn1.OBJECTID().decode, \ rsp['encoded_oids'])) # Decode BER encoded values associated with Object IDs. vals = map(lambda x: x[0](), map(asn1.decode, rsp['encoded_vals'])) # Check for remote SNMP agent failure if rsp['error_status']: # SNMP agent reports 'no such name' when walk is over if rsp['error_status'] == 2: # Switch over to GETNEXT req on error # XXX what if one of multiple vars fails? if not (req is nextReq): req = nextReq continue # One of the tables exceeded for l in oids, vals, head_oids: del l[rsp['error_index'] - 1] else: raise Exception('SNMP error #' + str(rsp['error_status']) + ' for OID #' \ + str(rsp['error_index'])) # Exclude completed OIDs while 1: for idx in range(len(head_oids)): if not asn1.OBJECTID(head_oids[idx]).isaprefix(oids[idx]): # One of the tables exceeded for l in oids, vals, head_oids: del l[idx] break else: break if not head_oids: return False # Print out results for (oid, val) in map(None, oids, vals): if str(val) != "": print oidToHuman(oid) + ' = ' + str(val) # BER encode next SNMP Object IDs to query encoded_oids = map(asn1.OBJECTID().encode, oids) # Update request object req['request_id'] = req['request_id'] + 1 # Switch over GETNEXT PDU for if not done if not (req is nextReq): req = nextReq return True
def snmpenum(self, h_oids, title): try: from pysnmp import asn1, v1, v2c from pysnmp import role except: self.log("Error: you need pysnmp to use this exploit") return 1 client = role.manager((self.host, 161)) client.timeout = 1 client.retries = 5 t = 0 req = eval('v' + self.snmpver).GETREQUEST() nextReq = eval('v' + self.snmpver).GETNEXTREQUEST() rsp = eval('v' + self.snmpver).GETRESPONSE() encoded_oids = map(asn1.OBJECTID().encode, h_oids) while 1: try: (answer, src) = client.send_and_receive( req.encode(community=self.community, encoded_oids=encoded_oids)) except: self.log("%s : bad community ?" % self.community) return 1 rsp.decode(answer) if req != rsp: raise 'Unmatched response: %s vs %s' % (str(req), str(rsp)) oids = map(lambda x: x[0], map(asn1.OBJECTID().decode, rsp['encoded_oids'])) vals = map(lambda x: x[0](), map(asn1.decode, rsp['encoded_vals'])) if rsp['error_status']: if rsp['error_status'] == 2: if not (req is nextReq): req = nextReq continue for l in oids, vals, h_oids: del l[rsp['error_index'] - 1] else: raise 'SNMP error #' + str( rsp['error_status']) + ' for OID #' + str( rsp['error_index']) while 1: for idx in range(len(h_oids)): if not asn1.OBJECTID(h_oids[idx]).isaprefix(oids[idx]): for l in oids, vals, h_oids: del l[idx] break else: break if not h_oids: return 0 if not t: self.log("[#] %s" % title) t += 1 for (oid, val) in map(None, oids, vals): self.log(str(val)) encoded_oids = map(asn1.OBJECTID().encode, oids) req['request_id'] = req['request_id'] + 1 if not (req is nextReq): req = nextReq return 0
return ip return r[0] except: return ip # Listen for SNMP messages from remote SNMP managers while 1: # Receive a request message (question, src) = server.receive() # Decode request of any version (req, rest) = v2c.decode(question) # Decode BER encoded Object IDs. oids = map(lambda x: x[0], map(asn1.OBJECTID().decode, \ req['encoded_oids'])) # Decode BER encoded values associated with Object IDs. vals = map(lambda x: x[0](), map(asn1.decode, req['encoded_vals'])) # Print it out print 'SNMP message from: ' + str(src) print 'Version: ' + str(req['version'] + 1) + ', type: ' + str(req['tag']) if req['version'] == 0: print 'Enterprise OID: ' + str(req['enterprise']) print 'Trap agent: ' + str(req['agent_addr']) for t in v1.GENERIC_TRAP_TYPES.keys(): if req['generic_trap'] == v1.GENERIC_TRAP_TYPES[t]: print 'Generic trap: %s (%d)' % (t, req['generic_trap']) break
def listen(self, community, callback): """Listens for and dispatches incoming traps to callback.""" # Listen for SNMP messages from remote SNMP managers while 1: # Receive a request message try: (question, src) = self._agent.receive() except select.error as why: # resume loop if a signal interrupted the receive operation if why.args[0] == 4: # error 4 = system call interrupted continue else: raise why if question is None: continue logger.debug("Packet content: %r", question) try: # Decode request of any version (req, rest) = v2c.decode(question) # Decode BER encoded Object IDs. oids = map(lambda x: x[0], map(asn1.OBJECTID().decode, req['encoded_oids'])) # Decode BER encoded values associated with Object IDs. vals = map(lambda x: x[0](), map(asn1.decode, req['encoded_vals'])) except Exception as why: # We must not die because of any malformed packets; log # and ignore any exception logger.exception( "Exception while decoding snmp trap packet " "from %r, ignoring trap", src) continue agent = None type = None genericType = None varbinds = {} # Prepare variables for making of SNMPTrap-object if req['version'] == 0: agent = str(req['agent_addr']) type = str(req['tag']) uptime = str(req['time_stamp']) # Create snmpoid based on RFC2576 snmpTrapOID, genericType = transform(req) else: uptime = vals.pop(0) oids.pop(0) snmpTrapOID = vals.pop(0) oids.pop(0) # Add varbinds to array for (oid, val) in map(None, oids, vals): varbinds[oid] = str(val) community = req['community'] version = str(req['version'] + 1) src = src[0] # Create trap object, let callback decide what to do with it. trap = SNMPTrap(str(src), agent or str(src), type, genericType, snmpTrapOID, uptime, community, version, varbinds) callback(trap) # Exit nicely sys.exit(0)