1 背景
小伙伴打印机扫描完文件后通过SMB协议发送至电脑上,提示密码错误(配置的密码肯定是正确的),需要完成的效果是通过密码认证传输文件。本文写了整个问题解决的心路历程(内容主要按照时间顺序编写),涉及到了Netbios,NTLM认证,Windows本地组策略相关配置。
PS:因为只能远程测试,所以还在自己虚拟环境里做了测试,涉及的IP做个说明
实际环境:
小伙伴IP:192.168.9.11
打印机IP:192.168.9.252
同事IP:192.168.9.31
实验环境:
虚拟机:192.168.182.129
网络都是可达的,端口都是开放的。
2 权限检查
小伙伴电脑上没有截图,因此此处截图是在自己的虚拟机上的。
查看文件夹的权限
属性->共享->高级共享->权限
控制面板->所有控制面板项->网络和共享中心->高级共享设置,启用密码保护
本地组策略->计算机配置->Windows设置->安全设置->用户权限分配
黑白名单,需要远程访问的用户或者组既要在白名单中,又不能在黑名单中。
3 NTLM
为了节约纸张,先找了小伙伴的同事尝试net use
命令来测试,提示是网络密码错误。
既然提示是密码错误,就抓包看下传的认证信息。
本次抓包使用的认证协议为NTLMv2
,因为参考资料较多,没有做记录,这里附一个参考,也可自行搜索相关内容,Windows内网协议学习NTLM篇之NTLM基础介绍。
先将密码计算为NTLM hash,而NTLM认证是Challenge/Response
机制,Response需要依据NTLM hash来计算。
简述下NTLM认证过程
- 服务端发送
Challenge
- 客户端使用
NTLM hash
与Challenge
计算Response
,发送给服务端 - 服务端使用本地存储的
NTLM hash
与Challenge
计算,与客户端发送的Response
比较,相同则认证成功。
NTLMv1与NTLMv2的区别:
-
Challenge
位数不一样,v1是8字节,v2是16字节(PS:这个实际抓包发现v2也是8字节,没有深入细究了) - v1是将 16字节的NTLM hash空填充为21个字节,然后分成三组,每组7比特,作为3DES加密算法的三组密钥,加密Server发来的
Challenge
。 将这三个密文值连接起来得到Response
。 - v2使用16字节NTLMv2哈希作为密钥,将HMAC-MD5消息认证代码算法加密一个值(
Challenge
与Blob
拼接在一起)。得到一个16字节的NTProofStr
。Blob
结构如下
3.1 NTLM hash
密码:123456为例
- 转十六进制:
313233343536
- 转Unicode(utf-16le):
310032003300340035003600
MD4 hash:32ed87bdb5fdc5e9cba88547376818d4
import hashlib,binascii
def ntlm_hash(password):
hash = hashlib.new("md4",password.encode("utf-16le")).digest()
return hash
3.2 NTLMv2
演示如何从Wireshark中抓取信息,利用hashcat爆破出密码。
NTLMv2的格式为:username::domain:challenge:NTProofStr:blob
challenge
NTLMv2 Response是NTProofStr+blob,前16字节为NTProofStr,剩余部分为Blob
username和domain,此处domain为空
利用hashcat破解
hashcat -m 5600 -a 0 administrator:::c772777d484e72b0:9430...000 <dictionary>
-m:指定类型 5600是NTLM v2
-a:0表示使用字典
小伙伴弱密码,就打码了,不丢人了
密码是正确的,因此大概率认定是小伙伴电脑上的配置问题导致即使正确的密码也是提示密码错误了。
4 Windows本地组策略
上述检查完发现密码发送的的确是正确之后,只能去寻找其他原因了,再次搜索到了相关组策略设置。
本地组策略->计算机配置->Windows设置->安全设置->安全选项
网络安全:LAN管理器身份验证级别(PS:这个搜到的最多的,每个配置下基本就是字面意思,但是我试了几个都没效果,因为通过3.2部分的内容可以知道不是协商失败,而是认证的时候失败了)
网络安全:限制NTLM:传入NTLM流量
从没有定义明确指定了允许所有,然而并没有什么用。
另外还有一些明显跟NTLM相关的,但都不是现在问题的关键。
后来小伙伴的同事不空了,就只好用打印机直接测试了,抓完包就懵了,因为打印机使用了SMBv1协议,还不是445端口,是基于Netbios的,因此只能再去学习下Netbios和SMBv1(后来才知道也称为CIFS)
5 Netbios
参照Wiki上的描述,NetBIOS
是一个API
,在不同协议上的实现则是不同的协议。
NetBIOS:1983年由IBM推出,用于IBM PC网络局域网上软件通信的API。
NBF协议:1985年IBM推出NetBIOS Extended User Interface (NetBEUI)
,扩展了基础NetBIOS API,用于令牌环网
NBX协议:基于IPX/SPX
的NetBIOS实现,1986年由Novell推出。
NBT:基于TCP/IP
的NetBIOS实现,RFC 1001:NBT的概念和方法、RFC 1002:NBT的详细规范
显然抓包的数据是NBT
NetBIOS提供三种不同的服务
- 名称服务(NetBIOS-NS),用于名称注册和解析
- 数据分发服务(NetBIOS-DGM),用于无连接通信
- 会话服务(NetBIOS-SSN),用户面向连接的通信
三种服务使用的端口
打印机先通过UDP 137端口进行Name到IP的转换
之后通过TCP 139端口进行认证和文件传输,此时就涉及到CIFS协议了。
6 CIFS
6.1 介绍
微软文档
根据文档介绍可知CIFS
也是SMB
,应该可以理解为SMB中用于文件传输的部分(如果有错望指正)。
文档下载发现页数700+,全看是不可能的了,直接看需要了解的部分。
需要了解的是Negotiate
和Session Setup AndX
6.2 SMB消息结构
参考微软文档的2.2.3 SMB Message Structure
部分
SMB消息结构由三部分组成
- 定长消息头(SMB Header)
- 变长参数块(Parameter Block)
变长数据块(Data Block)
SMB_Header{
UCHAR Protocol[4];
UCHAR Command;
SMB_ERROR Status;
UCHAR Flags;
USHORT Flags2;
USHORT PIDHigh;
UCHAR SecurityFeatures[8];
USHORT Reserved;
USHORT TID;
USHORT PIDLow;
USHORT UID;
USHORT MID;
}
关心的其实就Command
和SMB_ERROR Status
Command:1个字节,用于表示当前命令。
SMB_ERROR Status:4个字节,由服务端返回错误信息给客户端。
关心的Command:Negotiate(0x72)
和Session Setup AndX(0x73)
SMB_ERROR Status
由三部分组成:
1字节ErrorClass
1字节保留
2字节ErrorCode
ErrorClass和ErrorCode对应表见参考微软文档2.2.2.4 SMB Error Classes and Codes
6.3 SMB_COM_NEGOTIATE(0x72)
参考微软文档的2.2.4.52 SMB_COM_NEGOTIATE (0x72)
部分。
于初始化SMB连接,所有SMB消息前必须先发送该命令。
SMB_Parameters{
UCHAR WordCount;
}
SMB_Data{
USHORT ByteCount;
Bytes{
UCHAR Dialects[];
}
}
SMB_Dialect{
UCHAR BufferFormat;
OEM_STRING DialectString;
}
Parameter部分无内容,因此WordCount
填充0x00
ByteCount:Bytes内容的长度
Bytes:可用认证协议列表,单个为SMB_Dialect结构体
BufferFormat:固定为0x02
DialectString:认证协议名称字符串
根据选择的认证协议的不同,结构体内容也不同,本次只关注NTLM认证
SMB_Parameters{
UCHAR WordCount;
Words{
USHORT DialectIndex;
UCHAR SecurityMode;
USHORT MaxMpxCount;
USHORT MaxNumberVcs;
ULONG MaxBufferSize;
ULONG MaxRawSize;
ULONG SessionKey;
ULONG Capabilities;
FILETIME SystemTime;
SHORT ServerTimeZone;
UCHAR ChallengeLength;
}
}
SMB_Data{
USHORT ByteCount;
Bytes{
UCHAR Challenge[];
SMB_STRING DomainName[];
}
}
关心的是Data部分,会返回Challenge
值
6.4 SMB_COM_SESSION_SETUP_ANDX (0x73)
参考微软文档的2.2.4.53 SMB_COM_SESSION_SETUP_ANDX (0x73)
部分。
用于NTLM认证登陆。
SMB_Parameters{
UCHAR WordCount;
Words{
UCHAR AndXCommand;
UCHAR AndXReserved;
USHORT AndXOffset;
USHORT MaxBufferSize;
USHORT MaxMpxCount;
USHORT VcNumber;
ULONG SessionKey;
USHORT OEMPasswordLen;
USHORT UnicodePasswordLen;
ULONG Reserved;
ULONG Capabilities;
}
}
SMB_Data{
USHORT ByteCount;
Bytes{
UCHAR OEMPassword[];
UCHAR UnicodePassword[];
UCHAR Pad[];
SMB_STRING AccountName[];
SMB_STRING PrimaryDomain[];
SMB_STRING NativeOS[];
SMB_STRING NativeLanMan[];
}
}
关注的内容是Data部分,又因为选择认证的不同意义会不一样,此处就是NTLM认证的情况下的说明。
OEMPassword:LM response(v1或者v2)
UnicodePassword:NTLM response(v1或者v2)
AccountName:用户名
PrimaryDomain:域名或计算机名
其中OEMPassword和UnicodePassword的意义是在3.2.4.2.4 User Authentication
这部分不是关心的内容了,仅列个结构体
SMB_Parameters{
UCHAR WordCount;
Words{
UCHAR AndXCommand;
UCHAR AndXReserved;
USHORT AndXOffset;
USHORT Action;
}
}
SMB_Data{
USHORT ByteCount;
Bytes{
UCHAR Pad[];
SMB_STRING NativeOS[];
SMB_STRING NativeLanMan[];
SMB_STRING PrimaryDomain[];
}
}
认证失败是没有内容的,是看SMB Header中的Error Class 0x01
和Error Code 0x05
7 NTLMv1
演示如何从Wireshark中抓取信息,利用hashcat爆破出密码。
NTLMv1的格式为:username::hostname:LM response:NTLM response:challenge
需要的字段已经在上面内容中说明了。
challenge
其他信息
利用hashcat破解
hashcat64.exe -m 5500 -a 0 administrator::aaa:aba89b38ddfe21a...:20c41a8ddd3f8...:b204217... <dictionary>
发现密码发送的的确是正确的。
8 脑洞
提示的是网络密码错误,但是通过抓包分析,发现发送的密码是正确的,就已经很无奈了,不过知道了Windows认证使用的是NTLM,那么远程桌面登陆肯定也是(不考虑域的情况),因此不再搜索文件共享密码错误,换成搜索远程桌面连接密码错误之后,搜到了解决方案,还有一个组策略配置项,令人万万没想到。远程桌面连接密码错误
本地组策略->计算机配置->Windows设置->安全设置->安全选项
网络访问:本地账户的共享和安全模型(设置为经典)
发表评论
您还未登录,请先登录。
登录