我需要找出我正在编写的脚本,该脚本是smb共享中文件的真正所有者(当然是使用mount -t cifs
安装在我的服务器上,并通过windows机器使用net use
)。
事实证明,在linux服务器上使用python查找这些信息是一个真正的挑战。
我尝试过使用许多smb库(例如smbprotocol、smbclient和其他库),但都没有用。
我发现很少有针对windows的解决方案,它们都使用pywin32或其他特定于windows的包。
我还用smbcalcs
从bash成功地做了这件事,但是我不能干净地做,但是使用subprocess.popen('smbcacls')
。
知道怎么解决吗?
发布于 2022-07-12 19:05:03
我添加这个答案是为了让您知道使用smbprotocol的选项,以及在术语被误解的情况下展开。
SMBProtocol所有者信息
也可以使用smbprotocol库获得SID (就像pysmb库一样)。
这是在github发行的smbprotocol回购部分和一个如何做到这一点的例子一起提出的。所提供的例子非常棒,而且工作非常完美。极为精简的版本
但是,这也只是检索一个SID,并且需要一个辅助库来执行查找。
下面是一个函数,用于获取所有者SID (只需在函数中包装gist中的内容)。包括这里,以防要旨因任何原因被删除或丢失)。
import smbclient
from ldap3 import Server, Connection, ALL,NTLM,SUBTREE
def getFileOwner(smb: smbclient, conn: Connection, filePath: str):
from smbprotocol.file_info import InfoType
from smbprotocol.open import FilePipePrinterAccessMask,SMB2QueryInfoRequest, SMB2QueryInfoResponse
from smbprotocol.security_descriptor import SMB2CreateSDBuffer
class SecurityInfo:
# 100% just pulled from gist example
Owner = 0x00000001
Group = 0x00000002
Dacl = 0x00000004
Sacl = 0x00000008
Label = 0x00000010
Attribute = 0x00000020
Scope = 0x00000040
Backup = 0x00010000
def guid2hex(text_sid):
"""convert the text string SID to a hex encoded string"""
s = ['\\{:02X}'.format(ord(x)) for x in text_sid]
return ''.join(s)
def get_sd(fd, info):
""" Get the Security Descriptor for the opened file. """
query_req = SMB2QueryInfoRequest()
query_req['info_type'] = InfoType.SMB2_0_INFO_SECURITY
query_req['output_buffer_length'] = 65535
query_req['additional_information'] = info
query_req['file_id'] = fd.file_id
req = fd.connection.send(query_req, sid=fd.tree_connect.session.session_id, tid=fd.tree_connect.tree_connect_id)
resp = fd.connection.receive(req)
query_resp = SMB2QueryInfoResponse()
query_resp.unpack(resp['data'].get_value())
security_descriptor = SMB2CreateSDBuffer()
security_descriptor.unpack(query_resp['buffer'].get_value())
return security_descriptor
with smbclient.open_file(filePath, mode='rb', buffering=0,
desired_access=FilePipePrinterAccessMask.READ_CONTROL) as fd:
sd = get_sd(fd.fd, SecurityInfo.Owner | SecurityInfo.Dacl)
# returns SID
_sid = sd.get_owner()
try:
# Don't forget to convert the SID string-like object to a string
# or you get an error related to "0" not existing
sid = guid2hex(str(_sid))
except:
print(f"Failed to convert SID {_sid} to HEX")
raise
conn.search('DC=dell,DC=com',f"(&(objectSid={sid}))",SUBTREE)
# Will return an empty array if no results are found
return [res['dn'].split(",")[0].replace("CN=","") for res in conn.response if 'dn' in res]
使用:
# Client config is required if on linux, not if running on windows
smbclient.ClientConfig(username=username, password=password)
# Setup LDAP session
server = Server('mydomain.com',get_info=ALL,use_ssl = True)
# you can turn off raise_exceptions, or leave it out of the ldap connection
# but I prefer to know when there are issues vs. silently failing
conn = Connection(server, user="domain\username", password=password, raise_exceptions=True,authentication=NTLM)
conn.start_tls()
conn.open()
conn.bind()
# Run the check
fileCheck = r"\\shareserver.server.com\someNetworkShare\someFile.txt"
owner = getFileOwner(smbclient, conn, fileCheck)
# Unbind ldap session
# I'm not clear if this is 100% required, I don't THINK so
# but better safe than sorry
conn.unbind()
# Print results
print(owner)
现在,这不是超级高效。运行这个文件需要6秒。因此,如果您想运行某种类型的所有权扫描,那么您可能只想用C++或其他一些低级语言编写程序,而不是尝试使用python。但对于那些既快又脏的东西来说,这是可行的。还可以设置线程池并运行批处理。耗时最长的部分是连接到文件本身,而不是运行ldap查询,因此如果您能够找到一种更有效的方法来实现这一点,那么您将是最棒的。
术语警告,所有者!= Creator/作者
最后一张纸条。所有者!=文件作者许多域环境,特别是SMB共享,会自动将创建者的所有权更改为一个组。就我而言,上述结果是:
我真正要找的是文件的创建者。默认情况下,文件创建者和修饰符不是windows跟踪的属性。管理员可以启用策略来审核共享中的文件更改,或者可以使用单个文件的安全->高级->审计功能(这无助于帮助您确定创建者)逐个文件启用审核。
尽管如此,有些应用程序会为自己保存这些信息。例如,如果您正在寻找Excel,这个答案提供了一种方法来获取任何xls或xlsx文件的创建者(由于文件的二进制性质,xlsb不适用于xlsb)。不幸的是,很少有文件存储这种信息。在我的例子中,我希望获得tblu、pbix和其他报告类型文件的信息。但是,它们不包含这些信息(从隐私的角度来看,这是很好的)。
因此,如果有人找到这个答案,试图解决我所做的同样的事情-你最好的选择(获得实际的作者信息)是与您的领域IT管理员一起工作,以获得审计设置。
https://stackoverflow.com/questions/62021329
复制相似问题