Revert "run smbv1 scan in runfinger"

This commit is contained in:
lgandx 2022-11-08 09:22:41 -03:00 committed by GitHub
parent 8d25d04f13
commit f39079da77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -32,9 +32,7 @@ parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython
parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None) parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None)
parser.add_option('-f','--filename', action="store", help="Target file", dest="Filename", metavar="ips.txt", default=None) parser.add_option('-f','--filename', action="store", help="Target file", dest="Filename", metavar="ips.txt", default=None)
parser.add_option('-o','--outfile', action="store", help="Output file", dest="OutFilename", metavar="output.txt", default=None)
parser.add_option('-t','--timeout', action="store", help="Timeout for all connections. Use this option to fine tune Runfinger.", dest="Timeout", type="float", metavar="0.9", default=2) parser.add_option('-t','--timeout', action="store", help="Timeout for all connections. Use this option to fine tune Runfinger.", dest="Timeout", type="float", metavar="0.9", default=2)
parser.add_option('-s','--smbv1', action='store_true', help="Enable smbv1 scan", dest="Smbv1", default=False)
options, args = parser.parse_args() options, args = parser.parse_args()
@ -46,11 +44,9 @@ if options.TARGET == None and options.Filename == None:
Timeout = options.Timeout Timeout = options.Timeout
Host = options.TARGET Host = options.TARGET
Filename = options.Filename Filename = options.Filename
Outputfile = None if options.OutFilename==None else open(options.OutFilename,"w")
SMB1 = "True" SMB1 = "True"
SMB2signing = "False" SMB2signing = "False"
DB = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/RunFinger.db" DB = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/RunFinger.db"
SCAN_SMBV1 = options.Smbv1
class Packet(): class Packet():
fields = OrderedDict([ fields = OrderedDict([
@ -73,10 +69,10 @@ else:
if not os.path.exists(DB): if not os.path.exists(DB):
cursor = sqlite3.connect(DB) cursor = sqlite3.connect(DB)
cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT, SMB1 TEXT, MSSQL TEXT)') cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT, SMB1 TEXT, MSSQL TEXT)')
cursor.commit() cursor.commit()
cursor.close() cursor.close()
def StructWithLenPython2or3(endian,data): def StructWithLenPython2or3(endian,data):
#Python2... #Python2...
@ -103,108 +99,104 @@ def longueur(payload):
return length return length
def ParseNegotiateSMB2Ans(data): def ParseNegotiateSMB2Ans(data):
if data[4:8] == b"\xfeSMB": if data[4:8] == b"\xfeSMB":
return True return True
else: else:
return False return False
def SMB2SigningMandatory(data): def SMB2SigningMandatory(data):
global SMB2signing global SMB2signing
if data[70] == "\x03": if data[70] == "\x03":
SMB2signing = "True" SMB2signing = "True"
else: else:
SMB2signing = "False" SMB2signing = "False"
def WorkstationFingerPrint(data): def WorkstationFingerPrint(data):
return { return {
b"\x04\x00" :"Windows 95", b"\x04\x00" :"Windows 95",
b"\x04\x0A" :"Windows 98", b"\x04\x0A" :"Windows 98",
b"\x04\x5A" :"Windows ME", b"\x04\x5A" :"Windows ME",
b"\x05\x00" :"Windows 2000", b"\x05\x00" :"Windows 2000",
b"\x05\x01" :"Windows XP", b"\x05\x01" :"Windows XP",
b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003", b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003",
b"\x06\x00" :"Windows Vista/Server 2008", b"\x06\x00" :"Windows Vista/Server 2008",
b"\x06\x01" :"Windows 7/Server 2008R2", b"\x06\x01" :"Windows 7/Server 2008R2",
b"\x06\x02" :"Windows 8/Server 2012", b"\x06\x02" :"Windows 8/Server 2012",
b"\x06\x03" :"Windows 8.1/Server 2012R2", b"\x06\x03" :"Windows 8.1/Server 2012R2",
b"\x0A\x00" :"Windows 10/Server 2016/2019 (check build)", b"\x0A\x00" :"Windows 10/Server 2016/2019 (check build)",
}.get(data, 'Other than Microsoft') }.get(data, 'Other than Microsoft')
def GetOsBuildNumber(data): def GetOsBuildNumber(data):
ProductBuild = struct.unpack("<h",data)[0] ProductBuild = struct.unpack("<h",data)[0]
return ProductBuild return ProductBuild
def SaveRunFingerToDb(result): def SaveRunFingerToDb(result):
for k in [ 'Protocol', 'Host', 'WindowsVersion', 'OsVer', 'DomainJoined', 'Bootime', 'Signing','NullSess', 'IsRPDOn', 'SMB1','MSSQL']: for k in [ 'Protocol', 'Host', 'WindowsVersion', 'OsVer', 'DomainJoined', 'Bootime', 'Signing','NullSess', 'IsRPDOn', 'SMB1','MSSQL']:
if not k in result: if not k in result:
result[k] = '' result[k] = ''
cursor = sqlite3.connect(DB) cursor = sqlite3.connect(DB)
cursor.text_factory = sqlite3.Binary cursor.text_factory = sqlite3.Binary
res = cursor.execute("SELECT COUNT(*) AS count FROM RunFinger WHERE Protocol=? AND Host=? AND WindowsVersion=? AND OsVer=? AND DomainJoined=? AND Bootime=? AND Signing=? AND NullSess=? AND IsRDPOn=? AND SMB1=? AND MSSQL=?", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'], result['SMB1'], result['MSSQL'])) res = cursor.execute("SELECT COUNT(*) AS count FROM RunFinger WHERE Protocol=? AND Host=? AND WindowsVersion=? AND OsVer=? AND DomainJoined=? AND Bootime=? AND Signing=? AND NullSess=? AND IsRDPOn=? AND SMB1=? AND MSSQL=?", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'], result['SMB1'], result['MSSQL']))
(count,) = res.fetchone() (count,) = res.fetchone()
if not count: if not count:
cursor.execute("INSERT INTO RunFinger VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'], result['SMB1'], result['MSSQL'])) cursor.execute("INSERT INTO RunFinger VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn'], result['SMB1'], result['MSSQL']))
cursor.commit() cursor.commit()
cursor.close()
cursor.close()
def ParseSMBNTLM2Exchange(data, host, bootime, signing): #Parse SMB NTLMSSP Response def ParseSMBNTLM2Exchange(data, host, bootime, signing): #Parse SMB NTLMSSP Response
data = data.encode('latin-1') data = data.encode('latin-1')
SSPIStart = data.find(b'NTLMSSP') SSPIStart = data.find(b'NTLMSSP')
SSPIString = data[SSPIStart:] SSPIString = data[SSPIStart:]
TargetNameLen = struct.unpack('<H',data[SSPIStart+12:SSPIStart+14])[0] TargetNameLen = struct.unpack('<H',data[SSPIStart+12:SSPIStart+14])[0]
TargetNameOffset = struct.unpack('<L',data[SSPIStart+16:SSPIStart+20])[0] TargetNameOffset = struct.unpack('<L',data[SSPIStart+16:SSPIStart+20])[0]
Domain = SSPIString[TargetNameOffset:TargetNameOffset+TargetNameLen].decode('UTF-16LE') Domain = SSPIString[TargetNameOffset:TargetNameOffset+TargetNameLen].decode('UTF-16LE')
AvPairsLen = struct.unpack('<H',data[SSPIStart+40:SSPIStart+42])[0] AvPairsLen = struct.unpack('<H',data[SSPIStart+40:SSPIStart+42])[0]
AvPairsOffset = struct.unpack('<L',data[SSPIStart+44:SSPIStart+48])[0] AvPairsOffset = struct.unpack('<L',data[SSPIStart+44:SSPIStart+48])[0]
#AvPairs = SSPIString[AvPairsOffset:AvPairsOffset+AvPairsLen].decode('UTF-16LE') #AvPairs = SSPIString[AvPairsOffset:AvPairsOffset+AvPairsLen].decode('UTF-16LE')
WindowsVers = WorkstationFingerPrint(data[SSPIStart+48:SSPIStart+50]) WindowsVers = WorkstationFingerPrint(data[SSPIStart+48:SSPIStart+50])
WindowsBuildVers = GetOsBuildNumber(data[SSPIStart+50:SSPIStart+52]) WindowsBuildVers = GetOsBuildNumber(data[SSPIStart+50:SSPIStart+52])
Hostname, DomainJoined = DomainGrab((host, 445)) DomainGrab((host, 445))
RDP = IsServiceOn((host,3389)) RDP = IsServiceOn((host,3389))
SQL = IsServiceOn((host,1433)) SQL = IsServiceOn((host,1433))
outstr = (f"[SMB2]:['{host}', Os:'{WindowsVers}', Hostname:'{Hostname}' Build:'{str(WindowsBuildVers)}', Domain:'{Domain}', Bootime: '{Bootime}', Signing:'{signing}', RDP:'{RDP}', SMB1:'{SMB1}', MSSQL:'{SQL}']") print(("[SMB2]:['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime: '{}', Signing:'{}', RDP:'{}', SMB1:'{}', MSSQL:'{}']".format(host, WindowsVers, str(WindowsBuildVers), Domain, Bootime, signing, RDP,SMB1, SQL)))
print(outstr) SaveRunFingerToDb({
if Outputfile != None: 'Protocol': '[SMB2]',
Outputfile.write(outstr+"\n") # save result in file 'Host': host,
SaveRunFingerToDb({ 'WindowsVersion': WindowsVers,
'Protocol': '[SMB2]', 'OsVer': str(WindowsBuildVers),
'Host': host, 'DomainJoined': Domain,
'Hostname':Hostname, 'Bootime': Bootime,
'WindowsVersion': WindowsVers, 'Signing': signing,
'OsVer': str(WindowsBuildVers), 'NullSess': 'N/A',
'DomainJoined': Domain, 'IsRDPOn':RDP,
'Bootime': Bootime, 'SMB1': SMB1,
'Signing': signing, 'MSSQL': SQL
'NullSess': 'N/A', })
'IsRDPOn':RDP,
'SMB1': SMB1,
'MSSQL': SQL
})
def GetBootTime(data): def GetBootTime(data):
data = data.encode('latin-1') data = data.encode('latin-1')
Filetime = int(struct.unpack('<q',data)[0]) Filetime = int(struct.unpack('<q',data)[0])
if Filetime == 0: # server may not disclose this info if Filetime == 0: # server may not disclose this info
return 0, "Unknown" return 0, "Unknown"
t = divmod(Filetime - 116444736000000000, 10000000) t = divmod(Filetime - 116444736000000000, 10000000)
time = datetime.datetime.fromtimestamp(t[0]) time = datetime.datetime.fromtimestamp(t[0])
return time, time.strftime('%Y-%m-%d %H:%M:%S') return time, time.strftime('%Y-%m-%d %H:%M:%S')
def IsDCVuln(t, host): def IsDCVuln(t, host):
if t[0] == 0: if t[0] == 0:
return ("Unknown") return ("Unknown")
Date = datetime.datetime(2014, 11, 17, 0, 30) Date = datetime.datetime(2014, 11, 17, 0, 30)
if t[0] < Date: if t[0] < Date:
return("This system may be vulnerable to MS14-068") return("This system may be vulnerable to MS14-068")
Date = datetime.datetime(2017, 3, 14, 0, 30) Date = datetime.datetime(2017, 3, 14, 0, 30)
if t[0] < Date: if t[0] < Date:
return("This system may be vulnerable to MS17-010") return("This system may be vulnerable to MS17-010")
return(t[1]) return(t[1])
##################### #####################
@ -248,26 +240,26 @@ def GetHostnameAndDomainName(data):
return "Could not get Hostname.", "Could not get Domain joined" return "Could not get Hostname.", "Could not get Domain joined"
def DomainGrab(Host): def DomainGrab(Host):
global SMB1 global SMB1
s = socket(AF_INET, SOCK_STREAM) s = socket(AF_INET, SOCK_STREAM)
s.settimeout(Timeout) s.settimeout(Timeout)
try: try:
s.connect(Host) s.connect(Host)
h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00") h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00")
n = SMBNegoDataLanMan() n = SMBNegoDataLanMan()
packet0 = str(h)+str(n) packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0 buffer0 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(buffer0)) s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(2048) data = s.recv(2048)
s.close() s.close()
if data[8:10] == b'\x72\x00': if data[8:10] == b'\x72\x00':
return GetHostnameAndDomainName(data) return GetHostnameAndDomainName(data)
except IOError as e: except IOError as e:
if e.errno == errno.ECONNRESET: if e.errno == errno.ECONNRESET:
SMB1 = "False" SMB1 = "False"
return False return False
else: else:
return False return False
def SmbFinger(Host): def SmbFinger(Host):
s = socket(AF_INET, SOCK_STREAM) s = socket(AF_INET, SOCK_STREAM)
@ -336,104 +328,91 @@ def check_smb_null_session(host):
s.send(NetworkSendBufferPython2or3(buffer0)) s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(2048) data = s.recv(2048)
if data[8:10] == b'\x75\x00': if data[8:10] == b'\x75\x00':
h = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),mid="\xc0\x00") return 'True'
n = SMBTransRAPData()
n.calculate()
packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(2048)
if data[9:13] == b"\x05\x02\x00\xc0":
return ('True', 'True')
return ('True', 'False')
else: else:
return ('False', 'False') return 'False'
except Exception as e: except Exception:
print(f"Test on null session and ms17 fail on {host[0]} Error: {e}", file=sys.stderr) return False
################## ##################
#SMB2 part: #SMB2 part:
def ConnectAndChoseSMB(host): def ConnectAndChoseSMB(host):
s = socket(AF_INET, SOCK_STREAM) s = socket(AF_INET, SOCK_STREAM)
s.settimeout(Timeout) s.settimeout(Timeout)
try: try:
s.connect(host) s.connect(host)
h = SMBHeader(cmd="\x72",flag1="\x00") h = SMBHeader(cmd="\x72",flag1="\x00")
n = SMBNego(Data = SMB2NegoData()) n = SMBNego(Data = SMB2NegoData())
n.calculate() n.calculate()
packet0 = str(h)+str(n) packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0 buffer0 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(buffer0)) s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(4096) data = s.recv(4096)
except: except:
return False return False
if ParseNegotiateSMB2Ans(data): if ParseNegotiateSMB2Ans(data):
try: try:
while True: while True:
s.send(NetworkSendBufferPython2or3(handle(data.decode('latin-1'), host))) s.send(NetworkSendBufferPython2or3(handle(data.decode('latin-1'), host)))
data = s.recv(4096) data = s.recv(4096)
if not data: if not data:
break break
except Exception: except Exception:
pass pass
else: else:
return False return False
def handle(data, host): def handle(data, host):
if data[28] == "\x00": if data[28] == "\x00":
a = SMBv2Head() a = SMBv2Head()
a.calculate() a.calculate()
b = SMBv2Negotiate() b = SMBv2Negotiate()
b.calculate() b.calculate()
packet0 =str(a)+str(b) packet0 =str(a)+str(b)
buffer0 = longueur(packet0)+packet0 buffer0 = longueur(packet0)+packet0
return buffer0 return buffer0
if data[28] == "\x01": if data[28] == "\x01":
global Bootime global Bootime
SMB2SigningMandatory(data) SMB2SigningMandatory(data)
Bootime = IsDCVuln(GetBootTime(data[116:124]), host[0]) Bootime = IsDCVuln(GetBootTime(data[116:124]), host[0])
a = SMBv2Head(SMBv2Command="\x01\x00",CommandSequence= "\x02\x00\x00\x00\x00\x00\x00\x00") a = SMBv2Head(SMBv2Command="\x01\x00",CommandSequence= "\x02\x00\x00\x00\x00\x00\x00\x00")
a.calculate() a.calculate()
b = SMBv2Session1() b = SMBv2Session1()
b.calculate() b.calculate()
packet0 =str(a)+str(b) packet0 =str(a)+str(b)
buffer0 = longueur(packet0)+packet0 buffer0 = longueur(packet0)+packet0
return buffer0 return buffer0
if data[28] == "\x02": if data[28] == "\x02":
ParseSMBNTLM2Exchange(data, host[0], Bootime, SMB2signing) ParseSMBNTLM2Exchange(data, host[0], Bootime, SMB2signing)
################## ##################
def ShowSmallResults(Host): def ShowSmallResults(Host):
ConnectAndChoseSMB((Host,445)) if ConnectAndChoseSMB((Host,445)) == False:
if SCAN_SMBV1 and SMB1 == "True": try:
try: Hostname, DomainJoined = DomainGrab((Host, 445))
Hostname, DomainJoined = DomainGrab((Host, 445)) Signing, OsVer, LanManClient = SmbFinger((Host, 445))
Signing, OsVer, LanManClient = SmbFinger((Host, 445)) NullSess = check_smb_null_session((Host, 445))
NullSess, ms17_10_ready = check_smb_null_session((Host, 445)) RDP = IsServiceOn((Host,3389))
RDP = IsServiceOn((Host,3389)) SQL = IsServiceOn((Host,1433))
SQL = IsServiceOn((Host,1433)) print(("[SMB1]:['{}', Os:'{}', Domain:'{}', Signing:'{}', Null Session: '{}', RDP:'{}', MSSQL:'{}']".format(Host, OsVer, DomainJoined, Signing, NullSess,RDP, SQL)))
outstr = f"[SMB1]:['{Host}', Hostname:'{Hostname}', Os:'{OsVer}', Domain:'{DomainJoined}', Null Session: '{NullSess}', Vulnerable to MS17-010: '{ms17_10_ready}', Lanman Client: '{LanManClient}', RDP:'{RDP}', MSSQL:'{SQL}']" SaveRunFingerToDb({
print(outstr) 'Protocol': '[SMB1]',
if Outputfile != None: 'Host': Host,
Outputfile.write(outstr+"\n") # save result in file 'WindowsVersion':OsVer,
SaveRunFingerToDb({ 'OsVer': OsVer,
'Protocol': '[SMB1]', 'DomainJoined':DomainJoined,
'Host': Host, 'Bootime': 'N/A',
'WindowsVersion':OsVer, 'Signing': Signing,
'OsVer': OsVer, 'NullSess': NullSess,
'DomainJoined':DomainJoined, 'IsRDPOn':RDP,
'Bootime': 'N/A', 'SMB1': 'True',
'Signing': Signing, 'MSSQL': SQL
'NullSess': NullSess, })
'IsRDPOn':RDP, except:
'SMB1': 'True', return False
'MSSQL': SQL
})
except:
return False
def IsServiceOn(Host): def IsServiceOn(Host):
@ -470,7 +449,7 @@ def RunFinger(Host):
proc.get() proc.get()
else: else:
ShowSmallResults(Ln) ShowSmallResults(Ln)
if Filename == None: if Filename == None:
m = re.search("/", str(Host)) m = re.search("/", str(Host))
if m: if m:
@ -487,6 +466,6 @@ def RunFinger(Host):
proc.get() proc.get()
else: else:
ShowSmallResults(Host) ShowSmallResults(Host)
RunFinger(Host) RunFinger(Host)