gpt4 book ai didi

powershell - 为什么Test-Connection强制枚举重解析点?

转载 作者:行者123 更新时间:2023-12-02 22:39:28 29 4
gpt4 key购买 nike

我注意到我无法解释PowerShell中的某些行为,但我希望其他人可以。

如果要从驱动器C:\构建文件对象列表,并且想忽略诸如C:\Documents and Settings\之类的快捷方式文件夹(重新解析点)。以下命令运行良好:

$FileList = @(Get-ChildItem -Path C:\ -Recurse -Force -Attributes !ReparsePoint);
$FileList | Where-Object {$_.DirectoryName -like "*Documents and Settings*"};
Where-Object命令不返回任何预期的文件,因为 C:\Documents and Settings\是一个重新解析点。

但是,如果我先运行 Test-Connection命令,那么 Get-ChildItem命令似乎会忽略 -Attributes !ReparsePoint参数,并且会遍历 C:\Documents and Settings\
Test-Connection -Computer MyComputer;
$FileList = @(Get-ChildItem -Path C:\ -Recurse -Force -Attributes !ReparsePoint);
$FileList | Where-Object {$_.DirectoryName -like "*Documents and Settings*"};

在这种情况下, Where-Object命令显示很多文件。请注意, Test-Connection可以在任何计算机上运行,​​而不仅限于本地计算机,以表现出此行为。

我已经在运行PowerShell 4.0和PowerShell 5.1的计算机上重复了此行为。谁能解释一下发生了什么?

附加说明:若要重复此行为,请确保您使用的是PowerShell的提升实例(以管理员身份运行)。如果使用PowerShell的标准实例,则没有查看 C:\Documents and Settings\的权限。

最佳答案

要回答第一个似乎忽略-Attributes !ReparsePoint的问题,请在此处查看我的完整SO示例示例:How to prevent recursion through node_modules for gci script。 TLDR就是,通过将-Recurse参数添加到Get-ChildItem意味着它将迭代 -all- 项目首先,然后将应用过滤。这意味着它将忠实地排除“解析点”,即特定的文件夹:C:\Documents and Settings,但由于它首先获得了的所有项目,因此也将返回该文件夹下的所有内容。例如C:\Documents and Settings\desktop.ini,因为它不是Reparse Point,而是文档。因此,如果您打算这样做,那么就无法在没有附加目录级别过滤的情况下使用-Recurse参数。

第二个问题是执行Test-Connection会更改Get-ChildItem返回的内容,这看起来像是一个错误,似乎是由于PowerShell在首次执行Get-ChildItem时没有“完全”提升用户的情况。但是同时,PowerShell团队可能有意消除返回意外重复项目的情况。

为了进行调查,我们以管理员身份打开一个新的PowerShell提示符。我将略微更改代码以包括-Depth 1,只是为了更轻松地遍历代码而不必枚举整个C:驱动器;-),但是,它仍然可以说明问题:

$FileList = @(Get-ChildItem -Path C:\ -Depth 1 -Recurse -Force -Attributes !ReparsePoint);
$FileList | Where-Object {$_.DirectoryName -like "*Documents and Settings*"};

当我运行此命令时,发生错误的第一个线索是错误消息:

Get-ChildItem : Access to the path 'C:\Documents and Settings' is denied.



这突显了一个事实,即使我们以管理员身份运行PowerShell提示符,但运行的方式“提升”程度不足以访问隐藏的,重新解析点,系统文件夹,“文档和设置”。我们必须记住,“文档和设置”文件夹是与Windows Vista等兼容的旧版(坏代码;-)兼容性的一种廉价解决方法,而不是“日常”正常使用。并且,如果我们确实使用它,则可能会导致意外的重复/递归项被退回。 IE。:
PS C:\> $FileList | Where-Object {$_.DirectoryName -like "*Documents and Settings*"};
PS C:\>
PS C:\> $FileList | Where-Object {$_.DirectoryName -like "*Users*"};


Directory: C:\Users


Mode LastWriteTime Length Name
---- ------------- ------ ----
-a-hs- 2018-09-15 1:31 AM 174 desktop.ini

我们看到已经获得了Users文件夹的内容,但是由于先前的错误,我们没有返回Documents and Settings文件夹的内容。这很好,可能是故意的,因为我们没有得到任何重复的物品。我们仅在“真实”路径上获得了“真实”项目。

如果接下来运行Test-Connection命令,然后再运行同一命令(使用不同的变量名以消除混淆):
Test-Connection -Computer MyComputer;
$FileList2 = @(Get-ChildItem -Path C:\ -Depth 1 -Recurse -Force -Attributes !ReparsePoint);
$FileList2 | Where-Object {$_.DirectoryName -like "*Documents and Settings*"};

我们注意到两件事:
  • 我们没有收到任何拒绝访问错误消息。
  • 我们可以得到更多(重复)的物品:


  • PS C:\> $FileList2 | Where-Object {$_.DirectoryName -like "*Documents and Settings*"};    

    Directory: C:\Documents and Settings


    Mode LastWriteTime Length Name
    ---- ------------- ------ ----
    -a-hs- 2018-09-15 1:31 AM 174 desktop.ini

    PS C:\> $FileList2 | Where-Object {$_.DirectoryName -like "*Users*"};


    Directory: C:\Users


    Mode LastWriteTime Length Name
    ---- ------------- ------ ----
    -a-hs- 2018-09-15 1:31 AM 174 desktop.ini

    我会说这是无意的。不需要从“重新分析点”路径返回项目。如果我们将这些信息提供给其他脚本任务,例如Remove-Item,那么我们可能会遇到意想不到的问题。

    现在,让我们继续研究为什么看似无害的命令Test-Connection会导致不同的结果。较早的“访问被拒绝”错误消息给我一个线索,即身份验证周围的某些问题似乎引起了这种差异。让我们关闭PowerShell提示符并重新打开它。让我们重新运行相同的第一个命令:
    $FileList = @(Get-ChildItem -Path C:\ -Depth 1 -Recurse -Force -Attributes !ReparsePoint);
    $FileList | Where-Object {$_.DirectoryName -like "*Documents and Settings*"};

    让我们检查凭据以确保我们以管理员身份运行:
    PS C:\> $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
    PS C:\> $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    True

    确实,我们以管理员身份运行提示,所以这不是问题。让我们进一步研究一下身份:
    PS C:\> $currentPrincipal.Identities


    AuthenticationType : Kerberos
    ImpersonationLevel : None
    IsAuthenticated : True
    IsGuest : False
    IsSystem : False
    IsAnonymous : False
    Name : Contoso\HAL9256
    Owner : S-1-5-32-544
    ....
    Token : 3076
    ....

    由此,我们可以看到“知名”组S-1-5-32-544为管理员。请注意模拟级别为“无”。如果我们运行Test-Connection和相同的命令:
    Test-Connection -Computer D4700;
    $FileList2 = @(Get-ChildItem -Path C:\ -Depth 1 -Recurse -Force -Attributes !ReparsePoint);
    $FileList2 | Where-Object {$_.DirectoryName -like "*Documents and Settings*"};

    并获取主要对象:
    PS C:\> $currentPrincipal2 = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
    PS C:\> $currentPrincipal2.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    True

    这证明我们仍在以管理员身份运行。现在让我们看一下身份:
    PS C:\> $currentPrincipal2.Identities


    AuthenticationType : Kerberos
    ImpersonationLevel : Impersonation
    IsAuthenticated : True
    IsGuest : False
    IsSystem : False
    IsAnonymous : False
    Name : Contoso\HAL9256
    Owner : S-1-5-32-544
    ....
    Token : 4500
    ....

    这次我们看到模拟级别是Impersonation。从Impersonation Level Enum Docs:

    Impersonation 3

    The server process can impersonate the client's security context on its local system. The server cannot impersonate the client on remote systems.



    当我们执行Test-Connection时,它需要本地计算机上的网络资源才能执行ping操作。为了做到这一点,它透明地将提示从Impersonate提升到None级别(我们甚至可以看到发生这种情况,因为 token 号已更改)。这样做的副作用是允许Get-ChildItem现在具有访问系统文件“文档和设置”的提升权限。即就像在文件资源管理器中选中“显示隐藏的文件”,现在允许它通过“重新解析点”进行枚举。

    我们还可以观察到这是我们远程访问另一台机器时的原因:
    PS C:\> Enter-PSSession -ComputerName RemoteMachine -Credential (Get-Credential) -Authentication Kerberos

    [RemoteMachine]: PS C:\Users\HAL9256\Documents> $FileList = @(Get-ChildItem -Path C:\ -Depth 1 -Recurse -Force -Attributes !ReparsePoint);
    [RemoteMachine]: PS C:\Users\HAL9256\Documents> $FileList | Where-Object {$_.DirectoryName -like "*Documents and Settings*"};


    Directory: C:\Documents and Settings


    Mode LastWriteTime Length Name
    ---- ------------- ------ ----
    -a-hs- 7/16/2016 7:21 AM 174 desktop.ini


    [RemoteMachine]: PS C:\Users\HAL9256\Documents>
    [RemoteMachine]: PS C:\Users\HAL9256\Documents> $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
    [RemoteMachine]: PS C:\Users\HAL9256\Documents> $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    True
    [RemoteMachine]: PS C:\Users\HAL9256\Documents>
    [RemoteMachine]: PS C:\Users\HAL9256\Documents> $currentPrincipal.Identities

    AuthenticationType : Kerberos
    ImpersonationLevel : Impersonation
    IsAuthenticated : True
    IsGuest : False
    IsSystem : False
    IsAnonymous : False
    Name : Contoso\HAL9256
    Owner : S-1-5-32-544
    ....
    Token : 4420
    ....

    当我们这样做时,我们看到它返回了Documents and Settings,而无需首先执行Test-Connection。查看主体,我们看到模拟级别设置为Impersonation

    最终,这告诉我们造成这种不一致的原因是“模拟级别”设置。为了访问隐藏的系统文件和Reparse Point,我们需要将“模拟级别”至少设置为Impersonation

    关于powershell - 为什么Test-Connection强制枚举重解析点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47802040/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com