smbclient Windows 打印和文件传输安全
Microsoft Windows 通常是大多数计算环境中存在的,UNIX 管理员可能不得不时不时地使用 Windows 网络中的资源。虽然许多人熟悉 Samba 服务器软件,但匹配的 smbclient 实用程序常常被忽视。
Windows 的“映射网络驱动器”功能依赖于 服务器消息块 网络协议,该协议主要在 NT 的后代中发展起来。smbclient 实用程序提供了一个类似于 FTP 的界面,允许在启用了共享的 SMB 上与 NT 服务器上的磁盘目录和打印机进行文件传输。
在本文中,我将介绍 Windows 服务的连接示例,然后开发一个通用脚本,用于将内容推送到 Windows 共享。我将讨论何时应该使用 SMB 协议,更重要的是,何时不应该使用。
连接示例用于 UNIX 的 Samba 以其与 Windows 网络上的客户端互操作的服务器软件而闻名。但是,它也包括可以操作任何 SMB 服务器的 smbclient 程序。对于那些有命令行 FTP 经验的人来说,smbclient 程序会立即熟悉。
smbclient 程序可以使用 -L
选项查询 SMB 服务器以获取可见共享的列表
$ smbclient -L dc.somecompany.com -U nt_username -W nt_domain
Enter nt_username's password:
Domain=[NT_DOMAIN]
OS=[Windows Server 2008 R2 Standard 7601 Service Pack 1]
Server=[Windows Server 2008 R2 Standard 6.1]
Sharename Type Comment
--------- ---- -------
C$ Disk Default share
file_stash Disk
Fancy_laser Printer Really Expensive
Cheap_laser Printer What a deal!
在编目服务器上的文件和打印机共享之后,您可以连接到特定的共享并对其进行操作。以下是几种传输类型的示例
$ smbclient //dc.somecompany.com/file_stash -U nt_username -W nt_domain
Enter nt_username's password:
Domain=[NT_DOMAIN]
OS=[Windows Server 2008 R2 Standard 7601 Service Pack 1]
Server=[Windows Server 2008 R2 Standard 6.1]
smb: \> mkdir "smbclient test"
smb: \> cd "smbclient test
smb: \smbclient test\> prompt
smb: \smbclient test\> mput samba*
putting file samba.schema.oc.IBM-DS as
\smbclient test\samba.schema.oc.IBM-DS
(955.7 kb/s) (average 955.7 kb/s)
putting file samba.schema.at.IBM-DS as
\smbclient test\samba.schema.at.IBM-DS
(3590.1 kb/s) (average 2272.9 kb/s)
putting file samba.schema as
\smbclient test\samba.schema
(7454.2 kb/s) (average 4000.1 kb/s)
putting file samba.ldif as
\smbclient test\samba.ldif
(1615.9 kb/s) (average 2808.0 kb/s)
putting file samba-schema.IBMSecureWay as
\smbclient test\samba-schema.IBMSecureWay
(1023.7 kb/s) (average 2553.1 kb/s)
putting file samba-schema-netscapeds5.x.README as
\smbclient test\samba-schema-netscapeds5.x.README
(61.0 kb/s) (average 2336.4 kb/s)
putting file samba-schema-FDS.ldif as
\smbclient test\samba-schema-FDS.ldif
(5572.1 kb/s) (average 2709.8 kb/s)
putting file samba-nds.schema as
\smbclient test\samba-nds.schema
(247.3 kb/s) (average 862.9 kb/s)
smb: \smbclient test\> dir
. D 0 Fri Mar 3 13:31:24 2017
.. D 0 Fri Mar 3 13:31:24 2017
samba-nds.schema A 19754 Fri Mar 3 13:31:24 2017
samba-schema-FDS.ldif A 17118 Fri Mar 3 13:31:24 2017
samba-schema-netscapeds5.x.README A 125 Fri Mar 3 13:31:24 2017
samba-schema.IBMSecureWay A 3145 Fri Mar 3 13:31:24 2017
samba.ldif A 14892 Fri Mar 3 13:31:24 2017
samba.schema A 22900 Fri Mar 3 13:31:24 2017
samba.schema.at.IBM-DS A 11029 Fri Mar 3 13:31:24 2017
samba.schema.oc.IBM-DS A 2936 Fri Mar 3 13:31:24 2017
708626943 blocks of size 4096. 95072482 blocks available
smb: \smbclient test\> lcd /tmp
smb: \smbclient test\> get samba.schema.oc.IBM-DS
getting file \smbclient test\samba.schema.oc.IBM-DS of size 2936 as
samba.schema.oc.IBM-DS
(409.6 KiloBytes/sec) (average 409.6 KiloBytes/sec)
smb: \> help
? allinfo altname archive backup
blocksize cancel case_sensitive cd chmod
chown close del dir du
echo exit get getfacl geteas
hardlink help history iosize lcd
link lock lowercase ls l
mask md mget mkdir more
mput newer notify open posix
posix_encrypt posix_open posix_mkdir posix_rmdir posix_unlink
print prompt put pwd q
queue quit readlink rd recurse
reget rename reput rm rmdir
showacls setea setmode scopy stat
symlink tar tarmode timeout translate
unlock volume vuid wdel logon
listconnect showconnect tcon tdis tid
logoff .. !
smb: \> quit
打印机共享的一个独特属性是,登录并发出任何类型的 put 命令都会将文件传输直接发送到连接的打印机。大多数商用激光打印机除了带有 DOS 样式行尾的文本文件外,还会接受 PostScript 输出。
多年来,SMB 协议经历了多次修订。版本 1 协议在 1990 年代后期最终确定并作为互联网标准“通用互联网文件系统”(CIFS) 提供。各种方面为 CIFS 开发了许多具有新功能的扩展,但 Microsoft 没有将其中任何一个接受到 Windows 实现中。
Windows Vista 标志着 SMB2 的首次出现,它是协议的完全重新设计,它整合了命令集并减少了数据传输所需的往返次数。Samba 3.5 服务器实验性地引入了对 SMB2 的协议支持,并在 Samba 3.6 中投入生产。请注意,smbclient 直到 4.1 版本才收到 SMB2。
Windows 8(和 Server 2012)通过 SMB3 引入了进一步的重要改进,SMB3(最终)引入了加密和高可用性功能。Samba 4.1 引入了对 SMB3 的协议支持,其中 Samba 服务器和客户端实现了协议版本对等。
以下是 Samba 项目关于 SMB 各个修订版本的文档
SMB1:原始 DOS/Windows LANMAN 协议,它经历了多个版本的发展。
CORE:最早的版本。没有用户名的概念。
COREPLUS:CORE 的轻微改进,以提高效率。
LANMAN1:协议的第一个现代版本。长文件名支持。
LANMAN2:Lanman1 协议的更新。
NT1:当前最新的协议版本。Windows NT 使用。被称为 CIFS。
SMB2:SMB 协议的重新实现。Windows Vista 和更高版本的 Windows 使用。SMB2 有可用的子协议。
SMB2_02:最早的 SMB2 版本。
SMB2_10:Windows 7 SMB2 版本。
SMB2_22:早期 Windows 8 SMB2 版本。
SMB2_24:Windows 8 beta SMB2 版本。
默认情况下,SMB2 选择 SMB2_10 变体。
SMB3:与 SMB2 相同。Windows 8 使用。SMB3 有可用的子协议。
SMB3_00:Windows 8 SMB3 版本。(与 SMB2_24 大致相同。)
SMB3_02:Windows 8.1 SMB3 版本。
SMB3_10:早期 Windows 10 技术预览 SMB3 版本。
SMB3_11:Windows 10 技术预览 SMB3 版本(可能是最终版本)。
默认情况下,SMB3 选择 SMB3_11 变体。
smbclient 程序允许将特定协议版本锁定到服务器作为最大支持的修订版本
-m|--max-protocol protocol
这允许用户选择 smbclient 将用于连接到服务器的最高 SMB 协议级别。默认情况下,这设置为 NT1,它是最高的可用 SMB1 协议。要使用 SMB2 或 SMB3 协议连接,请分别使用字符串 SMB2 或 SMB3。请注意,要使用加密传输连接到 Windows 2012 服务器,需要选择 SMB3 的最大协议。
当选择不同的协议修订版本时,初始登录时显示的注释(域、操作系统和服务器)可能会更改(之前的登录在同一服务器上识别为 Server 2008)
$ smbclient //dc.somecompany.com/file_stash -U nt_username -W nt_domain -mSMB3
Enter nt_username's password:
Domain=[NT_DOMAIN] OS=[] Server=[]
smb: \>
打印机脚本
下面的脚本使用许多 shell 功能来传输打印作业。它捆绑了一个用于提示和设置环境变量的机制,提示输入没有字符回显的密码,并使用命名管道 (fifo) 来传输凭据和重新格式化的文本
#!/bin/sh
function chkv { # $1:var $2:default_value $3:prompt
[[ -z "$(eval echo \$$1))" ]] && if [[ -z "$2" ]]
then echo -n "$3"; eval read $1
else eval $1=$2; fi;
}
chkv W_DOM YOUR_WIN_DOMAIN ''
chkv W_SERVER dc.yourcompany.com ''
chkv W_PRINTER office_laser ''
chkv W_USER '' 'NT Uname: '
if [[ -z "${W_PASS}" ]]
then echo -n 'NT Pass: '; stty -echo; read W_PASS; stty echo; echo ''; fi
W=$(mktemp -dt W-XXXXXX); mkfifo -m 600 "$W/fifo"
for x
do (echo -e "username=${W_USER}\npassword=${W_PASS}\ndomain=${W_DOM}" > \
"$W/fifo"; awk 'BEGIN{ORS="\r\n"}; {print}' < "${x}" > "$W/fifo") &
smbclient "//${W_SERVER}/${W_PRINTER}" -A "$W/fifo" \
-c "put $W/fifo $(basename ${x}).txt"
done; rm -f "$W/fifo"; rmdir "$W"
Below is an example of a run of the script:
$ export W_USER=$LOGNAME W_SERVER=winserv.foo.com
$ export W_PRINTER=a_laser W_DOM=DFOO
$ ./winprint /etc/passwd /etc/group
NT Pass:
Domain=[DFOO] OS=[Windows Server 2008 R2 Standard 7601 Service Pack 1]
Server=[Windows Server 2008 R2 Standard 6.1]
putting file /tmp/W-s14793/fifo as \passwd.txt (130.1 kb/s)
(average 130.1 kb/s)...
关于脚本的一些具体观察
上面的 chkv 函数允许凭据、服务器和打印机的设置来自环境、脚本默认值或在运行时来自用户的提示。
上面的 stty 调用允许从键盘将密码输入到 shell 变量中,而无需屏幕回显。它还允许密码通过环境变量到达,这对于某些人来说可能是一个安全问题——/proc/self/environ 文件对 root 可见,并且父 shell 的许多子进程可能会显示一个(对他们而言)不相关的密码。为了最大限度地保护 Windows 密码,请删除 if/then/fi 控制结构,并强制每次运行都提示输入密码,以确保它永远不会出现在 /proc/self/environ 中。一般来说,在导出包含敏感内容的环境变量时应谨慎。
安全地创建了一个 fifo 或“命名管道”,并且此 fifo 服务于两个目的。首先,用户名/密码/域被写入其中,并且 fifo 被关闭。接下来,文本文件被写入同一个 fifo,并且将“回车符”(ASCII 代码 13)添加到每一行作为行尾标记。这对活动被集体作为子 shell 中的后台进程启动。
凭据也可以使用
-Uuser%password
和-W domain
选项在命令行上传递给 smbclient。这在某些平台上是不安全的,因为这些参数将出现在进程列表中 (ps -ef
)——一种流行的隐藏程序参数的解决方案是 Oracle 的 hide.c,但脚本使用带有-A
选项的 fifo 来代替 smbclient。请注意,Oracle Linux 7 下的 smbclient 从ps -ef
中看到的内容中清除了密码,但 Oracle Linux 5 没有。为了在所有平台上获得更高的安全性,凭据通过 fifo 传递。为此脚本测试的激光打印机在打印仅以换行符(ASCII 代码 10)作为行尾标记的 UNIX 样式文本文件时,不会返回到左边距——正常打印还需要回车符。这可以在不需要临时磁盘文件的情况下实现,方法是通过 fifo 传递带有添加的 CR 的内容。选择 awk 实用程序用于此功能,因为它在处理回车符方面具有 最佳 POSIX 可移植性 覆盖范围(此脚本已在 HP-UX 上进行了测试,只需进行最少的更改)。
此脚本未定义正式的打印机队列(即,CUPS、lpd 或 lp),但它将允许任何非特权用户将内容注入到他们有权访问的 Windows 网络打印机队列中。接受 SMB 凭据的正式 UNIX 打印机队列正在执行类似于此处所做的事情。
该脚本使用 SMB1 的默认 NT1 变体——可能需要更改此设置,这将在下一节中讨论。
最后,此脚本可以像将文本文件传输到具有正确 DOS 样式行尾的磁盘共享一样容易地使用(即,FTP 中的“ASCII”模式)。
通过将 smbclient 作为“协进程”启动,仅验证一次身份,然后发出多个 puts 而不退出客户端,可以提高脚本的效率。Korn shell 长期以来的协进程语法在新引入的 Bash 协进程中被忽略,因此这种对效率的追求将需要根据 Bourne shell 树的分支使用不同的语法。
SMB 协议安全SMB 安全的不幸概要是,在很大程度上,根本没有安全。
虽然建立登录的凭据已加密,但网络负载(即,打印作业或文件传输)在 Microsoft 的 SMB1 和 SMB2 协议中以明文传输,并且没有本机加密功能。Microsoft 为 SMB3 引入了加密选项,但由于性能原因,默认情况下未启用它们。除非服务器强制执行加密传输,并且客户端尝试明文登录确认了这一点,否则不应通过任何版本的 SMB 传输敏感内容。
用于 UNIX 的 Samba 从 2008 年的 3.2 版本开始为 SMB1/NT1 实现了加密扩展。Microsoft 忽略了这些改进,Windows 用户被迫等到 2012 年才能使用 SMB3 加密。Microsoft 在此期间对 SMB2 的改进愚蠢地侧重于吞吐量,就好像性能在某种程度上比安全性更重要一样(即使在完全赢得市场之后,他们仍在努力在技术上击败 Novell IPX/SPX)。
Windows 7 和 Server 2008 缺少 SMB3,并且在这些平台上使用本机客户端和服务器的 SMB 传输是完全开放的。不要通过您不完全信任的网络使用任何 SMB 明文协议传输敏感数据。不幸的是,Windows 7 仍然是该领域最受欢迎的版本(由于 Windows 8 的审美挑战和 Windows 10 的斯大林式监督)。
截至 2017 年 2 月,Windows 7 是 桌面操作系统领导者,占市场份额的 48.41%。由于 Windows XP 仍然占 8.45%,可以说大多数 Windows 市场选择了明文 SMB 而不是加密。Windows 7 社区拒绝升级的不幸副作用是他们的网络充斥着明文传输。
存在一种解决方法,它使用第三方工具将 SMB 包装在 TLS 加密中。stunnel 实用程序可以将任何版本的 SMB 伪装成 NetBSD 教程 中演示的那样。不幸的是,UNIX 客户端上使用了 \\localhost 共享,仅允许单个加密连接——如果您需要访问两个敏感服务器,则必须决定您更喜欢哪一个。对于 Windows 客户端,需要精心调用配置了完全虚构地址的“localhost”接口(放弃所有理智,所有进入此处的人)——这实际上意味着“映射网络驱动器”对于普通用户来说太复杂了(并且需要他们不应拥有的提升的权限)。此类驱动器映射将需要知识渊博的管理员。
另请注意,在启用 Microsoft 的 SMB3 加密时,必须完全禁用 SMB1(用于 UNIX 的 Samba 没有此问题)。由于显而易见的原因,Microsoft 已在 Windows 10 中默认禁用 SMB1,并且正在 宣传 在旧系统上删除它。用户社区可能更希望 Microsoft 只是用 Samba 替换其 SMB 堆栈(人们可以梦想)。更现实的替代方案是安装 Microsoft 的 SSH 的本机端口,用于安全传输文件和打印作业,如果 Windows 管理员最终有决心放弃 SMB 的缺陷(sshfs 文件系统可能特别令人感兴趣)。
在任何情况下,您都可以强制 smbclient 坚持某种类型的加密(Samba 的 NT1 或 SMB3 变体),使用 -e
标志——当加密不可用时,它将中止(请注意,您可能需要在用于 UNIX 的 Samba 上设置 server signing = auto
配置选项)。以下是连接到加密 SMB1/NT1 服务器的示例
$ smbclient -e //badsmb-cleartext.somecompany.com/public -U ntid -W w_dom
Enter ntid's password:
smb_signing_good: BAD SIG: seq 1
session setup failed: NT_STATUS_ACCESS_DENIED
$ smbclient -e //samba-secure.somecompany.com/public -U ntid -W w_dom
Enter ntid's password:
Domain=[W_DOM] OS=[Unix] Server=[Samba 3.6.23-13.0.1.el5_11]
smb: \> quit;
It will be necessary to enable SMB3 to successfully connect with forced encryption
where it is supported on Windows. If you attempt forced encryption without
enabling SMB3, you might see an error similar to the following:
$ smbclient -e //smb3enc.somecompany.com/shush -U nt_username -W dom
Enter DOM\NT_USERNAME's password:
Domain=[DOM]
OS=[Windows Server 2012 R2 Standard 9600]
Server=[Windows Server 2012 R2 Standard 6.3]
Encryption required and server that doesn't support UNIX extensions - failing
connect
请注意,上面的 OS
和 Server
条目已填充,并且提到了 (NT1) UNIX 扩展——这暗示连接是通过 SMB1 建立的。回想一下,SMB3 传输清除了这些条目。
特别要注意的是,只有 Samba 4.1 版本在 smbclient 实用程序中启用了 SMB2 和 SMB3。即使 Samba 3.6 完全支持服务器软件中的 SMB2,但客户端直到 4.1 版本才能使用它
Jeremy Allison 2013-08-20 18:19:11 UTC
One more thing in support of this patchset for 4.1.0...
I really want to enable -e encryption for SMB3 connections from [our] client
tools. In the current climate the only rational response is [to] encrypt
everything. Let's make that possible for our users!
Jeremy.
在有能力的 smbclient 中提升允许的协议可以启用此行为。使用 smbclient,Windows 服务器甚至可以与加密的 SMB3 会话同时运行 SMB1(这是任何现有 Windows 客户端都无法实现的功能)
$ smbclient -e //smb3enc.somecompany.com/shush -U nt_username -W dom -mSMB3
Enter DOM\NT_USERNAME's password:
Domain=[DOM] OS=[] Server=[]
smb: \> quit
如果 smbclient -e
拒绝连接到持有敏感数据的服务器,尽管彻底使用了可用的协议,那么请斥责管理员,直到协议得到保护。如果传输涉及公共互联网,这一点尤其重要。
有些人可能会断言,UNIX 下的 NFS 也是一种明文协议,具有与 SMB 相同的安全漏洞。虽然这非常正确,但 NFS 通常由数据中心中服务器之间的知识渊博的管理员启用,并且与 SMB 类似,有一些程序可以将其包装在 TLS 中。但是,SMB 由数据中心之外的非管理员通过(公司)网络使用,这些网络的物理防御能力较差。访问 SMB 的用户可能也对数据风险的技术理解要少得多。Microsoft 工具中缺乏任何数据安全讨论或警告使用户面临不必要的风险。
特别令人恼火的是,Samba 在 2008 年通过其对 NT1 的加密扩展解决了这个问题,该扩展本应出现在 XP 中。它们的缺席很容易解释为“非我发明”的一个例子,这对于操作系统供应商来说是不合理的行为。
有更强大的工具来操作 SMB——Linux 内核尤其可以使用历史悠久的“smbmount”实用程序将 Windows 共享挂载为本机网络文件系统,并且可以在 SMBNetFS 和 FuseSMB 中找到新的实现。但是,由于协议由不接受用户社区反馈或贡献的公司控制,因此更基本的问题是是否应该鼓励 SMB 扩散?
也许出于这些原因,应该以最小的热情欢迎更用户友好的 SMB 工具。
免责声明:此处表达的观点是作者的观点,不一定反映 Linux Journal 的立场。