首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >通过在linux上使用python从smb共享获取文件所有者

通过在linux上使用python从smb共享获取文件所有者
EN

Stack Overflow用户
提问于 2020-05-26 11:40:37
回答 2查看 1.4K关注 0票数 1

我需要找出我正在编写的脚本,该脚本是smb共享中文件的真正所有者(当然是使用mount -t cifs安装在我的服务器上,并通过windows机器使用net use )。

事实证明,在linux服务器上使用python查找这些信息是一个真正的挑战。

我尝试过使用许多smb库(例如smbprotocol、smbclient和其他库),但都没有用。

我发现很少有针对windows的解决方案,它们都使用pywin32或其他特定于windows的包。

我还用smbcalcs从bash成功地做了这件事,但是我不能干净地做,但是使用subprocess.popen('smbcacls')

知道怎么解决吗?

EN

Stack Overflow用户

发布于 2022-07-12 19:05:03

我添加这个答案是为了让您知道使用smbprotocol的选项,以及在术语被误解的情况下展开。

SMBProtocol所有者信息

也可以使用smbprotocol库获得SID (就像pysmb库一样)。

这是在github发行的smbprotocol回购部分一个如何做到这一点的例子一起提出的。所提供的例子非常棒,而且工作非常完美。极为精简的版本

但是,这也只是检索一个SID,并且需要一个辅助库来执行查找。

下面是一个函数,用于获取所有者SID (只需在函数中包装gist中的内容)。包括这里,以防要旨因任何原因被删除或丢失)。

代码语言:javascript
运行
复制
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]

使用:

代码语言:javascript
运行
复制
# 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管理员一起工作,以获得审计设置。

票数 1
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62021329

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档